summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Hall (GMCH) <chris.hall@highwayman.com>2009-12-10 21:20:03 +0000
committerChris Hall (GMCH) <chris.hall@highwayman.com>2009-12-10 21:20:03 +0000
commit977e8eceb3fdc2e3d5cf72677cbaf8528b3ba865 (patch)
tree6bfc6202c1bc3be4074c3620a8494c82a569555c
parent553285d84f469027a0fbe38cfcfe773cff927553 (diff)
downloadquagga-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.c229
-rw-r--r--lib/qpthreads.h166
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 */