Diff for /src/sys/kern/kern_sysctl.c between versions 1.14 and 1.15

version 1.14, 2003/11/23 22:15:22 version 1.15, 2004/03/29 14:06:31
Line 49 Line 49
 #include <sys/malloc.h>  #include <sys/malloc.h>
 #include <sys/proc.h>  #include <sys/proc.h>
 #include <sys/sysproto.h>  #include <sys/sysproto.h>
   #include <sys/lock.h>
 #include <vm/vm.h>  #include <vm/vm.h>
 #include <vm/vm_extern.h>  #include <vm/vm_extern.h>
   
 static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic");  static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic");
 static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids");  static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids");
   
/*static struct lock sysctl_lkp;
 * Locking and statsstatic struct lock sysctl_ctx_lkp;
 */ 
static struct sysctl_lock { 
        int     sl_lock; 
        int     sl_want; 
        int     sl_locked; 
} memlock; 
   
static int sysctl_root(SYSCTL_HANDLER_ARGS);static void     sysctl_lock(int type);
 static void     sysctl_unlock(void);
 static void     sysctl_ctx_lock(int type);
 static void     sysctl_ctx_unlock(void);
 
 static int      sysctl_root(SYSCTL_HANDLER_ARGS);
 static void     sysctl_register_oid_int(struct sysctl_oid *oipd);
 static void     sysctl_unregister_oid_int(struct sysctl_oid *oipd);
 static struct sysctl_ctx_entry* sysctl_ctx_entry_find_int
         (struct sysctl_ctx_list *, struct sysctl_oid *oidp);
   
 struct sysctl_oid_list sysctl__children; /* root list */  struct sysctl_oid_list sysctl__children; /* root list */
   
 static struct sysctl_oid *  static struct sysctl_oid *
sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)sysctl_find_oidname(const char *name, struct sysctl_oid_list *list, int lock)
 {  {
         struct sysctl_oid *oidp;          struct sysctl_oid *oidp;
   
         SLIST_FOREACH(oidp, list, oid_link) {          SLIST_FOREACH(oidp, list, oid_link) {
                 if (strcmp(oidp->oid_name, name) == 0) {                  if (strcmp(oidp->oid_name, name) == 0) {
                        return (oidp);                        break;
                 }                  }
         }          }
        return (NULL);        return (oidp);
 }  }
   
 /*  /*
Line 87  sysctl_find_oidname(const char *name, st Line 91  sysctl_find_oidname(const char *name, st
  * Order by number in each list.   * Order by number in each list.
  */   */
   
