[BACK]Return to subr_autoconf.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/kern/subr_autoconf.c between version 1.250 and 1.251

version 1.250, 2017/03/20 01:06:29 version 1.251, 2017/03/20 01:13:07
Line 217  static TAILQ_HEAD(, finalize_hook) confi
Line 217  static TAILQ_HEAD(, finalize_hook) confi
 static int config_finalize_done;  static int config_finalize_done;
   
 /* list of all devices */  /* list of all devices */
 static struct devicelist alldevs = TAILQ_HEAD_INITIALIZER(alldevs);  static struct {
 static kmutex_t alldevs_mtx;          kmutex_t                lock;
 static bool alldevs_garbage = false;          struct devicelist       list;
 static devgen_t alldevs_gen = 1;          devgen_t                gen;
 static int alldevs_nread = 0;          int                     nread;
 static int alldevs_nwrite = 0;          int                     nwrite;
           bool                    garbage;
   } alldevs __cacheline_aligned = {
           .list = TAILQ_HEAD_INITIALIZER(alldevs.list),
           .gen = 1,
           .nread = 0,
           .nwrite = 0,
           .garbage = false,
   };
   
 static int config_pending;              /* semaphore for mountroot */  static int config_pending;              /* semaphore for mountroot */
 static kmutex_t config_misc_lock;  static kmutex_t config_misc_lock;
Line 341  config_init(void)
Line 349  config_init(void)
   
         KASSERT(config_initialized == false);          KASSERT(config_initialized == false);
   
         mutex_init(&alldevs_mtx, MUTEX_DEFAULT, IPL_VM);          mutex_init(&alldevs.lock, MUTEX_DEFAULT, IPL_VM);
   
         mutex_init(&config_misc_lock, MUTEX_DEFAULT, IPL_NONE);          mutex_init(&config_misc_lock, MUTEX_DEFAULT, IPL_NONE);
         cv_init(&config_misc_cv, "cfgmisc");          cv_init(&config_misc_cv, "cfgmisc");
Line 1155  number(char *ep, int n)
Line 1163  number(char *ep, int n)
 /*  /*
  * Expand the size of the cd_devs array if necessary.   * Expand the size of the cd_devs array if necessary.
  *   *
  * The caller must hold alldevs_mtx. config_makeroom() may release and   * The caller must hold alldevs.lock. config_makeroom() may release and
  * re-acquire alldevs_mtx, so callers should re-check conditions such   * re-acquire alldevs.lock, so callers should re-check conditions such
  * as alldevs_nwrite == 0 and alldevs_nread == 0 when config_makeroom()   * as alldevs.nwrite == 0 and alldevs.nread == 0 when config_makeroom()
  * returns.   * returns.
  */   */
 static void  static void
