PERFORCE change 38192 for review
Hrishikesh Dandekar
hdandeka at FreeBSD.org
Wed Sep 17 17:10:53 GMT 2003
http://perforce.freebsd.org/chv.cgi?CH=38192
Change 38192 by hdandeka at hdandeka_yash on 2003/09/17 10:10:45
Integrate the POSIX semaphore related changes.
Affected files ...
.. //depot/projects/trustedbsd/mac/sys/kern/uipc_sem.c#10 integrate
.. //depot/projects/trustedbsd/mac/sys/posix4/ksem.h#2 integrate
Differences ...
==== //depot/projects/trustedbsd/mac/sys/kern/uipc_sem.c#10 (text+ko) ====
@@ -61,7 +61,7 @@
static struct ksem *sem_lookup_byname(const char *name);
static int sem_create(struct thread *td, const char *name,
struct ksem **ksret, mode_t mode, unsigned int value);
-static void sem_free(struct ksem *ksnew);
+static void sem_free(struct ksem *ksnew, int checkrefs);
static int sem_perm(struct thread *td, struct ksem *ks);
static void sem_enter(struct proc *p, struct ksem *ks);
static int sem_leave(struct proc *p, struct ksem *ks);
@@ -75,6 +75,8 @@
semid_t *idp);
static int kern_sem_open(struct thread *td, int dir, const char *name,
int oflag, mode_t mode, unsigned int value, semid_t *idp);
+static int ksem_open_existing(struct thread *td, struct ksem *ks, int dir,
+ semid_t *idpu, semid_t *idpk);
static int kern_sem_unlink(struct thread *td, const char *name);
#ifndef SEM_MAX
@@ -85,6 +87,8 @@
#define SEM_TO_ID(x) ((intptr_t)(x))
#define ID_TO_SEM(x) id_to_sem(x)
+#define SEM_FREE(ks) sem_free(ks, 1)
+#define SEM_DROP(ks) sem_free(ks, 0)
#ifndef MAC
struct kuser {
@@ -104,6 +108,8 @@
struct cv ks_cv; /* waiters sleep here */
int ks_waiters; /* number of waiters */
LIST_HEAD(, kuser) ks_users; /* pids using this sem */
+ struct mtx ks_mtx; /* mutex protecting this semaphore */
+ int ks_unlinked; /* Whether the named sem is unlinked */
};
#else
struct kuser;
@@ -115,10 +121,6 @@
* created via sem_open that have not yet been unlinked.
*/
LIST_HEAD(, ksem) ksem_head = LIST_HEAD_INITIALIZER(&ksem_head);
-/*
- * semaphores still in use but have been sem_unlink()'d go here.
- */
-LIST_HEAD(, ksem) ksem_deadhead = LIST_HEAD_INITIALIZER(&ksem_deadhead);
static struct mtx sem_lock;
static MALLOC_DEFINE(M_SEM, "sems", "semaphore data");
@@ -129,6 +131,9 @@
static eventhandler_tag sem_exit_tag, sem_exec_tag;
+#ifndef SEM_DEBUG
+#define SEM_DEBUG
+#endif
#ifdef SEM_DEBUG
#define DP(x) printf x
#else
@@ -139,7 +144,7 @@
void
sem_ref(struct ksem *ks)
{
-
+ mtx_assert(&sem_lock, MA_OWNED);
ks->ks_ref++;
DP(("sem_ref: ks = %p, ref = %d\n", ks, ks->ks_ref));
}
@@ -149,9 +154,9 @@
sem_rel(struct ksem *ks)
{
+ mtx_assert(&sem_lock, MA_OWNED);
+ ks->ks_ref--;
DP(("sem_rel: ks = %p, ref = %d\n", ks, ks->ks_ref - 1));
- if (--ks->ks_ref == 0)
- sem_free(ks);
}
static __inline struct ksem *id_to_sem(semid_t id);
@@ -163,6 +168,7 @@
{
struct ksem *ks;
+ mtx_assert(&sem_lock,MA_OWNED);
DP(("id_to_sem: id = %0x,%p\n", id, (struct ksem *)id));
LIST_FOREACH(ks, &ksem_head, ks_entry) {
DP(("id_to_sem: ks = %p\n", ks));
@@ -178,12 +184,15 @@
{
struct ksem *ks;
+ mtx_assert(&sem_lock, MA_OWNED);
LIST_FOREACH(ks, &ksem_head, ks_entry)
if (ks->ks_name != NULL && strcmp(ks->ks_name, name) == 0)
return (ks);
return (NULL);
}
+/* Used by both sem_init and sem_open to create a new semaphore. */
+
static int
sem_create(td, name, ksret, mode, value)
struct thread *td;
@@ -196,14 +205,15 @@
struct proc *p;
struct ucred *uc;
size_t len;
- int error;
DP(("sem_create\n"));
p = td->td_proc;
uc = td->td_ucred;
+ /* XXX Use p31b_getcfg(CTL_P1003_1B_SEM_VALUE_MAX) instead? */
if (value > SEM_VALUE_MAX)
return (EINVAL);
- ret = malloc(sizeof(*ret), M_SEM, M_WAITOK | M_ZERO);
+ if( (ret = malloc(sizeof(*ret), M_SEM, M_WAITOK | M_ZERO)) == NULL)
+ return (ENOMEM);
if (name != NULL) {
len = strlen(name);
if (len > SEM_MAX_NAMELEN) {
@@ -215,39 +225,44 @@
free(ret, M_SEM);
return (EINVAL);
}
- ret->ks_name = malloc(len + 1, M_SEM, M_WAITOK);
+ if( (ret->ks_name = malloc(len + 1, M_SEM, M_WAITOK)) == NULL){
+ free(ret, M_SEM);
+ return (ENOMEM);
+ }
strcpy(ret->ks_name, name);
} else {
ret->ks_name = NULL;
}
ret->ks_mode = mode;
ret->ks_value = value;
- ret->ks_ref = 1;
+ ret->ks_ref = 0;
ret->ks_waiters = 0;
ret->ks_uid = uc->cr_uid;
ret->ks_gid = uc->cr_gid;
ret->ks_onlist = 0;
cv_init(&ret->ks_cv, "sem");
LIST_INIT(&ret->ks_users);
+ mtx_init(&ret->ks_mtx, "ks_mtx", "ks_mtx", MTX_DEF);
if (name != NULL)
- sem_enter(td->td_proc, ret);
+ sem_enter(td->td_proc, ret); /* This invokes sem_ref */
+ else
+ ret->ks_ref = 1;
#ifdef MAC
mac_init_posix_ksem(ret);
mac_create_posix_ksem(uc, ret);
#endif
- *ksret = ret;
mtx_lock(&sem_lock);
+ nsems++;
if (nsems >= p31b_getcfg(CTL_P1003_1B_SEM_NSEMS_MAX)) {
- /*XXX Should sem_leave be here at all ? */
- sem_leave(td->td_proc, ret);
- sem_free(ret);
- error = ENFILE;
- } else {
- nsems++;
- error = 0;
- }
+ if (name != NULL)
+ sem_leave(td->td_proc, ret); /* This invokes sem_rel */
+ SEM_DROP(ret); /* sem_free does a nsem-- */
+ mtx_unlock(&sem_lock);
+ return (ENFILE);
+ }
mtx_unlock(&sem_lock);
- return (error);
+ *ksret = ret;
+ return (0);
}
#ifndef _SYS_SYSPROTO_H_
@@ -279,15 +294,14 @@
semid_t id;
int error;
- error = sem_create(td, NULL, &ks, S_IRWXU | S_IRWXG, value);
- if (error)
+ if((error = sem_create(td, NULL, &ks, S_IRWXU | S_IRWXG, value)))
return (error);
id = SEM_TO_ID(ks);
if (dir == UIO_USERSPACE) {
error = copyout(&id, idp, sizeof(id));
if (error) {
mtx_lock(&sem_lock);
- sem_rel(ks);
+ SEM_DROP(ks);
mtx_unlock(&sem_lock);
return (error);
}
@@ -322,12 +336,62 @@
error = copyinstr(uap->name, name, SEM_MAX_NAMELEN + 1, &done);
if (error)
- return (error);
+ return (-1);
DP((">>> sem_open start\n"));
error = kern_sem_open(td, UIO_USERSPACE,
name, uap->oflag, uap->mode, uap->value, uap->idp);
DP(("<<< sem_open end\n"));
- return (error);
+ if(error)
+ return (-1);
+ return (0);
+}
+
+static int
+ksem_open_existing(struct thread *td, struct ksem *ks, int dir, semid_t *idpu,
+ semid_t *idpk)
+{
+ int error = 0;
+ mtx_assert(&sem_lock,MA_OWNED);
+ mtx_assert(&ks->ks_mtx,MA_NOTOWNED);
+ if((error = sem_perm(td, ks))) {
+ mtx_unlock(&sem_lock);
+ return (error);
+ }
+ /*
+ * If already queued up for unlinking.
+ * Then according to spec cant let reconnect to this semaphore.
+ */
+ if(ks->ks_unlinked) {
+ mtx_unlock(&sem_lock);
+ return (EPERM);
+ }
+ *idpk = SEM_TO_ID(ks);
+ sem_ref(ks); /* Pump up the refs to avoid the race with SEM_FREE */
+ mtx_unlock(&sem_lock);
+#ifdef MAC
+ mtx_lock(&ks->ks_mtx);
+ if((error = mac_check_posix_sem_openexisting(td->td_ucred, ks))) {
+ DP(("MAC Framework: mac_check_posix_sem_openexisting access denied\n"));
+ mtx_unlock(&ks->ks_mtx);
+ goto err_open_existing;
+ }
+ mtx_unlock(&ks->ks_mtx);
+#endif
+ if (dir == UIO_USERSPACE) {
+ if ((error = copyout(idpk, idpu, sizeof(*idpk)))) {
+ goto err_open_existing;
+ }
+ } else {
+ *idpu = *idpk;
+ }
+ sem_enter(td->td_proc, ks);
+err_open_existing:
+ mtx_lock(&sem_lock);
+ sem_rel(ks); /* Pump down */
+ if(ks->ks_unlinked && LIST_EMPTY(&ks->ks_users))
+ SEM_FREE(ks);
+ mtx_unlock(&sem_lock);
+ return(error);
}
static int
@@ -341,7 +405,7 @@
semid_t *idp;
{
struct ksem *ksnew, *ks;
- int error;
+ int error = 0;
semid_t id;
ksnew = NULL;
@@ -369,8 +433,7 @@
* We may block during creation, so drop the lock.
*/
mtx_unlock(&sem_lock);
- error = sem_create(td, name, &ksnew, mode, value);
- if (error != 0)
+ if((error = sem_create(td, name, &ksnew, mode, value)))
return (error);
id = SEM_TO_ID(ksnew);
if (dir == UIO_USERSPACE) {
@@ -379,7 +442,7 @@
if (error) {
mtx_lock(&sem_lock);
sem_leave(td->td_proc, ksnew);
- sem_rel(ksnew);
+ SEM_DROP(ksnew);
mtx_unlock(&sem_lock);
return (error);
}
@@ -396,53 +459,26 @@
if (ks != NULL) {
/* we lost... */
sem_leave(td->td_proc, ksnew);
- sem_rel(ksnew);
+ SEM_DROP(ksnew);
/* we lost and we can't loose... */
if ((oflag & O_EXCL) != 0) {
mtx_unlock(&sem_lock);
return (EEXIST);
}
+ /* Use the sem created by the winner */
+ else {
+ error = ksem_open_existing(td, ks, dir, idp, &id);
+ }
} else {
DP(("sem_create: about to add to list...\n"));
LIST_INSERT_HEAD(&ksem_head, ksnew, ks_entry);
DP(("sem_create: setting list bit...\n"));
ksnew->ks_onlist = 1;
DP(("sem_create: done, about to unlock...\n"));
+ mtx_unlock(&sem_lock);
}
- mtx_unlock(&sem_lock);
} else {
- /*
- * if we aren't the creator, then enforce permissions.
- */
- if((error = sem_perm(td, ks)))
- goto err;
-#ifdef MAC
- if((error = mac_check_posix_sem_openexisting(td->td_ucred, ks))) {
- DP(("MAC Framework: mac_check_posix_sem_openexisting access denied\n"));
- goto err;
- }
-#endif
- sem_ref(ks);
-err:
- mtx_unlock(&sem_lock);
- if (error)
- return (error);
- id = SEM_TO_ID(ks);
- if (dir == UIO_USERSPACE) {
- error = copyout(&id, idp, sizeof(id));
- if (error) {
- mtx_lock(&sem_lock);
- sem_rel(ks);
- mtx_unlock(&sem_lock);
- return (error);
- }
- } else {
- *idp = id;
- }
- sem_enter(td->td_proc, ks);
- mtx_lock(&sem_lock);
- sem_rel(ks);
- mtx_unlock(&sem_lock);
+ error = ksem_open_existing(td, ks, dir, idp, &id);
}
return (error);
}
@@ -466,21 +502,27 @@
}
static void
-sem_free(struct ksem *ks)
+sem_free(struct ksem *ks, int checkrefs)
{
-
+ mtx_assert(&sem_lock, MA_OWNED);
+ mtx_assert(&ks->ks_mtx, MA_NOTOWNED);
+ if(checkrefs && (ks->ks_ref > 0))
+ return;
nsems--;
if (ks->ks_onlist)
LIST_REMOVE(ks, ks_entry);
+
if (ks->ks_name != NULL)
free(ks->ks_name, M_SEM);
cv_destroy(&ks->ks_cv);
#ifdef MAC
mac_destroy_posix_ksem(ks);
#endif
+ mtx_destroy(&ks->ks_mtx);
free(ks, M_SEM);
}
+
static __inline struct kuser *sem_getuser(struct proc *p, struct ksem *ks);
static __inline struct kuser *
@@ -489,7 +531,8 @@
struct ksem *ks;
{
struct kuser *k;
-
+
+ mtx_assert(&sem_lock, MA_OWNED);
LIST_FOREACH(k, &ks->ks_users, ku_next)
if (k->ku_pid == p->p_pid)
return (k);
@@ -501,9 +544,15 @@
struct thread *td;
struct ksem *ks;
{
+ struct kuser *k;
+ int ret = 0;
+
+ mtx_assert(&sem_lock, MA_OWNED);
+ k = sem_getuser(td->td_proc, ks);
+ if ((ks->ks_name == NULL && sem_perm(td, ks)) || k != NULL)
+ ret = 1;
+ return ret;
- return ((ks->ks_name == NULL && sem_perm(td, ks))
- || sem_getuser(td->td_proc, ks) != NULL);
}
static int
@@ -511,20 +560,21 @@
struct proc *p;
struct ksem *ks;
{
- struct kuser *k;
+ struct kuser *k=NULL;
DP(("sem_leave: ks = %p\n", ks));
+ mtx_assert(&sem_lock, MA_OWNED);
+ DP(("sem_leave: ks = %p, k = %p\n", ks, k));
k = sem_getuser(p, ks);
- DP(("sem_leave: ks = %p, k = %p\n", ks, k));
- if (k != NULL) {
- LIST_REMOVE(k, ku_next);
- sem_rel(ks);
- DP(("sem_leave: about to free k\n"));
- free(k, M_SEM);
- DP(("sem_leave: returning\n"));
- return (0);
+ if (k == NULL) {
+ return (EINVAL);
}
- return (EINVAL);
+ LIST_REMOVE(k, ku_next);
+ sem_rel(ks);
+ DP(("sem_leave: about to free k\n"));
+ free(k, M_SEM);
+ DP(("sem_leave: returning\n"));
+ return (0);
}
static void
@@ -534,7 +584,10 @@
{
struct kuser *ku, *k;
- ku = malloc(sizeof(*ku), M_SEM, M_WAITOK | M_ZERO);
+ mtx_assert(&sem_lock, MA_NOTOWNED);
+ mtx_assert(&ks->ks_mtx, MA_NOTOWNED);
+ if( (ku = malloc(sizeof(*ku), M_SEM, M_WAITOK | M_ZERO)) == NULL)
+ return;
ku->ku_pid = p->p_pid;
mtx_lock(&sem_lock);
k = sem_getuser(p, ks);
@@ -579,26 +632,24 @@
mtx_lock(&sem_lock);
ks = sem_lookup_byname(name);
- if (ks == NULL)
+ if (ks == NULL) {
error = ENOENT;
- else {
- if ((error = sem_perm(td, ks)))
- goto err;
+ goto err_unlink;
+ }
+ if ((error = sem_perm(td, ks)))
+ goto err_unlink;
#ifdef MAC
- if((error = mac_check_posix_sem_unlink(td->td_ucred, ks))) {
- DP(("MAC Framework: mac_check_posix_sem_unlink access \
- denied\n"));
- goto err;
- }
+ if((error = mac_check_posix_sem_unlink(td->td_ucred, ks))) {
+ DP(("MAC Framework: mac_check_posix_sem_unlink access \
+ denied\n"));
+ goto err_unlink;
+ }
#endif
- }
DP(("sem_unlink: '%s' ks = %p, error = %d\n", name, ks, error));
- if (error == 0) {
- LIST_REMOVE(ks, ks_entry);
- LIST_INSERT_HEAD(&ksem_deadhead, ks, ks_entry);
- sem_rel(ks);
- }
-err:
+ ks->ks_unlinked = 1;
+ if(LIST_EMPTY(&ks->ks_users))
+ SEM_FREE(ks);
+err_unlink:
mtx_unlock(&sem_lock);
return (error);
}
@@ -631,15 +682,18 @@
/* this is not a valid operation for unnamed sems */
if (ks != NULL && ks->ks_name != NULL) {
#ifdef MAC
- if((error = mac_check_posix_sem_close(td->td_ucred, ks))) {
+ if ((error = mac_check_posix_sem_close(td->td_ucred, ks))) {
DP(("MAC Framework: mac_check_posix_sem_close access \
denied\n"));
- goto err;
+ goto err_close;
}
#endif
- error = sem_leave(td->td_proc, ks);
+ if ((error = sem_leave(td->td_proc, ks)))
+ goto err_close;
+ if (ks->ks_unlinked && LIST_EMPTY(&ks->ks_users))
+ SEM_FREE(ks);
}
-err:
+err_close:
mtx_unlock(&sem_lock);
return (error);
}
@@ -665,29 +719,37 @@
semid_t id;
{
struct ksem *ks;
- int error;
+ int error = 0;
mtx_lock(&sem_lock);
ks = ID_TO_SEM(id);
if (ks == NULL || !sem_hasopen(td, ks)) {
- error = EINVAL;
- goto err;
+ mtx_unlock(&sem_lock);
+ return (EINVAL);
}
+ sem_ref(ks);/* Pump up the refs to avoid the race with SEM_FREE */
+ mtx_unlock(&sem_lock);
+
+ mtx_lock(&ks->ks_mtx);
if (ks->ks_value == SEM_VALUE_MAX) {
error = EOVERFLOW;
- goto err;
+ goto err_post;
}
#ifdef MAC
- if((error = mac_check_posix_sem_post(td->td_ucred, ks))) {
+ if ((error = mac_check_posix_sem_post(td->td_ucred, ks))) {
DP(("MAC Framework: mac_check_posix_sem_post access denied\n"));
- goto err;
+ goto err_post;
}
#endif
++ks->ks_value;
if (ks->ks_waiters > 0)
cv_signal(&ks->ks_cv);
- error = 0;
-err:
+err_post:
+ mtx_unlock(&ks->ks_mtx);
+ mtx_lock(&sem_lock);
+ sem_rel(ks); /* Pump down */
+ if (ks->ks_unlinked && LIST_EMPTY(&ks->ks_users))
+ SEM_FREE(ks);
mtx_unlock(&sem_lock);
return (error);
}
@@ -730,43 +792,49 @@
int tryflag;
{
struct ksem *ks;
- int error;
+ int error = 0;
DP((">>> kern_sem_wait entered!\n"));
mtx_lock(&sem_lock);
ks = ID_TO_SEM(id);
if (ks == NULL) {
DP(("kern_sem_wait ks == NULL\n"));
- error = EINVAL;
- goto err;
+ mtx_unlock(&sem_lock);
+ return (EINVAL);
}
- sem_ref(ks);
if (!sem_hasopen(td, ks)) {
DP(("kern_sem_wait hasopen failed\n"));
- error = EINVAL;
- goto err;
+ mtx_unlock(&sem_lock);
+ return (EINVAL);
}
+ sem_ref(ks);/* Pump up the refs to avoid the race with SEM_FREE */
+ mtx_unlock(&sem_lock);
+
+ mtx_lock(&ks->ks_mtx);
#ifdef MAC
- if((error = mac_check_posix_sem_wait(td->td_ucred, ks))) {
+ if ((error = mac_check_posix_sem_wait(td->td_ucred, ks))) {
DP(("MAC Framework: mac_check_posix_sem_wait access denied\n"));
- goto err;
+ goto err_wait;
}
#endif
DP(("kern_sem_wait value = %d, tryflag %d\n", ks->ks_value, tryflag));
if (ks->ks_value == 0) {
ks->ks_waiters++;
- error = tryflag ? EAGAIN : cv_wait_sig(&ks->ks_cv, &sem_lock);
+ error = tryflag ? EAGAIN : cv_wait_sig(&ks->ks_cv, &ks->ks_mtx);
ks->ks_waiters--;
if (error)
- goto err;
+ goto err_wait;
}
ks->ks_value--;
error = 0;
-err:
- if (ks != NULL)
- sem_rel(ks);
+err_wait:
+ mtx_unlock(&ks->ks_mtx);
+ DP(("<<< kern_sem_wait leaving, error = %d\n", error));
+ mtx_lock(&sem_lock);
+ sem_rel(ks); /* Pump down */
+ if (ks->ks_unlinked && LIST_EMPTY(&ks->ks_users))
+ SEM_FREE(ks);
mtx_unlock(&sem_lock);
- DP(("<<< kern_sem_wait leaving, error = %d\n", error));
return (error);
}
@@ -791,16 +859,26 @@
mtx_unlock(&sem_lock);
return (EINVAL);
}
+ sem_ref(ks);/* Pump up the refs to avoid the race with SEM_FREE */
+ mtx_unlock(&sem_lock);
+
+ mtx_lock(&ks->ks_mtx);
#ifdef MAC
if((error = mac_check_posix_sem_getvalue(td->td_ucred, ks))) {
DP(("MAC Framework: mac_check_posix_sem_getvalue access denied\n"));
- mtx_unlock(&sem_lock);
- return (error);
+ mtx_unlock(&ks->ks_mtx);
+ goto err_getvalue;
}
#endif
val = ks->ks_value;
+ mtx_unlock(&ks->ks_mtx);
+ error = copyout(&val, uap->val, sizeof(val));
+err_getvalue:
+ mtx_lock(&sem_lock);
+ sem_rel(ks); /* Pump down */
+ if (ks->ks_unlinked && LIST_EMPTY(&ks->ks_users))
+ SEM_FREE(ks);
mtx_unlock(&sem_lock);
- error = copyout(&val, uap->val, sizeof(val));
return (error);
}
@@ -816,28 +894,24 @@
struct ksem_destroy_args *uap;
{
struct ksem *ks;
- int error;
+ int error = 0;
mtx_lock(&sem_lock);
ks = ID_TO_SEM(uap->id);
if (ks == NULL || !sem_hasopen(td, ks) ||
ks->ks_name != NULL) {
error = EINVAL;
- goto err;
+ goto err_destroy;
}
- if (ks->ks_waiters != 0) {
- error = EBUSY;
- goto err;
- }
#ifdef MAC
if((error = mac_check_posix_sem_destroy(td->td_ucred, ks))) {
DP(("MAC Framework: mac_check_posix_sem_destroy access denied\n"));
- goto err;
+ goto err_destroy;
}
#endif
- sem_rel(ks);
- error = 0;
-err:
+ ks->ks_unlinked = 1; /* Indicate that the sem needs to be destroyed */
+ SEM_FREE(ks);
+err_destroy:
mtx_unlock(&sem_lock);
return (error);
}
@@ -853,13 +927,9 @@
ks = LIST_FIRST(&ksem_head);
while (ks != NULL) {
ksnext = LIST_NEXT(ks, ks_entry);
- sem_leave(p, ks);
- ks = ksnext;
- }
- ks = LIST_FIRST(&ksem_deadhead);
- while (ks != NULL) {
- ksnext = LIST_NEXT(ks, ks_entry);
- sem_leave(p, ks);
+ if(!sem_leave(p, ks))
+ if (ks->ks_unlinked && LIST_EMPTY(&ks->ks_users))
+ SEM_FREE(ks);
ks = ksnext;
}
mtx_unlock(&sem_lock);
==== //depot/projects/trustedbsd/mac/sys/posix4/ksem.h#2 (text+ko) ====
@@ -69,7 +69,9 @@
struct cv ks_cv; /* waiters sleep here */
int ks_waiters; /* number of waiters */
LIST_HEAD(, kuser) ks_users; /* pids using this sem */
+ struct mtx ks_mtx; /* mutex protecting the ks_users list */
struct label ks_label; /* MAC label */
+ int ks_unlinked; /* Whether the named sem is unlinked */
};
#endif /* _KERNEL */
To Unsubscribe: send mail to majordomo at trustedbsd.org
with "unsubscribe trustedbsd-cvs" in the body of the message
More information about the trustedbsd-cvs
mailing list