void sysctl_register_oid(struct sysctl_oid *oidp)void
 sysctl_register_oid(struct sysctl_oid *oidp)
 {
         sysctl_lock(LK_EXCLUSIVE);
         sysctl_register_oid_int(oidp);
         sysctl_unlock();
 }
 
 static void
 sysctl_register_oid_int(struct sysctl_oid *oidp)
 {  {
         struct sysctl_oid_list *parent = oidp->oid_parent;          struct sysctl_oid_list *parent = oidp->oid_parent;
         struct sysctl_oid *p;          struct sysctl_oid *p;
Line 97  void sysctl_register_oid(struct sysctl_o Line 110  void sysctl_register_oid(struct sysctl_o
          * First check if another oid with the same name already           * First check if another oid with the same name already
          * exists in the parent's list.           * exists in the parent's list.
          */           */
        p = sysctl_find_oidname(oidp->oid_name, parent);        p = sysctl_find_oidname(oidp->oid_name, parent, 0);
         if (p != NULL) {          if (p != NULL) {
                if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) {                if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE)
                         p->oid_refcnt++;                          p->oid_refcnt++;
                        return;                else
                } else { 
                         printf("can't re-use a leaf (%s)!\n", p->oid_name);                          printf("can't re-use a leaf (%s)!\n", p->oid_name);
                        return;                return;
                } 
         }          }
   
         /*          /*
          * If this oid has a number OID_AUTO, give it a number which           * If this oid has a number OID_AUTO, give it a number which
          * is greater than any current oid.  Make sure it is at least           * is greater than any current oid.  Make sure it is at least
Line 140  void sysctl_register_oid(struct sysctl_o Line 152  void sysctl_register_oid(struct sysctl_o
                 SLIST_INSERT_HEAD(parent, oidp, oid_link);                  SLIST_INSERT_HEAD(parent, oidp, oid_link);
 }  }
   
void sysctl_unregister_oid(struct sysctl_oid *oidp)void
 sysctl_unregister_oid(struct sysctl_oid *oidp)
 {
         sysctl_lock(LK_EXCLUSIVE);
         sysctl_unregister_oid_int(oidp);
         sysctl_unlock();
 }
 
 static void
 sysctl_unregister_oid_int(struct sysctl_oid *oidp)
 {  {
         struct sysctl_oid *p;          struct sysctl_oid *p;
         int error;  
   
        error = ENOENT;        if (oidp->oid_number == OID_AUTO)
        if (oidp->oid_number == OID_AUTO) {                panic("Trying to unregister OID_AUTO entry: %p\n", oidp);
                error = EINVAL;
        } else {        SLIST_FOREACH(p, oidp->oid_parent, oid_link) {
                SLIST_FOREACH(p, oidp->oid_parent, oid_link) {                if (p != oidp)
                        if (p == oidp) {                        continue;
                                SLIST_REMOVE(oidp->oid_parent, oidp,                SLIST_REMOVE(oidp->oid_parent, oidp, sysctl_oid, oid_link);
                                                sysctl_oid, oid_link);                return;
                                error = 0; 
                                break; 
                        } 
                } 
         }          }
   
         /*          /*
Line 164  void sysctl_unregister_oid(struct sysctl Line 180  void sysctl_unregister_oid(struct sysctl
          * being unloaded afterwards.  It should not be a panic()           * being unloaded afterwards.  It should not be a panic()
          * for normal use.           * for normal use.
          */           */
        if (error)        printf("%s: failed to unregister sysctl\n", __func__);
                printf("%s: failed to unregister sysctl\n", __func__); 
 }  }
   
 /* Initialize a new context to keep track of dynamically added sysctls. */  /* Initialize a new context to keep track of dynamically added sysctls. */
 int  int
 sysctl_ctx_init(struct sysctl_ctx_list *c)  sysctl_ctx_init(struct sysctl_ctx_list *c)
 {  {
        if (c == NULL)
        if (c == NULL) {                return(EINVAL);
                return (EINVAL); 
        } 
         TAILQ_INIT(c);          TAILQ_INIT(c);
        return (0);        return(0);
 }  }
   
 /* Free the context, and destroy all dynamic oids registered in this context */  /* Free the context, and destroy all dynamic oids registered in this context */
Line 188  sysctl_ctx_free(struct sysctl_ctx_list * Line 201  sysctl_ctx_free(struct sysctl_ctx_list *
         int error;          int error;
   
         error = 0;          error = 0;
           sysctl_ctx_lock(LK_EXCLUSIVE);
         /*          /*
          * First perform a "dry run" to check if it's ok to remove oids.           * First perform a "dry run" to check if it's ok to remove oids.
          * XXX FIXME           * XXX FIXME
Line 212  sysctl_ctx_free(struct sysctl_ctx_list * Line 226  sysctl_ctx_free(struct sysctl_ctx_list *
                 sysctl_register_oid(e1->entry);                  sysctl_register_oid(e1->entry);
                 e1 = TAILQ_PREV(e1, sysctl_ctx_list, link);                  e1 = TAILQ_PREV(e1, sysctl_ctx_list, link);
         }          }
        if (error)        if (error) {
                 sysctl_ctx_unlock();
                 return(EBUSY);                  return(EBUSY);
           }
         /* Now really delete the entries */          /* Now really delete the entries */
         e = TAILQ_FIRST(clist);          e = TAILQ_FIRST(clist);
         while (e != NULL) {          while (e != NULL) {
Line 225  sysctl_ctx_free(struct sysctl_ctx_list * Line 241  sysctl_ctx_free(struct sysctl_ctx_list *
                 free(e, M_SYSCTLOID);                  free(e, M_SYSCTLOID);
                 e = e1;                  e = e1;
         }          }
           sysctl_ctx_unlock();
         return (error);          return (error);
 }  }
   
Line 238  sysctl_ctx_entry_add(struct sysctl_ctx_l Line 255  sysctl_ctx_entry_add(struct sysctl_ctx_l
                 return(NULL);                  return(NULL);
         e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK);          e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK);
         e->entry = oidp;          e->entry = oidp;
           sysctl_ctx_lock(LK_EXCLUSIVE);
         TAILQ_INSERT_HEAD(clist, e, link);          TAILQ_INSERT_HEAD(clist, e, link);
           sysctl_ctx_unlock();
         return (e);          return (e);
 }  }
   
