1*2b15cb3dSCy Schubert /* 2*2b15cb3dSCy Schubert * Copyright (c) 2008-2012 Niels Provos, Nick Mathewson 3*2b15cb3dSCy Schubert * 4*2b15cb3dSCy Schubert * Redistribution and use in source and binary forms, with or without 5*2b15cb3dSCy Schubert * modification, are permitted provided that the following conditions 6*2b15cb3dSCy Schubert * are met: 7*2b15cb3dSCy Schubert * 1. Redistributions of source code must retain the above copyright 8*2b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer. 9*2b15cb3dSCy Schubert * 2. Redistributions in binary form must reproduce the above copyright 10*2b15cb3dSCy Schubert * notice, this list of conditions and the following disclaimer in the 11*2b15cb3dSCy Schubert * documentation and/or other materials provided with the distribution. 12*2b15cb3dSCy Schubert * 3. The name of the author may not be used to endorse or promote products 13*2b15cb3dSCy Schubert * derived from this software without specific prior written permission. 14*2b15cb3dSCy Schubert * 15*2b15cb3dSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16*2b15cb3dSCy Schubert * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17*2b15cb3dSCy Schubert * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18*2b15cb3dSCy Schubert * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19*2b15cb3dSCy Schubert * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20*2b15cb3dSCy Schubert * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21*2b15cb3dSCy Schubert * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22*2b15cb3dSCy Schubert * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23*2b15cb3dSCy Schubert * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24*2b15cb3dSCy Schubert * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*2b15cb3dSCy Schubert */ 26*2b15cb3dSCy Schubert #ifndef EVTHREAD_INTERNAL_H_INCLUDED_ 27*2b15cb3dSCy Schubert #define EVTHREAD_INTERNAL_H_INCLUDED_ 28*2b15cb3dSCy Schubert 29*2b15cb3dSCy Schubert #ifdef __cplusplus 30*2b15cb3dSCy Schubert extern "C" { 31*2b15cb3dSCy Schubert #endif 32*2b15cb3dSCy Schubert 33*2b15cb3dSCy Schubert #include "event2/event-config.h" 34*2b15cb3dSCy Schubert #include "evconfig-private.h" 35*2b15cb3dSCy Schubert 36*2b15cb3dSCy Schubert #include "event2/thread.h" 37*2b15cb3dSCy Schubert #include "util-internal.h" 38*2b15cb3dSCy Schubert 39*2b15cb3dSCy Schubert struct event_base; 40*2b15cb3dSCy Schubert 41*2b15cb3dSCy Schubert #ifndef _WIN32 42*2b15cb3dSCy Schubert /* On Windows, the way we currently make DLLs, it's not allowed for us to 43*2b15cb3dSCy Schubert * have shared global structures. Thus, we only do the direct-call-to-function 44*2b15cb3dSCy Schubert * code path if we know that the local shared library system supports it. 45*2b15cb3dSCy Schubert */ 46*2b15cb3dSCy Schubert #define EVTHREAD_EXPOSE_STRUCTS 47*2b15cb3dSCy Schubert #endif 48*2b15cb3dSCy Schubert 49*2b15cb3dSCy Schubert #if ! defined(EVENT__DISABLE_THREAD_SUPPORT) && defined(EVTHREAD_EXPOSE_STRUCTS) 50*2b15cb3dSCy Schubert /* Global function pointers to lock-related functions. NULL if locking isn't 51*2b15cb3dSCy Schubert enabled. */ 52*2b15cb3dSCy Schubert extern struct evthread_lock_callbacks evthread_lock_fns_; 53*2b15cb3dSCy Schubert extern struct evthread_condition_callbacks evthread_cond_fns_; 54*2b15cb3dSCy Schubert extern unsigned long (*evthread_id_fn_)(void); 55*2b15cb3dSCy Schubert extern int evthread_lock_debugging_enabled_; 56*2b15cb3dSCy Schubert 57*2b15cb3dSCy Schubert /** Return the ID of the current thread, or 1 if threading isn't enabled. */ 58*2b15cb3dSCy Schubert #define EVTHREAD_GET_ID() \ 59*2b15cb3dSCy Schubert (evthread_id_fn_ ? evthread_id_fn_() : 1) 60*2b15cb3dSCy Schubert 61*2b15cb3dSCy Schubert /** Return true iff we're in the thread that is currently (or most recently) 62*2b15cb3dSCy Schubert * running a given event_base's loop. Requires lock. */ 63*2b15cb3dSCy Schubert #define EVBASE_IN_THREAD(base) \ 64*2b15cb3dSCy Schubert (evthread_id_fn_ == NULL || \ 65*2b15cb3dSCy Schubert (base)->th_owner_id == evthread_id_fn_()) 66*2b15cb3dSCy Schubert 67*2b15cb3dSCy Schubert /** Return true iff we need to notify the base's main thread about changes to 68*2b15cb3dSCy Schubert * its state, because it's currently running the main loop in another 69*2b15cb3dSCy Schubert * thread. Requires lock. */ 70*2b15cb3dSCy Schubert #define EVBASE_NEED_NOTIFY(base) \ 71*2b15cb3dSCy Schubert (evthread_id_fn_ != NULL && \ 72*2b15cb3dSCy Schubert (base)->running_loop && \ 73*2b15cb3dSCy Schubert (base)->th_owner_id != evthread_id_fn_()) 74*2b15cb3dSCy Schubert 75*2b15cb3dSCy Schubert /** Allocate a new lock, and store it in lockvar, a void*. Sets lockvar to 76*2b15cb3dSCy Schubert NULL if locking is not enabled. */ 77*2b15cb3dSCy Schubert #define EVTHREAD_ALLOC_LOCK(lockvar, locktype) \ 78*2b15cb3dSCy Schubert ((lockvar) = evthread_lock_fns_.alloc ? \ 79*2b15cb3dSCy Schubert evthread_lock_fns_.alloc(locktype) : NULL) 80*2b15cb3dSCy Schubert 81*2b15cb3dSCy Schubert /** Free a given lock, if it is present and locking is enabled. */ 82*2b15cb3dSCy Schubert #define EVTHREAD_FREE_LOCK(lockvar, locktype) \ 83*2b15cb3dSCy Schubert do { \ 84*2b15cb3dSCy Schubert void *lock_tmp_ = (lockvar); \ 85*2b15cb3dSCy Schubert if (lock_tmp_ && evthread_lock_fns_.free) \ 86*2b15cb3dSCy Schubert evthread_lock_fns_.free(lock_tmp_, (locktype)); \ 87*2b15cb3dSCy Schubert } while (0) 88*2b15cb3dSCy Schubert 89*2b15cb3dSCy Schubert /** Acquire a lock. */ 90*2b15cb3dSCy Schubert #define EVLOCK_LOCK(lockvar,mode) \ 91*2b15cb3dSCy Schubert do { \ 92*2b15cb3dSCy Schubert if (lockvar) \ 93*2b15cb3dSCy Schubert evthread_lock_fns_.lock(mode, lockvar); \ 94*2b15cb3dSCy Schubert } while (0) 95*2b15cb3dSCy Schubert 96*2b15cb3dSCy Schubert /** Release a lock */ 97*2b15cb3dSCy Schubert #define EVLOCK_UNLOCK(lockvar,mode) \ 98*2b15cb3dSCy Schubert do { \ 99*2b15cb3dSCy Schubert if (lockvar) \ 100*2b15cb3dSCy Schubert evthread_lock_fns_.unlock(mode, lockvar); \ 101*2b15cb3dSCy Schubert } while (0) 102*2b15cb3dSCy Schubert 103*2b15cb3dSCy Schubert /** Helper: put lockvar1 and lockvar2 into pointerwise ascending order. */ 104*2b15cb3dSCy Schubert #define EVLOCK_SORTLOCKS_(lockvar1, lockvar2) \ 105*2b15cb3dSCy Schubert do { \ 106*2b15cb3dSCy Schubert if (lockvar1 && lockvar2 && lockvar1 > lockvar2) { \ 107*2b15cb3dSCy Schubert void *tmp = lockvar1; \ 108*2b15cb3dSCy Schubert lockvar1 = lockvar2; \ 109*2b15cb3dSCy Schubert lockvar2 = tmp; \ 110*2b15cb3dSCy Schubert } \ 111*2b15cb3dSCy Schubert } while (0) 112*2b15cb3dSCy Schubert 113*2b15cb3dSCy Schubert /** Lock an event_base, if it is set up for locking. Acquires the lock 114*2b15cb3dSCy Schubert in the base structure whose field is named 'lockvar'. */ 115*2b15cb3dSCy Schubert #define EVBASE_ACQUIRE_LOCK(base, lockvar) do { \ 116*2b15cb3dSCy Schubert EVLOCK_LOCK((base)->lockvar, 0); \ 117*2b15cb3dSCy Schubert } while (0) 118*2b15cb3dSCy Schubert 119*2b15cb3dSCy Schubert /** Unlock an event_base, if it is set up for locking. */ 120*2b15cb3dSCy Schubert #define EVBASE_RELEASE_LOCK(base, lockvar) do { \ 121*2b15cb3dSCy Schubert EVLOCK_UNLOCK((base)->lockvar, 0); \ 122*2b15cb3dSCy Schubert } while (0) 123*2b15cb3dSCy Schubert 124*2b15cb3dSCy Schubert /** If lock debugging is enabled, and lock is non-null, assert that 'lock' is 125*2b15cb3dSCy Schubert * locked and held by us. */ 126*2b15cb3dSCy Schubert #define EVLOCK_ASSERT_LOCKED(lock) \ 127*2b15cb3dSCy Schubert do { \ 128*2b15cb3dSCy Schubert if ((lock) && evthread_lock_debugging_enabled_) { \ 129*2b15cb3dSCy Schubert EVUTIL_ASSERT(evthread_is_debug_lock_held_(lock)); \ 130*2b15cb3dSCy Schubert } \ 131*2b15cb3dSCy Schubert } while (0) 132*2b15cb3dSCy Schubert 133*2b15cb3dSCy Schubert /** Try to grab the lock for 'lockvar' without blocking, and return 1 if we 134*2b15cb3dSCy Schubert * manage to get it. */ 135*2b15cb3dSCy Schubert static inline int EVLOCK_TRY_LOCK_(void *lock); 136*2b15cb3dSCy Schubert static inline int 137*2b15cb3dSCy Schubert EVLOCK_TRY_LOCK_(void *lock) 138*2b15cb3dSCy Schubert { 139*2b15cb3dSCy Schubert if (lock && evthread_lock_fns_.lock) { 140*2b15cb3dSCy Schubert int r = evthread_lock_fns_.lock(EVTHREAD_TRY, lock); 141*2b15cb3dSCy Schubert return !r; 142*2b15cb3dSCy Schubert } else { 143*2b15cb3dSCy Schubert /* Locking is disabled either globally or for this thing; 144*2b15cb3dSCy Schubert * of course we count as having the lock. */ 145*2b15cb3dSCy Schubert return 1; 146*2b15cb3dSCy Schubert } 147*2b15cb3dSCy Schubert } 148*2b15cb3dSCy Schubert 149*2b15cb3dSCy Schubert /** Allocate a new condition variable and store it in the void *, condvar */ 150*2b15cb3dSCy Schubert #define EVTHREAD_ALLOC_COND(condvar) \ 151*2b15cb3dSCy Schubert do { \ 152*2b15cb3dSCy Schubert (condvar) = evthread_cond_fns_.alloc_condition ? \ 153*2b15cb3dSCy Schubert evthread_cond_fns_.alloc_condition(0) : NULL; \ 154*2b15cb3dSCy Schubert } while (0) 155*2b15cb3dSCy Schubert /** Deallocate and free a condition variable in condvar */ 156*2b15cb3dSCy Schubert #define EVTHREAD_FREE_COND(cond) \ 157*2b15cb3dSCy Schubert do { \ 158*2b15cb3dSCy Schubert if (cond) \ 159*2b15cb3dSCy Schubert evthread_cond_fns_.free_condition((cond)); \ 160*2b15cb3dSCy Schubert } while (0) 161*2b15cb3dSCy Schubert /** Signal one thread waiting on cond */ 162*2b15cb3dSCy Schubert #define EVTHREAD_COND_SIGNAL(cond) \ 163*2b15cb3dSCy Schubert ( (cond) ? evthread_cond_fns_.signal_condition((cond), 0) : 0 ) 164*2b15cb3dSCy Schubert /** Signal all threads waiting on cond */ 165*2b15cb3dSCy Schubert #define EVTHREAD_COND_BROADCAST(cond) \ 166*2b15cb3dSCy Schubert ( (cond) ? evthread_cond_fns_.signal_condition((cond), 1) : 0 ) 167*2b15cb3dSCy Schubert /** Wait until the condition 'cond' is signalled. Must be called while 168*2b15cb3dSCy Schubert * holding 'lock'. The lock will be released until the condition is 169*2b15cb3dSCy Schubert * signalled, at which point it will be acquired again. Returns 0 for 170*2b15cb3dSCy Schubert * success, -1 for failure. */ 171*2b15cb3dSCy Schubert #define EVTHREAD_COND_WAIT(cond, lock) \ 172*2b15cb3dSCy Schubert ( (cond) ? evthread_cond_fns_.wait_condition((cond), (lock), NULL) : 0 ) 173*2b15cb3dSCy Schubert /** As EVTHREAD_COND_WAIT, but gives up after 'tv' has elapsed. Returns 1 174*2b15cb3dSCy Schubert * on timeout. */ 175*2b15cb3dSCy Schubert #define EVTHREAD_COND_WAIT_TIMED(cond, lock, tv) \ 176*2b15cb3dSCy Schubert ( (cond) ? evthread_cond_fns_.wait_condition((cond), (lock), (tv)) : 0 ) 177*2b15cb3dSCy Schubert 178*2b15cb3dSCy Schubert /** True iff locking functions have been configured. */ 179*2b15cb3dSCy Schubert #define EVTHREAD_LOCKING_ENABLED() \ 180*2b15cb3dSCy Schubert (evthread_lock_fns_.lock != NULL) 181*2b15cb3dSCy Schubert 182*2b15cb3dSCy Schubert #elif ! defined(EVENT__DISABLE_THREAD_SUPPORT) 183*2b15cb3dSCy Schubert 184*2b15cb3dSCy Schubert unsigned long evthreadimpl_get_id_(void); 185*2b15cb3dSCy Schubert int evthreadimpl_is_lock_debugging_enabled_(void); 186*2b15cb3dSCy Schubert void *evthreadimpl_lock_alloc_(unsigned locktype); 187*2b15cb3dSCy Schubert void evthreadimpl_lock_free_(void *lock, unsigned locktype); 188*2b15cb3dSCy Schubert int evthreadimpl_lock_lock_(unsigned mode, void *lock); 189*2b15cb3dSCy Schubert int evthreadimpl_lock_unlock_(unsigned mode, void *lock); 190*2b15cb3dSCy Schubert void *evthreadimpl_cond_alloc_(unsigned condtype); 191*2b15cb3dSCy Schubert void evthreadimpl_cond_free_(void *cond); 192*2b15cb3dSCy Schubert int evthreadimpl_cond_signal_(void *cond, int broadcast); 193*2b15cb3dSCy Schubert int evthreadimpl_cond_wait_(void *cond, void *lock, const struct timeval *tv); 194*2b15cb3dSCy Schubert int evthreadimpl_locking_enabled_(void); 195*2b15cb3dSCy Schubert 196*2b15cb3dSCy Schubert #define EVTHREAD_GET_ID() evthreadimpl_get_id_() 197*2b15cb3dSCy Schubert #define EVBASE_IN_THREAD(base) \ 198*2b15cb3dSCy Schubert ((base)->th_owner_id == evthreadimpl_get_id_()) 199*2b15cb3dSCy Schubert #define EVBASE_NEED_NOTIFY(base) \ 200*2b15cb3dSCy Schubert ((base)->running_loop && \ 201*2b15cb3dSCy Schubert ((base)->th_owner_id != evthreadimpl_get_id_())) 202*2b15cb3dSCy Schubert 203*2b15cb3dSCy Schubert #define EVTHREAD_ALLOC_LOCK(lockvar, locktype) \ 204*2b15cb3dSCy Schubert ((lockvar) = evthreadimpl_lock_alloc_(locktype)) 205*2b15cb3dSCy Schubert 206*2b15cb3dSCy Schubert #define EVTHREAD_FREE_LOCK(lockvar, locktype) \ 207*2b15cb3dSCy Schubert do { \ 208*2b15cb3dSCy Schubert void *lock_tmp_ = (lockvar); \ 209*2b15cb3dSCy Schubert if (lock_tmp_) \ 210*2b15cb3dSCy Schubert evthreadimpl_lock_free_(lock_tmp_, (locktype)); \ 211*2b15cb3dSCy Schubert } while (0) 212*2b15cb3dSCy Schubert 213*2b15cb3dSCy Schubert /** Acquire a lock. */ 214*2b15cb3dSCy Schubert #define EVLOCK_LOCK(lockvar,mode) \ 215*2b15cb3dSCy Schubert do { \ 216*2b15cb3dSCy Schubert if (lockvar) \ 217*2b15cb3dSCy Schubert evthreadimpl_lock_lock_(mode, lockvar); \ 218*2b15cb3dSCy Schubert } while (0) 219*2b15cb3dSCy Schubert 220*2b15cb3dSCy Schubert /** Release a lock */ 221*2b15cb3dSCy Schubert #define EVLOCK_UNLOCK(lockvar,mode) \ 222*2b15cb3dSCy Schubert do { \ 223*2b15cb3dSCy Schubert if (lockvar) \ 224*2b15cb3dSCy Schubert evthreadimpl_lock_unlock_(mode, lockvar); \ 225*2b15cb3dSCy Schubert } while (0) 226*2b15cb3dSCy Schubert 227*2b15cb3dSCy Schubert /** Lock an event_base, if it is set up for locking. Acquires the lock 228*2b15cb3dSCy Schubert in the base structure whose field is named 'lockvar'. */ 229*2b15cb3dSCy Schubert #define EVBASE_ACQUIRE_LOCK(base, lockvar) do { \ 230*2b15cb3dSCy Schubert EVLOCK_LOCK((base)->lockvar, 0); \ 231*2b15cb3dSCy Schubert } while (0) 232*2b15cb3dSCy Schubert 233*2b15cb3dSCy Schubert /** Unlock an event_base, if it is set up for locking. */ 234*2b15cb3dSCy Schubert #define EVBASE_RELEASE_LOCK(base, lockvar) do { \ 235*2b15cb3dSCy Schubert EVLOCK_UNLOCK((base)->lockvar, 0); \ 236*2b15cb3dSCy Schubert } while (0) 237*2b15cb3dSCy Schubert 238*2b15cb3dSCy Schubert /** If lock debugging is enabled, and lock is non-null, assert that 'lock' is 239*2b15cb3dSCy Schubert * locked and held by us. */ 240*2b15cb3dSCy Schubert #define EVLOCK_ASSERT_LOCKED(lock) \ 241*2b15cb3dSCy Schubert do { \ 242*2b15cb3dSCy Schubert if ((lock) && evthreadimpl_is_lock_debugging_enabled_()) { \ 243*2b15cb3dSCy Schubert EVUTIL_ASSERT(evthread_is_debug_lock_held_(lock)); \ 244*2b15cb3dSCy Schubert } \ 245*2b15cb3dSCy Schubert } while (0) 246*2b15cb3dSCy Schubert 247*2b15cb3dSCy Schubert /** Try to grab the lock for 'lockvar' without blocking, and return 1 if we 248*2b15cb3dSCy Schubert * manage to get it. */ 249*2b15cb3dSCy Schubert static inline int EVLOCK_TRY_LOCK_(void *lock); 250*2b15cb3dSCy Schubert static inline int 251*2b15cb3dSCy Schubert EVLOCK_TRY_LOCK_(void *lock) 252*2b15cb3dSCy Schubert { 253*2b15cb3dSCy Schubert if (lock) { 254*2b15cb3dSCy Schubert int r = evthreadimpl_lock_lock_(EVTHREAD_TRY, lock); 255*2b15cb3dSCy Schubert return !r; 256*2b15cb3dSCy Schubert } else { 257*2b15cb3dSCy Schubert /* Locking is disabled either globally or for this thing; 258*2b15cb3dSCy Schubert * of course we count as having the lock. */ 259*2b15cb3dSCy Schubert return 1; 260*2b15cb3dSCy Schubert } 261*2b15cb3dSCy Schubert } 262*2b15cb3dSCy Schubert 263*2b15cb3dSCy Schubert /** Allocate a new condition variable and store it in the void *, condvar */ 264*2b15cb3dSCy Schubert #define EVTHREAD_ALLOC_COND(condvar) \ 265*2b15cb3dSCy Schubert do { \ 266*2b15cb3dSCy Schubert (condvar) = evthreadimpl_cond_alloc_(0); \ 267*2b15cb3dSCy Schubert } while (0) 268*2b15cb3dSCy Schubert /** Deallocate and free a condition variable in condvar */ 269*2b15cb3dSCy Schubert #define EVTHREAD_FREE_COND(cond) \ 270*2b15cb3dSCy Schubert do { \ 271*2b15cb3dSCy Schubert if (cond) \ 272*2b15cb3dSCy Schubert evthreadimpl_cond_free_((cond)); \ 273*2b15cb3dSCy Schubert } while (0) 274*2b15cb3dSCy Schubert /** Signal one thread waiting on cond */ 275*2b15cb3dSCy Schubert #define EVTHREAD_COND_SIGNAL(cond) \ 276*2b15cb3dSCy Schubert ( (cond) ? evthreadimpl_cond_signal_((cond), 0) : 0 ) 277*2b15cb3dSCy Schubert /** Signal all threads waiting on cond */ 278*2b15cb3dSCy Schubert #define EVTHREAD_COND_BROADCAST(cond) \ 279*2b15cb3dSCy Schubert ( (cond) ? evthreadimpl_cond_signal_((cond), 1) : 0 ) 280*2b15cb3dSCy Schubert /** Wait until the condition 'cond' is signalled. Must be called while 281*2b15cb3dSCy Schubert * holding 'lock'. The lock will be released until the condition is 282*2b15cb3dSCy Schubert * signalled, at which point it will be acquired again. Returns 0 for 283*2b15cb3dSCy Schubert * success, -1 for failure. */ 284*2b15cb3dSCy Schubert #define EVTHREAD_COND_WAIT(cond, lock) \ 285*2b15cb3dSCy Schubert ( (cond) ? evthreadimpl_cond_wait_((cond), (lock), NULL) : 0 ) 286*2b15cb3dSCy Schubert /** As EVTHREAD_COND_WAIT, but gives up after 'tv' has elapsed. Returns 1 287*2b15cb3dSCy Schubert * on timeout. */ 288*2b15cb3dSCy Schubert #define EVTHREAD_COND_WAIT_TIMED(cond, lock, tv) \ 289*2b15cb3dSCy Schubert ( (cond) ? evthreadimpl_cond_wait_((cond), (lock), (tv)) : 0 ) 290*2b15cb3dSCy Schubert 291*2b15cb3dSCy Schubert #define EVTHREAD_LOCKING_ENABLED() \ 292*2b15cb3dSCy Schubert (evthreadimpl_locking_enabled_()) 293*2b15cb3dSCy Schubert 294*2b15cb3dSCy Schubert #else /* EVENT__DISABLE_THREAD_SUPPORT */ 295*2b15cb3dSCy Schubert 296*2b15cb3dSCy Schubert #define EVTHREAD_GET_ID() 1 297*2b15cb3dSCy Schubert #define EVTHREAD_ALLOC_LOCK(lockvar, locktype) EVUTIL_NIL_STMT_ 298*2b15cb3dSCy Schubert #define EVTHREAD_FREE_LOCK(lockvar, locktype) EVUTIL_NIL_STMT_ 299*2b15cb3dSCy Schubert 300*2b15cb3dSCy Schubert #define EVLOCK_LOCK(lockvar, mode) EVUTIL_NIL_STMT_ 301*2b15cb3dSCy Schubert #define EVLOCK_UNLOCK(lockvar, mode) EVUTIL_NIL_STMT_ 302*2b15cb3dSCy Schubert #define EVLOCK_LOCK2(lock1,lock2,mode1,mode2) EVUTIL_NIL_STMT_ 303*2b15cb3dSCy Schubert #define EVLOCK_UNLOCK2(lock1,lock2,mode1,mode2) EVUTIL_NIL_STMT_ 304*2b15cb3dSCy Schubert 305*2b15cb3dSCy Schubert #define EVBASE_IN_THREAD(base) 1 306*2b15cb3dSCy Schubert #define EVBASE_NEED_NOTIFY(base) 0 307*2b15cb3dSCy Schubert #define EVBASE_ACQUIRE_LOCK(base, lock) EVUTIL_NIL_STMT_ 308*2b15cb3dSCy Schubert #define EVBASE_RELEASE_LOCK(base, lock) EVUTIL_NIL_STMT_ 309*2b15cb3dSCy Schubert #define EVLOCK_ASSERT_LOCKED(lock) EVUTIL_NIL_STMT_ 310*2b15cb3dSCy Schubert 311*2b15cb3dSCy Schubert #define EVLOCK_TRY_LOCK_(lock) 1 312*2b15cb3dSCy Schubert 313*2b15cb3dSCy Schubert #define EVTHREAD_ALLOC_COND(condvar) EVUTIL_NIL_STMT_ 314*2b15cb3dSCy Schubert #define EVTHREAD_FREE_COND(cond) EVUTIL_NIL_STMT_ 315*2b15cb3dSCy Schubert #define EVTHREAD_COND_SIGNAL(cond) EVUTIL_NIL_STMT_ 316*2b15cb3dSCy Schubert #define EVTHREAD_COND_BROADCAST(cond) EVUTIL_NIL_STMT_ 317*2b15cb3dSCy Schubert #define EVTHREAD_COND_WAIT(cond, lock) EVUTIL_NIL_STMT_ 318*2b15cb3dSCy Schubert #define EVTHREAD_COND_WAIT_TIMED(cond, lock, howlong) EVUTIL_NIL_STMT_ 319*2b15cb3dSCy Schubert 320*2b15cb3dSCy Schubert #define EVTHREAD_LOCKING_ENABLED() 0 321*2b15cb3dSCy Schubert 322*2b15cb3dSCy Schubert #endif 323*2b15cb3dSCy Schubert 324*2b15cb3dSCy Schubert /* This code is shared between both lock impls */ 325*2b15cb3dSCy Schubert #if ! defined(EVENT__DISABLE_THREAD_SUPPORT) 326*2b15cb3dSCy Schubert /** Helper: put lockvar1 and lockvar2 into pointerwise ascending order. */ 327*2b15cb3dSCy Schubert #define EVLOCK_SORTLOCKS_(lockvar1, lockvar2) \ 328*2b15cb3dSCy Schubert do { \ 329*2b15cb3dSCy Schubert if (lockvar1 && lockvar2 && lockvar1 > lockvar2) { \ 330*2b15cb3dSCy Schubert void *tmp = lockvar1; \ 331*2b15cb3dSCy Schubert lockvar1 = lockvar2; \ 332*2b15cb3dSCy Schubert lockvar2 = tmp; \ 333*2b15cb3dSCy Schubert } \ 334*2b15cb3dSCy Schubert } while (0) 335*2b15cb3dSCy Schubert 336*2b15cb3dSCy Schubert /** Acquire both lock1 and lock2. Always allocates locks in the same order, 337*2b15cb3dSCy Schubert * so that two threads locking two locks with LOCK2 will not deadlock. */ 338*2b15cb3dSCy Schubert #define EVLOCK_LOCK2(lock1,lock2,mode1,mode2) \ 339*2b15cb3dSCy Schubert do { \ 340*2b15cb3dSCy Schubert void *lock1_tmplock_ = (lock1); \ 341*2b15cb3dSCy Schubert void *lock2_tmplock_ = (lock2); \ 342*2b15cb3dSCy Schubert EVLOCK_SORTLOCKS_(lock1_tmplock_,lock2_tmplock_); \ 343*2b15cb3dSCy Schubert EVLOCK_LOCK(lock1_tmplock_,mode1); \ 344*2b15cb3dSCy Schubert if (lock2_tmplock_ != lock1_tmplock_) \ 345*2b15cb3dSCy Schubert EVLOCK_LOCK(lock2_tmplock_,mode2); \ 346*2b15cb3dSCy Schubert } while (0) 347*2b15cb3dSCy Schubert /** Release both lock1 and lock2. */ 348*2b15cb3dSCy Schubert #define EVLOCK_UNLOCK2(lock1,lock2,mode1,mode2) \ 349*2b15cb3dSCy Schubert do { \ 350*2b15cb3dSCy Schubert void *lock1_tmplock_ = (lock1); \ 351*2b15cb3dSCy Schubert void *lock2_tmplock_ = (lock2); \ 352*2b15cb3dSCy Schubert EVLOCK_SORTLOCKS_(lock1_tmplock_,lock2_tmplock_); \ 353*2b15cb3dSCy Schubert if (lock2_tmplock_ != lock1_tmplock_) \ 354*2b15cb3dSCy Schubert EVLOCK_UNLOCK(lock2_tmplock_,mode2); \ 355*2b15cb3dSCy Schubert EVLOCK_UNLOCK(lock1_tmplock_,mode1); \ 356*2b15cb3dSCy Schubert } while (0) 357*2b15cb3dSCy Schubert 358*2b15cb3dSCy Schubert int evthread_is_debug_lock_held_(void *lock); 359*2b15cb3dSCy Schubert void *evthread_debug_get_real_lock_(void *lock); 360*2b15cb3dSCy Schubert 361*2b15cb3dSCy Schubert void *evthread_setup_global_lock_(void *lock_, unsigned locktype, 362*2b15cb3dSCy Schubert int enable_locks); 363*2b15cb3dSCy Schubert 364*2b15cb3dSCy Schubert #define EVTHREAD_SETUP_GLOBAL_LOCK(lockvar, locktype) \ 365*2b15cb3dSCy Schubert do { \ 366*2b15cb3dSCy Schubert lockvar = evthread_setup_global_lock_(lockvar, \ 367*2b15cb3dSCy Schubert (locktype), enable_locks); \ 368*2b15cb3dSCy Schubert if (!lockvar) { \ 369*2b15cb3dSCy Schubert event_warn("Couldn't allocate %s", #lockvar); \ 370*2b15cb3dSCy Schubert return -1; \ 371*2b15cb3dSCy Schubert } \ 372*2b15cb3dSCy Schubert } while (0); 373*2b15cb3dSCy Schubert 374*2b15cb3dSCy Schubert int event_global_setup_locks_(const int enable_locks); 375*2b15cb3dSCy Schubert int evsig_global_setup_locks_(const int enable_locks); 376*2b15cb3dSCy Schubert int evutil_global_setup_locks_(const int enable_locks); 377*2b15cb3dSCy Schubert int evutil_secure_rng_global_setup_locks_(const int enable_locks); 378*2b15cb3dSCy Schubert 379*2b15cb3dSCy Schubert #endif 380*2b15cb3dSCy Schubert 381*2b15cb3dSCy Schubert #ifdef __cplusplus 382*2b15cb3dSCy Schubert } 383*2b15cb3dSCy Schubert #endif 384*2b15cb3dSCy Schubert 385*2b15cb3dSCy Schubert #endif /* EVTHREAD_INTERNAL_H_INCLUDED_ */ 386