Line 1166  config_makeroom(int n, struct cfdriver *
Line 1174  config_makeroom(int n, struct cfdriver *
         int ondevs, nndevs;          int ondevs, nndevs;
         device_t *osp, *nsp;          device_t *osp, *nsp;
   
         KASSERT(mutex_owned(&alldevs_mtx));          KASSERT(mutex_owned(&alldevs.lock));
         alldevs_nwrite++;          alldevs.nwrite++;
   
         for (nndevs = MAX(4, cd->cd_ndevs); nndevs <= n; nndevs += nndevs)          for (nndevs = MAX(4, cd->cd_ndevs); nndevs <= n; nndevs += nndevs)
                 ;                  ;
Line 1179  config_makeroom(int n, struct cfdriver *
Line 1187  config_makeroom(int n, struct cfdriver *
                 ondevs = cd->cd_ndevs;                  ondevs = cd->cd_ndevs;
                 osp = cd->cd_devs;                  osp = cd->cd_devs;
   
                 /* Release alldevs_mtx around allocation, which may                  /*
                    * Release alldevs.lock around allocation, which may
                  * sleep.                   * sleep.
                  */                   */
                 mutex_exit(&alldevs_mtx);                  mutex_exit(&alldevs.lock);
                 nsp = kmem_alloc(sizeof(device_t[nndevs]), KM_SLEEP);                  nsp = kmem_alloc(sizeof(device_t[nndevs]), KM_SLEEP);
                 if (nsp == NULL)                  if (nsp == NULL)
                         panic("%s: could not expand cd_devs", __func__);                          panic("%s: could not expand cd_devs", __func__);
                 mutex_enter(&alldevs_mtx);                  mutex_enter(&alldevs.lock);
   
                 /* If another thread moved the array while we did                  /*
                  * not hold alldevs_mtx, try again.                   * If another thread moved the array while we did
                    * not hold alldevs.lock, try again.
                  */                   */
                 if (cd->cd_devs != osp) {                  if (cd->cd_devs != osp) {
                         mutex_exit(&alldevs_mtx);                          mutex_exit(&alldevs.lock);
                         kmem_free(nsp, sizeof(device_t[nndevs]));                          kmem_free(nsp, sizeof(device_t[nndevs]));
                         mutex_enter(&alldevs_mtx);                          mutex_enter(&alldevs.lock);
                         continue;                          continue;
                 }                  }
   
Line 1205  config_makeroom(int n, struct cfdriver *
Line 1215  config_makeroom(int n, struct cfdriver *
                 cd->cd_ndevs = nndevs;                  cd->cd_ndevs = nndevs;
                 cd->cd_devs = nsp;                  cd->cd_devs = nsp;
                 if (ondevs != 0) {                  if (ondevs != 0) {
                         mutex_exit(&alldevs_mtx);                          mutex_exit(&alldevs.lock);
                         kmem_free(osp, sizeof(device_t[ondevs]));                          kmem_free(osp, sizeof(device_t[ondevs]));
                         mutex_enter(&alldevs_mtx);                          mutex_enter(&alldevs.lock);
                 }                  }
         }          }
         KASSERT(mutex_owned(&alldevs_mtx));          KASSERT(mutex_owned(&alldevs.lock));
         alldevs_nwrite--;          alldevs.nwrite--;
 }  }
   
 /*  /*
Line 1221  static void
Line 1231  static void
 config_devlink(device_t dev)  config_devlink(device_t dev)
 {  {
   
         mutex_enter(&alldevs_mtx);          mutex_enter(&alldevs.lock);
   
         KASSERT(device_cfdriver(dev)->cd_devs[dev->dv_unit] == dev);          KASSERT(device_cfdriver(dev)->cd_devs[dev->dv_unit] == dev);
   
         dev->dv_add_gen = alldevs_gen;          dev->dv_add_gen = alldevs.gen;
         /* It is safe to add a device to the tail of the list while          /* It is safe to add a device to the tail of the list while
          * readers and writers are in the list.           * readers and writers are in the list.
          */           */
         TAILQ_INSERT_TAIL(&alldevs, dev, dv_list);          TAILQ_INSERT_TAIL(&alldevs.list, dev, dv_list);
         mutex_exit(&alldevs_mtx);          mutex_exit(&alldevs.lock);
 }  }
   
 static void  static void
Line 1245  config_devfree(device_t dev)
Line 1255  config_devfree(device_t dev)
 }  }
   
 /*  /*
  * Caller must hold alldevs_mtx.   * Caller must hold alldevs.lock.
  */   */
 static void  static void
 config_devunlink(device_t dev, struct devicelist *garbage)  config_devunlink(device_t dev, struct devicelist *garbage)