Line 250  sysctl_ctx_entry_find(struct sysctl_ctx_ Line 269  sysctl_ctx_entry_find(struct sysctl_ctx_
   
         if (clist == NULL || oidp == NULL)          if (clist == NULL || oidp == NULL)
                 return(NULL);                  return(NULL);
   
           sysctl_ctx_lock(LK_SHARED);
           e = sysctl_ctx_entry_find_int(clist, oidp);
           sysctl_ctx_unlock();
   
           return(e);
   }
   
   struct sysctl_ctx_entry *
   sysctl_ctx_entry_find_int(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
   {
           struct sysctl_ctx_entry *e;
   
           KKASSERT(clist != NULL && oidp != NULL);
   
         for (e = TAILQ_FIRST(clist); e != NULL; e = TAILQ_NEXT(e, link)) {          for (e = TAILQ_FIRST(clist); e != NULL; e = TAILQ_NEXT(e, link)) {
                 if(e->entry == oidp)                  if(e->entry == oidp)
                        return(e);                        break;
         }          }
   
         return (e);          return (e);
 }  }
   
Line 269  sysctl_ctx_entry_del(struct sysctl_ctx_l Line 304  sysctl_ctx_entry_del(struct sysctl_ctx_l
   
         if (clist == NULL || oidp == NULL)          if (clist == NULL || oidp == NULL)
                 return (EINVAL);                  return (EINVAL);
        e = sysctl_ctx_entry_find(clist, oidp);
        if (e != NULL) {        sysctl_ctx_lock(LK_EXCLUSIVE);
                TAILQ_REMOVE(clist, e, link);        e = sysctl_ctx_entry_find_int(clist, oidp);
                free(e, M_SYSCTLOID);        if (e == NULL) {
                return (0);                sysctl_ctx_unlock();
        } else 
                 return (ENOENT);                  return (ENOENT);
           }
           TAILQ_REMOVE(clist, e, link);
           free(e, M_SYSCTLOID);
           sysctl_ctx_unlock();
   
           return(0);
 }  }
   
 /*  /*
Line 296  sysctl_remove_oid(struct sysctl_oid *oid Line 336  sysctl_remove_oid(struct sysctl_oid *oid
                 printf("can't remove non-dynamic nodes!\n");                  printf("can't remove non-dynamic nodes!\n");
                 return (EINVAL);                  return (EINVAL);
         }          }
           sysctl_lock(LK_EXCLUSIVE | LK_CANRECURSE);
         /*          /*
          * WARNING: normal method to do this should be through           * WARNING: normal method to do this should be through
          * sysctl_ctx_free(). Use recursing as the last resort           * sysctl_ctx_free(). Use recursing as the last resort
Line 306  sysctl_remove_oid(struct sysctl_oid *oid Line 347  sysctl_remove_oid(struct sysctl_oid *oid
         if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {          if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
                 if (oidp->oid_refcnt == 1) {                  if (oidp->oid_refcnt == 1) {
                         SLIST_FOREACH(p, SYSCTL_CHILDREN(oidp), oid_link) {                          SLIST_FOREACH(p, SYSCTL_CHILDREN(oidp), oid_link) {
                                if (!recurse)                                if (!recurse) {
                                        return (ENOTEMPTY);                                        sysctl_unlock();
                                         return(ENOTEMPTY);
                                 }
                                 error = sysctl_remove_oid(p, del, recurse);                                  error = sysctl_remove_oid(p, del, recurse);
                                if (error)                                if (error) {
                                        return (error);                                        sysctl_unlock();
                                         return(error);
                                 }
                         }                          }
                         if (del)                          if (del)
                                 free(SYSCTL_CHILDREN(oidp), M_SYSCTLOID);                                  free(SYSCTL_CHILDREN(oidp), M_SYSCTLOID);
Line 321  sysctl_remove_oid(struct sysctl_oid *oid Line 366  sysctl_remove_oid(struct sysctl_oid *oid
         } else {          } else {
                 if (oidp->oid_refcnt == 0) {                  if (oidp->oid_refcnt == 0) {
                         printf("Warning: bad oid_refcnt=%u (%s)!\n",                          printf("Warning: bad oid_refcnt=%u (%s)!\n",
                                oidp->oid_refcnt, oidp->oid_name);                               oidp->oid_refcnt, oidp->oid_name);
                        return (EINVAL);                        sysctl_unlock();
                         return(EINVAL);
                 }                  }
                sysctl_unregister_oid(oidp);                sysctl_unregister_oid_int(oidp);
                 if (del) {                  if (del) {
                         if (oidp->oid_descr)                          if (oidp->oid_descr)
                                free((void *)(uintptr_t)(const void *)oidp->oid_descr, M_SYSCTLOID);                                free(__DECONST(char *,oidp->oid_descr),
                        free((void *)(uintptr_t)(const void *)oidp->oid_name,                                     M_SYSCTLOID);
                             M_SYSCTLOID);                        free(__DECONST(char *, oidp->oid_name), M_SYSCTLOID);
                         free(oidp, M_SYSCTLOID);                          free(oidp, M_SYSCTLOID);
                 }                  }
         }          }
        return (0);        sysctl_unlock();
         return(0);
 }  }
   
 /*  /*
Line 352  sysctl_add_oid(struct sysctl_ctx_list *c Line 399  sysctl_add_oid(struct sysctl_ctx_list *c
         /* You have to hook up somewhere.. */          /* You have to hook up somewhere.. */
         if (parent == NULL)          if (parent == NULL)
                 return(NULL);                  return(NULL);
           sysctl_lock(LK_EXCLUSIVE);
         /* Check if the node already exists, otherwise create it */          /* Check if the node already exists, otherwise create it */
        oidp = sysctl_find_oidname(name, parent);        oidp = sysctl_find_oidname(name, parent, 0);
         if (oidp != NULL) {          if (oidp != NULL) {
                 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {                  if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
                         oidp->oid_refcnt++;                          oidp->oid_refcnt++;
                         /* Update the context */                          /* Update the context */
                         if (clist != NULL)                          if (clist != NULL)
                                 sysctl_ctx_entry_add(clist, oidp);                                  sysctl_ctx_entry_add(clist, oidp);
                           sysctl_unlock();
                         return (oidp);                          return (oidp);
                 } else {                  } else {
                         printf("can't re-use a leaf (%s)!\n", name);                          printf("can't re-use a leaf (%s)!\n", name);
                           sysctl_unlock();
                         return (NULL);                          return (NULL);
                 }                  }
         }          }
        oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK);        oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK | M_ZERO);
        bzero(oidp, sizeof(struct sysctl_oid)); 
         oidp->oid_parent = parent;          oidp->oid_parent = parent;
         SLIST_NEXT(oidp, oid_link) = NULL;          SLIST_NEXT(oidp, oid_link) = NULL;
         oidp->oid_number = number;          oidp->oid_number = number;
