xref: /aosp_15_r20/external/libevent/evthread-internal.h (revision 663afb9b963571284e0f0a60f257164ab54f64bf)
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