summaryrefslogtreecommitdiffstats
path: root/lib/qpthreads.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/qpthreads.h')
-rw-r--r--lib/qpthreads.h166
1 files changed, 110 insertions, 56 deletions
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 */