Line 399  sysctl_add_oid(struct sysctl_ctx_list *c Line 448  sysctl_add_oid(struct sysctl_ctx_list *c
         if (clist != NULL)          if (clist != NULL)
                 sysctl_ctx_entry_add(clist, oidp);                  sysctl_ctx_entry_add(clist, oidp);
         /* Register this oid */          /* Register this oid */
        sysctl_register_oid(oidp);        sysctl_register_oid_int(oidp);
         sysctl_unlock();
         return (oidp);          return (oidp);
 }  }
   
Line 412  static void sysctl_register_all(void *ar Line 462  static void sysctl_register_all(void *ar
 {  {
         struct sysctl_oid **oidp;          struct sysctl_oid **oidp;
   
           lockinit(&sysctl_lkp, 0, "sysctl", 0, 0);
           lockinit(&sysctl_ctx_lkp, 0, "sysctl ctx", 0, 0);
         SET_FOREACH(oidp, sysctl_set)          SET_FOREACH(oidp, sysctl_set)
                sysctl_register_oid(*oidp);                sysctl_register_oid_int(*oidp);
 }  }
   
 SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_register_all, 0);  SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_register_all, 0);
Line 442  sysctl_sysctl_debug_dump_node(struct sys Line 494  sysctl_sysctl_debug_dump_node(struct sys
         int k;          int k;
         struct sysctl_oid *oidp;          struct sysctl_oid *oidp;
   
           sysctl_lock(LK_SHARED);
         SLIST_FOREACH(oidp, l, oid_link) {          SLIST_FOREACH(oidp, l, oid_link) {
   
                 for (k=0; k<i; k++)                  for (k=0; k<i; k++)
Line 472  sysctl_sysctl_debug_dump_node(struct sys Line 525  sysctl_sysctl_debug_dump_node(struct sys
                 }                  }
   
         }          }
           sysctl_unlock();
 }  }
   
 static int  static int
