diff options
Diffstat (limited to 'lib/libthr/thread/thr_cond.c')
-rw-r--r-- | lib/libthr/thread/thr_cond.c | 127 |
1 files changed, 38 insertions, 89 deletions
diff --git a/lib/libthr/thread/thr_cond.c b/lib/libthr/thread/thr_cond.c index e587a6d..eb50366 100644 --- a/lib/libthr/thread/thr_cond.c +++ b/lib/libthr/thread/thr_cond.c @@ -67,16 +67,12 @@ cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) int rval = 0; if ((pcond = (pthread_cond_t) - malloc(sizeof(struct pthread_cond))) == NULL) { + calloc(1, sizeof(struct pthread_cond))) == NULL) { rval = ENOMEM; } else { /* * Initialise the condition variable structure: */ - _thr_umutex_init(&pcond->c_lock); - pcond->c_seqno = 0; - pcond->c_waiters = 0; - pcond->c_wakeups = 0; if (cond_attr == NULL || *cond_attr == NULL) { pcond->c_pshared = 0; pcond->c_clockid = CLOCK_REALTIME; @@ -84,6 +80,7 @@ cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) pcond->c_pshared = (*cond_attr)->c_pshared; pcond->c_clockid = (*cond_attr)->c_clockid; } + _thr_umutex_init(&pcond->c_lock); *cond = pcond; } /* Return the completion status: */ @@ -118,31 +115,26 @@ _pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) int _pthread_cond_destroy(pthread_cond_t *cond) { - struct pthread_cond *cv; struct pthread *curthread = _get_curthread(); + struct pthread_cond *cv; int rval = 0; if (*cond == NULL) rval = EINVAL; else { + cv = *cond; + THR_UMUTEX_LOCK(curthread, &cv->c_lock); /* Lock the condition variable structure: */ - THR_LOCK_ACQUIRE(curthread, &(*cond)->c_lock); - if ((*cond)->c_waiters + (*cond)->c_wakeups != 0) { - THR_LOCK_RELEASE(curthread, &(*cond)->c_lock); + if (cv->c_kerncv.c_has_waiters) { + THR_UMUTEX_UNLOCK(curthread, &cv->c_lock); return (EBUSY); } - /* * NULL the caller's pointer now that the condition * variable has been destroyed: */ - cv = *cond; *cond = NULL; - - /* Unlock the condition variable structure: */ - THR_LOCK_RELEASE(curthread, &cv->c_lock); - - /* Free the cond lock structure: */ + THR_UMUTEX_UNLOCK(curthread, &cv->c_lock); /* * Free the memory allocated for the condition @@ -159,7 +151,6 @@ struct cond_cancel_info { pthread_mutex_t *mutex; pthread_cond_t *cond; - long seqno; int count; }; @@ -168,21 +159,11 @@ cond_cancel_handler(void *arg) { struct pthread *curthread = _get_curthread(); struct cond_cancel_info *info = (struct cond_cancel_info *)arg; - pthread_cond_t cv; + pthread_cond_t cv; cv = *(info->cond); - THR_LOCK_ACQUIRE(curthread, &cv->c_lock); - if (cv->c_seqno != info->seqno && cv->c_wakeups != 0) { - if (cv->c_waiters > 0) { - cv->c_seqno++; - _thr_umtx_wake(&cv->c_seqno, 1); - } else - cv->c_wakeups--; - } else { - cv->c_waiters--; - } - THR_LOCK_RELEASE(curthread, &cv->c_lock); - + if ((cv->c_lock.m_owner & ~UMUTEX_CONTESTED) == TID(curthread)) + THR_UMUTEX_UNLOCK(curthread, &cv->c_lock); _mutex_cv_lock(info->mutex, info->count); } @@ -194,7 +175,6 @@ cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec ts, ts2, *tsp; struct cond_cancel_info info; pthread_cond_t cv; - long seq, oldseq; int ret = 0; /* @@ -206,56 +186,34 @@ cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex, return (ret); cv = *cond; - THR_LOCK_ACQUIRE(curthread, &cv->c_lock); + THR_UMUTEX_LOCK(curthread, &cv->c_lock); ret = _mutex_cv_unlock(mutex, &info.count); if (ret) { - THR_LOCK_RELEASE(curthread, &cv->c_lock); + THR_UMUTEX_UNLOCK(curthread, &cv->c_lock); return (ret); } - oldseq = seq = cv->c_seqno; + info.mutex = mutex; info.cond = cond; - info.seqno = oldseq; - - cv->c_waiters++; - do { - THR_LOCK_RELEASE(curthread, &cv->c_lock); - - if (abstime != NULL) { - clock_gettime(cv->c_clockid, &ts); - TIMESPEC_SUB(&ts2, abstime, &ts); - tsp = &ts2; - } else - tsp = NULL; - - if (cancel) { - THR_CLEANUP_PUSH(curthread, cond_cancel_handler, &info); - _thr_cancel_enter(curthread); - ret = _thr_umtx_wait(&cv->c_seqno, seq, tsp); - _thr_cancel_leave(curthread); - THR_CLEANUP_POP(curthread, 0); - } else { - ret = _thr_umtx_wait(&cv->c_seqno, seq, tsp); - } - - THR_LOCK_ACQUIRE(curthread, &cv->c_lock); - seq = cv->c_seqno; - if (abstime != NULL && ret == ETIMEDOUT) - break; - /* - * loop if we have never been told to wake up - * or we lost a race. - */ - } while (seq == oldseq || cv->c_wakeups == 0); - - if (seq != oldseq && cv->c_wakeups != 0) { - cv->c_wakeups--; - ret = 0; + if (abstime != NULL) { + clock_gettime(cv->c_clockid, &ts); + TIMESPEC_SUB(&ts2, abstime, &ts); + tsp = &ts2; + } else + tsp = NULL; + + if (cancel) { + THR_CLEANUP_PUSH(curthread, cond_cancel_handler, &info); + _thr_cancel_enter_defer(curthread); + ret = _thr_ucond_wait(&cv->c_kerncv, &cv->c_lock, tsp, 1); + _thr_cancel_leave_defer(curthread, ret); + THR_CLEANUP_POP(curthread, 0); } else { - cv->c_waiters--; + ret = _thr_ucond_wait(&cv->c_kerncv, &cv->c_lock, tsp, 0); } - THR_LOCK_RELEASE(curthread, &cv->c_lock); + if (ret == EINTR) + ret = 0; _mutex_cv_lock(mutex, info.count); return (ret); } @@ -303,7 +261,7 @@ cond_signal_common(pthread_cond_t *cond, int broadcast) { struct pthread *curthread = _get_curthread(); pthread_cond_t cv; - int ret = 0, oldwaiters; + int ret = 0; /* * If the condition variable is statically initialized, perform dynamic @@ -314,23 +272,14 @@ cond_signal_common(pthread_cond_t *cond, int broadcast) return (ret); cv = *cond; - /* Lock the condition variable structure. */ - THR_LOCK_ACQUIRE(curthread, &cv->c_lock); - if (cv->c_waiters) { - if (!broadcast) { - cv->c_wakeups++; - cv->c_waiters--; - cv->c_seqno++; - _thr_umtx_wake(&cv->c_seqno, 1); - } else { - oldwaiters = cv->c_waiters; - cv->c_wakeups += cv->c_waiters; - cv->c_waiters = 0; - cv->c_seqno++; - _thr_umtx_wake(&cv->c_seqno, oldwaiters); - } + THR_UMUTEX_LOCK(curthread, &cv->c_lock); + if (cv->c_kerncv.c_has_waiters) { + if (!broadcast) + ret = _thr_ucond_signal(&cv->c_kerncv); + else + ret = _thr_ucond_broadcast(&cv->c_kerncv); } - THR_LOCK_RELEASE(curthread, &cv->c_lock); + THR_UMUTEX_UNLOCK(curthread, &cv->c_lock); return (ret); } |