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