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