Source-Changes-D archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: CVS commit: src/sys



On Thu, Dec 10, 2009 at 01:50:28AM +0000, Mindaugas Rasiukevicius wrote:
> Hello,
> 
> > Module Name:    src
> > Committed By:   dyoung
> > Date:           Thu Nov 12 19:10:31 UTC 2009
> > 
> > Modified Files:
> >         src/sys/kern: subr_autoconf.c
> >         src/sys/sys: device.h
> > 
> > Log Message:
> > Move a device-deactivation pattern that is replicated throughout
> > the system into config_deactivate(dev): deactivate dev and all of
> > its descendants.  Block all interrupts while calling each device's
> > activation hook, ca_activate.  Now it is possible to simplify or
> > to delete several device-activation hooks throughout the system.
> >
> > ...
> >
> > To generate a diff of this commit:
> > cvs rdiff -u -r1.186 -r1.187 src/sys/kern/subr_autoconf.c
> > cvs rdiff -u -r1.124 -r1.125 src/sys/sys/device.h
> 
> - Can you tell what relevant code requires alldevs_mtx to be at IPL_HIGH?
> 
> - Since alldevs_mtx became a spin-lock, it is no longer valid to assert for
>   mutex _not_ being held.  In other words, such cases are wrong:
> 
>       KASSERT(!mutex_owned(&alldevs_mtx));

Ah!  Thanks.

> - You have added config_collect_garbage(), which is mostly called before
>   config_alldevs_lock().  How about changing it to be used as/with last
>   unlock?  That is, collect the objects into a list, release the lock and
>   then destroy all objects.  Apart from avoiding unecessary unlock/relock
>   dances, it would also be simpler.

Thank you for the suggestion.  To make the change is easy.  I have
attached a patch.

> - May I suggest to avoid "inverted" logic like this:
> 
>       if (rv != 0)
>               ;
>       else if (dev->dv_del_gen != 0)
>               ;
>       else {
>               dev->dv_del_gen = alldevs_gen;
>               alldevs_garbage = true;
>       }

Thanks.  I will change this to the short form.

Dave

-- 
David Young             OJC Technologies
dyoung%ojctech.com@localhost      Urbana, IL * (217) 278-3933
Index: sys/sys/device.h
===================================================================
RCS file: /cvsroot/src/sys/sys/device.h,v
retrieving revision 1.127
diff -u -p -u -p -r1.127 device.h
--- sys/sys/device.h    7 Dec 2009 19:45:13 -0000       1.127
+++ sys/sys/device.h    10 Dec 2009 18:17:54 -0000
@@ -181,6 +181,10 @@ struct device {
        device_suspensor_t      dv_bus_suspensors[DEVICE_SUSPENSORS_MAX];
        device_suspensor_t      dv_driver_suspensors[DEVICE_SUSPENSORS_MAX];
        device_suspensor_t      dv_class_suspensors[DEVICE_SUSPENSORS_MAX];
+       struct device_garbage {
+               device_t        *dg_devs;
+               int             dg_ndevs;
+       } dv_garbage;
 };
 
 /* dv_flags */
Index: sys/kern/subr_autoconf.c
===================================================================
RCS file: /cvsroot/src/sys/kern/subr_autoconf.c,v
retrieving revision 1.188
diff -u -p -u -p -r1.188 subr_autoconf.c
--- sys/kern/subr_autoconf.c    12 Nov 2009 23:16:28 -0000      1.188
+++ sys/kern/subr_autoconf.c    10 Dec 2009 18:17:54 -0000
@@ -166,12 +166,14 @@ static char *number(char *, int);
 static void mapply(struct matchinfo *, cfdata_t);
 static device_t config_devalloc(const device_t, const cfdata_t, const int *);
 static void config_devdelete(device_t);
+static void config_devunlink(device_t, struct devicelist *);
 static void config_makeroom(int, struct cfdriver *);
 static void config_devlink(device_t);
 static void config_alldevs_unlock(int);
 static int config_alldevs_lock(void);
 
-static void config_collect_garbage(void);
+static void config_collect_garbage(struct devicelist *);
+static void config_dump_garbage(struct devicelist *);
 
 static void pmflock_debug(device_t, const char *, int);
 
