svn commit: r233260 - in user/davidxu/pth_objdestroy/sys: kern sys
David Xu
davidxu at FreeBSD.org
Wed Mar 21 07:07:01 UTC 2012
Author: davidxu
Date: Wed Mar 21 07:07:00 2012
New Revision: 233260
URL: http://svn.freebsd.org/changeset/base/233260
Log:
Change semaphore to merge waiter bit and count in same word, this allows
us gracefully to destroy semaphore, also remove rmb() ambiguity.
Modified:
user/davidxu/pth_objdestroy/sys/kern/kern_umtx.c
user/davidxu/pth_objdestroy/sys/sys/umtx.h
Modified: user/davidxu/pth_objdestroy/sys/kern/kern_umtx.c
==============================================================================
--- user/davidxu/pth_objdestroy/sys/kern/kern_umtx.c Wed Mar 21 07:05:29 2012 (r233259)
+++ user/davidxu/pth_objdestroy/sys/kern/kern_umtx.c Wed Mar 21 07:07:00 2012 (r233260)
@@ -2870,16 +2870,38 @@ do_sem_wait(struct thread *td, struct _u
umtxq_insert(uq);
umtxq_unlock(&uq->uq_key);
- casuword32(__DEVOLATILE(uint32_t *, &sem->_has_waiters), 0, 1);
- rmb();
- count = fuword32(__DEVOLATILE(uint32_t *, &sem->_count));
- if (count != 0) {
- umtxq_lock(&uq->uq_key);
- umtxq_unbusy(&uq->uq_key);
- umtxq_remove(uq);
- umtxq_unlock(&uq->uq_key);
- umtx_key_release(&uq->uq_key);
- return (0);
+ if (__predict_false((flags & SEM_VER2) == 0)) {
+ casuword32(__DEVOLATILE(uint32_t *, &sem->_has_waiters), 0, 1);
+ rmb();
+ count = fuword32(__DEVOLATILE(uint32_t *, &sem->_count));
+ if (count != 0) {
+ umtxq_lock(&uq->uq_key);
+ umtxq_unbusy(&uq->uq_key);
+ umtxq_remove(uq);
+ umtxq_unlock(&uq->uq_key);
+ umtx_key_release(&uq->uq_key);
+ return (0);
+ }
+ } else {
+ count = fuword32(__DEVOLATILE(uint32_t *, &sem->_count));
+ for (;;) {
+ if ((count & ~SEM_WAITERS) != 0) {
+ umtxq_lock(&uq->uq_key);
+ umtxq_unbusy(&uq->uq_key);
+ umtxq_remove(uq);
+ umtxq_unlock(&uq->uq_key);
+ umtx_key_release(&uq->uq_key);
+ return (0);
+ }
+ if ((count & SEM_WAITERS) == 0) {
+ int old = casuword32(__DEVOLATILE(uint32_t *,
+ &sem->_count), count, count | SEM_WAITERS);
+ if (old == count)
+ break;
+ count = old;
+ } else
+ break;
+ }
}
umtxq_lock(&uq->uq_key);
@@ -2932,22 +2954,42 @@ static int
do_sem_wake(struct thread *td, struct _usem *sem)
{
struct umtx_key key;
- int error, cnt, nwake;
- uint32_t flags;
+ int error, nwait;
+ uint32_t flags, count;
flags = fuword32(&sem->_flags);
if ((error = umtx_key_get(sem, TYPE_SEM, GET_SHARE(flags), &key)) != 0)
return (error);
umtxq_lock(&key);
umtxq_busy(&key);
- cnt = umtxq_count(&key);
- nwake = umtxq_signal(&key, 1);
- if (cnt <= nwake) {
- umtxq_unlock(&key);
- error = suword32(
- __DEVOLATILE(uint32_t *, &sem->_has_waiters), 0);
- umtxq_lock(&key);
+ nwait = umtxq_count(&key);
+ umtxq_unlock(&key);
+ if ((flags & SEM_VER2) != 0) {
+ error = 0;
+ count = fuword32(__DEVOLATILE(uint32_t *, &sem->_count));
+ for (;;) {
+ if (__predict_false((count & ~SEM_WAITERS) == __INT_MAX)) {
+ umtxq_lock(&key);
+ umtxq_unbusy(&key);
+ umtxq_unlock(&key);
+ return (ERANGE);
+ }
+ int new = count + 1;
+ if (nwait <= 1)
+ new &= ~SEM_WAITERS;
+ int old = casuword32(__DEVOLATILE(uint32_t *,
+ &sem->_count), count, new);
+ if (old == count)
+ break;
+ count = old;
+ }
+ } else {
+ if (nwait <= 1)
+ error = suword32(
+ __DEVOLATILE(uint32_t *, &sem->_has_waiters), 0);
}
+ umtxq_lock(&key);
+ umtxq_signal(&key, 1);
umtxq_unbusy(&key);
umtxq_unlock(&key);
umtx_key_release(&key);
Modified: user/davidxu/pth_objdestroy/sys/sys/umtx.h
==============================================================================
--- user/davidxu/pth_objdestroy/sys/sys/umtx.h Wed Mar 21 07:05:29 2012 (r233259)
+++ user/davidxu/pth_objdestroy/sys/sys/umtx.h Wed Mar 21 07:07:00 2012 (r233260)
@@ -55,7 +55,9 @@
#define URWLOCK_READER_COUNT(c) ((c) & URWLOCK_MAX_READERS)
/* _usem flags */
-#define SEM_NAMED 0x0002
+#define SEM_NAMED 0x00000002
+#define SEM_VER2 0x00000004
+#define SEM_WAITERS 0x80000000
/* op code for _umtx_op */
#define UMTX_OP_LOCK 0
More information about the svn-src-user
mailing list