Line 1254  config_devunlink(device_t dev, struct de
Line 1264  config_devunlink(device_t dev, struct de
         cfdriver_t cd = device_cfdriver(dev);          cfdriver_t cd = device_cfdriver(dev);
         int i;          int i;
   
         KASSERT(mutex_owned(&alldevs_mtx));          KASSERT(mutex_owned(&alldevs.lock));
   
         /* Unlink from device list.  Link to garbage list. */          /* Unlink from device list.  Link to garbage list. */
         TAILQ_REMOVE(&alldevs, dev, dv_list);          TAILQ_REMOVE(&alldevs.list, dev, dv_list);
         TAILQ_INSERT_TAIL(garbage, dev, dv_list);          TAILQ_INSERT_TAIL(garbage, dev, dv_list);
   
         /* Remove from cfdriver's array. */          /* Remove from cfdriver's array. */
Line 1660  config_attach_pseudo(cfdata_t cf)
Line 1670  config_attach_pseudo(cfdata_t cf)
 }  }
   
 /*  /*
  * Caller must hold alldevs_mtx.   * Caller must hold alldevs.lock.
  */   */
 static void  static void
 config_collect_garbage(struct devicelist *garbage)  config_collect_garbage(struct devicelist *garbage)
Line 1669  config_collect_garbage(struct devicelist
Line 1679  config_collect_garbage(struct devicelist
   
         KASSERT(!cpu_intr_p());          KASSERT(!cpu_intr_p());
         KASSERT(!cpu_softintr_p());          KASSERT(!cpu_softintr_p());
         KASSERT(mutex_owned(&alldevs_mtx));          KASSERT(mutex_owned(&alldevs.lock));
   
         while (alldevs_nwrite == 0 && alldevs_nread == 0 && alldevs_garbage) {          while (alldevs.nwrite == 0 && alldevs.nread == 0 && alldevs.garbage) {
                 TAILQ_FOREACH(dv, &alldevs, dv_list) {                  TAILQ_FOREACH(dv, &alldevs.list, dv_list) {
                         if (dv->dv_del_gen != 0)                          if (dv->dv_del_gen != 0)
                                 break;                                  break;
                 }                  }
                 if (dv == NULL) {                  if (dv == NULL) {
                         alldevs_garbage = false;                          alldevs.garbage = false;
                         break;                          break;
                 }                  }
                 config_devunlink(dv, garbage);                  config_devunlink(dv, garbage);
         }          }
         KASSERT(mutex_owned(&alldevs_mtx));          KASSERT(mutex_owned(&alldevs.lock));
 }  }
   
 static void  static void