@@ -368,10 +370,11 @@ config_cfdriver_attach(struct cfdriver *
 int
 config_cfdriver_detach(struct cfdriver *cd)
 {
+       struct devicelist garbage = TAILQ_HEAD_INITIALIZER(garbage);
        int i, rc = 0, s;
 
        s = config_alldevs_lock();
-       config_collect_garbage();
+       config_collect_garbage(&garbage);
        /* Make sure there are no active instances. */
        for (i = 0; i < cd->cd_ndevs; i++) {
                if (cd->cd_devs[i] != NULL) {
@@ -380,6 +383,7 @@ config_cfdriver_detach(struct cfdriver *
                }
        }
        config_alldevs_unlock(s);
+       config_dump_garbage(&garbage);
 
        if (rc != 0)
                return rc;
@@ -441,6 +445,7 @@ config_cfattach_attach(const char *drive
 int
 config_cfattach_detach(const char *driver, struct cfattach *ca)
 {
+       struct devicelist garbage = TAILQ_HEAD_INITIALIZER(garbage);
        struct cfdriver *cd;
        device_t dev;
        int i, rc = 0, s;
@@ -450,7 +455,7 @@ config_cfattach_detach(const char *drive
                return ESRCH;
 
        s = config_alldevs_lock();
-       config_collect_garbage();
+       config_collect_garbage(&garbage);
        /* Make sure there are no active instances. */
        for (i = 0; i < cd->cd_ndevs; i++) {
                if ((dev = cd->cd_devs[i]) == NULL)
@@ -461,6 +466,7 @@ config_cfattach_detach(const char *drive
                }
        }
        config_alldevs_unlock(s);
+       config_dump_garbage(&garbage);
 
        if (rc != 0)
                return rc;
@@ -1007,49 +1013,49 @@ config_devlink(device_t dev)
 }
 
 /*
- * Caller must hold alldevs_mtx. config_devdelete() may release and
- * re-acquire alldevs_mtx, so callers should re-check conditions such as
- * alldevs_nwrite == 0 && alldevs_nread == 0 after config_devdelete()
- * returns.
+ * Caller must hold alldevs_mtx.
  */
 static void
-config_devdelete(device_t dev)
+config_devunlink(device_t dev, struct devicelist *garbage)
 {
-       device_lock_t dvl = device_getlock(dev);
-       int priv = (dev->dv_flags & DVF_PRIV_ALLOC);
+       struct device_garbage *dg = &dev->dv_garbage;
        struct cfdriver *cd = dev->dv_cfdriver;
-       device_t *devs = NULL;
-       int i, ndevs = 0;
+       int i;
 
        KASSERT(mutex_owned(&alldevs_mtx));
 
-       /* Unlink from device list. */
+       /* Unlink from device list.  Link to garbage list. */
        TAILQ_REMOVE(&alldevs, dev, dv_list);
+       TAILQ_INSERT_TAIL(garbage, dev, dv_list);
 
        /* Remove from cfdriver's array. */
        cd->cd_devs[dev->dv_unit] = NULL;
 
        /*
-        * If the device now has no units in use, deallocate its softc array.
+        * If the device now has no units in use, unlink its softc array.
         */
        for (i = 0; i < cd->cd_ndevs; i++) {
                if (cd->cd_devs[i] != NULL)
                        break;
        }
-       /* nothing found.  unlink, now.  deallocate below. */
+       /* Nothing found.  Unlink, now.  Deallocate, later. */
        if (i == cd->cd_ndevs) {
-               ndevs = cd->cd_ndevs;
-               devs = cd->cd_devs;
+               dg->dg_ndevs = cd->cd_ndevs;
+               dg->dg_devs = cd->cd_devs;
                cd->cd_devs = NULL;
                cd->cd_ndevs = 0;
        }
+}
 
-       mutex_exit(&alldevs_mtx);
-
-       KASSERT(!mutex_owned(&alldevs_mtx));
+static void
+config_devdelete(device_t dev)
+{
+       struct device_garbage *dg = &dev->dv_garbage;
+       int priv = (dev->dv_flags & DVF_PRIV_ALLOC);
+       device_lock_t dvl = device_getlock(dev);
 
-       if (devs != NULL)
-               kmem_free(devs, sizeof(device_t [ndevs]));
+       if (dg->dg_devs != NULL)
+               kmem_free(dg->dg_devs, sizeof(device_t[dg->dg_ndevs]));
 
        cv_destroy(&dvl->dvl_cv);
        mutex_destroy(&dvl->dvl_mtx);
@@ -1069,15 +1075,12 @@ config_devdelete(device_t dev)
                kmem_free(dev->dv_private, dev->dv_cfattach->ca_devsize);
        if (priv)
                kmem_free(dev, sizeof(*dev));
-
-       KASSERT(!mutex_owned(&alldevs_mtx));
-
-       mutex_enter(&alldevs_mtx);
 }
 
 static device_t
 config_devalloc(const device_t parent, const cfdata_t cf, const int *locs)
 {
+       struct devicelist garbage = TAILQ_HEAD_INITIALIZER(garbage);
        struct cfdriver *cd;
        struct cfattach *ca;
        size_t lname, lunit;
@@ -1103,7 +1106,7 @@ config_devalloc(const device_t parent, c
 
 #ifndef __BROKEN_CONFIG_UNIT_USAGE
        s = config_alldevs_lock();
-       config_collect_garbage();
+       config_collect_garbage(&garbage);
        if (cf->cf_fstate == FSTATE_STAR) {
                for (myunit = cf->cf_unit; myunit < cd->cd_ndevs; myunit++)
                        if (cd->cd_devs[myunit] == NULL)
@@ -1118,6 +1121,7 @@ config_devalloc(const device_t parent, c
                        myunit = -1;
        }
        config_alldevs_unlock(s);
+       config_dump_garbage(&garbage);
        if (myunit == -1)
                return NULL;
 #else
@@ -1334,13 +1338,10 @@ config_attach_pseudo(cfdata_t cf)
 }
 
 /*
- * Caller must hold alldevs_mtx. config_collect_garbage() may
- * release and re-acquire alldevs_mtx, so callers should re-check
- * conditions such as alldevs_nwrite == 0 && alldevs_nread == 0 after
- * config_collect_garbage() returns.
+ * Caller must hold alldevs_mtx.
  */
 static void
-config_collect_garbage(void)
+config_collect_garbage(struct devicelist *garbage)
 {
        device_t dv;
 
@@ -1355,11 +1356,22 @@ config_collect_garbage(void)
                        alldevs_garbage = false;
                        break;
                }
-               config_devdelete(dv);
+               config_devunlink(dv, garbage);
        }
        KASSERT(mutex_owned(&alldevs_mtx));
 }
 
+static void
+config_dump_garbage(struct devicelist *garbage)
+{
+       device_t dv;
+
+       while ((dv = TAILQ_FIRST(garbage)) != NULL) {
+               TAILQ_REMOVE(garbage, dv, dv_list);
+               config_devdelete(dv);
+       }
+}
+
 /*
  * Detach a device.  Optionally forced (e.g. because of hardware
  * removal) and quiet.  Returns zero if successful, non-zero
@@ -1372,6 +1384,7 @@ config_collect_garbage(void)
 int
 config_detach(device_t dev, int flags)
 {
+       struct devicelist garbage = TAILQ_HEAD_INITIALIZER(garbage);
        struct cftable *ct;
        cfdata_t cf;
        const struct cfattach *ca;
@@ -1500,8 +1513,9 @@ out:
                dev->dv_del_gen = alldevs_gen;
                alldevs_garbage = true;
        }
-       config_collect_garbage();
+       config_collect_garbage(&garbage);
        config_alldevs_unlock(s);
+       config_dump_garbage(&garbage);
 
        return rv;
 }
@@ -1864,19 +1878,20 @@ config_alldevs_unlock(int s)
 device_t
 device_lookup(cfdriver_t cd, int unit)
 {
+       struct devicelist garbage = TAILQ_HEAD_INITIALIZER(garbage);
        device_t dv;
        int s;
 
        s = config_alldevs_lock();
-       config_collect_garbage();
+       config_collect_garbage(&garbage);
        KASSERT(mutex_owned(&alldevs_mtx));
        if (unit < 0 || unit >= cd->cd_ndevs)
                dv = NULL;
        else
                dv = cd->cd_devs[unit];
        config_alldevs_unlock(s);
+       config_dump_garbage(&garbage);
 
-       KASSERT(!mutex_owned(&alldevs_mtx));
        return dv;
 }
 
@@ -1888,12 +1903,13 @@ device_lookup(cfdriver_t cd, int unit)
 void *
 device_lookup_private(cfdriver_t cd, int unit)
 {
+       struct devicelist garbage = TAILQ_HEAD_INITIALIZER(garbage);
        device_t dv;
        int s;
        void *priv;
 
        s = config_alldevs_lock();
-       config_collect_garbage();
+       config_collect_garbage(&garbage);
        KASSERT(mutex_owned(&alldevs_mtx));
        if (unit < 0 || unit >= cd->cd_ndevs)
                priv = NULL;
@@ -1902,8 +1918,8 @@ device_lookup_private(cfdriver_t cd, int
        else
                priv = dv->dv_private;
        config_alldevs_unlock(s);
+       config_dump_garbage(&garbage);
 
-       KASSERT(!mutex_owned(&alldevs_mtx));
        return priv;
 }
 


Home | Main Index | Thread Index | Old Index