Line 499  sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) Line 553  sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
         struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;          struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;
         char buf[10];          char buf[10];
   
           sysctl_lock(LK_SHARED);
         while (namelen) {          while (namelen) {
                 if (!lsp) {                  if (!lsp) {
                         snprintf(buf,sizeof(buf),"%d",*name);                          snprintf(buf,sizeof(buf),"%d",*name);
Line 506  sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) Line 561  sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
                                 error = SYSCTL_OUT(req, ".", 1);                                  error = SYSCTL_OUT(req, ".", 1);
                         if (!error)                          if (!error)
                                 error = SYSCTL_OUT(req, buf, strlen(buf));                                  error = SYSCTL_OUT(req, buf, strlen(buf));
                        if (error)                        if (error) {
                                 sysctl_unlock();
                                 return (error);                                  return (error);
                           }
                         namelen--;                          namelen--;
                         name++;                          name++;
                         continue;                          continue;
Line 522  sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) Line 579  sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
                         if (!error)                          if (!error)
                                 error = SYSCTL_OUT(req, oid->oid_name,                                  error = SYSCTL_OUT(req, oid->oid_name,
                                         strlen(oid->oid_name));                                          strlen(oid->oid_name));
                        if (error)                        if (error) {
                                 sysctl_unlock();
                                 return (error);                                  return (error);
                           }
   
                         namelen--;                          namelen--;
                         name++;                          name++;
Line 539  sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) Line 598  sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
                 }                  }
                 lsp = lsp2;                  lsp = lsp2;
         }          }
           sysctl_unlock();
         return (SYSCTL_OUT(req, "", 1));          return (SYSCTL_OUT(req, "", 1));
 }  }
   
Line 551  sysctl_sysctl_next_ls(struct sysctl_oid_ Line 611  sysctl_sysctl_next_ls(struct sysctl_oid_
         struct sysctl_oid *oidp;          struct sysctl_oid *oidp;
   
         *len = level;          *len = level;
           sysctl_lock(LK_SHARED);
         SLIST_FOREACH(oidp, lsp, oid_link) {          SLIST_FOREACH(oidp, lsp, oid_link) {
                 *next = oidp->oid_number;                  *next = oidp->oid_number;
                 *oidpp = oidp;                  *oidpp = oidp;
   
                 if (!namelen) {                  if (!namelen) {
                        if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)                         if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) {
                                 sysctl_unlock();
                                 return 0;                                  return 0;
                        if (oidp->oid_handler)                         }
                         if (oidp->oid_handler) {
                                 /* We really should call the handler here...*/                                  /* We really should call the handler here...*/
                                   sysctl_unlock();
                                 return 0;                                  return 0;
                           }
                         lsp = (struct sysctl_oid_list *)oidp->oid_arg1;                          lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
                         if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1,                           if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1, 
                                len, level+1, oidpp))                                len, level+1, oidpp)) {
                                 sysctl_unlock();
                                 return 0;                                  return 0;
                           }
                         goto emptynode;                          goto emptynode;
                 }                  }
   
