Index: sys/fs/devfs/devfs_devs.c =================================================================== --- sys/fs/devfs/devfs_devs.c +++ sys/fs/devfs/devfs_devs.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -52,7 +53,7 @@ /* * The one true (but secret) list of active devices in the system. - * Locked by dev_wlock()/devmtx + * Locked by dev_wlock()/devlock. */ struct cdev_priv_list cdevp_list = TAILQ_HEAD_INITIALIZER(cdevp_list); @@ -156,7 +157,7 @@ { struct cdev_priv *cdp; - dev_lock_assert_wlocked(); + dev_lock_assert_locked(); TAILQ_FOREACH(cdp, &cdevp_list, cdp_list) { if ((cdp->cdp_flags & CDP_ACTIVE) == 0) @@ -745,8 +746,7 @@ static void devfs_devs_init(void *junk __unused) { - - devfs_inos = new_unrhdr(DEVFS_ROOTINO + 1, INT_MAX, &devmtx); + devfs_inos = new_unrhdr_rw(DEVFS_ROOTINO + 1, INT_MAX, &devlock); } SYSINIT(devfs_devs, SI_SUB_DEVFS, SI_ORDER_FIRST, devfs_devs_init, NULL); Index: sys/fs/devfs/devfs_int.h =================================================================== --- sys/fs/devfs/devfs_int.h +++ sys/fs/devfs/devfs_int.h @@ -89,14 +89,15 @@ int devfs_pathpath(const char *, const char *); extern struct unrhdr *devfs_inos; -extern struct mtx devmtx; +extern struct rwlock devlock; extern struct mtx devfs_de_interlock; extern struct sx clone_drain_lock; extern struct mtx cdevpriv_mtx; extern TAILQ_HEAD(cdev_priv_list, cdev_priv) cdevp_list; -#define dev_lock_assert_wlocked() mtx_assert(&devmtx, MA_OWNED) -#define dev_lock_assert_unlocked() mtx_assert(&devmtx, MA_NOTOWNED) +#define dev_lock_assert_locked() rw_assert(&devlock, RA_LOCKED) +#define dev_lock_assert_wlocked() rw_assert(&devlock, RA_WLOCKED) +#define dev_lock_assert_unlocked() rw_assert(&devlock, RA_UNLOCKED) #endif /* _KERNEL */ Index: sys/kern/kern_conf.c =================================================================== --- sys/kern/kern_conf.c +++ sys/kern/kern_conf.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -53,7 +54,7 @@ static MALLOC_DEFINE(M_DEVT, "cdev", "cdev storage"); -struct mtx devmtx; +struct rwlock devlock; static void destroy_devl(struct cdev *dev); static int destroy_dev_sched_cbl(struct cdev *dev, void (*cb)(void *), void *arg); @@ -67,16 +68,21 @@ static SLIST_HEAD(free_cdevsw, cdevsw) cdevsw_gt_post_list = SLIST_HEAD_INITIALIZER(cdevsw_gt_post_list); +void +dev_rlock(void) +{ + rw_rlock(&devlock); +} + void dev_wlock(void) { - - mtx_lock(&devmtx); + rw_wlock(&devlock); } /* * Free all the memory collected while the cdev mutex was - * locked. Since devmtx is after the system map mutex, free() cannot + * locked. Since devlock is after the system map mutex, free() cannot * be called immediately and is postponed until cdev mutex can be * dropped. */ @@ -91,7 +97,7 @@ dev_lock_assert_wlocked(); /* - * Make the local copy of the list heads while the dev_mtx is + * Make the local copy of the list heads while the devlock is * held. Free it later. */ TAILQ_INIT(&cdp_free); @@ -99,7 +105,7 @@ csw_free = cdevsw_gt_post_list; SLIST_INIT(&cdevsw_gt_post_list); - mtx_unlock(&devmtx); + dev_unlock(); while ((cdp = TAILQ_FIRST(&cdp_free)) != NULL) { TAILQ_REMOVE(&cdp_free, cdp, cdp_list); @@ -131,11 +137,16 @@ SLIST_INSERT_HEAD(&cdevsw_gt_post_list, csw, d_postfree_list); } +void +dev_runlock(void) +{ + rw_runlock(&devlock); +} + void dev_unlock(void) { - - mtx_unlock(&devmtx); + rw_wunlock(&devlock); } void @@ -143,9 +154,9 @@ { dev_lock_assert_unlocked(); - mtx_lock(&devmtx); + dev_wlock(); dev->si_refcount++; - mtx_unlock(&devmtx); + dev_unlock(); } void @@ -1143,7 +1154,7 @@ while (csw != NULL && csw->d_purge != NULL && dev->si_threadcount) { csw->d_purge(dev); mtx_unlock(&cdp->cdp_threadlock); - msleep(csw, &devmtx, PRIBIO, "devprg", hz/10); + rw_sleep(csw, &devlock, PRIBIO, "devprg", hz / 10); mtx_lock(&cdp->cdp_threadlock); if (dev->si_threadcount) printf("Still %lu threads in %s\n", @@ -1152,7 +1163,7 @@ while (dev->si_threadcount != 0) { /* Use unique dummy wait ident */ mtx_unlock(&cdp->cdp_threadlock); - msleep(&csw, &devmtx, PRIBIO, "devdrn", hz / 10); + rw_sleep(&csw, &devlock, PRIBIO, "devdrn", hz / 10); mtx_lock(&cdp->cdp_threadlock); } @@ -1456,7 +1467,7 @@ } /* - * devmtx shall be locked on entry. devmtx will be unlocked after + * devlock shall be locked on entry. devlock will be unlocked after * function return. */ static int @@ -1501,7 +1512,7 @@ dev_wlock(); while (!LIST_EMPTY(&csw->d_devs)) { - msleep(&csw->d_devs, &devmtx, PRIBIO, "devscd", hz/10); + rw_sleep(&csw->d_devs, &devlock, PRIBIO, "devscd", hz / 10); } dev_unlock(); } Index: sys/kern/kern_mutex.c =================================================================== --- sys/kern/kern_mutex.c +++ sys/kern/kern_mutex.c @@ -69,8 +69,6 @@ #include -#include - #include #include @@ -1221,8 +1219,12 @@ mtx_init(&proc0.p_statmtx, "pstatl", NULL, MTX_SPIN); mtx_init(&proc0.p_itimmtx, "pitiml", NULL, MTX_SPIN); mtx_init(&proc0.p_profmtx, "pprofl", NULL, MTX_SPIN); - mtx_init(&devmtx, "cdev", NULL, MTX_DEF); mtx_lock(&Giant); + + /* + * Initialize other system locks. + */ + rwlock_system_init(); } static void __noinline Index: sys/kern/kern_rwlock.c =================================================================== --- sys/kern/kern_rwlock.c +++ sys/kern/kern_rwlock.c @@ -37,6 +37,7 @@ #include "opt_no_adaptive_rwlocks.h" #include +#include #include #include #include @@ -52,6 +53,8 @@ #include +#include + #if defined(SMP) && !defined(NO_ADAPTIVE_RWLOCKS) #define ADAPTIVE_RWLOCKS #endif @@ -1518,6 +1521,12 @@ } #endif /* INVARIANT_SUPPORT */ +void +rwlock_system_init(void) +{ + rw_init(&devlock, "cdev"); +} + #ifdef DDB void db_show_rwlock(const struct lock_object *lock) Index: sys/kern/subr_witness.c =================================================================== --- sys/kern/subr_witness.c +++ sys/kern/subr_witness.c @@ -613,7 +613,7 @@ */ { "vm map (system)", &lock_class_mtx_sleep }, { "vnode interlock", &lock_class_mtx_sleep }, - { "cdev", &lock_class_mtx_sleep }, + { "cdev", &lock_class_rw }, { "devthrd", &lock_class_mtx_sleep }, { NULL, NULL }, /* Index: sys/kern/vfs_subr.c =================================================================== --- sys/kern/vfs_subr.c +++ sys/kern/vfs_subr.c @@ -4995,14 +4995,14 @@ goto out; } error = 0; - dev_wlock(); + dev_rlock(); if (vp->v_rdev == NULL) error = ENXIO; else if (vp->v_rdev->si_devsw == NULL) error = ENXIO; else if (!(vp->v_rdev->si_devsw->d_flags & D_DISK)) error = ENOTBLK; - dev_unlock(); + dev_runlock(); out: if (errp != NULL) *errp = error; Index: sys/sys/conf.h =================================================================== --- sys/sys/conf.h +++ sys/sys/conf.h @@ -307,6 +307,8 @@ int make_dev_physpath_alias(int _flags, struct cdev **_cdev, struct cdev *_pdev, struct cdev *_old_alias, const char *_physpath); +void dev_rlock(void); +void dev_runlock(void); void dev_wlock(void); void dev_unlock(void); Index: sys/sys/lock.h =================================================================== --- sys/sys/lock.h +++ sys/sys/lock.h @@ -221,6 +221,7 @@ void lock_destroy(struct lock_object *); void lock_delay(struct lock_delay_arg *); void lock_delay_default_init(struct lock_delay_config *); +void rwlock_system_init(void); void spinlock_enter(void); void spinlock_exit(void); void witness_init(struct lock_object *, const char *);