Line 1731  config_detach(device_t dev, int flags)
Line 1741  config_detach(device_t dev, int flags)
         ca = dev->dv_cfattach;          ca = dev->dv_cfattach;
         KASSERT(ca != NULL);          KASSERT(ca != NULL);
   
         mutex_enter(&alldevs_mtx);          mutex_enter(&alldevs.lock);
         if (dev->dv_del_gen != 0) {          if (dev->dv_del_gen != 0) {
                 mutex_exit(&alldevs_mtx);                  mutex_exit(&alldevs.lock);
 #ifdef DIAGNOSTIC  #ifdef DIAGNOSTIC
                 printf("%s: %s is already detached\n", __func__,                  printf("%s: %s is already detached\n", __func__,
                     device_xname(dev));                      device_xname(dev));
 #endif /* DIAGNOSTIC */  #endif /* DIAGNOSTIC */
                 return ENOENT;                  return ENOENT;
         }          }
         alldevs_nwrite++;          alldevs.nwrite++;
         mutex_exit(&alldevs_mtx);          mutex_exit(&alldevs.lock);
   
         if (!detachall &&          if (!detachall &&
             (flags & (DETACH_SHUTDOWN|DETACH_FORCE)) == DETACH_SHUTDOWN &&              (flags & (DETACH_SHUTDOWN|DETACH_FORCE)) == DETACH_SHUTDOWN &&
Line 1818  config_detach(device_t dev, int flags)
Line 1828  config_detach(device_t dev, int flags)
   
 out:  out:
         config_alldevs_enter(&af);          config_alldevs_enter(&af);
         KASSERT(alldevs_nwrite != 0);          KASSERT(alldevs.nwrite != 0);
         --alldevs_nwrite;          --alldevs.nwrite;
         if (rv == 0 && dev->dv_del_gen == 0) {          if (rv == 0 && dev->dv_del_gen == 0) {
                 if (alldevs_nwrite == 0 && alldevs_nread == 0)                  if (alldevs.nwrite == 0 && alldevs.nread == 0)
                         config_devunlink(dev, &af.af_garbage);                          config_devunlink(dev, &af.af_garbage);
                 else {                  else {
                         dev->dv_del_gen = alldevs_gen;                          dev->dv_del_gen = alldevs.gen;
                         alldevs_garbage = true;                          alldevs.garbage = true;
                 }                  }
         }          }
         config_alldevs_exit(&af);          config_alldevs_exit(&af);
Line 2215  static void
Line 2225  static void
 config_alldevs_enter(struct alldevs_foray *af)  config_alldevs_enter(struct alldevs_foray *af)
 {  {
         TAILQ_INIT(&af->af_garbage);          TAILQ_INIT(&af->af_garbage);
         mutex_enter(&alldevs_mtx);          mutex_enter(&alldevs.lock);
         config_collect_garbage(&af->af_garbage);          config_collect_garbage(&af->af_garbage);
 }  }
   
 static void  static void
 config_alldevs_exit(struct alldevs_foray *af)  config_alldevs_exit(struct alldevs_foray *af)
 {  {
         mutex_exit(&alldevs_mtx);          mutex_exit(&alldevs.lock);
         config_dump_garbage(&af->af_garbage);          config_dump_garbage(&af->af_garbage);
 }  }
   
Line 2236  device_lookup(cfdriver_t cd, int unit)
Line 2246  device_lookup(cfdriver_t cd, int unit)
 {  {
         device_t dv;          device_t dv;
   
         mutex_enter(&alldevs_mtx);          mutex_enter(&alldevs.lock);
         if (unit < 0 || unit >= cd->cd_ndevs)          if (unit < 0 || unit >= cd->cd_ndevs)
                 dv = NULL;                  dv = NULL;
         else if ((dv = cd->cd_devs[unit]) != NULL && dv->dv_del_gen != 0)          else if ((dv = cd->cd_devs[unit]) != NULL && dv->dv_del_gen != 0)
                 dv = NULL;                  dv = NULL;
         mutex_exit(&alldevs_mtx);          mutex_exit(&alldevs.lock);
   
         return dv;          return dv;
 }  }
Line 2786  deviter_init(deviter_t *di, deviter_flag
Line 2796  deviter_init(deviter_t *di, deviter_flag
         if ((flags & DEVITER_F_SHUTDOWN) != 0)          if ((flags & DEVITER_F_SHUTDOWN) != 0)
                 flags |= DEVITER_F_RW;                  flags |= DEVITER_F_RW;
   
         mutex_enter(&alldevs_mtx);          mutex_enter(&alldevs.lock);
         if ((flags & DEVITER_F_RW) != 0)          if ((flags & DEVITER_F_RW) != 0)
                 alldevs_nwrite++;                  alldevs.nwrite++;
         else          else
                 alldevs_nread++;                  alldevs.nread++;
         di->di_gen = alldevs_gen++;          di->di_gen = alldevs.gen++;
         di->di_flags = flags;          di->di_flags = flags;
   
         switch (di->di_flags & (DEVITER_F_LEAVES_FIRST|DEVITER_F_ROOT_FIRST)) {          switch (di->di_flags & (DEVITER_F_LEAVES_FIRST|DEVITER_F_ROOT_FIRST)) {
         case DEVITER_F_LEAVES_FIRST:          case DEVITER_F_LEAVES_FIRST:
                 TAILQ_FOREACH(dv, &alldevs, dv_list) {                  TAILQ_FOREACH(dv, &alldevs.list, dv_list) {
                         if (!deviter_visits(di, dv))                          if (!deviter_visits(di, dv))
                                 continue;                                  continue;
                         di->di_curdepth = MAX(di->di_curdepth, dv->dv_depth);                          di->di_curdepth = MAX(di->di_curdepth, dv->dv_depth);
                 }                  }
                 break;                  break;
         case DEVITER_F_ROOT_FIRST:          case DEVITER_F_ROOT_FIRST:
                 TAILQ_FOREACH(dv, &alldevs, dv_list) {                  TAILQ_FOREACH(dv, &alldevs.list, dv_list) {
                         if (!deviter_visits(di, dv))                          if (!deviter_visits(di, dv))
                                 continue;                                  continue;
                         di->di_maxdepth = MAX(di->di_maxdepth, dv->dv_depth);                          di->di_maxdepth = MAX(di->di_maxdepth, dv->dv_depth);
Line 2814  deviter_init(deviter_t *di, deviter_flag
Line 2824  deviter_init(deviter_t *di, deviter_flag
         }          }
   
         deviter_reinit(di);          deviter_reinit(di);
         mutex_exit(&alldevs_mtx);          mutex_exit(&alldevs.lock);
 }  }
   
 static void  static void
 deviter_reinit(deviter_t *di)  deviter_reinit(deviter_t *di)
 {  {
   
         KASSERT(mutex_owned(&alldevs_mtx));          KASSERT(mutex_owned(&alldevs.lock));
         if ((di->di_flags & DEVITER_F_RW) != 0)          if ((di->di_flags & DEVITER_F_RW) != 0)
                 di->di_prev = TAILQ_LAST(&alldevs, devicelist);                  di->di_prev = TAILQ_LAST(&alldevs.list, devicelist);
         else          else
                 di->di_prev = TAILQ_FIRST(&alldevs);                  di->di_prev = TAILQ_FIRST(&alldevs.list);
 }  }
   
 device_t  device_t
Line 2841  deviter_next2(deviter_t *di)
Line 2851  deviter_next2(deviter_t *di)
 {  {
         device_t dv;          device_t dv;
   
         KASSERT(mutex_owned(&alldevs_mtx));          KASSERT(mutex_owned(&alldevs.lock));
   
         dv = di->di_prev;          dv = di->di_prev;
   
Line 2861  deviter_next1(deviter_t *di)
Line 2871  deviter_next1(deviter_t *di)
 {  {
         device_t dv;          device_t dv;
   
         KASSERT(mutex_owned(&alldevs_mtx));          KASSERT(mutex_owned(&alldevs.lock));
   
         do {          do {
                 dv = deviter_next2(di);                  dv = deviter_next2(di);
Line 2875  deviter_next(deviter_t *di)
Line 2885  deviter_next(deviter_t *di)
 {  {
         device_t dv = NULL;          device_t dv = NULL;
   
         mutex_enter(&alldevs_mtx);          mutex_enter(&alldevs.lock);
         switch (di->di_flags & (DEVITER_F_LEAVES_FIRST|DEVITER_F_ROOT_FIRST)) {          switch (di->di_flags & (DEVITER_F_LEAVES_FIRST|DEVITER_F_ROOT_FIRST)) {
         case 0:          case 0:
                 dv = deviter_next1(di);                  dv = deviter_next1(di);
Line 2901  deviter_next(deviter_t *di)
Line 2911  deviter_next(deviter_t *di)
         default:          default:
                 break;                  break;
         }          }
         mutex_exit(&alldevs_mtx);          mutex_exit(&alldevs.lock);
   
         return dv;          return dv;
 }  }
Line 2911  deviter_release(deviter_t *di)
Line 2921  deviter_release(deviter_t *di)
 {  {
         bool rw = (di->di_flags & DEVITER_F_RW) != 0;          bool rw = (di->di_flags & DEVITER_F_RW) != 0;
   
         mutex_enter(&alldevs_mtx);          mutex_enter(&alldevs.lock);
         if (rw)          if (rw)
                 --alldevs_nwrite;                  --alldevs.nwrite;
         else          else
                 --alldevs_nread;                  --alldevs.nread;
         /* XXX wake a garbage-collection thread */          /* XXX wake a garbage-collection thread */
         mutex_exit(&alldevs_mtx);          mutex_exit(&alldevs.lock);
 }  }
   
 const char *  const char *

Legend:
Removed from v.1.250  
changed lines
  Added in v.1.251

CVSweb <webmaster@jp.NetBSD.org>