Line 572  sysctl_sysctl_next_ls(struct sysctl_oid_ Line 639  sysctl_sysctl_next_ls(struct sysctl_oid_
                         continue;                          continue;
   
                 if (oidp->oid_number > *name) {                  if (oidp->oid_number > *name) {
                        if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)                        if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) {
                                 sysctl_unlock();
                                 return 0;                                  return 0;
                        if (oidp->oid_handler)                        }
                         if (oidp->oid_handler) {
                                 sysctl_unlock();
                                 return 0;                                  return 0;
                           }
                         lsp = (struct sysctl_oid_list *)oidp->oid_arg1;                          lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
                         if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1,                           if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, 
                                next+1, len, level+1, oidpp))                                next+1, len, level+1, oidpp)) {
                                 sysctl_unlock();
                                 return (0);                                  return (0);
                           }
                         goto next;                          goto next;
                 }                  }
                 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)                  if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
Line 590  sysctl_sysctl_next_ls(struct sysctl_oid_ Line 663  sysctl_sysctl_next_ls(struct sysctl_oid_
   
                 lsp = (struct sysctl_oid_list *)oidp->oid_arg1;                  lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
                 if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1,                   if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1, 
                        len, level+1, oidpp))                        len, level+1, oidpp)) {
                         sysctl_unlock();
                         return (0);                          return (0);
                   }
         next:          next:
                 namelen = 1;                  namelen = 1;
                 *len = level;                  *len = level;
         emptynode:          emptynode:
                 *len = level;                  *len = level;
         }          }
           sysctl_unlock();
         return 1;          return 1;
 }  }
   
