Change loginclass mutex to an rwlock.
While here reduce nesting in loginclass_free. Submitted by: Tiwei Bie <btw mail.ustc.edu.cn> X-Additional: JuniorJobs project MFC after: 2 weeks
This commit is contained in:
parent
b8ded963c9
commit
b720dc9749
@ -51,13 +51,13 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/lock.h>
|
||||
#include <sys/loginclass.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/racct.h>
|
||||
#include <sys/refcount.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
@ -68,8 +68,8 @@ LIST_HEAD(, loginclass) loginclasses;
|
||||
/*
|
||||
* Lock protecting loginclasses list.
|
||||
*/
|
||||
static struct mtx loginclasses_lock;
|
||||
MTX_SYSINIT(loginclasses_init, &loginclasses_lock, "loginclasses lock", MTX_DEF);
|
||||
static struct rwlock loginclasses_lock;
|
||||
RW_SYSINIT(loginclasses_init, &loginclasses_lock, "loginclasses lock");
|
||||
|
||||
void
|
||||
loginclass_hold(struct loginclass *lc)
|
||||
@ -87,16 +87,37 @@ loginclass_free(struct loginclass *lc)
|
||||
if (old > 1 && atomic_cmpset_int(&lc->lc_refcount, old, old - 1))
|
||||
return;
|
||||
|
||||
mtx_lock(&loginclasses_lock);
|
||||
if (refcount_release(&lc->lc_refcount)) {
|
||||
racct_destroy(&lc->lc_racct);
|
||||
LIST_REMOVE(lc, lc_next);
|
||||
mtx_unlock(&loginclasses_lock);
|
||||
free(lc, M_LOGINCLASS);
|
||||
|
||||
rw_wlock(&loginclasses_lock);
|
||||
if (!refcount_release(&lc->lc_refcount)) {
|
||||
rw_wunlock(&loginclasses_lock);
|
||||
return;
|
||||
}
|
||||
mtx_unlock(&loginclasses_lock);
|
||||
|
||||
racct_destroy(&lc->lc_racct);
|
||||
LIST_REMOVE(lc, lc_next);
|
||||
rw_wunlock(&loginclasses_lock);
|
||||
|
||||
free(lc, M_LOGINCLASS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up a loginclass struct for the parameter name.
|
||||
* loginclasses_lock must be locked.
|
||||
* Increase refcount on loginclass struct returned.
|
||||
*/
|
||||
static struct loginclass *
|
||||
loginclass_lookup(const char *name)
|
||||
{
|
||||
struct loginclass *lc;
|
||||
|
||||
rw_assert(&loginclasses_lock, RA_LOCKED);
|
||||
LIST_FOREACH(lc, &loginclasses, lc_next)
|
||||
if (strcmp(name, lc->lc_name) == 0) {
|
||||
loginclass_hold(lc);
|
||||
break;
|
||||
}
|
||||
|
||||
return (lc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -109,34 +130,39 @@ loginclass_free(struct loginclass *lc)
|
||||
struct loginclass *
|
||||
loginclass_find(const char *name)
|
||||
{
|
||||
struct loginclass *lc, *newlc;
|
||||
struct loginclass *lc, *new_lc;
|
||||
|
||||
if (name[0] == '\0' || strlen(name) >= MAXLOGNAME)
|
||||
return (NULL);
|
||||
|
||||
newlc = malloc(sizeof(*newlc), M_LOGINCLASS, M_ZERO | M_WAITOK);
|
||||
racct_create(&newlc->lc_racct);
|
||||
|
||||
mtx_lock(&loginclasses_lock);
|
||||
LIST_FOREACH(lc, &loginclasses, lc_next) {
|
||||
if (strcmp(name, lc->lc_name) != 0)
|
||||
continue;
|
||||
|
||||
/* Found loginclass with a matching name? */
|
||||
loginclass_hold(lc);
|
||||
mtx_unlock(&loginclasses_lock);
|
||||
racct_destroy(&newlc->lc_racct);
|
||||
free(newlc, M_LOGINCLASS);
|
||||
rw_rlock(&loginclasses_lock);
|
||||
lc = loginclass_lookup(name);
|
||||
rw_runlock(&loginclasses_lock);
|
||||
if (lc != NULL)
|
||||
return (lc);
|
||||
|
||||
new_lc = malloc(sizeof(*new_lc), M_LOGINCLASS, M_ZERO | M_WAITOK);
|
||||
racct_create(&new_lc->lc_racct);
|
||||
refcount_init(&new_lc->lc_refcount, 1);
|
||||
strcpy(new_lc->lc_name, name);
|
||||
|
||||
rw_wlock(&loginclasses_lock);
|
||||
/*
|
||||
* There's a chance someone created our loginclass while we
|
||||
* were in malloc and not holding the lock, so we have to
|
||||
* make sure we don't insert a duplicate loginclass.
|
||||
*/
|
||||
if ((lc = loginclass_lookup(name)) == NULL) {
|
||||
LIST_INSERT_HEAD(&loginclasses, new_lc, lc_next);
|
||||
rw_wunlock(&loginclasses_lock);
|
||||
lc = new_lc;
|
||||
} else {
|
||||
rw_wunlock(&loginclasses_lock);
|
||||
racct_destroy(&new_lc->lc_racct);
|
||||
free(new_lc, M_LOGINCLASS);
|
||||
}
|
||||
|
||||
/* Add new loginclass. */
|
||||
strcpy(newlc->lc_name, name);
|
||||
refcount_init(&newlc->lc_refcount, 1);
|
||||
LIST_INSERT_HEAD(&loginclasses, newlc, lc_next);
|
||||
mtx_unlock(&loginclasses_lock);
|
||||
|
||||
return (newlc);
|
||||
return (lc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -222,8 +248,8 @@ loginclass_racct_foreach(void (*callback)(struct racct *racct,
|
||||
{
|
||||
struct loginclass *lc;
|
||||
|
||||
mtx_lock(&loginclasses_lock);
|
||||
rw_rlock(&loginclasses_lock);
|
||||
LIST_FOREACH(lc, &loginclasses, lc_next)
|
||||
(callback)(lc->lc_racct, arg2, arg3);
|
||||
mtx_unlock(&loginclasses_lock);
|
||||
rw_runlock(&loginclasses_lock);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user