Use atomics to adjust the credential reference count.

This commit is contained in:
ad 2007-11-29 17:48:27 +00:00
parent aadcb17f11
commit 7ec1c5e617

View File

@ -1,4 +1,40 @@
/* $NetBSD: kern_auth.c,v 1.54 2007/11/11 23:22:23 matt Exp $ */
/* $NetBSD: kern_auth.c,v 1.55 2007/11/29 17:48:27 ad Exp $ */
/*-
* Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Andrew Doran.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (c) 2005, 2006 Elad Efrat <elad@NetBSD.org>
@ -28,7 +64,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_auth.c,v 1.54 2007/11/11 23:22:23 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_auth.c,v 1.55 2007/11/29 17:48:27 ad Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -40,7 +76,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_auth.c,v 1.54 2007/11/11 23:22:23 matt Exp $");
#include <sys/kmem.h>
#include <sys/rwlock.h>
#include <sys/sysctl.h> /* for pi_[p]cread */
#include <sys/mutex.h>
#include <sys/atomic.h>
#include <sys/specificdata.h>
/*
@ -66,11 +102,9 @@ struct kauth_cred {
* Keeping it seperate from the rest of the data prevents false
* sharing between CPUs.
*/
kmutex_t cr_lock; /* lock on cr_refcnt */
u_int cr_refcnt; /* reference count */
uid_t cr_uid
__aligned(CACHE_LINE_SIZE); /* user id */
u_int cr_pad[CACHE_LINE_SIZE - sizeof(u_int)];
uid_t cr_uid; /* user id */
uid_t cr_euid; /* effective user id */
uid_t cr_svuid; /* saved effective user id */
gid_t cr_gid; /* group id */
@ -103,8 +137,6 @@ struct kauth_scope {
};
static int kauth_cred_hook(kauth_cred_t, kauth_action_t, void *, void *);
static int kauth_cred_ctor(void *, void *, int);
static void kauth_cred_dtor(void *, void *);
/* List of scopes and its lock. */
static SIMPLEQ_HEAD(, kauth_scope) scope_list =
@ -148,26 +180,6 @@ kauth_cred_alloc(void)
return (cred);
}
static int
kauth_cred_ctor(void *arg, void *obj, int flags)
{
kauth_cred_t cred;
cred = obj;
mutex_init(&cred->cr_lock, MUTEX_DEFAULT, IPL_NONE);
return 0;
}
static void
kauth_cred_dtor(void *arg, void *obj)
{
kauth_cred_t cred;
cred = obj;
mutex_destroy(&cred->cr_lock);
}
/* Increment reference count to cred. */
void
kauth_cred_hold(kauth_cred_t cred)
@ -175,29 +187,23 @@ kauth_cred_hold(kauth_cred_t cred)
KASSERT(cred != NULL);
KASSERT(cred->cr_refcnt > 0);
mutex_enter(&cred->cr_lock);
cred->cr_refcnt++;
mutex_exit(&cred->cr_lock);
atomic_inc_uint(&cred->cr_refcnt);
}
/* Decrease reference count to cred. If reached zero, free it. */
void
kauth_cred_free(kauth_cred_t cred)
{
u_int refcnt;
KASSERT(cred != NULL);
KASSERT(cred->cr_refcnt > 0);
mutex_enter(&cred->cr_lock);
refcnt = --cred->cr_refcnt;
mutex_exit(&cred->cr_lock);
if (atomic_dec_uint_nv(&cred->cr_refcnt) != 0)
return;
if (refcnt == 0) {
kauth_cred_hook(cred, KAUTH_CRED_FREE, NULL, NULL);
specificdata_fini(kauth_domain, &cred->cr_sd);
pool_cache_put(kauth_cred_cache, cred);
}
kauth_cred_hook(cred, KAUTH_CRED_FREE, NULL, NULL);
specificdata_fini(kauth_domain, &cred->cr_sd);
pool_cache_put(kauth_cred_cache, cred);
}
static void
@ -801,7 +807,7 @@ kauth_init(void)
kauth_cred_cache = pool_cache_init(sizeof(struct kauth_cred),
CACHE_LINE_SIZE, 0, 0, "kcredpl", NULL, IPL_NONE,
kauth_cred_ctor, kauth_cred_dtor, NULL);
NULL, NULL, NULL);
/* Create specificdata domain. */
kauth_domain = specificdata_domain_create();