summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread/thr_cond.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libthr/thread/thr_cond.c')
-rw-r--r--lib/libthr/thread/thr_cond.c608
1 files changed, 238 insertions, 370 deletions
diff --git a/lib/libthr/thread/thr_cond.c b/lib/libthr/thread/thr_cond.c
index b2cbb83..cd50c4d 100644
--- a/lib/libthr/thread/thr_cond.c
+++ b/lib/libthr/thread/thr_cond.c
@@ -1,476 +1,344 @@
/*
- * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
+ * Copyright (c) 2005 David Xu <davidxu@freebsd.org>
* All rights reserved.
*
* 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.
+ * notice unmodified, 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 John Birrell.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL 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 AUTHOR 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.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
* $FreeBSD$
*/
+
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
+#include <limits.h>
+
#include "thr_private.h"
/*
- * Proctect two different threads calling a pthread_cond_* function
- * from accidentally initializing the condition variable twice.
+ * Prototypes
*/
-static spinlock_t static_cond_lock = _SPINLOCK_INITIALIZER;
+static int cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
+static int cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
+ const struct timespec *abstime, int cancel);
+static int cond_signal_common(pthread_cond_t *cond, int broadcast);
/*
- * Prototypes
+ * Double underscore versions are cancellation points. Single underscore
+ * versions are not and are provided for libc internal usage (which
+ * shouldn't introduce cancellation points).
*/
-static inline int cond_init(pthread_cond_t *);
-static pthread_t cond_queue_deq(pthread_cond_t);
-static void cond_queue_remove(pthread_cond_t, pthread_t);
-static void cond_queue_enq(pthread_cond_t, pthread_t);
-static int cond_signal(pthread_cond_t *, int);
-static int cond_wait_common(pthread_cond_t *,
- pthread_mutex_t *, const struct timespec *);
+__weak_reference(__pthread_cond_wait, pthread_cond_wait);
+__weak_reference(__pthread_cond_timedwait, pthread_cond_timedwait);
__weak_reference(_pthread_cond_init, pthread_cond_init);
__weak_reference(_pthread_cond_destroy, pthread_cond_destroy);
-__weak_reference(_pthread_cond_wait, pthread_cond_wait);
-__weak_reference(_pthread_cond_timedwait, pthread_cond_timedwait);
__weak_reference(_pthread_cond_signal, pthread_cond_signal);
__weak_reference(_pthread_cond_broadcast, pthread_cond_broadcast);
-#define COND_LOCK(c) \
-do { \
- if (umtx_lock(&(c)->c_lock, curthread->thr_id)) \
- abort(); \
-} while (0)
-
-#define COND_UNLOCK(c) \
-do { \
- if (umtx_unlock(&(c)->c_lock, curthread->thr_id)) \
- abort(); \
-} while (0)
-
-
-/* Reinitialize a condition variable to defaults. */
-int
-_cond_reinit(pthread_cond_t *cond)
+static int
+cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
{
- if (cond == NULL)
- return (EINVAL);
-
- if (*cond == NULL)
- return (pthread_cond_init(cond, NULL));
+ pthread_cond_t pcond;
+ int rval = 0;
- /*
- * Initialize the condition variable structure:
- */
- TAILQ_INIT(&(*cond)->c_queue);
- (*cond)->c_flags = COND_FLAGS_INITED;
- (*cond)->c_type = COND_TYPE_FAST;
- (*cond)->c_mutex = NULL;
- (*cond)->c_seqno = 0;
- bzero(&(*cond)->c_lock, sizeof((*cond)->c_lock));
-
- return (0);
+ if ((pcond = (pthread_cond_t)
+ malloc(sizeof(struct pthread_cond))) == NULL) {
+ rval = ENOMEM;
+ } else {
+ /*
+ * Initialise the condition variable structure:
+ */
+ _thr_umtx_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;
+ } else {
+ pcond->c_pshared = (*cond_attr)->c_pshared;
+ pcond->c_clockid = (*cond_attr)->c_clockid;
+ }
+ *cond = pcond;
+ }
+ /* Return the completion status: */
+ return (rval);
}
-int
-_pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
+static int
+init_static(struct pthread *thread, pthread_cond_t *cond)
{
- enum pthread_cond_type type;
- pthread_cond_t pcond;
+ int ret;
- if (cond == NULL)
- return (EINVAL);
+ THR_LOCK_ACQUIRE(thread, &_cond_static_lock);
- /*
- * Check if a pointer to a condition variable attribute
- * structure was passed by the caller:
- */
- if (cond_attr != NULL && *cond_attr != NULL)
- type = (*cond_attr)->c_type;
+ if (*cond == NULL)
+ ret = cond_init(cond, NULL);
else
- /* Default to a fast condition variable: */
- type = COND_TYPE_FAST;
-
- /* Process according to condition variable type: */
- switch (type) {
- case COND_TYPE_FAST:
- break;
- default:
- return (EINVAL);
- break;
- }
+ ret = 0;
- if ((pcond = (pthread_cond_t)
- malloc(sizeof(struct pthread_cond))) == NULL)
- return (ENOMEM);
- /*
- * Initialise the condition variable
- * structure:
- */
- TAILQ_INIT(&pcond->c_queue);
- pcond->c_flags |= COND_FLAGS_INITED;
- pcond->c_type = type;
- pcond->c_mutex = NULL;
- pcond->c_seqno = 0;
- bzero(&pcond->c_lock, sizeof(pcond->c_lock));
+ THR_LOCK_RELEASE(thread, &_cond_static_lock);
- *cond = pcond;
-
- return (0);
+ return (ret);
}
int
-_pthread_cond_destroy(pthread_cond_t *cond)
+_pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
{
- /*
- * Short circuit for a statically initialized condvar
- * that is being destroyed without having been used.
- */
- if (*cond == PTHREAD_COND_INITIALIZER)
- return (0);
-
- COND_LOCK(*cond);
-
- /*
- * Free the memory allocated for the condition
- * variable structure:
- */
- free(*cond);
- /*
- * NULL the caller's pointer now that the condition
- * variable has been destroyed:
- */
*cond = NULL;
-
- return (0);
+ return (cond_init(cond, cond_attr));
}
int
-_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
+_pthread_cond_destroy(pthread_cond_t *cond)
{
- int rval;
+ struct pthread_cond *cv;
+ struct pthread *curthread = _get_curthread();
+ int rval = 0;
+
+ if (*cond == NULL)
+ rval = EINVAL;
+ else {
+ /* 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);
+ return (EBUSY);
+ }
+
+ /*
+ * NULL the caller's pointer now that the condition
+ * variable has been destroyed:
+ */
+ cv = *cond;
+ *cond = NULL;
- rval = cond_wait_common(cond, mutex, NULL);
+ /* Unlock the condition variable structure: */
+ THR_LOCK_RELEASE(curthread, &cv->c_lock);
- /* This should never happen. */
- if (rval == ETIMEDOUT)
- abort();
+ /* Free the cond lock structure: */
+ /*
+ * Free the memory allocated for the condition
+ * variable structure:
+ */
+ free(cv);
+
+ }
+ /* Return the completion status: */
return (rval);
}
-int
-_pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
- const struct timespec * abstime)
+struct cond_cancel_info
{
- if (abstime == NULL || abstime->tv_nsec >= 1000000000)
- return (EINVAL);
+ pthread_mutex_t *mutex;
+ pthread_cond_t *cond;
+ long seqno;
+};
+
+static void
+cond_cancel_handler(void *arg)
+{
+ struct pthread *curthread = _get_curthread();
+ struct cond_cancel_info *cci = (struct cond_cancel_info *)arg;
+ pthread_cond_t cv;
+
+ cv = *(cci->cond);
+ THR_LOCK_ACQUIRE(curthread, &cv->c_lock);
+ if (cv->c_seqno != cci->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);
- return (cond_wait_common(cond, mutex, abstime));
+ _mutex_cv_lock(cci->mutex);
}
static int
-cond_wait_common(pthread_cond_t * cond, pthread_mutex_t * mutex,
- const struct timespec * abstime)
+cond_wait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
+ const struct timespec *abstime, int cancel)
{
- int rval = 0;
- int mtxrval;
+ struct pthread *curthread = _get_curthread();
+ struct timespec ts, ts2, *tsp;
+ struct cond_cancel_info cci;
+ pthread_cond_t cv;
+ long seq, oldseq;
+ int oldcancel;
+ int ret = 0;
-
- if (cond == NULL)
- return (EINVAL);
/*
- * If the condition variable is statically initialized, perform dynamic
- * initialization.
+ * If the condition variable is statically initialized,
+ * perform the dynamic initialization:
*/
- if (*cond == PTHREAD_COND_INITIALIZER && (rval = cond_init(cond)) != 0)
- return (rval);
-
- if ((*cond)->c_type != COND_TYPE_FAST)
- return (EINVAL);
-
- COND_LOCK(*cond);
-
- /*
- * If the condvar was statically allocated, properly
- * initialize the tail queue.
- */
- if (((*cond)->c_flags & COND_FLAGS_INITED) == 0) {
- TAILQ_INIT(&(*cond)->c_queue);
- (*cond)->c_flags |= COND_FLAGS_INITED;
- }
-
- if ((mutex == NULL) || (((*cond)->c_mutex != NULL) &&
- ((*cond)->c_mutex != *mutex))) {
- COND_UNLOCK(*cond);
- return (EINVAL);
- }
- /* Remember the mutex */
- (*cond)->c_mutex = *mutex;
-
- _thread_enter_cancellation_point();
- if ((rval = _mutex_cv_unlock(mutex)) != 0) {
- if (rval == -1){
- printf("mutex unlock by condvar failed!");
- fflush(stdout);
- abort();
- }
- _thread_leave_cancellation_point();
- COND_UNLOCK(*cond);
- return (rval);
+ if (__predict_false(*cond == NULL &&
+ (ret = init_static(curthread, cond)) != 0))
+ return (ret);
+
+ cv = *cond;
+ THR_LOCK_ACQUIRE(curthread, &cv->c_lock);
+ ret = _mutex_cv_unlock(mutex);
+ if (ret) {
+ THR_LOCK_RELEASE(curthread, &cv->c_lock);
+ return (ret);
}
+ oldseq = seq = cv->c_seqno;
+ cci.mutex = mutex;
+ cci.cond = cond;
+ cci.seqno = oldseq;
- /*
- * We need to protect the queue operations. It also
- * protects the pthread flag field. This is
- * dropped before calling _thread_suspend() and reaquired
- * when we return.
- */
- PTHREAD_LOCK(curthread);
-
- /*
- * Queue the running thread on the condition
- * variable and wait to be signaled.
- */
- cond_queue_enq(*cond, curthread);
+ cv->c_waiters++;
do {
- PTHREAD_UNLOCK(curthread);
- COND_UNLOCK(*cond);
- if (curthread->cancellation == CS_PENDING) {
- /*
- * Posix says we must lock the mutex
- * even if we're being canceled.
- */
- _mutex_cv_lock(mutex);
- _thread_leave_cancellation_point();
- PANIC("Shouldn't have come back.");
- }
- rval = _thread_suspend(curthread, (struct timespec *)abstime);
- if (rval != 0 && rval != ETIMEDOUT && rval != EINTR) {
- printf("thread suspend returned an invalid value");
- fflush(stdout);
- abort();
- }
- COND_LOCK(*cond);
- PTHREAD_LOCK(curthread);
- if (rval == ETIMEDOUT) {
- /*
- * Condition may have been signaled between the
- * time the thread timed out and locked the condvar.
- * If it wasn't, manually remove it from the queue.
- */
- if ((curthread->flags & PTHREAD_FLAGS_IN_CONDQ) == 0)
- rval = 0;
- else
- cond_queue_remove(*cond, curthread);
+ 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, &cci);
+ oldcancel = _thr_cancel_enter(curthread);
+ ret = _thr_umtx_wait(&cv->c_seqno, seq, tsp);
+ _thr_cancel_leave(curthread, oldcancel);
+ THR_CLEANUP_POP(curthread, 0);
+ } else {
+ ret = _thr_umtx_wait(&cv->c_seqno, seq, tsp);
}
- } while ((curthread->flags & PTHREAD_FLAGS_IN_CONDQ) != 0);
- PTHREAD_UNLOCK(curthread);
- COND_UNLOCK(*cond);
- mtxrval = _mutex_cv_lock(mutex);
+ THR_LOCK_ACQUIRE(curthread, &cv->c_lock);
+ seq = cv->c_seqno;
+ if (abstime != NULL && ret == ETIMEDOUT)
+ break;
- /* If the mutex failed return that error. */
- if (mtxrval == -1) {
- printf("mutex lock from condvar failed!");
- fflush(stdout);
- abort();
+ /*
+ * 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;
+ } else {
+ cv->c_waiters--;
}
- if (mtxrval != 0)
- rval = mtxrval;
-
- _thread_leave_cancellation_point();
- return (rval);
+ THR_LOCK_RELEASE(curthread, &cv->c_lock);
+ _mutex_cv_lock(mutex);
+ return (ret);
}
int
-_pthread_cond_signal(pthread_cond_t * cond)
+_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
{
- return (cond_signal(cond, 0));
+
+ return (cond_wait_common(cond, mutex, NULL, 0));
}
int
-_pthread_cond_broadcast(pthread_cond_t * cond)
+__pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
{
- return (cond_signal(cond, 1));
+
+ return (cond_wait_common(cond, mutex, NULL, 1));
}
-static int
-cond_signal(pthread_cond_t * cond, int broadcast)
+int
+_pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
+ const struct timespec * abstime)
{
- int rval = 0;
- pthread_t pthread;
- if (cond == NULL)
- return (EINVAL);
- /*
- * If the condition variable is statically initialized, perform dynamic
- * initialization.
- */
- if (*cond == PTHREAD_COND_INITIALIZER && (rval = cond_init(cond)) != 0)
- return (rval);
-
- if ((*cond)->c_type != COND_TYPE_FAST)
+ if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
+ abstime->tv_nsec >= 1000000000)
return (EINVAL);
- COND_LOCK(*cond);
- /*
- * Enter a loop to bring all (or only one) threads off the
- * condition queue:
- */
- do {
- /*
- * Wake up the signaled thread. It will be returned
- * to us locked.
- */
- if ((pthread = cond_queue_deq(*cond)) != NULL) {
- PTHREAD_WAKE(pthread);
- PTHREAD_UNLOCK(pthread);
- }
- } while (broadcast && pthread != NULL);
-
- COND_UNLOCK(*cond);
- return (rval);
+ return (cond_wait_common(cond, mutex, abstime, 0));
}
-void
-_cond_wait_backout(pthread_t pthread)
-{
- pthread_cond_t cond;
-
- cond = pthread->data.cond;
- if (cond == NULL)
- return;
-
- /* Process according to condition variable type: */
- switch (cond->c_type) {
- /* Fast condition variable: */
- case COND_TYPE_FAST:
- cond_queue_remove(cond, pthread);
- break;
- default:
- break;
- }
-}
-
-/*
- * Dequeue a waiting thread from the head of a condition queue in
- * descending priority order.
- */
-static pthread_t
-cond_queue_deq(pthread_cond_t cond)
+int
+__pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+ const struct timespec *abstime)
{
- pthread_t pthread;
- while ((pthread = TAILQ_FIRST(&cond->c_queue)) != NULL) {
- PTHREAD_LOCK(pthread);
- cond_queue_remove(cond, pthread);
-
- /*
- * Only exit the loop when we find a thread
- * that hasn't been canceled.
- */
- if (pthread->cancellation == CS_NULL)
- break;
- else
- PTHREAD_UNLOCK(pthread);
- }
+ if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
+ abstime->tv_nsec >= 1000000000)
+ return (EINVAL);
- return(pthread);
+ return (cond_wait_common(cond, mutex, abstime, 1));
}
-/*
- * Remove a waiting thread from a condition queue in descending priority
- * order.
- */
-static void
-cond_queue_remove(pthread_cond_t cond, pthread_t pthread)
+static int
+cond_signal_common(pthread_cond_t *cond, int broadcast)
{
+ struct pthread *curthread = _get_curthread();
+ pthread_cond_t cv;
+ int ret = 0, oldwaiters;
+
/*
- * Because pthread_cond_timedwait() can timeout as well
- * as be signaled by another thread, it is necessary to
- * guard against removing the thread from the queue if
- * it isn't in the queue.
+ * If the condition variable is statically initialized, perform dynamic
+ * initialization.
*/
- if (pthread->flags & PTHREAD_FLAGS_IN_CONDQ) {
- TAILQ_REMOVE(&cond->c_queue, pthread, sqe);
- pthread->flags &= ~PTHREAD_FLAGS_IN_CONDQ;
+ if (__predict_false(*cond == NULL &&
+ (ret = init_static(curthread, cond)) != 0))
+ 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);
+ }
}
- /* Check for no more waiters. */
- if (TAILQ_FIRST(&cond->c_queue) == NULL)
- cond->c_mutex = NULL;
+ THR_LOCK_RELEASE(curthread, &cv->c_lock);
+ return (ret);
}
-/*
- * Enqueue a waiting thread to a condition queue in descending priority
- * order.
- */
-static void
-cond_queue_enq(pthread_cond_t cond, pthread_t pthread)
+int
+_pthread_cond_signal(pthread_cond_t * cond)
{
- pthread_t tid = TAILQ_LAST(&cond->c_queue, cond_head);
- char *name;
-
- name = pthread->name ? pthread->name : "unknown";
- if ((pthread->flags & PTHREAD_FLAGS_IN_CONDQ) != 0)
- _thread_printf(2, "Thread (%s:%ld) already on condq\n",
- pthread->name, pthread->thr_id);
- if ((pthread->flags & PTHREAD_FLAGS_IN_MUTEXQ) != 0)
- _thread_printf(2, "Thread (%s:%ld) already on mutexq\n",
- pthread->name, pthread->thr_id);
- PTHREAD_ASSERT_NOT_IN_SYNCQ(pthread);
- /*
- * For the common case of all threads having equal priority,
- * we perform a quick check against the priority of the thread
- * at the tail of the queue.
- */
- if ((tid == NULL) || (pthread->active_priority <= tid->active_priority))
- TAILQ_INSERT_TAIL(&cond->c_queue, pthread, sqe);
- else {
- tid = TAILQ_FIRST(&cond->c_queue);
- while (pthread->active_priority <= tid->active_priority)
- tid = TAILQ_NEXT(tid, sqe);
- TAILQ_INSERT_BEFORE(tid, pthread, sqe);
- }
- pthread->flags |= PTHREAD_FLAGS_IN_CONDQ;
- pthread->data.cond = cond;
+ return (cond_signal_common(cond, 0));
}
-static inline int
-cond_init(pthread_cond_t *cond)
+int
+_pthread_cond_broadcast(pthread_cond_t * cond)
{
- int error = 0;
- _SPINLOCK(&static_cond_lock);
- if (*cond == PTHREAD_COND_INITIALIZER)
- error = _pthread_cond_init(cond, NULL);
- _SPINUNLOCK(&static_cond_lock);
- return (error);
-}
+ return (cond_signal_common(cond, 1));
+}
OpenPOWER on IntegriCloud