Line 643  name2oid (char *name, int *oid, int *len Line 719  name2oid (char *name, int *oid, int *len
         if (i == '.')          if (i == '.')
                 *p = '\0';                  *p = '\0';
   
           sysctl_lock(LK_SHARED);
         oidp = SLIST_FIRST(lsp);          oidp = SLIST_FIRST(lsp);
   
         while (oidp && *len < CTL_MAXNAME) {          while (oidp && *len < CTL_MAXNAME) {
Line 656  name2oid (char *name, int *oid, int *len Line 733  name2oid (char *name, int *oid, int *len
                 if (!i) {                  if (!i) {
                         if (oidpp)                          if (oidpp)
                                 *oidpp = oidp;                                  *oidpp = oidp;
                           sysctl_unlock();
                         return (0);                          return (0);
                 }                  }
   
Line 674  name2oid (char *name, int *oid, int *len Line 752  name2oid (char *name, int *oid, int *len
                 if (i == '.')                  if (i == '.')
                         *p = '\0';                          *p = '\0';
         }          }
           sysctl_unlock();
         return ENOENT;          return ENOENT;
 }  }
   
Line 934  kernel_sysctl(int *name, u_int namelen, Line 1013  kernel_sysctl(int *name, u_int namelen,
         req.newfunc = sysctl_new_kernel;          req.newfunc = sysctl_new_kernel;
         req.lock = 1;          req.lock = 1;
   
        /* XXX this should probably be done in a general way */        sysctl_lock(LK_SHARED);
        while (memlock.sl_lock) { 
                memlock.sl_want = 1; 
                (void) tsleep((caddr_t)&memlock, 0, "sysctl", 0); 
                memlock.sl_locked++; 
        } 
        memlock.sl_lock = 1; 
   
         error = sysctl_root(0, name, namelen, &req);          error = sysctl_root(0, name, namelen, &req);
   
         if (req.lock == 2)          if (req.lock == 2)
                 vsunlock(req.oldptr, req.oldlen);                  vsunlock(req.oldptr, req.oldlen);
   
        memlock.sl_lock = 0;        sysctl_unlock();
 
        if (memlock.sl_want) { 
                memlock.sl_want = 0; 
                wakeup((caddr_t)&memlock); 
        } 
   
         if (error && error != ENOMEM)          if (error && error != ENOMEM)
                 return (error);                  return (error);
Line 1038  sysctl_find_oid(int *name, u_int namelen Line 1106  sysctl_find_oid(int *name, u_int namelen
         struct sysctl_oid *oid;          struct sysctl_oid *oid;
         int indx;          int indx;
   
           sysctl_lock(LK_SHARED);
         oid = SLIST_FIRST(&sysctl__children);          oid = SLIST_FIRST(&sysctl__children);
         indx = 0;          indx = 0;
         while (oid && indx < CTL_MAXNAME) {          while (oid && indx < CTL_MAXNAME) {
Line 1051  sysctl_find_oid(int *name, u_int namelen Line 1120  sysctl_find_oid(int *name, u_int namelen
                                         *noid = oid;                                          *noid = oid;
                                         if (nindx != NULL)                                          if (nindx != NULL)
                                                 *nindx = indx;                                                  *nindx = indx;
                                           sysctl_unlock();
                                         return (0);                                          return (0);
                                 }                                  }
                                 oid = SLIST_FIRST(                                  oid = SLIST_FIRST(
Line 1059  sysctl_find_oid(int *name, u_int namelen Line 1129  sysctl_find_oid(int *name, u_int namelen
                                 *noid = oid;                                  *noid = oid;
                                 if (nindx != NULL)                                  if (nindx != NULL)
                                         *nindx = indx;                                          *nindx = indx;
                                   sysctl_unlock();
                                 return (0);                                  return (0);
                         } else {                          } else {
                                   sysctl_unlock();
                                 return (ENOTDIR);                                  return (ENOTDIR);
                         }                          }
                 } else {                  } else {
                         oid = SLIST_NEXT(oid, oid_link);                          oid = SLIST_NEXT(oid, oid_link);
                 }                  }
         }          }
           sysctl_unlock();
         return (ENOENT);          return (ENOENT);
 }  }
   
Line 1186  userland_sysctl(int *name, u_int namelen Line 1259  userland_sysctl(int *name, u_int namelen
         req.lock = 1;          req.lock = 1;
         req.td = curthread;          req.td = curthread;
   
        /* XXX this should probably be done in a general way */        sysctl_lock(LK_SHARED);
        while (memlock.sl_lock) { 
                memlock.sl_want = 1; 
                (void) tsleep((caddr_t)&memlock, 0, "sysctl", 0); 
                memlock.sl_locked++; 
        } 
        memlock.sl_lock = 1; 
   
         do {          do {
             req2 = req;              req2 = req;
Line 1203  userland_sysctl(int *name, u_int namelen Line 1270  userland_sysctl(int *name, u_int namelen
         if (req.lock == 2)          if (req.lock == 2)
                 vsunlock(req.oldptr, req.oldlen);                  vsunlock(req.oldptr, req.oldlen);
   
        memlock.sl_lock = 0;        sysctl_unlock();
 
        if (memlock.sl_want) { 
                memlock.sl_want = 0; 
                wakeup((caddr_t)&memlock); 
        } 
   
         if (error && error != ENOMEM)          if (error && error != ENOMEM)
                 return (error);                  return (error);
Line 1221  userland_sysctl(int *name, u_int namelen Line 1283  userland_sysctl(int *name, u_int namelen
         }          }
         return (error);          return (error);
 }  }
   
   static void
   sysctl_lock(int flag)
   {
           lockmgr(&sysctl_lkp, flag, NULL, curthread);
   }
   
   static void
   sysctl_unlock(void)
   {
           lockmgr(&sysctl_lkp, LK_RELEASE, NULL, curthread);
   }
   
   static void
   sysctl_ctx_lock(int flag)
   {
           lockmgr(&sysctl_ctx_lkp, flag, NULL, curthread);
   }
   
   static void
   sysctl_ctx_unlock(void)
   {
           lockmgr(&sysctl_ctx_lkp, LK_RELEASE, NULL, curthread);
   }

Removed from v.1.14  
changed lines
  Added in v.1.15