diff options
author | Chris Hall (GMCH) <chris.hall@highwayman.com> | 2009-12-10 21:20:03 +0000 |
---|---|---|
committer | Chris Hall (GMCH) <chris.hall@highwayman.com> | 2009-12-10 21:20:03 +0000 |
commit | 977e8eceb3fdc2e3d5cf72677cbaf8528b3ba865 (patch) | |
tree | 6bfc6202c1bc3be4074c3620a8494c82a569555c | |
parent | 553285d84f469027a0fbe38cfcfe773cff927553 (diff) | |
download | quagga-977e8eceb3fdc2e3d5cf72677cbaf8528b3ba865.tar.bz2 quagga-977e8eceb3fdc2e3d5cf72677cbaf8528b3ba865.tar.xz |
Introduced qpthreads_enabled flag in lib/qpthreads
This supports running without pthreads, but with code that is made
thread-safe. A Big Switch -- qpthreads_enabled -- enables or disables
all pthread functions. When disabled, all mutex calls become NOPs.
-rw-r--r-- | lib/qpthreads.c | 229 | ||||
-rw-r--r-- | lib/qpthreads.h | 166 |
2 files changed, 296 insertions, 99 deletions
diff --git a/lib/qpthreads.c b/lib/qpthreads.c index 5dd0cfc4..e7a8da2f 100644 --- a/lib/qpthreads.c +++ b/lib/qpthreads.c @@ -50,6 +50,21 @@ * * the ability to add any work-arounds which may be required if poorly * conforming pthreads implementations are encountered * + * Continued Working Without Pthreads + * ================================== + * + * A big Global Switch -- qpthreads_enabled -- is used to control whether the + * system is pthreaded or not. + * + * If this is never set, then the system runs without pthreads, and all the + * mutex and condition variable functions are NOPs. This allows, for example, + * mutex operations to be placed where they are needed for thread-safety, + * without affecting the code when running without pthreads. + * + * Before the first thread is created and before any mutexes or condition + * variables are initialised, the qpthreads_enabled MUST be set. And it MUST + * not be changed again ! + * * Pthread Requirements * ==================== * @@ -195,6 +210,79 @@ */ /*============================================================================== + * The Global Switch + * + * The state of the switch is: unset -- implicitly not enabled + * set_frozen -- implicitly not enabled & frozen + * set_disabled -- explicitly not enabled + * set_enabled -- explicitly set enabled + * + * "set_frozen" means that "qpthreads_freeze_enabled_state()" has been called, + * and the state was unset at the time. This means that some initialisation + * has been done on the basis of !qpthreads_enabled, and it is TOO LATE to + * enable qpthreads afterwards. + */ + +enum qpthreads_enabled_state +{ + qpt_state_unset = 0, + qpt_state_set_frozen = 1, + qpt_state_set_disabled = 2, + qpt_state_set_enabled = 3, +} ; + +static enum qpthreads_enabled_state qpthreads_enabled_state = qpt_state_unset ; + +int qpthreads_enabled_flag = 0 ; + +/* Function to set qpthreads_enabled, one way or the other. + * + * NB: can repeatedly set to the same state, but not change state once set. + */ +void +qpt_set_qpthreads_enabled(int how) +{ + + switch (qpthreads_enabled_state) + { + case qpt_state_unset: + break ; + case qpt_state_set_frozen: + if (how != 0) + zabort("Too late to enable qpthreads") ; + break ; + case qpt_state_set_disabled: + if (how != 0) + zabort("qpthreads_enabled is already set: cannot set enabled") ; + break ; + case qpt_state_set_enabled: + if (how == 0) + zabort("qpthreads_enabled is already set: cannot set disabled") ; + break ; + default: + break ; + } + + qpthreads_enabled_flag = (how != 0) ; + qpthreads_enabled_state = (how != 0) ? qpt_state_set_enabled + : qpt_state_set_disabled ; +} ; + +/* Get state of qpthreads_enabled, and freeze if not yet explictly set. + * + * Where some initialisation depends on the state of qpthreads_enabled(), this + * returns the state and freezes it if it is implicitly not enabled. + */ +extern int +qpt_freeze_qpthreads_enabled(void) +{ + if (qpthreads_enabled_state == qpt_state_unset) + qpthreads_enabled_state = qpt_state_set_frozen ; + + return qpthreads_enabled_flag ; +} ; + +/*============================================================================== * Thread creation and attributes. * * Threads may be created with a given set of attributes if required. @@ -234,15 +322,18 @@ * The scope, policy and priority arguments are use only if the corresponding * option is specified. * + * NB: FATAL error to attempt this is !qptthreads_enabled. + * * Returns the address of the qpt_thread_attr_t structure. */ qpt_thread_attr_t* qpt_thread_attr_init(qpt_thread_attr_t* attr, enum qpt_attr_options opts, - int scope, int policy, int priority) + int scope, int policy, int priority) { int err ; assert((opts & ~qpt_attr_known) == 0) ; + passert(qpthreads_enabled) ; /* Initialise thread attributes structure (allocating if required.) */ if (attr == NULL) @@ -309,6 +400,8 @@ qpt_thread_attr_init(qpt_thread_attr_t* attr, enum qpt_attr_options opts, * If no attributes are given (attr == NULL) the thread is created with system * default attributes -- *except* that it is created joinable. * + * NB: FATAL error to attempt this is !qptthreads_enabled. + * * Returns the qpt_thread_t "thread id". */ qpt_thread_t @@ -319,6 +412,8 @@ qpt_thread_create(void* (*start)(void*), void* arg, qpt_thread_attr_t* attr) int default_attr ; int err ; + passert(qpthreads_enabled) ; + default_attr = (attr == NULL) ; if (default_attr) attr = qpt_thread_attr_init(&thread_attr, qpt_attr_joinable, 0, 0, 0) ; @@ -341,7 +436,10 @@ qpt_thread_create(void* (*start)(void*), void* arg, qpt_thread_attr_t* attr) * Mutex initialise and destroy. */ -/* Initialise Mutex (allocating if required). +/* Initialise Mutex (allocating if required) + * + * Does nothing if !qpthreads_enabled -- but freezes the state (attempting to + * later enable qpthreads will be a FATAL error). * * Options: * @@ -353,14 +451,19 @@ qpt_thread_create(void* (*start)(void*), void* arg, qpt_thread_attr_t* attr) * * Of these _recursive is the most likely alternative to _quagga... BUT do * remember that such mutexes DO NOT play well with condition variables. + * + * Returns the mutex -- or original mx if !qpthreads_enabled. */ -qpt_mutex_t* -qpt_mutex_init(qpt_mutex_t* mx, enum qpt_mutex_options opts) +qpt_mutex +qpt_mutex_init_new(qpt_mutex mx, enum qpt_mutex_options opts) { pthread_mutexattr_t mutex_attr ; int type ; int err ; + if (!qpthreads_enabled_freeze) + return mx ; + if (mx == NULL) mx = XMALLOC(MTYPE_QPT_MUTEX, sizeof(qpt_mutex_t)) ; @@ -390,11 +493,9 @@ qpt_mutex_init(qpt_mutex_t* mx, enum qpt_mutex_options opts) zabort("Invalid qpt_mutex option") ; } ; -#ifndef PTHREAD_MUTEXATTR_SETTYPE_MISSING err = pthread_mutexattr_settype(&mutex_attr, type); if (err != 0) zabort_err("pthread_mutexattr_settype failed", err) ; -#endif /* Now we're ready to initialize the mutex itself */ err = pthread_mutex_init(mx, &mutex_attr) ; @@ -411,22 +512,30 @@ qpt_mutex_init(qpt_mutex_t* mx, enum qpt_mutex_options opts) } ; /* Destroy given mutex, and (if required) free it. + * -- or do nothing if !qpthreads_enabled. * - * Returns NULL. -*/ -qpt_mutex_t* -qpt_mutex_destroy(qpt_mutex_t* mx, int free_mutex) + * Returns NULL if freed the mutex, otherwise the address of same. + * + * NB: if !qpthreads_enabled qpt_mutex_init_new() will not have allocated + * anything, so there can be nothing to release -- so does nothing, but + * returns the original mutex address (if any). + */ +qpt_mutex +qpt_mutex_destroy(qpt_mutex mx, int free_mutex) { int err ; - err = pthread_mutex_destroy(mx) ; - if (err != 0) - zabort_err("pthread_mutex_destroy failed", err) ; + if (qpthreads_enabled) + { + err = pthread_mutex_destroy(mx) ; + if (err != 0) + zabort_err("pthread_mutex_destroy failed", err) ; - if (free_mutex) - XFREE(MTYPE_QPT_MUTEX, mx) ; + if (free_mutex) + XFREE(MTYPE_QPT_MUTEX, mx) ; /* sets mx == NULL */ + } ; - return NULL ; + return mx ; } ; /*============================================================================== @@ -435,18 +544,28 @@ qpt_mutex_destroy(qpt_mutex_t* mx, int free_mutex) /* Initialise Condition Variable (allocating if required). * + * Does nothing if !qpthreads_enabled -- but freezes the state (attempting to + * later enable qpthreads will be a FATAL error). + * * Options: * * qpt_cond_quagga -- use Quagga's default clock * qpt_cond_realtime -- force CLOCK_REALTIME * qpt_cond_monotonic -- force CLOCK_MONOTONIC (if available) + * + * NB: FATAL error to attempt this is !qptthreads_enabled. + * + * Returns the condition variable -- or original cv id !qpthreads_enabled. */ -qpt_cond_t* -qpt_cond_init(qpt_cond_t* cv, enum qpt_cond_options opts) +qpt_cond +qpt_cond_init_new(qpt_cond cv, enum qpt_cond_options opts) { pthread_condattr_t cond_attr ; int err ; + if (!qpthreads_enabled_freeze) + return cv ; + if (cv == NULL) cv = XMALLOC(MTYPE_QPT_COND, sizeof(qpt_cond_t)) ; @@ -481,26 +600,35 @@ qpt_cond_init(qpt_cond_t* cv, enum qpt_cond_options opts) return cv ; } ; -/* Destroy given mutex, and (if required) free it. +/* Destroy given condition variable, and (if required) free it + * -- or do nothing if !qpthreads_enabled. * - * Returns NULL. -*/ -qpt_cond_t* -qpt_cond_destroy(qpt_cond_t* cv, int free_cond) + * NB: if !qpthreads_enabled qpt_cond_init_new() will not have allocated + * anything, so there can be nothing to release -- so does nothing, but + * returns the original condition variable address (if any). + * + * Returns NULL if freed the condition variable, otherwise the address of same. + */ +qpt_cond +qpt_cond_destroy(qpt_cond cv, int free_cond) { int err ; - err = pthread_cond_destroy(cv) ; - if (err != 0) - zabort_err("pthread_cond_destroy failed", err) ; + if (qpthreads_enabled) + { + err = pthread_cond_destroy(cv) ; + if (err != 0) + zabort_err("pthread_cond_destroy failed", err) ; - if (free_cond) - XFREE(MTYPE_QPT_COND, cv) ; + if (free_cond) + XFREE(MTYPE_QPT_COND, cv) ; /* sets cv == NULL */ + } ; - return NULL ; + return cv ; } ; -/* Wait for given condition variable or time-out. +/* Wait for given condition variable or time-out + * -- or return immediate success if !qpthreads_enabled. * * Returns: wait succeeded (1 => success, 0 => timed-out). * @@ -510,41 +638,54 @@ qpt_cond_destroy(qpt_cond_t* cv, int free_cond) */ int -qpt_cond_timedwait(qpt_cond_t* cv, qpt_mutex_t* mx, qtime_mono_t timeout_time) +qpt_cond_timedwait(qpt_cond cv, qpt_mutex mx, qtime_mono_t timeout_time) { struct timespec ts ; + int err ; - if (QPT_COND_CLOCK_ID != CLOCK_MONOTONIC) + if (qpthreads_enabled) { - timeout_time = qt_clock_gettime(QPT_COND_CLOCK_ID) + if (QPT_COND_CLOCK_ID != CLOCK_MONOTONIC) + { + timeout_time = qt_clock_gettime(QPT_COND_CLOCK_ID) + (timeout_time - qt_get_monotonic()) ; - } ; + } ; - int err = pthread_cond_timedwait(cv, mx, qtime2timespec(&ts, timeout_time)) ; - if (err == 0) - return 1 ; /* got condition */ - if (err == ETIMEDOUT) - return 0 ; /* got time-out */ + err = pthread_cond_timedwait(cv, mx, qtime2timespec(&ts, timeout_time)) ; + if (err == 0) + return 1 ; /* got condition */ + if (err == ETIMEDOUT) + return 0 ; /* got time-out */ - zabort_err("pthread_cond_timedwait failed", err) ; - /* crunch */ + zabort_err("pthread_cond_timedwait failed", err) ; + } + else + return 0 ; } ; /*============================================================================== * Signal Handling. */ -/* Set thread signal mask +/* Set thread signal mask -- requires qpthreads_enabled. * * Thin wrapper around pthread_sigmask. * * zaborts if gets any error. + * + * NB: it is a FATAL error to do this if !qpthreads_enabled. + * + * This is mostly because wish to avoid all pthreads_xxx calls when not + * using pthreads. There is no reason not to use this in a single threaded + * program. */ void qpt_thread_sigmask(int how, const sigset_t* set, sigset_t* oset) { int err ; + passert(qpthreads_enabled) ; + if (oset != NULL) sigemptyset(oset) ; /* to make absolutely sure */ @@ -553,7 +694,7 @@ qpt_thread_sigmask(int how, const sigset_t* set, sigset_t* oset) zabort_err("pthread_sigmask failed", err) ; } ; -/* Send given thread the given signal +/* Send given thread the given signal -- requires qpthreads_enabled (!) * * Thin wrapper around pthread_kill. * @@ -564,6 +705,8 @@ qpt_thread_signal(qpt_thread_t thread, int signum) { int err ; + passert(qpthreads_enabled) ; + err = pthread_kill(thread, signum) ; if (err != 0) zabort_err("pthread_kill failed", err) ; diff --git a/lib/qpthreads.h b/lib/qpthreads.h index 5a442cc7..49a7c1e3 100644 --- a/lib/qpthreads.h +++ b/lib/qpthreads.h @@ -35,6 +35,10 @@ #define Inline static inline #endif +#ifndef private +#define private extern +#endif + /*============================================================================== * Quagga Pthread Interface -- qpt_xxxx * @@ -57,6 +61,22 @@ #endif /*============================================================================== + * Global Switch -- this allows the library to be run WITHOUT pthreads ! + * + * Nearly every qpthreads function is a NOP if !qpthreads_enabled. + * + * Early in the morning a decision may be made to enable qpthreads -- that must + * be done before any threads are created (or will zabort) and before any + * mutexes and condition variables are initialised. + * + * Use: qpthreads_enabled -- to test for the enabled-ness + * qpthreads_enabled_freeze -- to test and freeze unset if not yet enabled + */ + +#define qpthreads_enabled ((const int)qpthreads_enabled_flag) +#define qpthreads_enabled_freeze qpt_freeze_qpthreads_enabled() + +/*============================================================================== * Data types */ @@ -66,8 +86,13 @@ typedef pthread_cond_t qpt_cond_t ; typedef pthread_attr_t qpt_thread_attr_t ; +typedef qpt_mutex_t* qpt_mutex ; +typedef qpt_cond_t* qpt_cond ; + /*============================================================================== * Thread Creation -- see qpthreads.c for further discussion. + * + * NB: it is a FATAL error to attempt these if !qpthreads_enabled. */ enum qpt_attr_options @@ -92,19 +117,30 @@ enum qpt_attr_options #define qpt_attr_known ( qpt_attr_detached | qpt_attr_sched_setting ) -extern qpt_thread_attr_t* +extern qpt_thread_attr_t* /* FATAL error if !qpthreads_enabled */ qpt_thread_attr_init(qpt_thread_attr_t* attr, enum qpt_attr_options opts, int scope, int policy, int priority) ; -extern qpt_thread_t +extern qpt_thread_t /* FATAL error if !qpthreads_enabled */ qpt_thread_create(void* (*start)(void*), void* arg, qpt_thread_attr_t* attr) ; /*============================================================================== - * Thread self knowledge. + * qpthreads_enabled support -- NOT FOR PUBLIC CONSUMPTION ! + */ +private int qpthreads_enabled_flag ; /* DO NOT WRITE TO THIS PLEASE */ + +private void +qpt_set_qpthreads_enabled(int how) ; /* qpthreads_enabled := how */ + +private int +qpt_freeze_qpthreads_enabled(void) ; /* get and freeze qpthreads_enabled */ + +/*============================================================================== + * Thread self knowledge -- returns 'NULL' if !qpthreads_enabled */ Inline qpt_thread_t qpt_thread_self(void) { - return pthread_self() ; + return qpthreads_enabled ? pthread_self() : (qpt_thread_t)NULL; } ; /*============================================================================== @@ -127,6 +163,10 @@ Inline qpt_thread_t qpt_thread_self(void) * If _DEFAULT is faster than _NORMAL, then QPT_MUTEX_TYPE_DEFAULT may be * used to override this choice. * + * NB: if NOT qpthreads_enabled, all mutex actions are EMPTY. This allows + * code to be made thread-safe for when pthreads is running, but to work + * perfectly well without pthreads. + * * NB: do not (currently) support pthread_mutex_timedlock(). */ @@ -149,23 +189,25 @@ enum qpt_mutex_options # define QPT_MUTEX_TYPE PTHREAD_MUTEX_ERRORCHECK #endif -extern qpt_mutex_t* -qpt_mutex_init(qpt_mutex_t* mx, enum qpt_mutex_options opts) ; +extern qpt_mutex /* freezes qpthreads_enabled */ +qpt_mutex_init_new(qpt_mutex mx, enum qpt_mutex_options opts) ; -extern qpt_mutex_t* -qpt_mutex_destroy(qpt_mutex_t* mx, int free_mutex) ; +#define qpt_mutex_init qpt_mutex_init_new + +extern qpt_mutex /* do nothing if !qpthreads_enabled */ +qpt_mutex_destroy(qpt_mutex mx, int free_mutex) ; #define qpt_mutex_destroy_keep(mx) qpt_mutex_destroy(mx, 0) #define qpt_mutex_destroy_free(mx) qpt_mutex_destroy(mx, 1) Inline void -qpt_mutex_lock(qpt_mutex_t* mx) ; /* do nothing if mx == NULL */ +qpt_mutex_lock(qpt_mutex mx) ; /* do nothing if !qpthreads_enabled */ Inline int -qpt_mutex_trylock(qpt_mutex_t* mx) ; /* do nothing if mx == NULL */ +qpt_mutex_trylock(qpt_mutex mx) ; /* always succeeds if !qpthreads_enabled */ Inline void -qpt_mutex_unlock(qpt_mutex_t* mx) ; /* do nothing if mx == NULL */ +qpt_mutex_unlock(qpt_mutex mx) ; /* do nothing if !qpthreads_enabled */ /*============================================================================== * Condition Variable handling @@ -188,6 +230,10 @@ qpt_mutex_unlock(qpt_mutex_t* mx) ; /* do nothing if mx == NULL */ * * NB: static initialisation of condition variables is not supported, to avoid * confusion between the standard default and Quagga's default. + + * NB: if NOT qpthreads_enabled, all condition actions are EMPTY. This allows + * code to be made thread-safe for when pthreads is running, but to work + * perfectly well without pthreads. */ #ifndef QPT_COND_CLOCK_ID @@ -205,41 +251,41 @@ enum qpt_cond_options qpt_cond_quagga = 0x0000, /* Quagga's default */ } ; -extern qpt_cond_t* -qpt_cond_init(qpt_cond_t* cv, enum qpt_cond_options opts) ; +extern qpt_cond /* freezes qpthreads_enabled */ +qpt_cond_init_new(qpt_cond cv, enum qpt_cond_options opts) ; -extern qpt_cond_t* -qpt_cond_destroy(qpt_cond_t* cv, int free_cond) ; +extern qpt_cond /* do nothing if !qpthreads_enabled */ +qpt_cond_destroy(qpt_cond cv, int free_cond) ; #define qpt_cond_destroy_keep(cv) qpt_cond_destroy(cv, 0) #define qpt_cond_destroy_free(cv) qpt_cond_destroy(cv, 1) -Inline void -qpt_cond_wait(qpt_cond_t* cv, qpt_mutex_t* mx) ; +Inline void /* do nothing if !qpthreads_enabled */ +qpt_cond_wait(qpt_cond cv, qpt_mutex mx) ; -extern int -qpt_cond_timedwait(qpt_cond_t* cv, qpt_mutex_t* mx, qtime_mono_t timeout_time) ; +extern int /* returns !qpthreads_enabled */ +qpt_cond_timedwait(qpt_cond cv, qpt_mutex mx, qtime_mono_t timeout_time) ; -Inline void -qpt_cond_signal(qpt_cond_t* cv) ; +Inline void /* do nothing if !qpthreads_enabled */ +qpt_cond_signal(qpt_cond cv) ; -Inline void -qpt_cond_broadcast(qpt_cond_t* cv) ; +Inline void /* do nothing if !qpthreads_enabled */ +qpt_cond_broadcast(qpt_cond cv) ; /*============================================================================== * Mutex inline functions */ -/* Lock given mutex. +/* Lock given mutex -- or do nothing if !qpthreads_enabled. * * Unless both NCHECK_QPTHREADS and NDEBUG are defined, checks that the * return value is valid -- zabort_errno if it isn't. */ Inline void -qpt_mutex_lock(qpt_mutex_t* mx) /* do nothing if mx == NULL */ +qpt_mutex_lock(qpt_mutex mx) { - if (mx != NULL) + if (qpthreads_enabled) { #if defined(NDEBUG) && defined(NDEBUG_QPTHREADS) pthread_mutex_lock(mx) ; @@ -251,7 +297,7 @@ qpt_mutex_lock(qpt_mutex_t* mx) /* do nothing if mx == NULL */ } ; } ; -/* Try to lock given mutex. +/* Try to lock given mutex -- every time a winner if !qpthreads_enabled. * * Returns: lock succeeded (1 => have locked, 0 => unable to lock). * @@ -259,9 +305,9 @@ qpt_mutex_lock(qpt_mutex_t* mx) /* do nothing if mx == NULL */ */ Inline int -qpt_mutex_trylock(qpt_mutex_t* mx) /* do nothing if mx == NULL */ +qpt_mutex_trylock(qpt_mutex mx) { - if (mx != NULL) + if (qpthreads_enabled) { int err = pthread_mutex_trylock(mx) ; if (err == 0) @@ -270,19 +316,20 @@ qpt_mutex_trylock(qpt_mutex_t* mx) /* do nothing if mx == NULL */ return 0 ; /* unable to lock */ zabort_err("pthread_mutex_trylock failed", err) ; - /* crunch */ - } ; + } + else + return 1 ; } ; -/* Unlock given mutex. +/* Unlock given mutex -- or do nothing if !qpthreads_enabled. * * Unless both NCHECK_QPTHREADS and NDEBUG are defined, checks that the * return value is valid -- zabort_errno if it isn't. */ Inline void -qpt_mutex_unlock(qpt_mutex_t* mx) /* do nothing if mx == NULL */ +qpt_mutex_unlock(qpt_mutex mx) { - if (mx != NULL) + if (qpthreads_enabled) { #if defined(NDEBUG) && defined(NDEBUG_QPTHREADS) pthread_mutex_unlock(mx) ; @@ -298,66 +345,73 @@ qpt_mutex_unlock(qpt_mutex_t* mx) /* do nothing if mx == NULL */ * Condition variable inline functions */ -/* Wait for given condition variable. +/* Wait for given condition variable -- do nothing if !qpthreads_enabled * * Unless both NCHECK_QPTHREADS and NDEBUG are defined, checks that the * return value is valid -- zabort_errno if it isn't. */ - Inline void -qpt_cond_wait(qpt_cond_t* cv, qpt_mutex_t* mx) +qpt_cond_wait(qpt_cond cv, qpt_mutex mx) { + if (qpthreads_enabled) + { #if defined(NDEBUG) && defined(NDEBUG_QPTHREADS) - pthread_cond_wait(cv, mx) ; + pthread_cond_wait(cv, mx) ; #else - int err = pthread_cond_wait(cv, mx) ; - if (err != 0) - zabort_err("pthread_cond_wait failed", err) ; + int err = pthread_cond_wait(cv, mx) ; + if (err != 0) + zabort_err("pthread_cond_wait failed", err) ; #endif + } ; } ; -/* Signal given condition. +/* Signal given condition -- do nothing if !qpthreads_enabled * * Unless both NCHECK_QPTHREADS and NDEBUG are defined, checks that the * return value is valid -- zabort_errno if it isn't. */ - Inline void -qpt_cond_signal(qpt_cond_t* cv) +qpt_cond_signal(qpt_cond cv) { + if (qpthreads_enabled) + { #if defined(NDEBUG) && defined(NDEBUG_QPTHREADS) - pthread_cond_signal(cv) ; + pthread_cond_signal(cv) ; #else - int err = pthread_cond_signal(cv) ; - if (err != 0) - zabort_err("pthread_cond_signal failed", err) ; + int err = pthread_cond_signal(cv) ; + if (err != 0) + zabort_err("pthread_cond_signal failed", err) ; #endif + } ; } ; -/* Broadcast given condition. +/* Broadcast given condition -- do nothing if !qpthreads_enabled * * Unless both NCHECK_QPTHREADS and NDEBUG are defined, checks that the * return value is valid -- zabort_errno if it isn't. */ Inline void -qpt_cond_broadcast(qpt_cond_t* cv) +qpt_cond_broadcast(qpt_cond cv) { + if (qpthreads_enabled) + { #if defined(NDEBUG) && defined(NDEBUG_QPTHREADS) - pthread_cond_broadcast(cv) ; + pthread_cond_broadcast(cv) ; #else - int err = pthread_cond_broadcast(cv) ; - if (err != 0) - zabort_err("pthread_cond_broadcast failed", err) ; + int err = pthread_cond_broadcast(cv) ; + if (err != 0) + zabort_err("pthread_cond_broadcast failed", err) ; #endif + } ; } ; /*============================================================================== * Signal Handling. */ -void +void /* FATAL error if !qpthreads_enabled */ qpt_thread_sigmask(int how, const sigset_t* set, sigset_t* oset) ; -void +void /* FATAL error if !qpthreads_enabled */ qpt_thread_signal(qpt_thread_t thread, int signum) ; #endif /* _ZEBRA_QPTHREADS_H */ |