xref: /freebsd/contrib/libevent/event.c (revision b50261e21f39a6c7249a49e7b60aa878c98512a8)
1c43e99fdSEd Maste /*
2c43e99fdSEd Maste  * Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu>
3c43e99fdSEd Maste  * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
4c43e99fdSEd Maste  *
5c43e99fdSEd Maste  * Redistribution and use in source and binary forms, with or without
6c43e99fdSEd Maste  * modification, are permitted provided that the following conditions
7c43e99fdSEd Maste  * are met:
8c43e99fdSEd Maste  * 1. Redistributions of source code must retain the above copyright
9c43e99fdSEd Maste  *    notice, this list of conditions and the following disclaimer.
10c43e99fdSEd Maste  * 2. Redistributions in binary form must reproduce the above copyright
11c43e99fdSEd Maste  *    notice, this list of conditions and the following disclaimer in the
12c43e99fdSEd Maste  *    documentation and/or other materials provided with the distribution.
13c43e99fdSEd Maste  * 3. The name of the author may not be used to endorse or promote products
14c43e99fdSEd Maste  *    derived from this software without specific prior written permission.
15c43e99fdSEd Maste  *
16c43e99fdSEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17c43e99fdSEd Maste  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18c43e99fdSEd Maste  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19c43e99fdSEd Maste  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20c43e99fdSEd Maste  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21c43e99fdSEd Maste  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22c43e99fdSEd Maste  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23c43e99fdSEd Maste  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24c43e99fdSEd Maste  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25c43e99fdSEd Maste  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26c43e99fdSEd Maste  */
27c43e99fdSEd Maste #include "event2/event-config.h"
28c43e99fdSEd Maste #include "evconfig-private.h"
29c43e99fdSEd Maste 
30c43e99fdSEd Maste #ifdef _WIN32
31c43e99fdSEd Maste #include <winsock2.h>
32c43e99fdSEd Maste #define WIN32_LEAN_AND_MEAN
33c43e99fdSEd Maste #include <windows.h>
34c43e99fdSEd Maste #undef WIN32_LEAN_AND_MEAN
35c43e99fdSEd Maste #endif
36c43e99fdSEd Maste #include <sys/types.h>
37c43e99fdSEd Maste #if !defined(_WIN32) && defined(EVENT__HAVE_SYS_TIME_H)
38c43e99fdSEd Maste #include <sys/time.h>
39c43e99fdSEd Maste #endif
40c43e99fdSEd Maste #include <sys/queue.h>
41c43e99fdSEd Maste #ifdef EVENT__HAVE_SYS_SOCKET_H
42c43e99fdSEd Maste #include <sys/socket.h>
43c43e99fdSEd Maste #endif
44c43e99fdSEd Maste #include <stdio.h>
45c43e99fdSEd Maste #include <stdlib.h>
46c43e99fdSEd Maste #ifdef EVENT__HAVE_UNISTD_H
47c43e99fdSEd Maste #include <unistd.h>
48c43e99fdSEd Maste #endif
49c43e99fdSEd Maste #include <ctype.h>
50c43e99fdSEd Maste #include <errno.h>
51c43e99fdSEd Maste #include <signal.h>
52c43e99fdSEd Maste #include <string.h>
53c43e99fdSEd Maste #include <time.h>
54c43e99fdSEd Maste #include <limits.h>
55*b50261e2SCy Schubert #ifdef EVENT__HAVE_FCNTL_H
56*b50261e2SCy Schubert #include <fcntl.h>
57*b50261e2SCy Schubert #endif
58c43e99fdSEd Maste 
59c43e99fdSEd Maste #include "event2/event.h"
60c43e99fdSEd Maste #include "event2/event_struct.h"
61c43e99fdSEd Maste #include "event2/event_compat.h"
62c43e99fdSEd Maste #include "event-internal.h"
63c43e99fdSEd Maste #include "defer-internal.h"
64c43e99fdSEd Maste #include "evthread-internal.h"
65c43e99fdSEd Maste #include "event2/thread.h"
66c43e99fdSEd Maste #include "event2/util.h"
67c43e99fdSEd Maste #include "log-internal.h"
68c43e99fdSEd Maste #include "evmap-internal.h"
69c43e99fdSEd Maste #include "iocp-internal.h"
70c43e99fdSEd Maste #include "changelist-internal.h"
71c43e99fdSEd Maste #define HT_NO_CACHE_HASH_VALUES
72c43e99fdSEd Maste #include "ht-internal.h"
73c43e99fdSEd Maste #include "util-internal.h"
74c43e99fdSEd Maste 
75c43e99fdSEd Maste 
76c43e99fdSEd Maste #ifdef EVENT__HAVE_WORKING_KQUEUE
77c43e99fdSEd Maste #include "kqueue-internal.h"
78c43e99fdSEd Maste #endif
79c43e99fdSEd Maste 
80c43e99fdSEd Maste #ifdef EVENT__HAVE_EVENT_PORTS
81c43e99fdSEd Maste extern const struct eventop evportops;
82c43e99fdSEd Maste #endif
83c43e99fdSEd Maste #ifdef EVENT__HAVE_SELECT
84c43e99fdSEd Maste extern const struct eventop selectops;
85c43e99fdSEd Maste #endif
86c43e99fdSEd Maste #ifdef EVENT__HAVE_POLL
87c43e99fdSEd Maste extern const struct eventop pollops;
88c43e99fdSEd Maste #endif
89c43e99fdSEd Maste #ifdef EVENT__HAVE_EPOLL
90c43e99fdSEd Maste extern const struct eventop epollops;
91c43e99fdSEd Maste #endif
92c43e99fdSEd Maste #ifdef EVENT__HAVE_WORKING_KQUEUE
93c43e99fdSEd Maste extern const struct eventop kqops;
94c43e99fdSEd Maste #endif
95c43e99fdSEd Maste #ifdef EVENT__HAVE_DEVPOLL
96c43e99fdSEd Maste extern const struct eventop devpollops;
97c43e99fdSEd Maste #endif
98c43e99fdSEd Maste #ifdef _WIN32
99c43e99fdSEd Maste extern const struct eventop win32ops;
100c43e99fdSEd Maste #endif
101c43e99fdSEd Maste 
102c43e99fdSEd Maste /* Array of backends in order of preference. */
103c43e99fdSEd Maste static const struct eventop *eventops[] = {
104c43e99fdSEd Maste #ifdef EVENT__HAVE_EVENT_PORTS
105c43e99fdSEd Maste 	&evportops,
106c43e99fdSEd Maste #endif
107c43e99fdSEd Maste #ifdef EVENT__HAVE_WORKING_KQUEUE
108c43e99fdSEd Maste 	&kqops,
109c43e99fdSEd Maste #endif
110c43e99fdSEd Maste #ifdef EVENT__HAVE_EPOLL
111c43e99fdSEd Maste 	&epollops,
112c43e99fdSEd Maste #endif
113c43e99fdSEd Maste #ifdef EVENT__HAVE_DEVPOLL
114c43e99fdSEd Maste 	&devpollops,
115c43e99fdSEd Maste #endif
116c43e99fdSEd Maste #ifdef EVENT__HAVE_POLL
117c43e99fdSEd Maste 	&pollops,
118c43e99fdSEd Maste #endif
119c43e99fdSEd Maste #ifdef EVENT__HAVE_SELECT
120c43e99fdSEd Maste 	&selectops,
121c43e99fdSEd Maste #endif
122c43e99fdSEd Maste #ifdef _WIN32
123c43e99fdSEd Maste 	&win32ops,
124c43e99fdSEd Maste #endif
125c43e99fdSEd Maste 	NULL
126c43e99fdSEd Maste };
127c43e99fdSEd Maste 
128c43e99fdSEd Maste /* Global state; deprecated */
129*b50261e2SCy Schubert EVENT2_EXPORT_SYMBOL
130c43e99fdSEd Maste struct event_base *event_global_current_base_ = NULL;
131c43e99fdSEd Maste #define current_base event_global_current_base_
132c43e99fdSEd Maste 
133c43e99fdSEd Maste /* Global state */
134c43e99fdSEd Maste 
135c43e99fdSEd Maste static void *event_self_cbarg_ptr_ = NULL;
136c43e99fdSEd Maste 
137c43e99fdSEd Maste /* Prototypes */
138c43e99fdSEd Maste static void	event_queue_insert_active(struct event_base *, struct event_callback *);
139c43e99fdSEd Maste static void	event_queue_insert_active_later(struct event_base *, struct event_callback *);
140c43e99fdSEd Maste static void	event_queue_insert_timeout(struct event_base *, struct event *);
141c43e99fdSEd Maste static void	event_queue_insert_inserted(struct event_base *, struct event *);
142c43e99fdSEd Maste static void	event_queue_remove_active(struct event_base *, struct event_callback *);
143c43e99fdSEd Maste static void	event_queue_remove_active_later(struct event_base *, struct event_callback *);
144c43e99fdSEd Maste static void	event_queue_remove_timeout(struct event_base *, struct event *);
145c43e99fdSEd Maste static void	event_queue_remove_inserted(struct event_base *, struct event *);
146c43e99fdSEd Maste static void event_queue_make_later_events_active(struct event_base *base);
147c43e99fdSEd Maste 
148c43e99fdSEd Maste static int evthread_make_base_notifiable_nolock_(struct event_base *base);
149c43e99fdSEd Maste static int event_del_(struct event *ev, int blocking);
150c43e99fdSEd Maste 
151c43e99fdSEd Maste #ifdef USE_REINSERT_TIMEOUT
152c43e99fdSEd Maste /* This code seems buggy; only turn it on if we find out what the trouble is. */
153c43e99fdSEd Maste static void	event_queue_reinsert_timeout(struct event_base *,struct event *, int was_common, int is_common, int old_timeout_idx);
154c43e99fdSEd Maste #endif
155c43e99fdSEd Maste 
156c43e99fdSEd Maste static int	event_haveevents(struct event_base *);
157c43e99fdSEd Maste 
158c43e99fdSEd Maste static int	event_process_active(struct event_base *);
159c43e99fdSEd Maste 
160c43e99fdSEd Maste static int	timeout_next(struct event_base *, struct timeval **);
161c43e99fdSEd Maste static void	timeout_process(struct event_base *);
162c43e99fdSEd Maste 
163c43e99fdSEd Maste static inline void	event_signal_closure(struct event_base *, struct event *ev);
164c43e99fdSEd Maste static inline void	event_persist_closure(struct event_base *, struct event *ev);
165c43e99fdSEd Maste 
166c43e99fdSEd Maste static int	evthread_notify_base(struct event_base *base);
167c43e99fdSEd Maste 
168c43e99fdSEd Maste static void insert_common_timeout_inorder(struct common_timeout_list *ctl,
169c43e99fdSEd Maste     struct event *ev);
170c43e99fdSEd Maste 
171c43e99fdSEd Maste #ifndef EVENT__DISABLE_DEBUG_MODE
172c43e99fdSEd Maste /* These functions implement a hashtable of which 'struct event *' structures
173c43e99fdSEd Maste  * have been setup or added.  We don't want to trust the content of the struct
174c43e99fdSEd Maste  * event itself, since we're trying to work through cases where an event gets
175c43e99fdSEd Maste  * clobbered or freed.  Instead, we keep a hashtable indexed by the pointer.
176c43e99fdSEd Maste  */
177c43e99fdSEd Maste 
178c43e99fdSEd Maste struct event_debug_entry {
179c43e99fdSEd Maste 	HT_ENTRY(event_debug_entry) node;
180c43e99fdSEd Maste 	const struct event *ptr;
181c43e99fdSEd Maste 	unsigned added : 1;
182c43e99fdSEd Maste };
183c43e99fdSEd Maste 
184c43e99fdSEd Maste static inline unsigned
hash_debug_entry(const struct event_debug_entry * e)185c43e99fdSEd Maste hash_debug_entry(const struct event_debug_entry *e)
186c43e99fdSEd Maste {
187c43e99fdSEd Maste 	/* We need to do this silliness to convince compilers that we
188c43e99fdSEd Maste 	 * honestly mean to cast e->ptr to an integer, and discard any
189c43e99fdSEd Maste 	 * part of it that doesn't fit in an unsigned.
190c43e99fdSEd Maste 	 */
191c43e99fdSEd Maste 	unsigned u = (unsigned) ((ev_uintptr_t) e->ptr);
192c43e99fdSEd Maste 	/* Our hashtable implementation is pretty sensitive to low bits,
193c43e99fdSEd Maste 	 * and every struct event is over 64 bytes in size, so we can
194c43e99fdSEd Maste 	 * just say >>6. */
195c43e99fdSEd Maste 	return (u >> 6);
196c43e99fdSEd Maste }
197c43e99fdSEd Maste 
198c43e99fdSEd Maste static inline int
eq_debug_entry(const struct event_debug_entry * a,const struct event_debug_entry * b)199c43e99fdSEd Maste eq_debug_entry(const struct event_debug_entry *a,
200c43e99fdSEd Maste     const struct event_debug_entry *b)
201c43e99fdSEd Maste {
202c43e99fdSEd Maste 	return a->ptr == b->ptr;
203c43e99fdSEd Maste }
204c43e99fdSEd Maste 
205c43e99fdSEd Maste int event_debug_mode_on_ = 0;
206c43e99fdSEd Maste 
207c43e99fdSEd Maste 
208c43e99fdSEd Maste #if !defined(EVENT__DISABLE_THREAD_SUPPORT) && !defined(EVENT__DISABLE_DEBUG_MODE)
209c43e99fdSEd Maste /**
210c43e99fdSEd Maste  * @brief debug mode variable which is set for any function/structure that needs
211c43e99fdSEd Maste  *        to be shared across threads (if thread support is enabled).
212c43e99fdSEd Maste  *
213c43e99fdSEd Maste  *        When and if evthreads are initialized, this variable will be evaluated,
214c43e99fdSEd Maste  *        and if set to something other than zero, this means the evthread setup
215c43e99fdSEd Maste  *        functions were called out of order.
216c43e99fdSEd Maste  *
217c43e99fdSEd Maste  *        See: "Locks and threading" in the documentation.
218c43e99fdSEd Maste  */
219c43e99fdSEd Maste int event_debug_created_threadable_ctx_ = 0;
220c43e99fdSEd Maste #endif
221c43e99fdSEd Maste 
222c43e99fdSEd Maste /* Set if it's too late to enable event_debug_mode. */
223c43e99fdSEd Maste static int event_debug_mode_too_late = 0;
224c43e99fdSEd Maste #ifndef EVENT__DISABLE_THREAD_SUPPORT
225c43e99fdSEd Maste static void *event_debug_map_lock_ = NULL;
226c43e99fdSEd Maste #endif
227c43e99fdSEd Maste static HT_HEAD(event_debug_map, event_debug_entry) global_debug_map =
228c43e99fdSEd Maste 	HT_INITIALIZER();
229c43e99fdSEd Maste 
HT_PROTOTYPE(event_debug_map,event_debug_entry,node,hash_debug_entry,eq_debug_entry)230c43e99fdSEd Maste HT_PROTOTYPE(event_debug_map, event_debug_entry, node, hash_debug_entry,
231c43e99fdSEd Maste     eq_debug_entry)
232c43e99fdSEd Maste HT_GENERATE(event_debug_map, event_debug_entry, node, hash_debug_entry,
233c43e99fdSEd Maste     eq_debug_entry, 0.5, mm_malloc, mm_realloc, mm_free)
234c43e99fdSEd Maste 
235*b50261e2SCy Schubert /* record that ev is now setup (that is, ready for an add) */
236*b50261e2SCy Schubert static void event_debug_note_setup_(const struct event *ev)
237*b50261e2SCy Schubert {
238*b50261e2SCy Schubert 	struct event_debug_entry *dent, find;
239*b50261e2SCy Schubert 
240*b50261e2SCy Schubert 	if (!event_debug_mode_on_)
241*b50261e2SCy Schubert 		goto out;
242*b50261e2SCy Schubert 
243*b50261e2SCy Schubert 	find.ptr = ev;
244*b50261e2SCy Schubert 	EVLOCK_LOCK(event_debug_map_lock_, 0);
245*b50261e2SCy Schubert 	dent = HT_FIND(event_debug_map, &global_debug_map, &find);
246*b50261e2SCy Schubert 	if (dent) {
247*b50261e2SCy Schubert 		dent->added = 0;
248*b50261e2SCy Schubert 	} else {
249*b50261e2SCy Schubert 		dent = mm_malloc(sizeof(*dent));
250*b50261e2SCy Schubert 		if (!dent)
251*b50261e2SCy Schubert 			event_err(1,
252*b50261e2SCy Schubert 			    "Out of memory in debugging code");
253*b50261e2SCy Schubert 		dent->ptr = ev;
254*b50261e2SCy Schubert 		dent->added = 0;
255*b50261e2SCy Schubert 		HT_INSERT(event_debug_map, &global_debug_map, dent);
256*b50261e2SCy Schubert 	}
257*b50261e2SCy Schubert 	EVLOCK_UNLOCK(event_debug_map_lock_, 0);
258*b50261e2SCy Schubert 
259*b50261e2SCy Schubert out:
260*b50261e2SCy Schubert 	event_debug_mode_too_late = 1;
261*b50261e2SCy Schubert }
262*b50261e2SCy Schubert /* record that ev is no longer setup */
event_debug_note_teardown_(const struct event * ev)263*b50261e2SCy Schubert static void event_debug_note_teardown_(const struct event *ev)
264*b50261e2SCy Schubert {
265*b50261e2SCy Schubert 	struct event_debug_entry *dent, find;
266*b50261e2SCy Schubert 
267*b50261e2SCy Schubert 	if (!event_debug_mode_on_)
268*b50261e2SCy Schubert 		goto out;
269*b50261e2SCy Schubert 
270*b50261e2SCy Schubert 	find.ptr = ev;
271*b50261e2SCy Schubert 	EVLOCK_LOCK(event_debug_map_lock_, 0);
272*b50261e2SCy Schubert 	dent = HT_REMOVE(event_debug_map, &global_debug_map, &find);
273*b50261e2SCy Schubert 	if (dent)
274*b50261e2SCy Schubert 		mm_free(dent);
275*b50261e2SCy Schubert 	EVLOCK_UNLOCK(event_debug_map_lock_, 0);
276*b50261e2SCy Schubert 
277*b50261e2SCy Schubert out:
278*b50261e2SCy Schubert 	event_debug_mode_too_late = 1;
279*b50261e2SCy Schubert }
280c43e99fdSEd Maste /* Macro: record that ev is now added */
event_debug_note_add_(const struct event * ev)281*b50261e2SCy Schubert static void event_debug_note_add_(const struct event *ev)
282*b50261e2SCy Schubert {
283*b50261e2SCy Schubert 	struct event_debug_entry *dent,find;
284*b50261e2SCy Schubert 
285*b50261e2SCy Schubert 	if (!event_debug_mode_on_)
286*b50261e2SCy Schubert 		goto out;
287*b50261e2SCy Schubert 
288*b50261e2SCy Schubert 	find.ptr = ev;
289*b50261e2SCy Schubert 	EVLOCK_LOCK(event_debug_map_lock_, 0);
290*b50261e2SCy Schubert 	dent = HT_FIND(event_debug_map, &global_debug_map, &find);
291*b50261e2SCy Schubert 	if (dent) {
292*b50261e2SCy Schubert 		dent->added = 1;
293*b50261e2SCy Schubert 	} else {
294*b50261e2SCy Schubert 		event_errx(EVENT_ERR_ABORT_,
295*b50261e2SCy Schubert 		    "%s: noting an add on a non-setup event %p"
296*b50261e2SCy Schubert 		    " (events: 0x%x, fd: "EV_SOCK_FMT
297*b50261e2SCy Schubert 		    ", flags: 0x%x)",
298*b50261e2SCy Schubert 		    __func__, ev, ev->ev_events,
299*b50261e2SCy Schubert 		    EV_SOCK_ARG(ev->ev_fd), ev->ev_flags);
300*b50261e2SCy Schubert 	}
301*b50261e2SCy Schubert 	EVLOCK_UNLOCK(event_debug_map_lock_, 0);
302*b50261e2SCy Schubert 
303*b50261e2SCy Schubert out:
304*b50261e2SCy Schubert 	event_debug_mode_too_late = 1;
305*b50261e2SCy Schubert }
306*b50261e2SCy Schubert /* record that ev is no longer added */
event_debug_note_del_(const struct event * ev)307*b50261e2SCy Schubert static void event_debug_note_del_(const struct event *ev)
308*b50261e2SCy Schubert {
309*b50261e2SCy Schubert 	struct event_debug_entry *dent, find;
310*b50261e2SCy Schubert 
311*b50261e2SCy Schubert 	if (!event_debug_mode_on_)
312*b50261e2SCy Schubert 		goto out;
313*b50261e2SCy Schubert 
314*b50261e2SCy Schubert 	find.ptr = ev;
315*b50261e2SCy Schubert 	EVLOCK_LOCK(event_debug_map_lock_, 0);
316*b50261e2SCy Schubert 	dent = HT_FIND(event_debug_map, &global_debug_map, &find);
317*b50261e2SCy Schubert 	if (dent) {
318*b50261e2SCy Schubert 		dent->added = 0;
319*b50261e2SCy Schubert 	} else {
320*b50261e2SCy Schubert 		event_errx(EVENT_ERR_ABORT_,
321*b50261e2SCy Schubert 		    "%s: noting a del on a non-setup event %p"
322*b50261e2SCy Schubert 		    " (events: 0x%x, fd: "EV_SOCK_FMT
323*b50261e2SCy Schubert 		    ", flags: 0x%x)",
324*b50261e2SCy Schubert 		    __func__, ev, ev->ev_events,
325*b50261e2SCy Schubert 		    EV_SOCK_ARG(ev->ev_fd), ev->ev_flags);
326*b50261e2SCy Schubert 	}
327*b50261e2SCy Schubert 	EVLOCK_UNLOCK(event_debug_map_lock_, 0);
328*b50261e2SCy Schubert 
329*b50261e2SCy Schubert out:
330*b50261e2SCy Schubert 	event_debug_mode_too_late = 1;
331*b50261e2SCy Schubert }
332*b50261e2SCy Schubert /* assert that ev is setup (i.e., okay to add or inspect) */
event_debug_assert_is_setup_(const struct event * ev)333*b50261e2SCy Schubert static void event_debug_assert_is_setup_(const struct event *ev)
334*b50261e2SCy Schubert {
335*b50261e2SCy Schubert 	struct event_debug_entry *dent, find;
336*b50261e2SCy Schubert 
337*b50261e2SCy Schubert 	if (!event_debug_mode_on_)
338*b50261e2SCy Schubert 		return;
339*b50261e2SCy Schubert 
340*b50261e2SCy Schubert 	find.ptr = ev;
341*b50261e2SCy Schubert 	EVLOCK_LOCK(event_debug_map_lock_, 0);
342*b50261e2SCy Schubert 	dent = HT_FIND(event_debug_map, &global_debug_map, &find);
343*b50261e2SCy Schubert 	if (!dent) {
344*b50261e2SCy Schubert 		event_errx(EVENT_ERR_ABORT_,
345*b50261e2SCy Schubert 		    "%s called on a non-initialized event %p"
346*b50261e2SCy Schubert 		    " (events: 0x%x, fd: "EV_SOCK_FMT
347*b50261e2SCy Schubert 		    ", flags: 0x%x)",
348*b50261e2SCy Schubert 		    __func__, ev, ev->ev_events,
349*b50261e2SCy Schubert 		    EV_SOCK_ARG(ev->ev_fd), ev->ev_flags);
350*b50261e2SCy Schubert 	}
351*b50261e2SCy Schubert 	EVLOCK_UNLOCK(event_debug_map_lock_, 0);
352*b50261e2SCy Schubert }
353*b50261e2SCy Schubert /* assert that ev is not added (i.e., okay to tear down or set up again) */
event_debug_assert_not_added_(const struct event * ev)354*b50261e2SCy Schubert static void event_debug_assert_not_added_(const struct event *ev)
355*b50261e2SCy Schubert {
356*b50261e2SCy Schubert 	struct event_debug_entry *dent, find;
357*b50261e2SCy Schubert 
358*b50261e2SCy Schubert 	if (!event_debug_mode_on_)
359*b50261e2SCy Schubert 		return;
360*b50261e2SCy Schubert 
361*b50261e2SCy Schubert 	find.ptr = ev;
362*b50261e2SCy Schubert 	EVLOCK_LOCK(event_debug_map_lock_, 0);
363*b50261e2SCy Schubert 	dent = HT_FIND(event_debug_map, &global_debug_map, &find);
364*b50261e2SCy Schubert 	if (dent && dent->added) {
365*b50261e2SCy Schubert 		event_errx(EVENT_ERR_ABORT_,
366*b50261e2SCy Schubert 		    "%s called on an already added event %p"
367*b50261e2SCy Schubert 		    " (events: 0x%x, fd: "EV_SOCK_FMT", "
368*b50261e2SCy Schubert 		    "flags: 0x%x)",
369*b50261e2SCy Schubert 		    __func__, ev, ev->ev_events,
370*b50261e2SCy Schubert 		    EV_SOCK_ARG(ev->ev_fd), ev->ev_flags);
371*b50261e2SCy Schubert 	}
372*b50261e2SCy Schubert 	EVLOCK_UNLOCK(event_debug_map_lock_, 0);
373*b50261e2SCy Schubert }
event_debug_assert_socket_nonblocking_(evutil_socket_t fd)374*b50261e2SCy Schubert static void event_debug_assert_socket_nonblocking_(evutil_socket_t fd)
375*b50261e2SCy Schubert {
376*b50261e2SCy Schubert 	if (!event_debug_mode_on_)
377*b50261e2SCy Schubert 		return;
378*b50261e2SCy Schubert 	if (fd < 0)
379*b50261e2SCy Schubert 		return;
380*b50261e2SCy Schubert 
381*b50261e2SCy Schubert #ifndef _WIN32
382*b50261e2SCy Schubert 	{
383*b50261e2SCy Schubert 		int flags;
384*b50261e2SCy Schubert 		if ((flags = fcntl(fd, F_GETFL, NULL)) >= 0) {
385*b50261e2SCy Schubert 			EVUTIL_ASSERT(flags & O_NONBLOCK);
386*b50261e2SCy Schubert 		}
387*b50261e2SCy Schubert 	}
388*b50261e2SCy Schubert #endif
389*b50261e2SCy Schubert }
390c43e99fdSEd Maste #else
event_debug_note_setup_(const struct event * ev)391*b50261e2SCy Schubert static void event_debug_note_setup_(const struct event *ev) { (void)ev; }
event_debug_note_teardown_(const struct event * ev)392*b50261e2SCy Schubert static void event_debug_note_teardown_(const struct event *ev) { (void)ev; }
event_debug_note_add_(const struct event * ev)393*b50261e2SCy Schubert static void event_debug_note_add_(const struct event *ev) { (void)ev; }
event_debug_note_del_(const struct event * ev)394*b50261e2SCy Schubert static void event_debug_note_del_(const struct event *ev) { (void)ev; }
event_debug_assert_is_setup_(const struct event * ev)395*b50261e2SCy Schubert static void event_debug_assert_is_setup_(const struct event *ev) { (void)ev; }
event_debug_assert_not_added_(const struct event * ev)396*b50261e2SCy Schubert static void event_debug_assert_not_added_(const struct event *ev) { (void)ev; }
event_debug_assert_socket_nonblocking_(evutil_socket_t fd)397*b50261e2SCy Schubert static void event_debug_assert_socket_nonblocking_(evutil_socket_t fd) { (void)fd; }
398c43e99fdSEd Maste #endif
399c43e99fdSEd Maste 
400c43e99fdSEd Maste #define EVENT_BASE_ASSERT_LOCKED(base)		\
401c43e99fdSEd Maste 	EVLOCK_ASSERT_LOCKED((base)->th_base_lock)
402c43e99fdSEd Maste 
403c43e99fdSEd Maste /* How often (in seconds) do we check for changes in wall clock time relative
404c43e99fdSEd Maste  * to monotonic time?  Set this to -1 for 'never.' */
405c43e99fdSEd Maste #define CLOCK_SYNC_INTERVAL 5
406c43e99fdSEd Maste 
407c43e99fdSEd Maste /** Set 'tp' to the current time according to 'base'.  We must hold the lock
408c43e99fdSEd Maste  * on 'base'.  If there is a cached time, return it.  Otherwise, use
409c43e99fdSEd Maste  * clock_gettime or gettimeofday as appropriate to find out the right time.
410c43e99fdSEd Maste  * Return 0 on success, -1 on failure.
411c43e99fdSEd Maste  */
412c43e99fdSEd Maste static int
gettime(struct event_base * base,struct timeval * tp)413c43e99fdSEd Maste gettime(struct event_base *base, struct timeval *tp)
414c43e99fdSEd Maste {
415c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
416c43e99fdSEd Maste 
417c43e99fdSEd Maste 	if (base->tv_cache.tv_sec) {
418c43e99fdSEd Maste 		*tp = base->tv_cache;
419c43e99fdSEd Maste 		return (0);
420c43e99fdSEd Maste 	}
421c43e99fdSEd Maste 
422c43e99fdSEd Maste 	if (evutil_gettime_monotonic_(&base->monotonic_timer, tp) == -1) {
423c43e99fdSEd Maste 		return -1;
424c43e99fdSEd Maste 	}
425c43e99fdSEd Maste 
426c43e99fdSEd Maste 	if (base->last_updated_clock_diff + CLOCK_SYNC_INTERVAL
427c43e99fdSEd Maste 	    < tp->tv_sec) {
428c43e99fdSEd Maste 		struct timeval tv;
429c43e99fdSEd Maste 		evutil_gettimeofday(&tv,NULL);
430c43e99fdSEd Maste 		evutil_timersub(&tv, tp, &base->tv_clock_diff);
431c43e99fdSEd Maste 		base->last_updated_clock_diff = tp->tv_sec;
432c43e99fdSEd Maste 	}
433c43e99fdSEd Maste 
434c43e99fdSEd Maste 	return 0;
435c43e99fdSEd Maste }
436c43e99fdSEd Maste 
437c43e99fdSEd Maste int
event_base_gettimeofday_cached(struct event_base * base,struct timeval * tv)438c43e99fdSEd Maste event_base_gettimeofday_cached(struct event_base *base, struct timeval *tv)
439c43e99fdSEd Maste {
440c43e99fdSEd Maste 	int r;
441c43e99fdSEd Maste 	if (!base) {
442c43e99fdSEd Maste 		base = current_base;
443c43e99fdSEd Maste 		if (!current_base)
444c43e99fdSEd Maste 			return evutil_gettimeofday(tv, NULL);
445c43e99fdSEd Maste 	}
446c43e99fdSEd Maste 
447c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
448c43e99fdSEd Maste 	if (base->tv_cache.tv_sec == 0) {
449c43e99fdSEd Maste 		r = evutil_gettimeofday(tv, NULL);
450c43e99fdSEd Maste 	} else {
451c43e99fdSEd Maste 		evutil_timeradd(&base->tv_cache, &base->tv_clock_diff, tv);
452c43e99fdSEd Maste 		r = 0;
453c43e99fdSEd Maste 	}
454c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
455c43e99fdSEd Maste 	return r;
456c43e99fdSEd Maste }
457c43e99fdSEd Maste 
458c43e99fdSEd Maste /** Make 'base' have no current cached time. */
459c43e99fdSEd Maste static inline void
clear_time_cache(struct event_base * base)460c43e99fdSEd Maste clear_time_cache(struct event_base *base)
461c43e99fdSEd Maste {
462c43e99fdSEd Maste 	base->tv_cache.tv_sec = 0;
463c43e99fdSEd Maste }
464c43e99fdSEd Maste 
465c43e99fdSEd Maste /** Replace the cached time in 'base' with the current time. */
466c43e99fdSEd Maste static inline void
update_time_cache(struct event_base * base)467c43e99fdSEd Maste update_time_cache(struct event_base *base)
468c43e99fdSEd Maste {
469c43e99fdSEd Maste 	base->tv_cache.tv_sec = 0;
470c43e99fdSEd Maste 	if (!(base->flags & EVENT_BASE_FLAG_NO_CACHE_TIME))
471c43e99fdSEd Maste 	    gettime(base, &base->tv_cache);
472c43e99fdSEd Maste }
473c43e99fdSEd Maste 
474c43e99fdSEd Maste int
event_base_update_cache_time(struct event_base * base)475c43e99fdSEd Maste event_base_update_cache_time(struct event_base *base)
476c43e99fdSEd Maste {
477c43e99fdSEd Maste 
478c43e99fdSEd Maste 	if (!base) {
479c43e99fdSEd Maste 		base = current_base;
480c43e99fdSEd Maste 		if (!current_base)
481c43e99fdSEd Maste 			return -1;
482c43e99fdSEd Maste 	}
483c43e99fdSEd Maste 
484c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
485c43e99fdSEd Maste 	if (base->running_loop)
486c43e99fdSEd Maste 		update_time_cache(base);
487c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
488c43e99fdSEd Maste 	return 0;
489c43e99fdSEd Maste }
490c43e99fdSEd Maste 
491c43e99fdSEd Maste static inline struct event *
event_callback_to_event(struct event_callback * evcb)492c43e99fdSEd Maste event_callback_to_event(struct event_callback *evcb)
493c43e99fdSEd Maste {
494c43e99fdSEd Maste 	EVUTIL_ASSERT((evcb->evcb_flags & EVLIST_INIT));
495c43e99fdSEd Maste 	return EVUTIL_UPCAST(evcb, struct event, ev_evcallback);
496c43e99fdSEd Maste }
497c43e99fdSEd Maste 
498c43e99fdSEd Maste static inline struct event_callback *
event_to_event_callback(struct event * ev)499c43e99fdSEd Maste event_to_event_callback(struct event *ev)
500c43e99fdSEd Maste {
501c43e99fdSEd Maste 	return &ev->ev_evcallback;
502c43e99fdSEd Maste }
503c43e99fdSEd Maste 
504c43e99fdSEd Maste struct event_base *
event_init(void)505c43e99fdSEd Maste event_init(void)
506c43e99fdSEd Maste {
507c43e99fdSEd Maste 	struct event_base *base = event_base_new_with_config(NULL);
508c43e99fdSEd Maste 
509c43e99fdSEd Maste 	if (base == NULL) {
510c43e99fdSEd Maste 		event_errx(1, "%s: Unable to construct event_base", __func__);
511c43e99fdSEd Maste 		return NULL;
512c43e99fdSEd Maste 	}
513c43e99fdSEd Maste 
514c43e99fdSEd Maste 	current_base = base;
515c43e99fdSEd Maste 
516c43e99fdSEd Maste 	return (base);
517c43e99fdSEd Maste }
518c43e99fdSEd Maste 
519c43e99fdSEd Maste struct event_base *
event_base_new(void)520c43e99fdSEd Maste event_base_new(void)
521c43e99fdSEd Maste {
522c43e99fdSEd Maste 	struct event_base *base = NULL;
523c43e99fdSEd Maste 	struct event_config *cfg = event_config_new();
524c43e99fdSEd Maste 	if (cfg) {
525c43e99fdSEd Maste 		base = event_base_new_with_config(cfg);
526c43e99fdSEd Maste 		event_config_free(cfg);
527c43e99fdSEd Maste 	}
528c43e99fdSEd Maste 	return base;
529c43e99fdSEd Maste }
530c43e99fdSEd Maste 
531c43e99fdSEd Maste /** Return true iff 'method' is the name of a method that 'cfg' tells us to
532c43e99fdSEd Maste  * avoid. */
533c43e99fdSEd Maste static int
event_config_is_avoided_method(const struct event_config * cfg,const char * method)534c43e99fdSEd Maste event_config_is_avoided_method(const struct event_config *cfg,
535c43e99fdSEd Maste     const char *method)
536c43e99fdSEd Maste {
537c43e99fdSEd Maste 	struct event_config_entry *entry;
538c43e99fdSEd Maste 
539c43e99fdSEd Maste 	TAILQ_FOREACH(entry, &cfg->entries, next) {
540c43e99fdSEd Maste 		if (entry->avoid_method != NULL &&
541c43e99fdSEd Maste 		    strcmp(entry->avoid_method, method) == 0)
542c43e99fdSEd Maste 			return (1);
543c43e99fdSEd Maste 	}
544c43e99fdSEd Maste 
545c43e99fdSEd Maste 	return (0);
546c43e99fdSEd Maste }
547c43e99fdSEd Maste 
548c43e99fdSEd Maste /** Return true iff 'method' is disabled according to the environment. */
549c43e99fdSEd Maste static int
event_is_method_disabled(const char * name)550c43e99fdSEd Maste event_is_method_disabled(const char *name)
551c43e99fdSEd Maste {
552c43e99fdSEd Maste 	char environment[64];
553c43e99fdSEd Maste 	int i;
554c43e99fdSEd Maste 
555c43e99fdSEd Maste 	evutil_snprintf(environment, sizeof(environment), "EVENT_NO%s", name);
556c43e99fdSEd Maste 	for (i = 8; environment[i] != '\0'; ++i)
557c43e99fdSEd Maste 		environment[i] = EVUTIL_TOUPPER_(environment[i]);
558c43e99fdSEd Maste 	/* Note that evutil_getenv_() ignores the environment entirely if
559c43e99fdSEd Maste 	 * we're setuid */
560c43e99fdSEd Maste 	return (evutil_getenv_(environment) != NULL);
561c43e99fdSEd Maste }
562c43e99fdSEd Maste 
563c43e99fdSEd Maste int
event_base_get_features(const struct event_base * base)564c43e99fdSEd Maste event_base_get_features(const struct event_base *base)
565c43e99fdSEd Maste {
566c43e99fdSEd Maste 	return base->evsel->features;
567c43e99fdSEd Maste }
568c43e99fdSEd Maste 
569c43e99fdSEd Maste void
event_enable_debug_mode(void)570c43e99fdSEd Maste event_enable_debug_mode(void)
571c43e99fdSEd Maste {
572c43e99fdSEd Maste #ifndef EVENT__DISABLE_DEBUG_MODE
573c43e99fdSEd Maste 	if (event_debug_mode_on_)
574c43e99fdSEd Maste 		event_errx(1, "%s was called twice!", __func__);
575c43e99fdSEd Maste 	if (event_debug_mode_too_late)
576c43e99fdSEd Maste 		event_errx(1, "%s must be called *before* creating any events "
577c43e99fdSEd Maste 		    "or event_bases",__func__);
578c43e99fdSEd Maste 
579c43e99fdSEd Maste 	event_debug_mode_on_ = 1;
580c43e99fdSEd Maste 
581c43e99fdSEd Maste 	HT_INIT(event_debug_map, &global_debug_map);
582c43e99fdSEd Maste #endif
583c43e99fdSEd Maste }
584c43e99fdSEd Maste 
585c43e99fdSEd Maste void
event_disable_debug_mode(void)586c43e99fdSEd Maste event_disable_debug_mode(void)
587c43e99fdSEd Maste {
588c43e99fdSEd Maste #ifndef EVENT__DISABLE_DEBUG_MODE
589c43e99fdSEd Maste 	struct event_debug_entry **ent, *victim;
590c43e99fdSEd Maste 
591c43e99fdSEd Maste 	EVLOCK_LOCK(event_debug_map_lock_, 0);
592c43e99fdSEd Maste 	for (ent = HT_START(event_debug_map, &global_debug_map); ent; ) {
593c43e99fdSEd Maste 		victim = *ent;
594c43e99fdSEd Maste 		ent = HT_NEXT_RMV(event_debug_map, &global_debug_map, ent);
595c43e99fdSEd Maste 		mm_free(victim);
596c43e99fdSEd Maste 	}
597c43e99fdSEd Maste 	HT_CLEAR(event_debug_map, &global_debug_map);
598c43e99fdSEd Maste 	EVLOCK_UNLOCK(event_debug_map_lock_ , 0);
599c43e99fdSEd Maste 
600c43e99fdSEd Maste 	event_debug_mode_on_  = 0;
601c43e99fdSEd Maste #endif
602c43e99fdSEd Maste }
603c43e99fdSEd Maste 
604c43e99fdSEd Maste struct event_base *
event_base_new_with_config(const struct event_config * cfg)605c43e99fdSEd Maste event_base_new_with_config(const struct event_config *cfg)
606c43e99fdSEd Maste {
607c43e99fdSEd Maste 	int i;
608c43e99fdSEd Maste 	struct event_base *base;
609c43e99fdSEd Maste 	int should_check_environment;
610c43e99fdSEd Maste 
611c43e99fdSEd Maste #ifndef EVENT__DISABLE_DEBUG_MODE
612c43e99fdSEd Maste 	event_debug_mode_too_late = 1;
613c43e99fdSEd Maste #endif
614c43e99fdSEd Maste 
615c43e99fdSEd Maste 	if ((base = mm_calloc(1, sizeof(struct event_base))) == NULL) {
616c43e99fdSEd Maste 		event_warn("%s: calloc", __func__);
617c43e99fdSEd Maste 		return NULL;
618c43e99fdSEd Maste 	}
619c43e99fdSEd Maste 
620c43e99fdSEd Maste 	if (cfg)
621c43e99fdSEd Maste 		base->flags = cfg->flags;
622c43e99fdSEd Maste 
623c43e99fdSEd Maste 	should_check_environment =
624c43e99fdSEd Maste 	    !(cfg && (cfg->flags & EVENT_BASE_FLAG_IGNORE_ENV));
625c43e99fdSEd Maste 
626c43e99fdSEd Maste 	{
627c43e99fdSEd Maste 		struct timeval tmp;
628c43e99fdSEd Maste 		int precise_time =
629c43e99fdSEd Maste 		    cfg && (cfg->flags & EVENT_BASE_FLAG_PRECISE_TIMER);
630c43e99fdSEd Maste 		int flags;
631c43e99fdSEd Maste 		if (should_check_environment && !precise_time) {
632c43e99fdSEd Maste 			precise_time = evutil_getenv_("EVENT_PRECISE_TIMER") != NULL;
633*b50261e2SCy Schubert 			if (precise_time) {
634c43e99fdSEd Maste 				base->flags |= EVENT_BASE_FLAG_PRECISE_TIMER;
635c43e99fdSEd Maste 			}
636*b50261e2SCy Schubert 		}
637c43e99fdSEd Maste 		flags = precise_time ? EV_MONOT_PRECISE : 0;
638c43e99fdSEd Maste 		evutil_configure_monotonic_time_(&base->monotonic_timer, flags);
639c43e99fdSEd Maste 
640c43e99fdSEd Maste 		gettime(base, &tmp);
641c43e99fdSEd Maste 	}
642c43e99fdSEd Maste 
643c43e99fdSEd Maste 	min_heap_ctor_(&base->timeheap);
644c43e99fdSEd Maste 
645c43e99fdSEd Maste 	base->sig.ev_signal_pair[0] = -1;
646c43e99fdSEd Maste 	base->sig.ev_signal_pair[1] = -1;
647c43e99fdSEd Maste 	base->th_notify_fd[0] = -1;
648c43e99fdSEd Maste 	base->th_notify_fd[1] = -1;
649c43e99fdSEd Maste 
650c43e99fdSEd Maste 	TAILQ_INIT(&base->active_later_queue);
651c43e99fdSEd Maste 
652c43e99fdSEd Maste 	evmap_io_initmap_(&base->io);
653c43e99fdSEd Maste 	evmap_signal_initmap_(&base->sigmap);
654c43e99fdSEd Maste 	event_changelist_init_(&base->changelist);
655c43e99fdSEd Maste 
656c43e99fdSEd Maste 	base->evbase = NULL;
657c43e99fdSEd Maste 
658c43e99fdSEd Maste 	if (cfg) {
659c43e99fdSEd Maste 		memcpy(&base->max_dispatch_time,
660c43e99fdSEd Maste 		    &cfg->max_dispatch_interval, sizeof(struct timeval));
661c43e99fdSEd Maste 		base->limit_callbacks_after_prio =
662c43e99fdSEd Maste 		    cfg->limit_callbacks_after_prio;
663c43e99fdSEd Maste 	} else {
664c43e99fdSEd Maste 		base->max_dispatch_time.tv_sec = -1;
665c43e99fdSEd Maste 		base->limit_callbacks_after_prio = 1;
666c43e99fdSEd Maste 	}
667c43e99fdSEd Maste 	if (cfg && cfg->max_dispatch_callbacks >= 0) {
668c43e99fdSEd Maste 		base->max_dispatch_callbacks = cfg->max_dispatch_callbacks;
669c43e99fdSEd Maste 	} else {
670c43e99fdSEd Maste 		base->max_dispatch_callbacks = INT_MAX;
671c43e99fdSEd Maste 	}
672c43e99fdSEd Maste 	if (base->max_dispatch_callbacks == INT_MAX &&
673c43e99fdSEd Maste 	    base->max_dispatch_time.tv_sec == -1)
674c43e99fdSEd Maste 		base->limit_callbacks_after_prio = INT_MAX;
675c43e99fdSEd Maste 
676c43e99fdSEd Maste 	for (i = 0; eventops[i] && !base->evbase; i++) {
677c43e99fdSEd Maste 		if (cfg != NULL) {
678c43e99fdSEd Maste 			/* determine if this backend should be avoided */
679c43e99fdSEd Maste 			if (event_config_is_avoided_method(cfg,
680c43e99fdSEd Maste 				eventops[i]->name))
681c43e99fdSEd Maste 				continue;
682c43e99fdSEd Maste 			if ((eventops[i]->features & cfg->require_features)
683c43e99fdSEd Maste 			    != cfg->require_features)
684c43e99fdSEd Maste 				continue;
685c43e99fdSEd Maste 		}
686c43e99fdSEd Maste 
687c43e99fdSEd Maste 		/* also obey the environment variables */
688c43e99fdSEd Maste 		if (should_check_environment &&
689c43e99fdSEd Maste 		    event_is_method_disabled(eventops[i]->name))
690c43e99fdSEd Maste 			continue;
691c43e99fdSEd Maste 
692c43e99fdSEd Maste 		base->evsel = eventops[i];
693c43e99fdSEd Maste 
694c43e99fdSEd Maste 		base->evbase = base->evsel->init(base);
695c43e99fdSEd Maste 	}
696c43e99fdSEd Maste 
697c43e99fdSEd Maste 	if (base->evbase == NULL) {
698c43e99fdSEd Maste 		event_warnx("%s: no event mechanism available",
699c43e99fdSEd Maste 		    __func__);
700c43e99fdSEd Maste 		base->evsel = NULL;
701c43e99fdSEd Maste 		event_base_free(base);
702c43e99fdSEd Maste 		return NULL;
703c43e99fdSEd Maste 	}
704c43e99fdSEd Maste 
705c43e99fdSEd Maste 	if (evutil_getenv_("EVENT_SHOW_METHOD"))
706c43e99fdSEd Maste 		event_msgx("libevent using: %s", base->evsel->name);
707c43e99fdSEd Maste 
708c43e99fdSEd Maste 	/* allocate a single active event queue */
709c43e99fdSEd Maste 	if (event_base_priority_init(base, 1) < 0) {
710c43e99fdSEd Maste 		event_base_free(base);
711c43e99fdSEd Maste 		return NULL;
712c43e99fdSEd Maste 	}
713c43e99fdSEd Maste 
714c43e99fdSEd Maste 	/* prepare for threading */
715c43e99fdSEd Maste 
716c43e99fdSEd Maste #if !defined(EVENT__DISABLE_THREAD_SUPPORT) && !defined(EVENT__DISABLE_DEBUG_MODE)
717c43e99fdSEd Maste 	event_debug_created_threadable_ctx_ = 1;
718c43e99fdSEd Maste #endif
719c43e99fdSEd Maste 
720c43e99fdSEd Maste #ifndef EVENT__DISABLE_THREAD_SUPPORT
721c43e99fdSEd Maste 	if (EVTHREAD_LOCKING_ENABLED() &&
722c43e99fdSEd Maste 	    (!cfg || !(cfg->flags & EVENT_BASE_FLAG_NOLOCK))) {
723c43e99fdSEd Maste 		int r;
724c43e99fdSEd Maste 		EVTHREAD_ALLOC_LOCK(base->th_base_lock, 0);
725c43e99fdSEd Maste 		EVTHREAD_ALLOC_COND(base->current_event_cond);
726c43e99fdSEd Maste 		r = evthread_make_base_notifiable(base);
727c43e99fdSEd Maste 		if (r<0) {
728c43e99fdSEd Maste 			event_warnx("%s: Unable to make base notifiable.", __func__);
729c43e99fdSEd Maste 			event_base_free(base);
730c43e99fdSEd Maste 			return NULL;
731c43e99fdSEd Maste 		}
732c43e99fdSEd Maste 	}
733c43e99fdSEd Maste #endif
734c43e99fdSEd Maste 
735c43e99fdSEd Maste #ifdef _WIN32
736c43e99fdSEd Maste 	if (cfg && (cfg->flags & EVENT_BASE_FLAG_STARTUP_IOCP))
737c43e99fdSEd Maste 		event_base_start_iocp_(base, cfg->n_cpus_hint);
738c43e99fdSEd Maste #endif
739c43e99fdSEd Maste 
740c43e99fdSEd Maste 	return (base);
741c43e99fdSEd Maste }
742c43e99fdSEd Maste 
743c43e99fdSEd Maste int
event_base_start_iocp_(struct event_base * base,int n_cpus)744c43e99fdSEd Maste event_base_start_iocp_(struct event_base *base, int n_cpus)
745c43e99fdSEd Maste {
746c43e99fdSEd Maste #ifdef _WIN32
747c43e99fdSEd Maste 	if (base->iocp)
748c43e99fdSEd Maste 		return 0;
749c43e99fdSEd Maste 	base->iocp = event_iocp_port_launch_(n_cpus);
750c43e99fdSEd Maste 	if (!base->iocp) {
751c43e99fdSEd Maste 		event_warnx("%s: Couldn't launch IOCP", __func__);
752c43e99fdSEd Maste 		return -1;
753c43e99fdSEd Maste 	}
754c43e99fdSEd Maste 	return 0;
755c43e99fdSEd Maste #else
756c43e99fdSEd Maste 	return -1;
757c43e99fdSEd Maste #endif
758c43e99fdSEd Maste }
759c43e99fdSEd Maste 
760c43e99fdSEd Maste void
event_base_stop_iocp_(struct event_base * base)761c43e99fdSEd Maste event_base_stop_iocp_(struct event_base *base)
762c43e99fdSEd Maste {
763c43e99fdSEd Maste #ifdef _WIN32
764c43e99fdSEd Maste 	int rv;
765c43e99fdSEd Maste 
766c43e99fdSEd Maste 	if (!base->iocp)
767c43e99fdSEd Maste 		return;
768c43e99fdSEd Maste 	rv = event_iocp_shutdown_(base->iocp, -1);
769c43e99fdSEd Maste 	EVUTIL_ASSERT(rv >= 0);
770c43e99fdSEd Maste 	base->iocp = NULL;
771c43e99fdSEd Maste #endif
772c43e99fdSEd Maste }
773c43e99fdSEd Maste 
774c43e99fdSEd Maste static int
event_base_cancel_single_callback_(struct event_base * base,struct event_callback * evcb,int run_finalizers)775c43e99fdSEd Maste event_base_cancel_single_callback_(struct event_base *base,
776c43e99fdSEd Maste     struct event_callback *evcb,
777c43e99fdSEd Maste     int run_finalizers)
778c43e99fdSEd Maste {
779c43e99fdSEd Maste 	int result = 0;
780c43e99fdSEd Maste 
781c43e99fdSEd Maste 	if (evcb->evcb_flags & EVLIST_INIT) {
782c43e99fdSEd Maste 		struct event *ev = event_callback_to_event(evcb);
783c43e99fdSEd Maste 		if (!(ev->ev_flags & EVLIST_INTERNAL)) {
784c43e99fdSEd Maste 			event_del_(ev, EVENT_DEL_EVEN_IF_FINALIZING);
785c43e99fdSEd Maste 			result = 1;
786c43e99fdSEd Maste 		}
787c43e99fdSEd Maste 	} else {
788c43e99fdSEd Maste 		EVBASE_ACQUIRE_LOCK(base, th_base_lock);
789c43e99fdSEd Maste 		event_callback_cancel_nolock_(base, evcb, 1);
790c43e99fdSEd Maste 		EVBASE_RELEASE_LOCK(base, th_base_lock);
791c43e99fdSEd Maste 		result = 1;
792c43e99fdSEd Maste 	}
793c43e99fdSEd Maste 
794c43e99fdSEd Maste 	if (run_finalizers && (evcb->evcb_flags & EVLIST_FINALIZING)) {
795c43e99fdSEd Maste 		switch (evcb->evcb_closure) {
796c43e99fdSEd Maste 		case EV_CLOSURE_EVENT_FINALIZE:
797c43e99fdSEd Maste 		case EV_CLOSURE_EVENT_FINALIZE_FREE: {
798c43e99fdSEd Maste 			struct event *ev = event_callback_to_event(evcb);
799c43e99fdSEd Maste 			ev->ev_evcallback.evcb_cb_union.evcb_evfinalize(ev, ev->ev_arg);
800c43e99fdSEd Maste 			if (evcb->evcb_closure == EV_CLOSURE_EVENT_FINALIZE_FREE)
801c43e99fdSEd Maste 				mm_free(ev);
802c43e99fdSEd Maste 			break;
803c43e99fdSEd Maste 		}
804c43e99fdSEd Maste 		case EV_CLOSURE_CB_FINALIZE:
805c43e99fdSEd Maste 			evcb->evcb_cb_union.evcb_cbfinalize(evcb, evcb->evcb_arg);
806c43e99fdSEd Maste 			break;
807c43e99fdSEd Maste 		default:
808c43e99fdSEd Maste 			break;
809c43e99fdSEd Maste 		}
810c43e99fdSEd Maste 	}
811c43e99fdSEd Maste 	return result;
812c43e99fdSEd Maste }
813c43e99fdSEd Maste 
event_base_free_queues_(struct event_base * base,int run_finalizers)814c43e99fdSEd Maste static int event_base_free_queues_(struct event_base *base, int run_finalizers)
815c43e99fdSEd Maste {
816c43e99fdSEd Maste 	int deleted = 0, i;
817c43e99fdSEd Maste 
818c43e99fdSEd Maste 	for (i = 0; i < base->nactivequeues; ++i) {
819c43e99fdSEd Maste 		struct event_callback *evcb, *next;
820c43e99fdSEd Maste 		for (evcb = TAILQ_FIRST(&base->activequeues[i]); evcb; ) {
821c43e99fdSEd Maste 			next = TAILQ_NEXT(evcb, evcb_active_next);
822c43e99fdSEd Maste 			deleted += event_base_cancel_single_callback_(base, evcb, run_finalizers);
823c43e99fdSEd Maste 			evcb = next;
824c43e99fdSEd Maste 		}
825c43e99fdSEd Maste 	}
826c43e99fdSEd Maste 
827c43e99fdSEd Maste 	{
828c43e99fdSEd Maste 		struct event_callback *evcb;
829c43e99fdSEd Maste 		while ((evcb = TAILQ_FIRST(&base->active_later_queue))) {
830c43e99fdSEd Maste 			deleted += event_base_cancel_single_callback_(base, evcb, run_finalizers);
831c43e99fdSEd Maste 		}
832c43e99fdSEd Maste 	}
833c43e99fdSEd Maste 
834c43e99fdSEd Maste 	return deleted;
835c43e99fdSEd Maste }
836c43e99fdSEd Maste 
837c43e99fdSEd Maste static void
event_base_free_(struct event_base * base,int run_finalizers)838c43e99fdSEd Maste event_base_free_(struct event_base *base, int run_finalizers)
839c43e99fdSEd Maste {
840c43e99fdSEd Maste 	int i, n_deleted=0;
841c43e99fdSEd Maste 	struct event *ev;
842c43e99fdSEd Maste 	/* XXXX grab the lock? If there is contention when one thread frees
843c43e99fdSEd Maste 	 * the base, then the contending thread will be very sad soon. */
844c43e99fdSEd Maste 
845c43e99fdSEd Maste 	/* event_base_free(NULL) is how to free the current_base if we
846c43e99fdSEd Maste 	 * made it with event_init and forgot to hold a reference to it. */
847c43e99fdSEd Maste 	if (base == NULL && current_base)
848c43e99fdSEd Maste 		base = current_base;
849c43e99fdSEd Maste 	/* Don't actually free NULL. */
850c43e99fdSEd Maste 	if (base == NULL) {
851c43e99fdSEd Maste 		event_warnx("%s: no base to free", __func__);
852c43e99fdSEd Maste 		return;
853c43e99fdSEd Maste 	}
854c43e99fdSEd Maste 	/* XXX(niels) - check for internal events first */
855c43e99fdSEd Maste 
856c43e99fdSEd Maste #ifdef _WIN32
857c43e99fdSEd Maste 	event_base_stop_iocp_(base);
858c43e99fdSEd Maste #endif
859c43e99fdSEd Maste 
860c43e99fdSEd Maste 	/* threading fds if we have them */
861c43e99fdSEd Maste 	if (base->th_notify_fd[0] != -1) {
862c43e99fdSEd Maste 		event_del(&base->th_notify);
863c43e99fdSEd Maste 		EVUTIL_CLOSESOCKET(base->th_notify_fd[0]);
864c43e99fdSEd Maste 		if (base->th_notify_fd[1] != -1)
865c43e99fdSEd Maste 			EVUTIL_CLOSESOCKET(base->th_notify_fd[1]);
866c43e99fdSEd Maste 		base->th_notify_fd[0] = -1;
867c43e99fdSEd Maste 		base->th_notify_fd[1] = -1;
868c43e99fdSEd Maste 		event_debug_unassign(&base->th_notify);
869c43e99fdSEd Maste 	}
870c43e99fdSEd Maste 
871c43e99fdSEd Maste 	/* Delete all non-internal events. */
872c43e99fdSEd Maste 	evmap_delete_all_(base);
873c43e99fdSEd Maste 
874c43e99fdSEd Maste 	while ((ev = min_heap_top_(&base->timeheap)) != NULL) {
875c43e99fdSEd Maste 		event_del(ev);
876c43e99fdSEd Maste 		++n_deleted;
877c43e99fdSEd Maste 	}
878c43e99fdSEd Maste 	for (i = 0; i < base->n_common_timeouts; ++i) {
879c43e99fdSEd Maste 		struct common_timeout_list *ctl =
880c43e99fdSEd Maste 		    base->common_timeout_queues[i];
881c43e99fdSEd Maste 		event_del(&ctl->timeout_event); /* Internal; doesn't count */
882c43e99fdSEd Maste 		event_debug_unassign(&ctl->timeout_event);
883c43e99fdSEd Maste 		for (ev = TAILQ_FIRST(&ctl->events); ev; ) {
884c43e99fdSEd Maste 			struct event *next = TAILQ_NEXT(ev,
885c43e99fdSEd Maste 			    ev_timeout_pos.ev_next_with_common_timeout);
886c43e99fdSEd Maste 			if (!(ev->ev_flags & EVLIST_INTERNAL)) {
887c43e99fdSEd Maste 				event_del(ev);
888c43e99fdSEd Maste 				++n_deleted;
889c43e99fdSEd Maste 			}
890c43e99fdSEd Maste 			ev = next;
891c43e99fdSEd Maste 		}
892c43e99fdSEd Maste 		mm_free(ctl);
893c43e99fdSEd Maste 	}
894c43e99fdSEd Maste 	if (base->common_timeout_queues)
895c43e99fdSEd Maste 		mm_free(base->common_timeout_queues);
896c43e99fdSEd Maste 
897c43e99fdSEd Maste 	for (;;) {
898c43e99fdSEd Maste 		/* For finalizers we can register yet another finalizer out from
899c43e99fdSEd Maste 		 * finalizer, and iff finalizer will be in active_later_queue we can
900c43e99fdSEd Maste 		 * add finalizer to activequeues, and we will have events in
901c43e99fdSEd Maste 		 * activequeues after this function returns, which is not what we want
902c43e99fdSEd Maste 		 * (we even have an assertion for this).
903c43e99fdSEd Maste 		 *
904c43e99fdSEd Maste 		 * A simple case is bufferevent with underlying (i.e. filters).
905c43e99fdSEd Maste 		 */
906c43e99fdSEd Maste 		int i = event_base_free_queues_(base, run_finalizers);
907*b50261e2SCy Schubert 		event_debug(("%s: %d events freed", __func__, i));
908c43e99fdSEd Maste 		if (!i) {
909c43e99fdSEd Maste 			break;
910c43e99fdSEd Maste 		}
911c43e99fdSEd Maste 		n_deleted += i;
912c43e99fdSEd Maste 	}
913c43e99fdSEd Maste 
914c43e99fdSEd Maste 	if (n_deleted)
915c43e99fdSEd Maste 		event_debug(("%s: %d events were still set in base",
916c43e99fdSEd Maste 			__func__, n_deleted));
917c43e99fdSEd Maste 
918c43e99fdSEd Maste 	while (LIST_FIRST(&base->once_events)) {
919c43e99fdSEd Maste 		struct event_once *eonce = LIST_FIRST(&base->once_events);
920c43e99fdSEd Maste 		LIST_REMOVE(eonce, next_once);
921c43e99fdSEd Maste 		mm_free(eonce);
922c43e99fdSEd Maste 	}
923c43e99fdSEd Maste 
924c43e99fdSEd Maste 	if (base->evsel != NULL && base->evsel->dealloc != NULL)
925c43e99fdSEd Maste 		base->evsel->dealloc(base);
926c43e99fdSEd Maste 
927c43e99fdSEd Maste 	for (i = 0; i < base->nactivequeues; ++i)
928c43e99fdSEd Maste 		EVUTIL_ASSERT(TAILQ_EMPTY(&base->activequeues[i]));
929c43e99fdSEd Maste 
930c43e99fdSEd Maste 	EVUTIL_ASSERT(min_heap_empty_(&base->timeheap));
931c43e99fdSEd Maste 	min_heap_dtor_(&base->timeheap);
932c43e99fdSEd Maste 
933c43e99fdSEd Maste 	mm_free(base->activequeues);
934c43e99fdSEd Maste 
935c43e99fdSEd Maste 	evmap_io_clear_(&base->io);
936c43e99fdSEd Maste 	evmap_signal_clear_(&base->sigmap);
937c43e99fdSEd Maste 	event_changelist_freemem_(&base->changelist);
938c43e99fdSEd Maste 
939c43e99fdSEd Maste 	EVTHREAD_FREE_LOCK(base->th_base_lock, 0);
940c43e99fdSEd Maste 	EVTHREAD_FREE_COND(base->current_event_cond);
941c43e99fdSEd Maste 
942c43e99fdSEd Maste 	/* If we're freeing current_base, there won't be a current_base. */
943c43e99fdSEd Maste 	if (base == current_base)
944c43e99fdSEd Maste 		current_base = NULL;
945c43e99fdSEd Maste 	mm_free(base);
946c43e99fdSEd Maste }
947c43e99fdSEd Maste 
948c43e99fdSEd Maste void
event_base_free_nofinalize(struct event_base * base)949c43e99fdSEd Maste event_base_free_nofinalize(struct event_base *base)
950c43e99fdSEd Maste {
951c43e99fdSEd Maste 	event_base_free_(base, 0);
952c43e99fdSEd Maste }
953c43e99fdSEd Maste 
954c43e99fdSEd Maste void
event_base_free(struct event_base * base)955c43e99fdSEd Maste event_base_free(struct event_base *base)
956c43e99fdSEd Maste {
957c43e99fdSEd Maste 	event_base_free_(base, 1);
958c43e99fdSEd Maste }
959c43e99fdSEd Maste 
960c43e99fdSEd Maste /* Fake eventop; used to disable the backend temporarily inside event_reinit
961c43e99fdSEd Maste  * so that we can call event_del() on an event without telling the backend.
962c43e99fdSEd Maste  */
963c43e99fdSEd Maste static int
nil_backend_del(struct event_base * b,evutil_socket_t fd,short old,short events,void * fdinfo)964c43e99fdSEd Maste nil_backend_del(struct event_base *b, evutil_socket_t fd, short old,
965c43e99fdSEd Maste     short events, void *fdinfo)
966c43e99fdSEd Maste {
967c43e99fdSEd Maste 	return 0;
968c43e99fdSEd Maste }
969c43e99fdSEd Maste const struct eventop nil_eventop = {
970c43e99fdSEd Maste 	"nil",
971c43e99fdSEd Maste 	NULL, /* init: unused. */
972c43e99fdSEd Maste 	NULL, /* add: unused. */
973c43e99fdSEd Maste 	nil_backend_del, /* del: used, so needs to be killed. */
974c43e99fdSEd Maste 	NULL, /* dispatch: unused. */
975c43e99fdSEd Maste 	NULL, /* dealloc: unused. */
976c43e99fdSEd Maste 	0, 0, 0
977c43e99fdSEd Maste };
978c43e99fdSEd Maste 
979c43e99fdSEd Maste /* reinitialize the event base after a fork */
980c43e99fdSEd Maste int
event_reinit(struct event_base * base)981c43e99fdSEd Maste event_reinit(struct event_base *base)
982c43e99fdSEd Maste {
983c43e99fdSEd Maste 	const struct eventop *evsel;
984c43e99fdSEd Maste 	int res = 0;
985c43e99fdSEd Maste 	int was_notifiable = 0;
986c43e99fdSEd Maste 	int had_signal_added = 0;
987c43e99fdSEd Maste 
988c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
989c43e99fdSEd Maste 
990c43e99fdSEd Maste 	evsel = base->evsel;
991c43e99fdSEd Maste 
992c43e99fdSEd Maste 	/* check if this event mechanism requires reinit on the backend */
993c43e99fdSEd Maste 	if (evsel->need_reinit) {
994c43e99fdSEd Maste 		/* We're going to call event_del() on our notify events (the
995c43e99fdSEd Maste 		 * ones that tell about signals and wakeup events).  But we
996c43e99fdSEd Maste 		 * don't actually want to tell the backend to change its
997c43e99fdSEd Maste 		 * state, since it might still share some resource (a kqueue,
998c43e99fdSEd Maste 		 * an epoll fd) with the parent process, and we don't want to
999c43e99fdSEd Maste 		 * delete the fds from _that_ backend, we temporarily stub out
1000c43e99fdSEd Maste 		 * the evsel with a replacement.
1001c43e99fdSEd Maste 		 */
1002c43e99fdSEd Maste 		base->evsel = &nil_eventop;
1003c43e99fdSEd Maste 	}
1004c43e99fdSEd Maste 
1005c43e99fdSEd Maste 	/* We need to re-create a new signal-notification fd and a new
1006c43e99fdSEd Maste 	 * thread-notification fd.  Otherwise, we'll still share those with
1007c43e99fdSEd Maste 	 * the parent process, which would make any notification sent to them
1008c43e99fdSEd Maste 	 * get received by one or both of the event loops, more or less at
1009c43e99fdSEd Maste 	 * random.
1010c43e99fdSEd Maste 	 */
1011c43e99fdSEd Maste 	if (base->sig.ev_signal_added) {
1012c43e99fdSEd Maste 		event_del_nolock_(&base->sig.ev_signal, EVENT_DEL_AUTOBLOCK);
1013c43e99fdSEd Maste 		event_debug_unassign(&base->sig.ev_signal);
1014c43e99fdSEd Maste 		memset(&base->sig.ev_signal, 0, sizeof(base->sig.ev_signal));
1015c43e99fdSEd Maste 		had_signal_added = 1;
1016c43e99fdSEd Maste 		base->sig.ev_signal_added = 0;
1017c43e99fdSEd Maste 	}
1018c43e99fdSEd Maste 	if (base->sig.ev_signal_pair[0] != -1)
1019c43e99fdSEd Maste 		EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[0]);
1020c43e99fdSEd Maste 	if (base->sig.ev_signal_pair[1] != -1)
1021c43e99fdSEd Maste 		EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[1]);
1022c43e99fdSEd Maste 	if (base->th_notify_fn != NULL) {
1023c43e99fdSEd Maste 		was_notifiable = 1;
1024c43e99fdSEd Maste 		base->th_notify_fn = NULL;
1025c43e99fdSEd Maste 	}
1026c43e99fdSEd Maste 	if (base->th_notify_fd[0] != -1) {
1027c43e99fdSEd Maste 		event_del_nolock_(&base->th_notify, EVENT_DEL_AUTOBLOCK);
1028c43e99fdSEd Maste 		EVUTIL_CLOSESOCKET(base->th_notify_fd[0]);
1029c43e99fdSEd Maste 		if (base->th_notify_fd[1] != -1)
1030c43e99fdSEd Maste 			EVUTIL_CLOSESOCKET(base->th_notify_fd[1]);
1031c43e99fdSEd Maste 		base->th_notify_fd[0] = -1;
1032c43e99fdSEd Maste 		base->th_notify_fd[1] = -1;
1033c43e99fdSEd Maste 		event_debug_unassign(&base->th_notify);
1034c43e99fdSEd Maste 	}
1035c43e99fdSEd Maste 
1036c43e99fdSEd Maste 	/* Replace the original evsel. */
1037c43e99fdSEd Maste         base->evsel = evsel;
1038c43e99fdSEd Maste 
1039c43e99fdSEd Maste 	if (evsel->need_reinit) {
1040c43e99fdSEd Maste 		/* Reconstruct the backend through brute-force, so that we do
1041c43e99fdSEd Maste 		 * not share any structures with the parent process. For some
1042c43e99fdSEd Maste 		 * backends, this is necessary: epoll and kqueue, for
1043c43e99fdSEd Maste 		 * instance, have events associated with a kernel
1044c43e99fdSEd Maste 		 * structure. If didn't reinitialize, we'd share that
1045c43e99fdSEd Maste 		 * structure with the parent process, and any changes made by
1046c43e99fdSEd Maste 		 * the parent would affect our backend's behavior (and vice
1047c43e99fdSEd Maste 		 * versa).
1048c43e99fdSEd Maste 		 */
1049c43e99fdSEd Maste 		if (base->evsel->dealloc != NULL)
1050c43e99fdSEd Maste 			base->evsel->dealloc(base);
1051c43e99fdSEd Maste 		base->evbase = evsel->init(base);
1052c43e99fdSEd Maste 		if (base->evbase == NULL) {
1053c43e99fdSEd Maste 			event_errx(1,
1054c43e99fdSEd Maste 			   "%s: could not reinitialize event mechanism",
1055c43e99fdSEd Maste 			   __func__);
1056c43e99fdSEd Maste 			res = -1;
1057c43e99fdSEd Maste 			goto done;
1058c43e99fdSEd Maste 		}
1059c43e99fdSEd Maste 
1060c43e99fdSEd Maste 		/* Empty out the changelist (if any): we are starting from a
1061c43e99fdSEd Maste 		 * blank slate. */
1062c43e99fdSEd Maste 		event_changelist_freemem_(&base->changelist);
1063c43e99fdSEd Maste 
1064c43e99fdSEd Maste 		/* Tell the event maps to re-inform the backend about all
1065c43e99fdSEd Maste 		 * pending events. This will make the signal notification
1066c43e99fdSEd Maste 		 * event get re-created if necessary. */
1067c43e99fdSEd Maste 		if (evmap_reinit_(base) < 0)
1068c43e99fdSEd Maste 			res = -1;
1069c43e99fdSEd Maste 	} else {
1070c43e99fdSEd Maste 		res = evsig_init_(base);
1071c43e99fdSEd Maste 		if (res == 0 && had_signal_added) {
1072c43e99fdSEd Maste 			res = event_add_nolock_(&base->sig.ev_signal, NULL, 0);
1073c43e99fdSEd Maste 			if (res == 0)
1074c43e99fdSEd Maste 				base->sig.ev_signal_added = 1;
1075c43e99fdSEd Maste 		}
1076c43e99fdSEd Maste 	}
1077c43e99fdSEd Maste 
1078c43e99fdSEd Maste 	/* If we were notifiable before, and nothing just exploded, become
1079c43e99fdSEd Maste 	 * notifiable again. */
1080c43e99fdSEd Maste 	if (was_notifiable && res == 0)
1081c43e99fdSEd Maste 		res = evthread_make_base_notifiable_nolock_(base);
1082c43e99fdSEd Maste 
1083c43e99fdSEd Maste done:
1084c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
1085c43e99fdSEd Maste 	return (res);
1086c43e99fdSEd Maste }
1087c43e99fdSEd Maste 
1088c43e99fdSEd Maste /* Get the monotonic time for this event_base' timer */
1089c43e99fdSEd Maste int
event_gettime_monotonic(struct event_base * base,struct timeval * tv)1090c43e99fdSEd Maste event_gettime_monotonic(struct event_base *base, struct timeval *tv)
1091c43e99fdSEd Maste {
1092c43e99fdSEd Maste   int rv = -1;
1093c43e99fdSEd Maste 
1094c43e99fdSEd Maste   if (base && tv) {
1095c43e99fdSEd Maste     EVBASE_ACQUIRE_LOCK(base, th_base_lock);
1096c43e99fdSEd Maste     rv = evutil_gettime_monotonic_(&(base->monotonic_timer), tv);
1097c43e99fdSEd Maste     EVBASE_RELEASE_LOCK(base, th_base_lock);
1098c43e99fdSEd Maste   }
1099c43e99fdSEd Maste 
1100c43e99fdSEd Maste   return rv;
1101c43e99fdSEd Maste }
1102c43e99fdSEd Maste 
1103c43e99fdSEd Maste const char **
event_get_supported_methods(void)1104c43e99fdSEd Maste event_get_supported_methods(void)
1105c43e99fdSEd Maste {
1106c43e99fdSEd Maste 	static const char **methods = NULL;
1107c43e99fdSEd Maste 	const struct eventop **method;
1108c43e99fdSEd Maste 	const char **tmp;
1109c43e99fdSEd Maste 	int i = 0, k;
1110c43e99fdSEd Maste 
1111c43e99fdSEd Maste 	/* count all methods */
1112c43e99fdSEd Maste 	for (method = &eventops[0]; *method != NULL; ++method) {
1113c43e99fdSEd Maste 		++i;
1114c43e99fdSEd Maste 	}
1115c43e99fdSEd Maste 
1116c43e99fdSEd Maste 	/* allocate one more than we need for the NULL pointer */
1117c43e99fdSEd Maste 	tmp = mm_calloc((i + 1), sizeof(char *));
1118c43e99fdSEd Maste 	if (tmp == NULL)
1119c43e99fdSEd Maste 		return (NULL);
1120c43e99fdSEd Maste 
1121c43e99fdSEd Maste 	/* populate the array with the supported methods */
1122c43e99fdSEd Maste 	for (k = 0, i = 0; eventops[k] != NULL; ++k) {
1123c43e99fdSEd Maste 		tmp[i++] = eventops[k]->name;
1124c43e99fdSEd Maste 	}
1125c43e99fdSEd Maste 	tmp[i] = NULL;
1126c43e99fdSEd Maste 
1127c43e99fdSEd Maste 	if (methods != NULL)
1128c43e99fdSEd Maste 		mm_free((char**)methods);
1129c43e99fdSEd Maste 
1130c43e99fdSEd Maste 	methods = tmp;
1131c43e99fdSEd Maste 
1132c43e99fdSEd Maste 	return (methods);
1133c43e99fdSEd Maste }
1134c43e99fdSEd Maste 
1135c43e99fdSEd Maste struct event_config *
event_config_new(void)1136c43e99fdSEd Maste event_config_new(void)
1137c43e99fdSEd Maste {
1138c43e99fdSEd Maste 	struct event_config *cfg = mm_calloc(1, sizeof(*cfg));
1139c43e99fdSEd Maste 
1140c43e99fdSEd Maste 	if (cfg == NULL)
1141c43e99fdSEd Maste 		return (NULL);
1142c43e99fdSEd Maste 
1143c43e99fdSEd Maste 	TAILQ_INIT(&cfg->entries);
1144c43e99fdSEd Maste 	cfg->max_dispatch_interval.tv_sec = -1;
1145c43e99fdSEd Maste 	cfg->max_dispatch_callbacks = INT_MAX;
1146c43e99fdSEd Maste 	cfg->limit_callbacks_after_prio = 1;
1147c43e99fdSEd Maste 
1148c43e99fdSEd Maste 	return (cfg);
1149c43e99fdSEd Maste }
1150c43e99fdSEd Maste 
1151c43e99fdSEd Maste static void
event_config_entry_free(struct event_config_entry * entry)1152c43e99fdSEd Maste event_config_entry_free(struct event_config_entry *entry)
1153c43e99fdSEd Maste {
1154c43e99fdSEd Maste 	if (entry->avoid_method != NULL)
1155c43e99fdSEd Maste 		mm_free((char *)entry->avoid_method);
1156c43e99fdSEd Maste 	mm_free(entry);
1157c43e99fdSEd Maste }
1158c43e99fdSEd Maste 
1159c43e99fdSEd Maste void
event_config_free(struct event_config * cfg)1160c43e99fdSEd Maste event_config_free(struct event_config *cfg)
1161c43e99fdSEd Maste {
1162c43e99fdSEd Maste 	struct event_config_entry *entry;
1163c43e99fdSEd Maste 
1164c43e99fdSEd Maste 	while ((entry = TAILQ_FIRST(&cfg->entries)) != NULL) {
1165c43e99fdSEd Maste 		TAILQ_REMOVE(&cfg->entries, entry, next);
1166c43e99fdSEd Maste 		event_config_entry_free(entry);
1167c43e99fdSEd Maste 	}
1168c43e99fdSEd Maste 	mm_free(cfg);
1169c43e99fdSEd Maste }
1170c43e99fdSEd Maste 
1171c43e99fdSEd Maste int
event_config_set_flag(struct event_config * cfg,int flag)1172c43e99fdSEd Maste event_config_set_flag(struct event_config *cfg, int flag)
1173c43e99fdSEd Maste {
1174c43e99fdSEd Maste 	if (!cfg)
1175c43e99fdSEd Maste 		return -1;
1176c43e99fdSEd Maste 	cfg->flags |= flag;
1177c43e99fdSEd Maste 	return 0;
1178c43e99fdSEd Maste }
1179c43e99fdSEd Maste 
1180c43e99fdSEd Maste int
event_config_avoid_method(struct event_config * cfg,const char * method)1181c43e99fdSEd Maste event_config_avoid_method(struct event_config *cfg, const char *method)
1182c43e99fdSEd Maste {
1183c43e99fdSEd Maste 	struct event_config_entry *entry = mm_malloc(sizeof(*entry));
1184c43e99fdSEd Maste 	if (entry == NULL)
1185c43e99fdSEd Maste 		return (-1);
1186c43e99fdSEd Maste 
1187c43e99fdSEd Maste 	if ((entry->avoid_method = mm_strdup(method)) == NULL) {
1188c43e99fdSEd Maste 		mm_free(entry);
1189c43e99fdSEd Maste 		return (-1);
1190c43e99fdSEd Maste 	}
1191c43e99fdSEd Maste 
1192c43e99fdSEd Maste 	TAILQ_INSERT_TAIL(&cfg->entries, entry, next);
1193c43e99fdSEd Maste 
1194c43e99fdSEd Maste 	return (0);
1195c43e99fdSEd Maste }
1196c43e99fdSEd Maste 
1197c43e99fdSEd Maste int
event_config_require_features(struct event_config * cfg,int features)1198c43e99fdSEd Maste event_config_require_features(struct event_config *cfg,
1199c43e99fdSEd Maste     int features)
1200c43e99fdSEd Maste {
1201c43e99fdSEd Maste 	if (!cfg)
1202c43e99fdSEd Maste 		return (-1);
1203c43e99fdSEd Maste 	cfg->require_features = features;
1204c43e99fdSEd Maste 	return (0);
1205c43e99fdSEd Maste }
1206c43e99fdSEd Maste 
1207c43e99fdSEd Maste int
event_config_set_num_cpus_hint(struct event_config * cfg,int cpus)1208c43e99fdSEd Maste event_config_set_num_cpus_hint(struct event_config *cfg, int cpus)
1209c43e99fdSEd Maste {
1210c43e99fdSEd Maste 	if (!cfg)
1211c43e99fdSEd Maste 		return (-1);
1212c43e99fdSEd Maste 	cfg->n_cpus_hint = cpus;
1213c43e99fdSEd Maste 	return (0);
1214c43e99fdSEd Maste }
1215c43e99fdSEd Maste 
1216c43e99fdSEd Maste int
event_config_set_max_dispatch_interval(struct event_config * cfg,const struct timeval * max_interval,int max_callbacks,int min_priority)1217c43e99fdSEd Maste event_config_set_max_dispatch_interval(struct event_config *cfg,
1218c43e99fdSEd Maste     const struct timeval *max_interval, int max_callbacks, int min_priority)
1219c43e99fdSEd Maste {
1220c43e99fdSEd Maste 	if (max_interval)
1221c43e99fdSEd Maste 		memcpy(&cfg->max_dispatch_interval, max_interval,
1222c43e99fdSEd Maste 		    sizeof(struct timeval));
1223c43e99fdSEd Maste 	else
1224c43e99fdSEd Maste 		cfg->max_dispatch_interval.tv_sec = -1;
1225c43e99fdSEd Maste 	cfg->max_dispatch_callbacks =
1226c43e99fdSEd Maste 	    max_callbacks >= 0 ? max_callbacks : INT_MAX;
1227c43e99fdSEd Maste 	if (min_priority < 0)
1228c43e99fdSEd Maste 		min_priority = 0;
1229c43e99fdSEd Maste 	cfg->limit_callbacks_after_prio = min_priority;
1230c43e99fdSEd Maste 	return (0);
1231c43e99fdSEd Maste }
1232c43e99fdSEd Maste 
1233c43e99fdSEd Maste int
event_priority_init(int npriorities)1234c43e99fdSEd Maste event_priority_init(int npriorities)
1235c43e99fdSEd Maste {
1236c43e99fdSEd Maste 	return event_base_priority_init(current_base, npriorities);
1237c43e99fdSEd Maste }
1238c43e99fdSEd Maste 
1239c43e99fdSEd Maste int
event_base_priority_init(struct event_base * base,int npriorities)1240c43e99fdSEd Maste event_base_priority_init(struct event_base *base, int npriorities)
1241c43e99fdSEd Maste {
1242c43e99fdSEd Maste 	int i, r;
1243c43e99fdSEd Maste 	r = -1;
1244c43e99fdSEd Maste 
1245c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
1246c43e99fdSEd Maste 
1247c43e99fdSEd Maste 	if (N_ACTIVE_CALLBACKS(base) || npriorities < 1
1248c43e99fdSEd Maste 	    || npriorities >= EVENT_MAX_PRIORITIES)
1249c43e99fdSEd Maste 		goto err;
1250c43e99fdSEd Maste 
1251c43e99fdSEd Maste 	if (npriorities == base->nactivequeues)
1252c43e99fdSEd Maste 		goto ok;
1253c43e99fdSEd Maste 
1254c43e99fdSEd Maste 	if (base->nactivequeues) {
1255c43e99fdSEd Maste 		mm_free(base->activequeues);
1256c43e99fdSEd Maste 		base->nactivequeues = 0;
1257c43e99fdSEd Maste 	}
1258c43e99fdSEd Maste 
1259c43e99fdSEd Maste 	/* Allocate our priority queues */
1260c43e99fdSEd Maste 	base->activequeues = (struct evcallback_list *)
1261c43e99fdSEd Maste 	  mm_calloc(npriorities, sizeof(struct evcallback_list));
1262c43e99fdSEd Maste 	if (base->activequeues == NULL) {
1263c43e99fdSEd Maste 		event_warn("%s: calloc", __func__);
1264c43e99fdSEd Maste 		goto err;
1265c43e99fdSEd Maste 	}
1266c43e99fdSEd Maste 	base->nactivequeues = npriorities;
1267c43e99fdSEd Maste 
1268c43e99fdSEd Maste 	for (i = 0; i < base->nactivequeues; ++i) {
1269c43e99fdSEd Maste 		TAILQ_INIT(&base->activequeues[i]);
1270c43e99fdSEd Maste 	}
1271c43e99fdSEd Maste 
1272c43e99fdSEd Maste ok:
1273c43e99fdSEd Maste 	r = 0;
1274c43e99fdSEd Maste err:
1275c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
1276c43e99fdSEd Maste 	return (r);
1277c43e99fdSEd Maste }
1278c43e99fdSEd Maste 
1279c43e99fdSEd Maste int
event_base_get_npriorities(struct event_base * base)1280c43e99fdSEd Maste event_base_get_npriorities(struct event_base *base)
1281c43e99fdSEd Maste {
1282c43e99fdSEd Maste 
1283c43e99fdSEd Maste 	int n;
1284c43e99fdSEd Maste 	if (base == NULL)
1285c43e99fdSEd Maste 		base = current_base;
1286c43e99fdSEd Maste 
1287c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
1288c43e99fdSEd Maste 	n = base->nactivequeues;
1289c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
1290c43e99fdSEd Maste 	return (n);
1291c43e99fdSEd Maste }
1292c43e99fdSEd Maste 
1293c43e99fdSEd Maste int
event_base_get_num_events(struct event_base * base,unsigned int type)1294c43e99fdSEd Maste event_base_get_num_events(struct event_base *base, unsigned int type)
1295c43e99fdSEd Maste {
1296c43e99fdSEd Maste 	int r = 0;
1297c43e99fdSEd Maste 
1298c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
1299c43e99fdSEd Maste 
1300c43e99fdSEd Maste 	if (type & EVENT_BASE_COUNT_ACTIVE)
1301c43e99fdSEd Maste 		r += base->event_count_active;
1302c43e99fdSEd Maste 
1303c43e99fdSEd Maste 	if (type & EVENT_BASE_COUNT_VIRTUAL)
1304c43e99fdSEd Maste 		r += base->virtual_event_count;
1305c43e99fdSEd Maste 
1306c43e99fdSEd Maste 	if (type & EVENT_BASE_COUNT_ADDED)
1307c43e99fdSEd Maste 		r += base->event_count;
1308c43e99fdSEd Maste 
1309c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
1310c43e99fdSEd Maste 
1311c43e99fdSEd Maste 	return r;
1312c43e99fdSEd Maste }
1313c43e99fdSEd Maste 
1314c43e99fdSEd Maste int
event_base_get_max_events(struct event_base * base,unsigned int type,int clear)1315c43e99fdSEd Maste event_base_get_max_events(struct event_base *base, unsigned int type, int clear)
1316c43e99fdSEd Maste {
1317c43e99fdSEd Maste 	int r = 0;
1318c43e99fdSEd Maste 
1319c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
1320c43e99fdSEd Maste 
1321c43e99fdSEd Maste 	if (type & EVENT_BASE_COUNT_ACTIVE) {
1322c43e99fdSEd Maste 		r += base->event_count_active_max;
1323c43e99fdSEd Maste 		if (clear)
1324c43e99fdSEd Maste 			base->event_count_active_max = 0;
1325c43e99fdSEd Maste 	}
1326c43e99fdSEd Maste 
1327c43e99fdSEd Maste 	if (type & EVENT_BASE_COUNT_VIRTUAL) {
1328c43e99fdSEd Maste 		r += base->virtual_event_count_max;
1329c43e99fdSEd Maste 		if (clear)
1330c43e99fdSEd Maste 			base->virtual_event_count_max = 0;
1331c43e99fdSEd Maste 	}
1332c43e99fdSEd Maste 
1333c43e99fdSEd Maste 	if (type & EVENT_BASE_COUNT_ADDED) {
1334c43e99fdSEd Maste 		r += base->event_count_max;
1335c43e99fdSEd Maste 		if (clear)
1336c43e99fdSEd Maste 			base->event_count_max = 0;
1337c43e99fdSEd Maste 	}
1338c43e99fdSEd Maste 
1339c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
1340c43e99fdSEd Maste 
1341c43e99fdSEd Maste 	return r;
1342c43e99fdSEd Maste }
1343c43e99fdSEd Maste 
1344c43e99fdSEd Maste /* Returns true iff we're currently watching any events. */
1345c43e99fdSEd Maste static int
event_haveevents(struct event_base * base)1346c43e99fdSEd Maste event_haveevents(struct event_base *base)
1347c43e99fdSEd Maste {
1348c43e99fdSEd Maste 	/* Caller must hold th_base_lock */
1349c43e99fdSEd Maste 	return (base->virtual_event_count > 0 || base->event_count > 0);
1350c43e99fdSEd Maste }
1351c43e99fdSEd Maste 
1352c43e99fdSEd Maste /* "closure" function called when processing active signal events */
1353c43e99fdSEd Maste static inline void
event_signal_closure(struct event_base * base,struct event * ev)1354c43e99fdSEd Maste event_signal_closure(struct event_base *base, struct event *ev)
1355c43e99fdSEd Maste {
1356c43e99fdSEd Maste 	short ncalls;
1357c43e99fdSEd Maste 	int should_break;
1358c43e99fdSEd Maste 
1359c43e99fdSEd Maste 	/* Allows deletes to work */
1360c43e99fdSEd Maste 	ncalls = ev->ev_ncalls;
1361c43e99fdSEd Maste 	if (ncalls != 0)
1362c43e99fdSEd Maste 		ev->ev_pncalls = &ncalls;
1363c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
1364c43e99fdSEd Maste 	while (ncalls) {
1365c43e99fdSEd Maste 		ncalls--;
1366c43e99fdSEd Maste 		ev->ev_ncalls = ncalls;
1367c43e99fdSEd Maste 		if (ncalls == 0)
1368c43e99fdSEd Maste 			ev->ev_pncalls = NULL;
1369c43e99fdSEd Maste 		(*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg);
1370c43e99fdSEd Maste 
1371c43e99fdSEd Maste 		EVBASE_ACQUIRE_LOCK(base, th_base_lock);
1372c43e99fdSEd Maste 		should_break = base->event_break;
1373c43e99fdSEd Maste 		EVBASE_RELEASE_LOCK(base, th_base_lock);
1374c43e99fdSEd Maste 
1375c43e99fdSEd Maste 		if (should_break) {
1376c43e99fdSEd Maste 			if (ncalls != 0)
1377c43e99fdSEd Maste 				ev->ev_pncalls = NULL;
1378c43e99fdSEd Maste 			return;
1379c43e99fdSEd Maste 		}
1380c43e99fdSEd Maste 	}
1381c43e99fdSEd Maste }
1382c43e99fdSEd Maste 
1383c43e99fdSEd Maste /* Common timeouts are special timeouts that are handled as queues rather than
1384c43e99fdSEd Maste  * in the minheap.  This is more efficient than the minheap if we happen to
1385c43e99fdSEd Maste  * know that we're going to get several thousands of timeout events all with
1386c43e99fdSEd Maste  * the same timeout value.
1387c43e99fdSEd Maste  *
1388c43e99fdSEd Maste  * Since all our timeout handling code assumes timevals can be copied,
1389c43e99fdSEd Maste  * assigned, etc, we can't use "magic pointer" to encode these common
1390c43e99fdSEd Maste  * timeouts.  Searching through a list to see if every timeout is common could
1391c43e99fdSEd Maste  * also get inefficient.  Instead, we take advantage of the fact that tv_usec
1392c43e99fdSEd Maste  * is 32 bits long, but only uses 20 of those bits (since it can never be over
1393c43e99fdSEd Maste  * 999999.)  We use the top bits to encode 4 bites of magic number, and 8 bits
1394c43e99fdSEd Maste  * of index into the event_base's aray of common timeouts.
1395c43e99fdSEd Maste  */
1396c43e99fdSEd Maste 
1397c43e99fdSEd Maste #define MICROSECONDS_MASK       COMMON_TIMEOUT_MICROSECONDS_MASK
1398c43e99fdSEd Maste #define COMMON_TIMEOUT_IDX_MASK 0x0ff00000
1399c43e99fdSEd Maste #define COMMON_TIMEOUT_IDX_SHIFT 20
1400c43e99fdSEd Maste #define COMMON_TIMEOUT_MASK     0xf0000000
1401c43e99fdSEd Maste #define COMMON_TIMEOUT_MAGIC    0x50000000
1402c43e99fdSEd Maste 
1403c43e99fdSEd Maste #define COMMON_TIMEOUT_IDX(tv) \
1404c43e99fdSEd Maste 	(((tv)->tv_usec & COMMON_TIMEOUT_IDX_MASK)>>COMMON_TIMEOUT_IDX_SHIFT)
1405c43e99fdSEd Maste 
1406c43e99fdSEd Maste /** Return true iff if 'tv' is a common timeout in 'base' */
1407c43e99fdSEd Maste static inline int
is_common_timeout(const struct timeval * tv,const struct event_base * base)1408c43e99fdSEd Maste is_common_timeout(const struct timeval *tv,
1409c43e99fdSEd Maste     const struct event_base *base)
1410c43e99fdSEd Maste {
1411c43e99fdSEd Maste 	int idx;
1412c43e99fdSEd Maste 	if ((tv->tv_usec & COMMON_TIMEOUT_MASK) != COMMON_TIMEOUT_MAGIC)
1413c43e99fdSEd Maste 		return 0;
1414c43e99fdSEd Maste 	idx = COMMON_TIMEOUT_IDX(tv);
1415c43e99fdSEd Maste 	return idx < base->n_common_timeouts;
1416c43e99fdSEd Maste }
1417c43e99fdSEd Maste 
1418c43e99fdSEd Maste /* True iff tv1 and tv2 have the same common-timeout index, or if neither
1419c43e99fdSEd Maste  * one is a common timeout. */
1420c43e99fdSEd Maste static inline int
is_same_common_timeout(const struct timeval * tv1,const struct timeval * tv2)1421c43e99fdSEd Maste is_same_common_timeout(const struct timeval *tv1, const struct timeval *tv2)
1422c43e99fdSEd Maste {
1423c43e99fdSEd Maste 	return (tv1->tv_usec & ~MICROSECONDS_MASK) ==
1424c43e99fdSEd Maste 	    (tv2->tv_usec & ~MICROSECONDS_MASK);
1425c43e99fdSEd Maste }
1426c43e99fdSEd Maste 
1427c43e99fdSEd Maste /** Requires that 'tv' is a common timeout.  Return the corresponding
1428c43e99fdSEd Maste  * common_timeout_list. */
1429c43e99fdSEd Maste static inline struct common_timeout_list *
get_common_timeout_list(struct event_base * base,const struct timeval * tv)1430c43e99fdSEd Maste get_common_timeout_list(struct event_base *base, const struct timeval *tv)
1431c43e99fdSEd Maste {
1432c43e99fdSEd Maste 	return base->common_timeout_queues[COMMON_TIMEOUT_IDX(tv)];
1433c43e99fdSEd Maste }
1434c43e99fdSEd Maste 
1435c43e99fdSEd Maste #if 0
1436c43e99fdSEd Maste static inline int
1437c43e99fdSEd Maste common_timeout_ok(const struct timeval *tv,
1438c43e99fdSEd Maste     struct event_base *base)
1439c43e99fdSEd Maste {
1440c43e99fdSEd Maste 	const struct timeval *expect =
1441c43e99fdSEd Maste 	    &get_common_timeout_list(base, tv)->duration;
1442c43e99fdSEd Maste 	return tv->tv_sec == expect->tv_sec &&
1443c43e99fdSEd Maste 	    tv->tv_usec == expect->tv_usec;
1444c43e99fdSEd Maste }
1445c43e99fdSEd Maste #endif
1446c43e99fdSEd Maste 
1447c43e99fdSEd Maste /* Add the timeout for the first event in given common timeout list to the
1448c43e99fdSEd Maste  * event_base's minheap. */
1449c43e99fdSEd Maste static void
common_timeout_schedule(struct common_timeout_list * ctl,const struct timeval * now,struct event * head)1450c43e99fdSEd Maste common_timeout_schedule(struct common_timeout_list *ctl,
1451c43e99fdSEd Maste     const struct timeval *now, struct event *head)
1452c43e99fdSEd Maste {
1453c43e99fdSEd Maste 	struct timeval timeout = head->ev_timeout;
1454c43e99fdSEd Maste 	timeout.tv_usec &= MICROSECONDS_MASK;
1455c43e99fdSEd Maste 	event_add_nolock_(&ctl->timeout_event, &timeout, 1);
1456c43e99fdSEd Maste }
1457c43e99fdSEd Maste 
1458c43e99fdSEd Maste /* Callback: invoked when the timeout for a common timeout queue triggers.
1459c43e99fdSEd Maste  * This means that (at least) the first event in that queue should be run,
1460c43e99fdSEd Maste  * and the timeout should be rescheduled if there are more events. */
1461c43e99fdSEd Maste static void
common_timeout_callback(evutil_socket_t fd,short what,void * arg)1462c43e99fdSEd Maste common_timeout_callback(evutil_socket_t fd, short what, void *arg)
1463c43e99fdSEd Maste {
1464c43e99fdSEd Maste 	struct timeval now;
1465c43e99fdSEd Maste 	struct common_timeout_list *ctl = arg;
1466c43e99fdSEd Maste 	struct event_base *base = ctl->base;
1467c43e99fdSEd Maste 	struct event *ev = NULL;
1468c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
1469c43e99fdSEd Maste 	gettime(base, &now);
1470c43e99fdSEd Maste 	while (1) {
1471c43e99fdSEd Maste 		ev = TAILQ_FIRST(&ctl->events);
1472c43e99fdSEd Maste 		if (!ev || ev->ev_timeout.tv_sec > now.tv_sec ||
1473c43e99fdSEd Maste 		    (ev->ev_timeout.tv_sec == now.tv_sec &&
1474c43e99fdSEd Maste 			(ev->ev_timeout.tv_usec&MICROSECONDS_MASK) > now.tv_usec))
1475c43e99fdSEd Maste 			break;
1476c43e99fdSEd Maste 		event_del_nolock_(ev, EVENT_DEL_NOBLOCK);
1477c43e99fdSEd Maste 		event_active_nolock_(ev, EV_TIMEOUT, 1);
1478c43e99fdSEd Maste 	}
1479c43e99fdSEd Maste 	if (ev)
1480c43e99fdSEd Maste 		common_timeout_schedule(ctl, &now, ev);
1481c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
1482c43e99fdSEd Maste }
1483c43e99fdSEd Maste 
1484c43e99fdSEd Maste #define MAX_COMMON_TIMEOUTS 256
1485c43e99fdSEd Maste 
1486c43e99fdSEd Maste const struct timeval *
event_base_init_common_timeout(struct event_base * base,const struct timeval * duration)1487c43e99fdSEd Maste event_base_init_common_timeout(struct event_base *base,
1488c43e99fdSEd Maste     const struct timeval *duration)
1489c43e99fdSEd Maste {
1490c43e99fdSEd Maste 	int i;
1491c43e99fdSEd Maste 	struct timeval tv;
1492c43e99fdSEd Maste 	const struct timeval *result=NULL;
1493c43e99fdSEd Maste 	struct common_timeout_list *new_ctl;
1494c43e99fdSEd Maste 
1495c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
1496c43e99fdSEd Maste 	if (duration->tv_usec > 1000000) {
1497c43e99fdSEd Maste 		memcpy(&tv, duration, sizeof(struct timeval));
1498c43e99fdSEd Maste 		if (is_common_timeout(duration, base))
1499c43e99fdSEd Maste 			tv.tv_usec &= MICROSECONDS_MASK;
1500c43e99fdSEd Maste 		tv.tv_sec += tv.tv_usec / 1000000;
1501c43e99fdSEd Maste 		tv.tv_usec %= 1000000;
1502c43e99fdSEd Maste 		duration = &tv;
1503c43e99fdSEd Maste 	}
1504c43e99fdSEd Maste 	for (i = 0; i < base->n_common_timeouts; ++i) {
1505c43e99fdSEd Maste 		const struct common_timeout_list *ctl =
1506c43e99fdSEd Maste 		    base->common_timeout_queues[i];
1507c43e99fdSEd Maste 		if (duration->tv_sec == ctl->duration.tv_sec &&
1508c43e99fdSEd Maste 		    duration->tv_usec ==
1509c43e99fdSEd Maste 		    (ctl->duration.tv_usec & MICROSECONDS_MASK)) {
1510c43e99fdSEd Maste 			EVUTIL_ASSERT(is_common_timeout(&ctl->duration, base));
1511c43e99fdSEd Maste 			result = &ctl->duration;
1512c43e99fdSEd Maste 			goto done;
1513c43e99fdSEd Maste 		}
1514c43e99fdSEd Maste 	}
1515c43e99fdSEd Maste 	if (base->n_common_timeouts == MAX_COMMON_TIMEOUTS) {
1516c43e99fdSEd Maste 		event_warnx("%s: Too many common timeouts already in use; "
1517c43e99fdSEd Maste 		    "we only support %d per event_base", __func__,
1518c43e99fdSEd Maste 		    MAX_COMMON_TIMEOUTS);
1519c43e99fdSEd Maste 		goto done;
1520c43e99fdSEd Maste 	}
1521c43e99fdSEd Maste 	if (base->n_common_timeouts_allocated == base->n_common_timeouts) {
1522c43e99fdSEd Maste 		int n = base->n_common_timeouts < 16 ? 16 :
1523c43e99fdSEd Maste 		    base->n_common_timeouts*2;
1524c43e99fdSEd Maste 		struct common_timeout_list **newqueues =
1525c43e99fdSEd Maste 		    mm_realloc(base->common_timeout_queues,
1526c43e99fdSEd Maste 			n*sizeof(struct common_timeout_queue *));
1527c43e99fdSEd Maste 		if (!newqueues) {
1528c43e99fdSEd Maste 			event_warn("%s: realloc",__func__);
1529c43e99fdSEd Maste 			goto done;
1530c43e99fdSEd Maste 		}
1531c43e99fdSEd Maste 		base->n_common_timeouts_allocated = n;
1532c43e99fdSEd Maste 		base->common_timeout_queues = newqueues;
1533c43e99fdSEd Maste 	}
1534c43e99fdSEd Maste 	new_ctl = mm_calloc(1, sizeof(struct common_timeout_list));
1535c43e99fdSEd Maste 	if (!new_ctl) {
1536c43e99fdSEd Maste 		event_warn("%s: calloc",__func__);
1537c43e99fdSEd Maste 		goto done;
1538c43e99fdSEd Maste 	}
1539c43e99fdSEd Maste 	TAILQ_INIT(&new_ctl->events);
1540c43e99fdSEd Maste 	new_ctl->duration.tv_sec = duration->tv_sec;
1541c43e99fdSEd Maste 	new_ctl->duration.tv_usec =
1542c43e99fdSEd Maste 	    duration->tv_usec | COMMON_TIMEOUT_MAGIC |
1543c43e99fdSEd Maste 	    (base->n_common_timeouts << COMMON_TIMEOUT_IDX_SHIFT);
1544c43e99fdSEd Maste 	evtimer_assign(&new_ctl->timeout_event, base,
1545c43e99fdSEd Maste 	    common_timeout_callback, new_ctl);
1546c43e99fdSEd Maste 	new_ctl->timeout_event.ev_flags |= EVLIST_INTERNAL;
1547c43e99fdSEd Maste 	event_priority_set(&new_ctl->timeout_event, 0);
1548c43e99fdSEd Maste 	new_ctl->base = base;
1549c43e99fdSEd Maste 	base->common_timeout_queues[base->n_common_timeouts++] = new_ctl;
1550c43e99fdSEd Maste 	result = &new_ctl->duration;
1551c43e99fdSEd Maste 
1552c43e99fdSEd Maste done:
1553c43e99fdSEd Maste 	if (result)
1554c43e99fdSEd Maste 		EVUTIL_ASSERT(is_common_timeout(result, base));
1555c43e99fdSEd Maste 
1556c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
1557c43e99fdSEd Maste 	return result;
1558c43e99fdSEd Maste }
1559c43e99fdSEd Maste 
1560c43e99fdSEd Maste /* Closure function invoked when we're activating a persistent event. */
1561c43e99fdSEd Maste static inline void
event_persist_closure(struct event_base * base,struct event * ev)1562c43e99fdSEd Maste event_persist_closure(struct event_base *base, struct event *ev)
1563c43e99fdSEd Maste {
1564c43e99fdSEd Maste 	void (*evcb_callback)(evutil_socket_t, short, void *);
1565c43e99fdSEd Maste 
1566c43e99fdSEd Maste         // Other fields of *ev that must be stored before executing
1567c43e99fdSEd Maste         evutil_socket_t evcb_fd;
1568c43e99fdSEd Maste         short evcb_res;
1569c43e99fdSEd Maste         void *evcb_arg;
1570c43e99fdSEd Maste 
1571c43e99fdSEd Maste 	/* reschedule the persistent event if we have a timeout. */
1572c43e99fdSEd Maste 	if (ev->ev_io_timeout.tv_sec || ev->ev_io_timeout.tv_usec) {
1573c43e99fdSEd Maste 		/* If there was a timeout, we want it to run at an interval of
1574c43e99fdSEd Maste 		 * ev_io_timeout after the last time it was _scheduled_ for,
1575c43e99fdSEd Maste 		 * not ev_io_timeout after _now_.  If it fired for another
1576c43e99fdSEd Maste 		 * reason, though, the timeout ought to start ticking _now_. */
1577c43e99fdSEd Maste 		struct timeval run_at, relative_to, delay, now;
1578c43e99fdSEd Maste 		ev_uint32_t usec_mask = 0;
1579c43e99fdSEd Maste 		EVUTIL_ASSERT(is_same_common_timeout(&ev->ev_timeout,
1580c43e99fdSEd Maste 			&ev->ev_io_timeout));
1581c43e99fdSEd Maste 		gettime(base, &now);
1582c43e99fdSEd Maste 		if (is_common_timeout(&ev->ev_timeout, base)) {
1583c43e99fdSEd Maste 			delay = ev->ev_io_timeout;
1584c43e99fdSEd Maste 			usec_mask = delay.tv_usec & ~MICROSECONDS_MASK;
1585c43e99fdSEd Maste 			delay.tv_usec &= MICROSECONDS_MASK;
1586c43e99fdSEd Maste 			if (ev->ev_res & EV_TIMEOUT) {
1587c43e99fdSEd Maste 				relative_to = ev->ev_timeout;
1588c43e99fdSEd Maste 				relative_to.tv_usec &= MICROSECONDS_MASK;
1589c43e99fdSEd Maste 			} else {
1590c43e99fdSEd Maste 				relative_to = now;
1591c43e99fdSEd Maste 			}
1592c43e99fdSEd Maste 		} else {
1593c43e99fdSEd Maste 			delay = ev->ev_io_timeout;
1594c43e99fdSEd Maste 			if (ev->ev_res & EV_TIMEOUT) {
1595c43e99fdSEd Maste 				relative_to = ev->ev_timeout;
1596c43e99fdSEd Maste 			} else {
1597c43e99fdSEd Maste 				relative_to = now;
1598c43e99fdSEd Maste 			}
1599c43e99fdSEd Maste 		}
1600c43e99fdSEd Maste 		evutil_timeradd(&relative_to, &delay, &run_at);
1601c43e99fdSEd Maste 		if (evutil_timercmp(&run_at, &now, <)) {
1602c43e99fdSEd Maste 			/* Looks like we missed at least one invocation due to
1603c43e99fdSEd Maste 			 * a clock jump, not running the event loop for a
1604c43e99fdSEd Maste 			 * while, really slow callbacks, or
1605c43e99fdSEd Maste 			 * something. Reschedule relative to now.
1606c43e99fdSEd Maste 			 */
1607c43e99fdSEd Maste 			evutil_timeradd(&now, &delay, &run_at);
1608c43e99fdSEd Maste 		}
1609c43e99fdSEd Maste 		run_at.tv_usec |= usec_mask;
1610c43e99fdSEd Maste 		event_add_nolock_(ev, &run_at, 1);
1611c43e99fdSEd Maste 	}
1612c43e99fdSEd Maste 
1613c43e99fdSEd Maste 	// Save our callback before we release the lock
1614c43e99fdSEd Maste 	evcb_callback = ev->ev_callback;
1615c43e99fdSEd Maste         evcb_fd = ev->ev_fd;
1616c43e99fdSEd Maste         evcb_res = ev->ev_res;
1617c43e99fdSEd Maste         evcb_arg = ev->ev_arg;
1618c43e99fdSEd Maste 
1619c43e99fdSEd Maste 	// Release the lock
1620c43e99fdSEd Maste  	EVBASE_RELEASE_LOCK(base, th_base_lock);
1621c43e99fdSEd Maste 
1622c43e99fdSEd Maste 	// Execute the callback
1623c43e99fdSEd Maste         (evcb_callback)(evcb_fd, evcb_res, evcb_arg);
1624c43e99fdSEd Maste }
1625c43e99fdSEd Maste 
1626c43e99fdSEd Maste /*
1627c43e99fdSEd Maste   Helper for event_process_active to process all the events in a single queue,
1628c43e99fdSEd Maste   releasing the lock as we go.  This function requires that the lock be held
1629c43e99fdSEd Maste   when it's invoked.  Returns -1 if we get a signal or an event_break that
1630c43e99fdSEd Maste   means we should stop processing any active events now.  Otherwise returns
1631c43e99fdSEd Maste   the number of non-internal event_callbacks that we processed.
1632c43e99fdSEd Maste */
1633c43e99fdSEd Maste static int
event_process_active_single_queue(struct event_base * base,struct evcallback_list * activeq,int max_to_process,const struct timeval * endtime)1634c43e99fdSEd Maste event_process_active_single_queue(struct event_base *base,
1635c43e99fdSEd Maste     struct evcallback_list *activeq,
1636c43e99fdSEd Maste     int max_to_process, const struct timeval *endtime)
1637c43e99fdSEd Maste {
1638c43e99fdSEd Maste 	struct event_callback *evcb;
1639c43e99fdSEd Maste 	int count = 0;
1640c43e99fdSEd Maste 
1641c43e99fdSEd Maste 	EVUTIL_ASSERT(activeq != NULL);
1642c43e99fdSEd Maste 
1643c43e99fdSEd Maste 	for (evcb = TAILQ_FIRST(activeq); evcb; evcb = TAILQ_FIRST(activeq)) {
1644c43e99fdSEd Maste 		struct event *ev=NULL;
1645c43e99fdSEd Maste 		if (evcb->evcb_flags & EVLIST_INIT) {
1646c43e99fdSEd Maste 			ev = event_callback_to_event(evcb);
1647c43e99fdSEd Maste 
1648c43e99fdSEd Maste 			if (ev->ev_events & EV_PERSIST || ev->ev_flags & EVLIST_FINALIZING)
1649c43e99fdSEd Maste 				event_queue_remove_active(base, evcb);
1650c43e99fdSEd Maste 			else
1651c43e99fdSEd Maste 				event_del_nolock_(ev, EVENT_DEL_NOBLOCK);
1652c43e99fdSEd Maste 			event_debug((
1653c43e99fdSEd Maste 			    "event_process_active: event: %p, %s%s%scall %p",
1654c43e99fdSEd Maste 			    ev,
1655c43e99fdSEd Maste 			    ev->ev_res & EV_READ ? "EV_READ " : " ",
1656c43e99fdSEd Maste 			    ev->ev_res & EV_WRITE ? "EV_WRITE " : " ",
1657c43e99fdSEd Maste 			    ev->ev_res & EV_CLOSED ? "EV_CLOSED " : " ",
1658c43e99fdSEd Maste 			    ev->ev_callback));
1659c43e99fdSEd Maste 		} else {
1660c43e99fdSEd Maste 			event_queue_remove_active(base, evcb);
1661c43e99fdSEd Maste 			event_debug(("event_process_active: event_callback %p, "
1662c43e99fdSEd Maste 				"closure %d, call %p",
1663c43e99fdSEd Maste 				evcb, evcb->evcb_closure, evcb->evcb_cb_union.evcb_callback));
1664c43e99fdSEd Maste 		}
1665c43e99fdSEd Maste 
1666c43e99fdSEd Maste 		if (!(evcb->evcb_flags & EVLIST_INTERNAL))
1667c43e99fdSEd Maste 			++count;
1668c43e99fdSEd Maste 
1669c43e99fdSEd Maste 
1670c43e99fdSEd Maste 		base->current_event = evcb;
1671c43e99fdSEd Maste #ifndef EVENT__DISABLE_THREAD_SUPPORT
1672c43e99fdSEd Maste 		base->current_event_waiters = 0;
1673c43e99fdSEd Maste #endif
1674c43e99fdSEd Maste 
1675c43e99fdSEd Maste 		switch (evcb->evcb_closure) {
1676c43e99fdSEd Maste 		case EV_CLOSURE_EVENT_SIGNAL:
1677c43e99fdSEd Maste 			EVUTIL_ASSERT(ev != NULL);
1678c43e99fdSEd Maste 			event_signal_closure(base, ev);
1679c43e99fdSEd Maste 			break;
1680c43e99fdSEd Maste 		case EV_CLOSURE_EVENT_PERSIST:
1681c43e99fdSEd Maste 			EVUTIL_ASSERT(ev != NULL);
1682c43e99fdSEd Maste 			event_persist_closure(base, ev);
1683c43e99fdSEd Maste 			break;
1684c43e99fdSEd Maste 		case EV_CLOSURE_EVENT: {
1685c43e99fdSEd Maste 			void (*evcb_callback)(evutil_socket_t, short, void *);
1686*b50261e2SCy Schubert 			short res;
1687c43e99fdSEd Maste 			EVUTIL_ASSERT(ev != NULL);
1688c43e99fdSEd Maste 			evcb_callback = *ev->ev_callback;
1689*b50261e2SCy Schubert 			res = ev->ev_res;
1690c43e99fdSEd Maste 			EVBASE_RELEASE_LOCK(base, th_base_lock);
1691*b50261e2SCy Schubert 			evcb_callback(ev->ev_fd, res, ev->ev_arg);
1692c43e99fdSEd Maste 		}
1693c43e99fdSEd Maste 		break;
1694c43e99fdSEd Maste 		case EV_CLOSURE_CB_SELF: {
1695c43e99fdSEd Maste 			void (*evcb_selfcb)(struct event_callback *, void *) = evcb->evcb_cb_union.evcb_selfcb;
1696c43e99fdSEd Maste 			EVBASE_RELEASE_LOCK(base, th_base_lock);
1697c43e99fdSEd Maste 			evcb_selfcb(evcb, evcb->evcb_arg);
1698c43e99fdSEd Maste 		}
1699c43e99fdSEd Maste 		break;
1700c43e99fdSEd Maste 		case EV_CLOSURE_EVENT_FINALIZE:
1701c43e99fdSEd Maste 		case EV_CLOSURE_EVENT_FINALIZE_FREE: {
1702c43e99fdSEd Maste 			void (*evcb_evfinalize)(struct event *, void *);
1703c43e99fdSEd Maste 			int evcb_closure = evcb->evcb_closure;
1704c43e99fdSEd Maste 			EVUTIL_ASSERT(ev != NULL);
1705c43e99fdSEd Maste 			base->current_event = NULL;
1706c43e99fdSEd Maste 			evcb_evfinalize = ev->ev_evcallback.evcb_cb_union.evcb_evfinalize;
1707c43e99fdSEd Maste 			EVUTIL_ASSERT((evcb->evcb_flags & EVLIST_FINALIZING));
1708c43e99fdSEd Maste 			EVBASE_RELEASE_LOCK(base, th_base_lock);
1709c43e99fdSEd Maste 			event_debug_note_teardown_(ev);
1710*b50261e2SCy Schubert 			evcb_evfinalize(ev, ev->ev_arg);
1711c43e99fdSEd Maste 			if (evcb_closure == EV_CLOSURE_EVENT_FINALIZE_FREE)
1712c43e99fdSEd Maste 				mm_free(ev);
1713c43e99fdSEd Maste 		}
1714c43e99fdSEd Maste 		break;
1715c43e99fdSEd Maste 		case EV_CLOSURE_CB_FINALIZE: {
1716c43e99fdSEd Maste 			void (*evcb_cbfinalize)(struct event_callback *, void *) = evcb->evcb_cb_union.evcb_cbfinalize;
1717c43e99fdSEd Maste 			base->current_event = NULL;
1718c43e99fdSEd Maste 			EVUTIL_ASSERT((evcb->evcb_flags & EVLIST_FINALIZING));
1719c43e99fdSEd Maste 			EVBASE_RELEASE_LOCK(base, th_base_lock);
1720c43e99fdSEd Maste 			evcb_cbfinalize(evcb, evcb->evcb_arg);
1721c43e99fdSEd Maste 		}
1722c43e99fdSEd Maste 		break;
1723c43e99fdSEd Maste 		default:
1724c43e99fdSEd Maste 			EVUTIL_ASSERT(0);
1725c43e99fdSEd Maste 		}
1726c43e99fdSEd Maste 
1727c43e99fdSEd Maste 		EVBASE_ACQUIRE_LOCK(base, th_base_lock);
1728c43e99fdSEd Maste 		base->current_event = NULL;
1729c43e99fdSEd Maste #ifndef EVENT__DISABLE_THREAD_SUPPORT
1730c43e99fdSEd Maste 		if (base->current_event_waiters) {
1731c43e99fdSEd Maste 			base->current_event_waiters = 0;
1732c43e99fdSEd Maste 			EVTHREAD_COND_BROADCAST(base->current_event_cond);
1733c43e99fdSEd Maste 		}
1734c43e99fdSEd Maste #endif
1735c43e99fdSEd Maste 
1736c43e99fdSEd Maste 		if (base->event_break)
1737c43e99fdSEd Maste 			return -1;
1738c43e99fdSEd Maste 		if (count >= max_to_process)
1739c43e99fdSEd Maste 			return count;
1740c43e99fdSEd Maste 		if (count && endtime) {
1741c43e99fdSEd Maste 			struct timeval now;
1742c43e99fdSEd Maste 			update_time_cache(base);
1743c43e99fdSEd Maste 			gettime(base, &now);
1744c43e99fdSEd Maste 			if (evutil_timercmp(&now, endtime, >=))
1745c43e99fdSEd Maste 				return count;
1746c43e99fdSEd Maste 		}
1747c43e99fdSEd Maste 		if (base->event_continue)
1748c43e99fdSEd Maste 			break;
1749c43e99fdSEd Maste 	}
1750c43e99fdSEd Maste 	return count;
1751c43e99fdSEd Maste }
1752c43e99fdSEd Maste 
1753c43e99fdSEd Maste /*
1754c43e99fdSEd Maste  * Active events are stored in priority queues.  Lower priorities are always
1755c43e99fdSEd Maste  * process before higher priorities.  Low priority events can starve high
1756c43e99fdSEd Maste  * priority ones.
1757c43e99fdSEd Maste  */
1758c43e99fdSEd Maste 
1759c43e99fdSEd Maste static int
event_process_active(struct event_base * base)1760c43e99fdSEd Maste event_process_active(struct event_base *base)
1761c43e99fdSEd Maste {
1762c43e99fdSEd Maste 	/* Caller must hold th_base_lock */
1763c43e99fdSEd Maste 	struct evcallback_list *activeq = NULL;
1764c43e99fdSEd Maste 	int i, c = 0;
1765c43e99fdSEd Maste 	const struct timeval *endtime;
1766c43e99fdSEd Maste 	struct timeval tv;
1767c43e99fdSEd Maste 	const int maxcb = base->max_dispatch_callbacks;
1768c43e99fdSEd Maste 	const int limit_after_prio = base->limit_callbacks_after_prio;
1769c43e99fdSEd Maste 	if (base->max_dispatch_time.tv_sec >= 0) {
1770c43e99fdSEd Maste 		update_time_cache(base);
1771c43e99fdSEd Maste 		gettime(base, &tv);
1772c43e99fdSEd Maste 		evutil_timeradd(&base->max_dispatch_time, &tv, &tv);
1773c43e99fdSEd Maste 		endtime = &tv;
1774c43e99fdSEd Maste 	} else {
1775c43e99fdSEd Maste 		endtime = NULL;
1776c43e99fdSEd Maste 	}
1777c43e99fdSEd Maste 
1778c43e99fdSEd Maste 	for (i = 0; i < base->nactivequeues; ++i) {
1779c43e99fdSEd Maste 		if (TAILQ_FIRST(&base->activequeues[i]) != NULL) {
1780c43e99fdSEd Maste 			base->event_running_priority = i;
1781c43e99fdSEd Maste 			activeq = &base->activequeues[i];
1782c43e99fdSEd Maste 			if (i < limit_after_prio)
1783c43e99fdSEd Maste 				c = event_process_active_single_queue(base, activeq,
1784c43e99fdSEd Maste 				    INT_MAX, NULL);
1785c43e99fdSEd Maste 			else
1786c43e99fdSEd Maste 				c = event_process_active_single_queue(base, activeq,
1787c43e99fdSEd Maste 				    maxcb, endtime);
1788c43e99fdSEd Maste 			if (c < 0) {
1789c43e99fdSEd Maste 				goto done;
1790c43e99fdSEd Maste 			} else if (c > 0)
1791c43e99fdSEd Maste 				break; /* Processed a real event; do not
1792c43e99fdSEd Maste 					* consider lower-priority events */
1793c43e99fdSEd Maste 			/* If we get here, all of the events we processed
1794c43e99fdSEd Maste 			 * were internal.  Continue. */
1795c43e99fdSEd Maste 		}
1796c43e99fdSEd Maste 	}
1797c43e99fdSEd Maste 
1798c43e99fdSEd Maste done:
1799c43e99fdSEd Maste 	base->event_running_priority = -1;
1800c43e99fdSEd Maste 
1801c43e99fdSEd Maste 	return c;
1802c43e99fdSEd Maste }
1803c43e99fdSEd Maste 
1804c43e99fdSEd Maste /*
1805c43e99fdSEd Maste  * Wait continuously for events.  We exit only if no events are left.
1806c43e99fdSEd Maste  */
1807c43e99fdSEd Maste 
1808c43e99fdSEd Maste int
event_dispatch(void)1809c43e99fdSEd Maste event_dispatch(void)
1810c43e99fdSEd Maste {
1811c43e99fdSEd Maste 	return (event_loop(0));
1812c43e99fdSEd Maste }
1813c43e99fdSEd Maste 
1814c43e99fdSEd Maste int
event_base_dispatch(struct event_base * event_base)1815c43e99fdSEd Maste event_base_dispatch(struct event_base *event_base)
1816c43e99fdSEd Maste {
1817c43e99fdSEd Maste 	return (event_base_loop(event_base, 0));
1818c43e99fdSEd Maste }
1819c43e99fdSEd Maste 
1820c43e99fdSEd Maste const char *
event_base_get_method(const struct event_base * base)1821c43e99fdSEd Maste event_base_get_method(const struct event_base *base)
1822c43e99fdSEd Maste {
1823c43e99fdSEd Maste 	EVUTIL_ASSERT(base);
1824c43e99fdSEd Maste 	return (base->evsel->name);
1825c43e99fdSEd Maste }
1826c43e99fdSEd Maste 
1827c43e99fdSEd Maste /** Callback: used to implement event_base_loopexit by telling the event_base
1828c43e99fdSEd Maste  * that it's time to exit its loop. */
1829c43e99fdSEd Maste static void
event_loopexit_cb(evutil_socket_t fd,short what,void * arg)1830c43e99fdSEd Maste event_loopexit_cb(evutil_socket_t fd, short what, void *arg)
1831c43e99fdSEd Maste {
1832c43e99fdSEd Maste 	struct event_base *base = arg;
1833c43e99fdSEd Maste 	base->event_gotterm = 1;
1834c43e99fdSEd Maste }
1835c43e99fdSEd Maste 
1836c43e99fdSEd Maste int
event_loopexit(const struct timeval * tv)1837c43e99fdSEd Maste event_loopexit(const struct timeval *tv)
1838c43e99fdSEd Maste {
1839c43e99fdSEd Maste 	return (event_once(-1, EV_TIMEOUT, event_loopexit_cb,
1840c43e99fdSEd Maste 		    current_base, tv));
1841c43e99fdSEd Maste }
1842c43e99fdSEd Maste 
1843c43e99fdSEd Maste int
event_base_loopexit(struct event_base * event_base,const struct timeval * tv)1844c43e99fdSEd Maste event_base_loopexit(struct event_base *event_base, const struct timeval *tv)
1845c43e99fdSEd Maste {
1846c43e99fdSEd Maste 	return (event_base_once(event_base, -1, EV_TIMEOUT, event_loopexit_cb,
1847c43e99fdSEd Maste 		    event_base, tv));
1848c43e99fdSEd Maste }
1849c43e99fdSEd Maste 
1850c43e99fdSEd Maste int
event_loopbreak(void)1851c43e99fdSEd Maste event_loopbreak(void)
1852c43e99fdSEd Maste {
1853c43e99fdSEd Maste 	return (event_base_loopbreak(current_base));
1854c43e99fdSEd Maste }
1855c43e99fdSEd Maste 
1856c43e99fdSEd Maste int
event_base_loopbreak(struct event_base * event_base)1857c43e99fdSEd Maste event_base_loopbreak(struct event_base *event_base)
1858c43e99fdSEd Maste {
1859c43e99fdSEd Maste 	int r = 0;
1860c43e99fdSEd Maste 	if (event_base == NULL)
1861c43e99fdSEd Maste 		return (-1);
1862c43e99fdSEd Maste 
1863c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(event_base, th_base_lock);
1864c43e99fdSEd Maste 	event_base->event_break = 1;
1865c43e99fdSEd Maste 
1866c43e99fdSEd Maste 	if (EVBASE_NEED_NOTIFY(event_base)) {
1867c43e99fdSEd Maste 		r = evthread_notify_base(event_base);
1868c43e99fdSEd Maste 	} else {
1869c43e99fdSEd Maste 		r = (0);
1870c43e99fdSEd Maste 	}
1871c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(event_base, th_base_lock);
1872c43e99fdSEd Maste 	return r;
1873c43e99fdSEd Maste }
1874c43e99fdSEd Maste 
1875c43e99fdSEd Maste int
event_base_loopcontinue(struct event_base * event_base)1876c43e99fdSEd Maste event_base_loopcontinue(struct event_base *event_base)
1877c43e99fdSEd Maste {
1878c43e99fdSEd Maste 	int r = 0;
1879c43e99fdSEd Maste 	if (event_base == NULL)
1880c43e99fdSEd Maste 		return (-1);
1881c43e99fdSEd Maste 
1882c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(event_base, th_base_lock);
1883c43e99fdSEd Maste 	event_base->event_continue = 1;
1884c43e99fdSEd Maste 
1885c43e99fdSEd Maste 	if (EVBASE_NEED_NOTIFY(event_base)) {
1886c43e99fdSEd Maste 		r = evthread_notify_base(event_base);
1887c43e99fdSEd Maste 	} else {
1888c43e99fdSEd Maste 		r = (0);
1889c43e99fdSEd Maste 	}
1890c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(event_base, th_base_lock);
1891c43e99fdSEd Maste 	return r;
1892c43e99fdSEd Maste }
1893c43e99fdSEd Maste 
1894c43e99fdSEd Maste int
event_base_got_break(struct event_base * event_base)1895c43e99fdSEd Maste event_base_got_break(struct event_base *event_base)
1896c43e99fdSEd Maste {
1897c43e99fdSEd Maste 	int res;
1898c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(event_base, th_base_lock);
1899c43e99fdSEd Maste 	res = event_base->event_break;
1900c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(event_base, th_base_lock);
1901c43e99fdSEd Maste 	return res;
1902c43e99fdSEd Maste }
1903c43e99fdSEd Maste 
1904c43e99fdSEd Maste int
event_base_got_exit(struct event_base * event_base)1905c43e99fdSEd Maste event_base_got_exit(struct event_base *event_base)
1906c43e99fdSEd Maste {
1907c43e99fdSEd Maste 	int res;
1908c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(event_base, th_base_lock);
1909c43e99fdSEd Maste 	res = event_base->event_gotterm;
1910c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(event_base, th_base_lock);
1911c43e99fdSEd Maste 	return res;
1912c43e99fdSEd Maste }
1913c43e99fdSEd Maste 
1914c43e99fdSEd Maste /* not thread safe */
1915c43e99fdSEd Maste 
1916c43e99fdSEd Maste int
event_loop(int flags)1917c43e99fdSEd Maste event_loop(int flags)
1918c43e99fdSEd Maste {
1919c43e99fdSEd Maste 	return event_base_loop(current_base, flags);
1920c43e99fdSEd Maste }
1921c43e99fdSEd Maste 
1922c43e99fdSEd Maste int
event_base_loop(struct event_base * base,int flags)1923c43e99fdSEd Maste event_base_loop(struct event_base *base, int flags)
1924c43e99fdSEd Maste {
1925c43e99fdSEd Maste 	const struct eventop *evsel = base->evsel;
1926c43e99fdSEd Maste 	struct timeval tv;
1927c43e99fdSEd Maste 	struct timeval *tv_p;
1928c43e99fdSEd Maste 	int res, done, retval = 0;
1929c43e99fdSEd Maste 
1930c43e99fdSEd Maste 	/* Grab the lock.  We will release it inside evsel.dispatch, and again
1931c43e99fdSEd Maste 	 * as we invoke user callbacks. */
1932c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
1933c43e99fdSEd Maste 
1934c43e99fdSEd Maste 	if (base->running_loop) {
1935c43e99fdSEd Maste 		event_warnx("%s: reentrant invocation.  Only one event_base_loop"
1936c43e99fdSEd Maste 		    " can run on each event_base at once.", __func__);
1937c43e99fdSEd Maste 		EVBASE_RELEASE_LOCK(base, th_base_lock);
1938c43e99fdSEd Maste 		return -1;
1939c43e99fdSEd Maste 	}
1940c43e99fdSEd Maste 
1941c43e99fdSEd Maste 	base->running_loop = 1;
1942c43e99fdSEd Maste 
1943c43e99fdSEd Maste 	clear_time_cache(base);
1944c43e99fdSEd Maste 
1945c43e99fdSEd Maste 	if (base->sig.ev_signal_added && base->sig.ev_n_signals_added)
1946c43e99fdSEd Maste 		evsig_set_base_(base);
1947c43e99fdSEd Maste 
1948c43e99fdSEd Maste 	done = 0;
1949c43e99fdSEd Maste 
1950c43e99fdSEd Maste #ifndef EVENT__DISABLE_THREAD_SUPPORT
1951c43e99fdSEd Maste 	base->th_owner_id = EVTHREAD_GET_ID();
1952c43e99fdSEd Maste #endif
1953c43e99fdSEd Maste 
1954c43e99fdSEd Maste 	base->event_gotterm = base->event_break = 0;
1955c43e99fdSEd Maste 
1956c43e99fdSEd Maste 	while (!done) {
1957c43e99fdSEd Maste 		base->event_continue = 0;
1958c43e99fdSEd Maste 		base->n_deferreds_queued = 0;
1959c43e99fdSEd Maste 
1960c43e99fdSEd Maste 		/* Terminate the loop if we have been asked to */
1961c43e99fdSEd Maste 		if (base->event_gotterm) {
1962c43e99fdSEd Maste 			break;
1963c43e99fdSEd Maste 		}
1964c43e99fdSEd Maste 
1965c43e99fdSEd Maste 		if (base->event_break) {
1966c43e99fdSEd Maste 			break;
1967c43e99fdSEd Maste 		}
1968c43e99fdSEd Maste 
1969c43e99fdSEd Maste 		tv_p = &tv;
1970c43e99fdSEd Maste 		if (!N_ACTIVE_CALLBACKS(base) && !(flags & EVLOOP_NONBLOCK)) {
1971c43e99fdSEd Maste 			timeout_next(base, &tv_p);
1972c43e99fdSEd Maste 		} else {
1973c43e99fdSEd Maste 			/*
1974c43e99fdSEd Maste 			 * if we have active events, we just poll new events
1975c43e99fdSEd Maste 			 * without waiting.
1976c43e99fdSEd Maste 			 */
1977c43e99fdSEd Maste 			evutil_timerclear(&tv);
1978c43e99fdSEd Maste 		}
1979c43e99fdSEd Maste 
1980c43e99fdSEd Maste 		/* If we have no events, we just exit */
1981c43e99fdSEd Maste 		if (0==(flags&EVLOOP_NO_EXIT_ON_EMPTY) &&
1982c43e99fdSEd Maste 		    !event_haveevents(base) && !N_ACTIVE_CALLBACKS(base)) {
1983c43e99fdSEd Maste 			event_debug(("%s: no events registered.", __func__));
1984c43e99fdSEd Maste 			retval = 1;
1985c43e99fdSEd Maste 			goto done;
1986c43e99fdSEd Maste 		}
1987c43e99fdSEd Maste 
1988c43e99fdSEd Maste 		event_queue_make_later_events_active(base);
1989c43e99fdSEd Maste 
1990c43e99fdSEd Maste 		clear_time_cache(base);
1991c43e99fdSEd Maste 
1992c43e99fdSEd Maste 		res = evsel->dispatch(base, tv_p);
1993c43e99fdSEd Maste 
1994c43e99fdSEd Maste 		if (res == -1) {
1995c43e99fdSEd Maste 			event_debug(("%s: dispatch returned unsuccessfully.",
1996c43e99fdSEd Maste 				__func__));
1997c43e99fdSEd Maste 			retval = -1;
1998c43e99fdSEd Maste 			goto done;
1999c43e99fdSEd Maste 		}
2000c43e99fdSEd Maste 
2001c43e99fdSEd Maste 		update_time_cache(base);
2002c43e99fdSEd Maste 
2003c43e99fdSEd Maste 		timeout_process(base);
2004c43e99fdSEd Maste 
2005c43e99fdSEd Maste 		if (N_ACTIVE_CALLBACKS(base)) {
2006c43e99fdSEd Maste 			int n = event_process_active(base);
2007c43e99fdSEd Maste 			if ((flags & EVLOOP_ONCE)
2008c43e99fdSEd Maste 			    && N_ACTIVE_CALLBACKS(base) == 0
2009c43e99fdSEd Maste 			    && n != 0)
2010c43e99fdSEd Maste 				done = 1;
2011c43e99fdSEd Maste 		} else if (flags & EVLOOP_NONBLOCK)
2012c43e99fdSEd Maste 			done = 1;
2013c43e99fdSEd Maste 	}
2014c43e99fdSEd Maste 	event_debug(("%s: asked to terminate loop.", __func__));
2015c43e99fdSEd Maste 
2016c43e99fdSEd Maste done:
2017c43e99fdSEd Maste 	clear_time_cache(base);
2018c43e99fdSEd Maste 	base->running_loop = 0;
2019c43e99fdSEd Maste 
2020c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
2021c43e99fdSEd Maste 
2022c43e99fdSEd Maste 	return (retval);
2023c43e99fdSEd Maste }
2024c43e99fdSEd Maste 
2025c43e99fdSEd Maste /* One-time callback to implement event_base_once: invokes the user callback,
2026c43e99fdSEd Maste  * then deletes the allocated storage */
2027c43e99fdSEd Maste static void
event_once_cb(evutil_socket_t fd,short events,void * arg)2028c43e99fdSEd Maste event_once_cb(evutil_socket_t fd, short events, void *arg)
2029c43e99fdSEd Maste {
2030c43e99fdSEd Maste 	struct event_once *eonce = arg;
2031c43e99fdSEd Maste 
2032c43e99fdSEd Maste 	(*eonce->cb)(fd, events, eonce->arg);
2033c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(eonce->ev.ev_base, th_base_lock);
2034c43e99fdSEd Maste 	LIST_REMOVE(eonce, next_once);
2035c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(eonce->ev.ev_base, th_base_lock);
2036c43e99fdSEd Maste 	event_debug_unassign(&eonce->ev);
2037c43e99fdSEd Maste 	mm_free(eonce);
2038c43e99fdSEd Maste }
2039c43e99fdSEd Maste 
2040c43e99fdSEd Maste /* not threadsafe, event scheduled once. */
2041c43e99fdSEd Maste int
event_once(evutil_socket_t fd,short events,void (* callback)(evutil_socket_t,short,void *),void * arg,const struct timeval * tv)2042c43e99fdSEd Maste event_once(evutil_socket_t fd, short events,
2043c43e99fdSEd Maste     void (*callback)(evutil_socket_t, short, void *),
2044c43e99fdSEd Maste     void *arg, const struct timeval *tv)
2045c43e99fdSEd Maste {
2046c43e99fdSEd Maste 	return event_base_once(current_base, fd, events, callback, arg, tv);
2047c43e99fdSEd Maste }
2048c43e99fdSEd Maste 
2049c43e99fdSEd Maste /* Schedules an event once */
2050c43e99fdSEd Maste int
event_base_once(struct event_base * base,evutil_socket_t fd,short events,void (* callback)(evutil_socket_t,short,void *),void * arg,const struct timeval * tv)2051c43e99fdSEd Maste event_base_once(struct event_base *base, evutil_socket_t fd, short events,
2052c43e99fdSEd Maste     void (*callback)(evutil_socket_t, short, void *),
2053c43e99fdSEd Maste     void *arg, const struct timeval *tv)
2054c43e99fdSEd Maste {
2055c43e99fdSEd Maste 	struct event_once *eonce;
2056c43e99fdSEd Maste 	int res = 0;
2057c43e99fdSEd Maste 	int activate = 0;
2058c43e99fdSEd Maste 
2059*b50261e2SCy Schubert 	if (!base)
2060*b50261e2SCy Schubert 		return (-1);
2061*b50261e2SCy Schubert 
2062c43e99fdSEd Maste 	/* We cannot support signals that just fire once, or persistent
2063c43e99fdSEd Maste 	 * events. */
2064c43e99fdSEd Maste 	if (events & (EV_SIGNAL|EV_PERSIST))
2065c43e99fdSEd Maste 		return (-1);
2066c43e99fdSEd Maste 
2067c43e99fdSEd Maste 	if ((eonce = mm_calloc(1, sizeof(struct event_once))) == NULL)
2068c43e99fdSEd Maste 		return (-1);
2069c43e99fdSEd Maste 
2070c43e99fdSEd Maste 	eonce->cb = callback;
2071c43e99fdSEd Maste 	eonce->arg = arg;
2072c43e99fdSEd Maste 
2073c43e99fdSEd Maste 	if ((events & (EV_TIMEOUT|EV_SIGNAL|EV_READ|EV_WRITE|EV_CLOSED)) == EV_TIMEOUT) {
2074c43e99fdSEd Maste 		evtimer_assign(&eonce->ev, base, event_once_cb, eonce);
2075c43e99fdSEd Maste 
2076c43e99fdSEd Maste 		if (tv == NULL || ! evutil_timerisset(tv)) {
2077c43e99fdSEd Maste 			/* If the event is going to become active immediately,
2078c43e99fdSEd Maste 			 * don't put it on the timeout queue.  This is one
2079c43e99fdSEd Maste 			 * idiom for scheduling a callback, so let's make
2080c43e99fdSEd Maste 			 * it fast (and order-preserving). */
2081c43e99fdSEd Maste 			activate = 1;
2082c43e99fdSEd Maste 		}
2083c43e99fdSEd Maste 	} else if (events & (EV_READ|EV_WRITE|EV_CLOSED)) {
2084c43e99fdSEd Maste 		events &= EV_READ|EV_WRITE|EV_CLOSED;
2085c43e99fdSEd Maste 
2086c43e99fdSEd Maste 		event_assign(&eonce->ev, base, fd, events, event_once_cb, eonce);
2087c43e99fdSEd Maste 	} else {
2088c43e99fdSEd Maste 		/* Bad event combination */
2089c43e99fdSEd Maste 		mm_free(eonce);
2090c43e99fdSEd Maste 		return (-1);
2091c43e99fdSEd Maste 	}
2092c43e99fdSEd Maste 
2093c43e99fdSEd Maste 	if (res == 0) {
2094c43e99fdSEd Maste 		EVBASE_ACQUIRE_LOCK(base, th_base_lock);
2095c43e99fdSEd Maste 		if (activate)
2096c43e99fdSEd Maste 			event_active_nolock_(&eonce->ev, EV_TIMEOUT, 1);
2097c43e99fdSEd Maste 		else
2098c43e99fdSEd Maste 			res = event_add_nolock_(&eonce->ev, tv, 0);
2099c43e99fdSEd Maste 
2100c43e99fdSEd Maste 		if (res != 0) {
2101c43e99fdSEd Maste 			mm_free(eonce);
2102c43e99fdSEd Maste 			return (res);
2103c43e99fdSEd Maste 		} else {
2104c43e99fdSEd Maste 			LIST_INSERT_HEAD(&base->once_events, eonce, next_once);
2105c43e99fdSEd Maste 		}
2106c43e99fdSEd Maste 		EVBASE_RELEASE_LOCK(base, th_base_lock);
2107c43e99fdSEd Maste 	}
2108c43e99fdSEd Maste 
2109c43e99fdSEd Maste 	return (0);
2110c43e99fdSEd Maste }
2111c43e99fdSEd Maste 
2112c43e99fdSEd Maste int
event_assign(struct event * ev,struct event_base * base,evutil_socket_t fd,short events,void (* callback)(evutil_socket_t,short,void *),void * arg)2113c43e99fdSEd Maste event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, short events, void (*callback)(evutil_socket_t, short, void *), void *arg)
2114c43e99fdSEd Maste {
2115c43e99fdSEd Maste 	if (!base)
2116c43e99fdSEd Maste 		base = current_base;
2117c43e99fdSEd Maste 	if (arg == &event_self_cbarg_ptr_)
2118c43e99fdSEd Maste 		arg = ev;
2119c43e99fdSEd Maste 
2120*b50261e2SCy Schubert 	if (!(events & EV_SIGNAL))
2121*b50261e2SCy Schubert 		event_debug_assert_socket_nonblocking_(fd);
2122c43e99fdSEd Maste 	event_debug_assert_not_added_(ev);
2123c43e99fdSEd Maste 
2124c43e99fdSEd Maste 	ev->ev_base = base;
2125c43e99fdSEd Maste 
2126c43e99fdSEd Maste 	ev->ev_callback = callback;
2127c43e99fdSEd Maste 	ev->ev_arg = arg;
2128c43e99fdSEd Maste 	ev->ev_fd = fd;
2129c43e99fdSEd Maste 	ev->ev_events = events;
2130c43e99fdSEd Maste 	ev->ev_res = 0;
2131c43e99fdSEd Maste 	ev->ev_flags = EVLIST_INIT;
2132c43e99fdSEd Maste 	ev->ev_ncalls = 0;
2133c43e99fdSEd Maste 	ev->ev_pncalls = NULL;
2134c43e99fdSEd Maste 
2135c43e99fdSEd Maste 	if (events & EV_SIGNAL) {
2136c43e99fdSEd Maste 		if ((events & (EV_READ|EV_WRITE|EV_CLOSED)) != 0) {
2137c43e99fdSEd Maste 			event_warnx("%s: EV_SIGNAL is not compatible with "
2138c43e99fdSEd Maste 			    "EV_READ, EV_WRITE or EV_CLOSED", __func__);
2139c43e99fdSEd Maste 			return -1;
2140c43e99fdSEd Maste 		}
2141c43e99fdSEd Maste 		ev->ev_closure = EV_CLOSURE_EVENT_SIGNAL;
2142c43e99fdSEd Maste 	} else {
2143c43e99fdSEd Maste 		if (events & EV_PERSIST) {
2144c43e99fdSEd Maste 			evutil_timerclear(&ev->ev_io_timeout);
2145c43e99fdSEd Maste 			ev->ev_closure = EV_CLOSURE_EVENT_PERSIST;
2146c43e99fdSEd Maste 		} else {
2147c43e99fdSEd Maste 			ev->ev_closure = EV_CLOSURE_EVENT;
2148c43e99fdSEd Maste 		}
2149c43e99fdSEd Maste 	}
2150c43e99fdSEd Maste 
2151c43e99fdSEd Maste 	min_heap_elem_init_(ev);
2152c43e99fdSEd Maste 
2153c43e99fdSEd Maste 	if (base != NULL) {
2154c43e99fdSEd Maste 		/* by default, we put new events into the middle priority */
2155c43e99fdSEd Maste 		ev->ev_pri = base->nactivequeues / 2;
2156c43e99fdSEd Maste 	}
2157c43e99fdSEd Maste 
2158c43e99fdSEd Maste 	event_debug_note_setup_(ev);
2159c43e99fdSEd Maste 
2160c43e99fdSEd Maste 	return 0;
2161c43e99fdSEd Maste }
2162c43e99fdSEd Maste 
2163c43e99fdSEd Maste int
event_base_set(struct event_base * base,struct event * ev)2164c43e99fdSEd Maste event_base_set(struct event_base *base, struct event *ev)
2165c43e99fdSEd Maste {
2166c43e99fdSEd Maste 	/* Only innocent events may be assigned to a different base */
2167c43e99fdSEd Maste 	if (ev->ev_flags != EVLIST_INIT)
2168c43e99fdSEd Maste 		return (-1);
2169c43e99fdSEd Maste 
2170c43e99fdSEd Maste 	event_debug_assert_is_setup_(ev);
2171c43e99fdSEd Maste 
2172c43e99fdSEd Maste 	ev->ev_base = base;
2173c43e99fdSEd Maste 	ev->ev_pri = base->nactivequeues/2;
2174c43e99fdSEd Maste 
2175c43e99fdSEd Maste 	return (0);
2176c43e99fdSEd Maste }
2177c43e99fdSEd Maste 
2178c43e99fdSEd Maste void
event_set(struct event * ev,evutil_socket_t fd,short events,void (* callback)(evutil_socket_t,short,void *),void * arg)2179c43e99fdSEd Maste event_set(struct event *ev, evutil_socket_t fd, short events,
2180c43e99fdSEd Maste 	  void (*callback)(evutil_socket_t, short, void *), void *arg)
2181c43e99fdSEd Maste {
2182c43e99fdSEd Maste 	int r;
2183c43e99fdSEd Maste 	r = event_assign(ev, current_base, fd, events, callback, arg);
2184c43e99fdSEd Maste 	EVUTIL_ASSERT(r == 0);
2185c43e99fdSEd Maste }
2186c43e99fdSEd Maste 
2187c43e99fdSEd Maste void *
event_self_cbarg(void)2188c43e99fdSEd Maste event_self_cbarg(void)
2189c43e99fdSEd Maste {
2190c43e99fdSEd Maste 	return &event_self_cbarg_ptr_;
2191c43e99fdSEd Maste }
2192c43e99fdSEd Maste 
2193c43e99fdSEd Maste struct event *
event_base_get_running_event(struct event_base * base)2194c43e99fdSEd Maste event_base_get_running_event(struct event_base *base)
2195c43e99fdSEd Maste {
2196c43e99fdSEd Maste 	struct event *ev = NULL;
2197c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
2198c43e99fdSEd Maste 	if (EVBASE_IN_THREAD(base)) {
2199c43e99fdSEd Maste 		struct event_callback *evcb = base->current_event;
2200c43e99fdSEd Maste 		if (evcb->evcb_flags & EVLIST_INIT)
2201c43e99fdSEd Maste 			ev = event_callback_to_event(evcb);
2202c43e99fdSEd Maste 	}
2203c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
2204c43e99fdSEd Maste 	return ev;
2205c43e99fdSEd Maste }
2206c43e99fdSEd Maste 
2207c43e99fdSEd Maste struct event *
event_new(struct event_base * base,evutil_socket_t fd,short events,void (* cb)(evutil_socket_t,short,void *),void * arg)2208c43e99fdSEd Maste event_new(struct event_base *base, evutil_socket_t fd, short events, void (*cb)(evutil_socket_t, short, void *), void *arg)
2209c43e99fdSEd Maste {
2210c43e99fdSEd Maste 	struct event *ev;
2211c43e99fdSEd Maste 	ev = mm_malloc(sizeof(struct event));
2212c43e99fdSEd Maste 	if (ev == NULL)
2213c43e99fdSEd Maste 		return (NULL);
2214c43e99fdSEd Maste 	if (event_assign(ev, base, fd, events, cb, arg) < 0) {
2215c43e99fdSEd Maste 		mm_free(ev);
2216c43e99fdSEd Maste 		return (NULL);
2217c43e99fdSEd Maste 	}
2218c43e99fdSEd Maste 
2219c43e99fdSEd Maste 	return (ev);
2220c43e99fdSEd Maste }
2221c43e99fdSEd Maste 
2222c43e99fdSEd Maste void
event_free(struct event * ev)2223c43e99fdSEd Maste event_free(struct event *ev)
2224c43e99fdSEd Maste {
2225c43e99fdSEd Maste 	/* This is disabled, so that events which have been finalized be a
2226c43e99fdSEd Maste 	 * valid target for event_free(). That's */
2227c43e99fdSEd Maste 	// event_debug_assert_is_setup_(ev);
2228c43e99fdSEd Maste 
2229c43e99fdSEd Maste 	/* make sure that this event won't be coming back to haunt us. */
2230c43e99fdSEd Maste 	event_del(ev);
2231c43e99fdSEd Maste 	event_debug_note_teardown_(ev);
2232c43e99fdSEd Maste 	mm_free(ev);
2233c43e99fdSEd Maste 
2234c43e99fdSEd Maste }
2235c43e99fdSEd Maste 
2236c43e99fdSEd Maste void
event_debug_unassign(struct event * ev)2237c43e99fdSEd Maste event_debug_unassign(struct event *ev)
2238c43e99fdSEd Maste {
2239c43e99fdSEd Maste 	event_debug_assert_not_added_(ev);
2240c43e99fdSEd Maste 	event_debug_note_teardown_(ev);
2241c43e99fdSEd Maste 
2242c43e99fdSEd Maste 	ev->ev_flags &= ~EVLIST_INIT;
2243c43e99fdSEd Maste }
2244c43e99fdSEd Maste 
2245c43e99fdSEd Maste #define EVENT_FINALIZE_FREE_ 0x10000
2246c43e99fdSEd Maste static int
event_finalize_nolock_(struct event_base * base,unsigned flags,struct event * ev,event_finalize_callback_fn cb)2247c43e99fdSEd Maste event_finalize_nolock_(struct event_base *base, unsigned flags, struct event *ev, event_finalize_callback_fn cb)
2248c43e99fdSEd Maste {
2249c43e99fdSEd Maste 	ev_uint8_t closure = (flags & EVENT_FINALIZE_FREE_) ?
2250c43e99fdSEd Maste 	    EV_CLOSURE_EVENT_FINALIZE_FREE : EV_CLOSURE_EVENT_FINALIZE;
2251c43e99fdSEd Maste 
2252c43e99fdSEd Maste 	event_del_nolock_(ev, EVENT_DEL_NOBLOCK);
2253c43e99fdSEd Maste 	ev->ev_closure = closure;
2254c43e99fdSEd Maste 	ev->ev_evcallback.evcb_cb_union.evcb_evfinalize = cb;
2255c43e99fdSEd Maste 	event_active_nolock_(ev, EV_FINALIZE, 1);
2256c43e99fdSEd Maste 	ev->ev_flags |= EVLIST_FINALIZING;
2257c43e99fdSEd Maste 	return 0;
2258c43e99fdSEd Maste }
2259c43e99fdSEd Maste 
2260c43e99fdSEd Maste static int
event_finalize_impl_(unsigned flags,struct event * ev,event_finalize_callback_fn cb)2261c43e99fdSEd Maste event_finalize_impl_(unsigned flags, struct event *ev, event_finalize_callback_fn cb)
2262c43e99fdSEd Maste {
2263c43e99fdSEd Maste 	int r;
2264c43e99fdSEd Maste 	struct event_base *base = ev->ev_base;
2265c43e99fdSEd Maste 	if (EVUTIL_FAILURE_CHECK(!base)) {
2266c43e99fdSEd Maste 		event_warnx("%s: event has no event_base set.", __func__);
2267c43e99fdSEd Maste 		return -1;
2268c43e99fdSEd Maste 	}
2269c43e99fdSEd Maste 
2270c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
2271c43e99fdSEd Maste 	r = event_finalize_nolock_(base, flags, ev, cb);
2272c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
2273c43e99fdSEd Maste 	return r;
2274c43e99fdSEd Maste }
2275c43e99fdSEd Maste 
2276c43e99fdSEd Maste int
event_finalize(unsigned flags,struct event * ev,event_finalize_callback_fn cb)2277c43e99fdSEd Maste event_finalize(unsigned flags, struct event *ev, event_finalize_callback_fn cb)
2278c43e99fdSEd Maste {
2279c43e99fdSEd Maste 	return event_finalize_impl_(flags, ev, cb);
2280c43e99fdSEd Maste }
2281c43e99fdSEd Maste 
2282c43e99fdSEd Maste int
event_free_finalize(unsigned flags,struct event * ev,event_finalize_callback_fn cb)2283c43e99fdSEd Maste event_free_finalize(unsigned flags, struct event *ev, event_finalize_callback_fn cb)
2284c43e99fdSEd Maste {
2285c43e99fdSEd Maste 	return event_finalize_impl_(flags|EVENT_FINALIZE_FREE_, ev, cb);
2286c43e99fdSEd Maste }
2287c43e99fdSEd Maste 
2288c43e99fdSEd Maste void
event_callback_finalize_nolock_(struct event_base * base,unsigned flags,struct event_callback * evcb,void (* cb)(struct event_callback *,void *))2289c43e99fdSEd Maste event_callback_finalize_nolock_(struct event_base *base, unsigned flags, struct event_callback *evcb, void (*cb)(struct event_callback *, void *))
2290c43e99fdSEd Maste {
2291c43e99fdSEd Maste 	struct event *ev = NULL;
2292c43e99fdSEd Maste 	if (evcb->evcb_flags & EVLIST_INIT) {
2293c43e99fdSEd Maste 		ev = event_callback_to_event(evcb);
2294c43e99fdSEd Maste 		event_del_nolock_(ev, EVENT_DEL_NOBLOCK);
2295c43e99fdSEd Maste 	} else {
2296c43e99fdSEd Maste 		event_callback_cancel_nolock_(base, evcb, 0); /*XXX can this fail?*/
2297c43e99fdSEd Maste 	}
2298c43e99fdSEd Maste 
2299c43e99fdSEd Maste 	evcb->evcb_closure = EV_CLOSURE_CB_FINALIZE;
2300c43e99fdSEd Maste 	evcb->evcb_cb_union.evcb_cbfinalize = cb;
2301c43e99fdSEd Maste 	event_callback_activate_nolock_(base, evcb); /* XXX can this really fail?*/
2302c43e99fdSEd Maste 	evcb->evcb_flags |= EVLIST_FINALIZING;
2303c43e99fdSEd Maste }
2304c43e99fdSEd Maste 
2305c43e99fdSEd Maste void
event_callback_finalize_(struct event_base * base,unsigned flags,struct event_callback * evcb,void (* cb)(struct event_callback *,void *))2306c43e99fdSEd Maste event_callback_finalize_(struct event_base *base, unsigned flags, struct event_callback *evcb, void (*cb)(struct event_callback *, void *))
2307c43e99fdSEd Maste {
2308c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
2309c43e99fdSEd Maste 	event_callback_finalize_nolock_(base, flags, evcb, cb);
2310c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
2311c43e99fdSEd Maste }
2312c43e99fdSEd Maste 
2313c43e99fdSEd Maste /** Internal: Finalize all of the n_cbs callbacks in evcbs.  The provided
2314c43e99fdSEd Maste  * callback will be invoked on *one of them*, after they have *all* been
2315c43e99fdSEd Maste  * finalized. */
2316c43e99fdSEd Maste int
event_callback_finalize_many_(struct event_base * base,int n_cbs,struct event_callback ** evcbs,void (* cb)(struct event_callback *,void *))2317c43e99fdSEd Maste event_callback_finalize_many_(struct event_base *base, int n_cbs, struct event_callback **evcbs, void (*cb)(struct event_callback *, void *))
2318c43e99fdSEd Maste {
2319c43e99fdSEd Maste 	int n_pending = 0, i;
2320c43e99fdSEd Maste 
2321c43e99fdSEd Maste 	if (base == NULL)
2322c43e99fdSEd Maste 		base = current_base;
2323c43e99fdSEd Maste 
2324c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
2325c43e99fdSEd Maste 
2326c43e99fdSEd Maste 	event_debug(("%s: %d events finalizing", __func__, n_cbs));
2327c43e99fdSEd Maste 
2328c43e99fdSEd Maste 	/* At most one can be currently executing; the rest we just
2329c43e99fdSEd Maste 	 * cancel... But we always make sure that the finalize callback
2330c43e99fdSEd Maste 	 * runs. */
2331c43e99fdSEd Maste 	for (i = 0; i < n_cbs; ++i) {
2332c43e99fdSEd Maste 		struct event_callback *evcb = evcbs[i];
2333c43e99fdSEd Maste 		if (evcb == base->current_event) {
2334c43e99fdSEd Maste 			event_callback_finalize_nolock_(base, 0, evcb, cb);
2335c43e99fdSEd Maste 			++n_pending;
2336c43e99fdSEd Maste 		} else {
2337c43e99fdSEd Maste 			event_callback_cancel_nolock_(base, evcb, 0);
2338c43e99fdSEd Maste 		}
2339c43e99fdSEd Maste 	}
2340c43e99fdSEd Maste 
2341c43e99fdSEd Maste 	if (n_pending == 0) {
2342c43e99fdSEd Maste 		/* Just do the first one. */
2343c43e99fdSEd Maste 		event_callback_finalize_nolock_(base, 0, evcbs[0], cb);
2344c43e99fdSEd Maste 	}
2345c43e99fdSEd Maste 
2346c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
2347c43e99fdSEd Maste 	return 0;
2348c43e99fdSEd Maste }
2349c43e99fdSEd Maste 
2350c43e99fdSEd Maste /*
2351c43e99fdSEd Maste  * Set's the priority of an event - if an event is already scheduled
2352c43e99fdSEd Maste  * changing the priority is going to fail.
2353c43e99fdSEd Maste  */
2354c43e99fdSEd Maste 
2355c43e99fdSEd Maste int
event_priority_set(struct event * ev,int pri)2356c43e99fdSEd Maste event_priority_set(struct event *ev, int pri)
2357c43e99fdSEd Maste {
2358c43e99fdSEd Maste 	event_debug_assert_is_setup_(ev);
2359c43e99fdSEd Maste 
2360c43e99fdSEd Maste 	if (ev->ev_flags & EVLIST_ACTIVE)
2361c43e99fdSEd Maste 		return (-1);
2362c43e99fdSEd Maste 	if (pri < 0 || pri >= ev->ev_base->nactivequeues)
2363c43e99fdSEd Maste 		return (-1);
2364c43e99fdSEd Maste 
2365c43e99fdSEd Maste 	ev->ev_pri = pri;
2366c43e99fdSEd Maste 
2367c43e99fdSEd Maste 	return (0);
2368c43e99fdSEd Maste }
2369c43e99fdSEd Maste 
2370c43e99fdSEd Maste /*
2371c43e99fdSEd Maste  * Checks if a specific event is pending or scheduled.
2372c43e99fdSEd Maste  */
2373c43e99fdSEd Maste 
2374c43e99fdSEd Maste int
event_pending(const struct event * ev,short event,struct timeval * tv)2375c43e99fdSEd Maste event_pending(const struct event *ev, short event, struct timeval *tv)
2376c43e99fdSEd Maste {
2377c43e99fdSEd Maste 	int flags = 0;
2378c43e99fdSEd Maste 
2379c43e99fdSEd Maste 	if (EVUTIL_FAILURE_CHECK(ev->ev_base == NULL)) {
2380c43e99fdSEd Maste 		event_warnx("%s: event has no event_base set.", __func__);
2381c43e99fdSEd Maste 		return 0;
2382c43e99fdSEd Maste 	}
2383c43e99fdSEd Maste 
2384c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(ev->ev_base, th_base_lock);
2385c43e99fdSEd Maste 	event_debug_assert_is_setup_(ev);
2386c43e99fdSEd Maste 
2387c43e99fdSEd Maste 	if (ev->ev_flags & EVLIST_INSERTED)
2388c43e99fdSEd Maste 		flags |= (ev->ev_events & (EV_READ|EV_WRITE|EV_CLOSED|EV_SIGNAL));
2389c43e99fdSEd Maste 	if (ev->ev_flags & (EVLIST_ACTIVE|EVLIST_ACTIVE_LATER))
2390c43e99fdSEd Maste 		flags |= ev->ev_res;
2391c43e99fdSEd Maste 	if (ev->ev_flags & EVLIST_TIMEOUT)
2392c43e99fdSEd Maste 		flags |= EV_TIMEOUT;
2393c43e99fdSEd Maste 
2394c43e99fdSEd Maste 	event &= (EV_TIMEOUT|EV_READ|EV_WRITE|EV_CLOSED|EV_SIGNAL);
2395c43e99fdSEd Maste 
2396c43e99fdSEd Maste 	/* See if there is a timeout that we should report */
2397c43e99fdSEd Maste 	if (tv != NULL && (flags & event & EV_TIMEOUT)) {
2398c43e99fdSEd Maste 		struct timeval tmp = ev->ev_timeout;
2399c43e99fdSEd Maste 		tmp.tv_usec &= MICROSECONDS_MASK;
2400c43e99fdSEd Maste 		/* correctly remamp to real time */
2401c43e99fdSEd Maste 		evutil_timeradd(&ev->ev_base->tv_clock_diff, &tmp, tv);
2402c43e99fdSEd Maste 	}
2403c43e99fdSEd Maste 
2404c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(ev->ev_base, th_base_lock);
2405c43e99fdSEd Maste 
2406c43e99fdSEd Maste 	return (flags & event);
2407c43e99fdSEd Maste }
2408c43e99fdSEd Maste 
2409c43e99fdSEd Maste int
event_initialized(const struct event * ev)2410c43e99fdSEd Maste event_initialized(const struct event *ev)
2411c43e99fdSEd Maste {
2412c43e99fdSEd Maste 	if (!(ev->ev_flags & EVLIST_INIT))
2413c43e99fdSEd Maste 		return 0;
2414c43e99fdSEd Maste 
2415c43e99fdSEd Maste 	return 1;
2416c43e99fdSEd Maste }
2417c43e99fdSEd Maste 
2418c43e99fdSEd Maste void
event_get_assignment(const struct event * event,struct event_base ** base_out,evutil_socket_t * fd_out,short * events_out,event_callback_fn * callback_out,void ** arg_out)2419c43e99fdSEd Maste event_get_assignment(const struct event *event, struct event_base **base_out, evutil_socket_t *fd_out, short *events_out, event_callback_fn *callback_out, void **arg_out)
2420c43e99fdSEd Maste {
2421c43e99fdSEd Maste 	event_debug_assert_is_setup_(event);
2422c43e99fdSEd Maste 
2423c43e99fdSEd Maste 	if (base_out)
2424c43e99fdSEd Maste 		*base_out = event->ev_base;
2425c43e99fdSEd Maste 	if (fd_out)
2426c43e99fdSEd Maste 		*fd_out = event->ev_fd;
2427c43e99fdSEd Maste 	if (events_out)
2428c43e99fdSEd Maste 		*events_out = event->ev_events;
2429c43e99fdSEd Maste 	if (callback_out)
2430c43e99fdSEd Maste 		*callback_out = event->ev_callback;
2431c43e99fdSEd Maste 	if (arg_out)
2432c43e99fdSEd Maste 		*arg_out = event->ev_arg;
2433c43e99fdSEd Maste }
2434c43e99fdSEd Maste 
2435c43e99fdSEd Maste size_t
event_get_struct_event_size(void)2436c43e99fdSEd Maste event_get_struct_event_size(void)
2437c43e99fdSEd Maste {
2438c43e99fdSEd Maste 	return sizeof(struct event);
2439c43e99fdSEd Maste }
2440c43e99fdSEd Maste 
2441c43e99fdSEd Maste evutil_socket_t
event_get_fd(const struct event * ev)2442c43e99fdSEd Maste event_get_fd(const struct event *ev)
2443c43e99fdSEd Maste {
2444c43e99fdSEd Maste 	event_debug_assert_is_setup_(ev);
2445c43e99fdSEd Maste 	return ev->ev_fd;
2446c43e99fdSEd Maste }
2447c43e99fdSEd Maste 
2448c43e99fdSEd Maste struct event_base *
event_get_base(const struct event * ev)2449c43e99fdSEd Maste event_get_base(const struct event *ev)
2450c43e99fdSEd Maste {
2451c43e99fdSEd Maste 	event_debug_assert_is_setup_(ev);
2452c43e99fdSEd Maste 	return ev->ev_base;
2453c43e99fdSEd Maste }
2454c43e99fdSEd Maste 
2455c43e99fdSEd Maste short
event_get_events(const struct event * ev)2456c43e99fdSEd Maste event_get_events(const struct event *ev)
2457c43e99fdSEd Maste {
2458c43e99fdSEd Maste 	event_debug_assert_is_setup_(ev);
2459c43e99fdSEd Maste 	return ev->ev_events;
2460c43e99fdSEd Maste }
2461c43e99fdSEd Maste 
2462c43e99fdSEd Maste event_callback_fn
event_get_callback(const struct event * ev)2463c43e99fdSEd Maste event_get_callback(const struct event *ev)
2464c43e99fdSEd Maste {
2465c43e99fdSEd Maste 	event_debug_assert_is_setup_(ev);
2466c43e99fdSEd Maste 	return ev->ev_callback;
2467c43e99fdSEd Maste }
2468c43e99fdSEd Maste 
2469c43e99fdSEd Maste void *
event_get_callback_arg(const struct event * ev)2470c43e99fdSEd Maste event_get_callback_arg(const struct event *ev)
2471c43e99fdSEd Maste {
2472c43e99fdSEd Maste 	event_debug_assert_is_setup_(ev);
2473c43e99fdSEd Maste 	return ev->ev_arg;
2474c43e99fdSEd Maste }
2475c43e99fdSEd Maste 
2476c43e99fdSEd Maste int
event_get_priority(const struct event * ev)2477c43e99fdSEd Maste event_get_priority(const struct event *ev)
2478c43e99fdSEd Maste {
2479c43e99fdSEd Maste 	event_debug_assert_is_setup_(ev);
2480c43e99fdSEd Maste 	return ev->ev_pri;
2481c43e99fdSEd Maste }
2482c43e99fdSEd Maste 
2483c43e99fdSEd Maste int
event_add(struct event * ev,const struct timeval * tv)2484c43e99fdSEd Maste event_add(struct event *ev, const struct timeval *tv)
2485c43e99fdSEd Maste {
2486c43e99fdSEd Maste 	int res;
2487c43e99fdSEd Maste 
2488c43e99fdSEd Maste 	if (EVUTIL_FAILURE_CHECK(!ev->ev_base)) {
2489c43e99fdSEd Maste 		event_warnx("%s: event has no event_base set.", __func__);
2490c43e99fdSEd Maste 		return -1;
2491c43e99fdSEd Maste 	}
2492c43e99fdSEd Maste 
2493c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(ev->ev_base, th_base_lock);
2494c43e99fdSEd Maste 
2495c43e99fdSEd Maste 	res = event_add_nolock_(ev, tv, 0);
2496c43e99fdSEd Maste 
2497c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(ev->ev_base, th_base_lock);
2498c43e99fdSEd Maste 
2499c43e99fdSEd Maste 	return (res);
2500c43e99fdSEd Maste }
2501c43e99fdSEd Maste 
2502c43e99fdSEd Maste /* Helper callback: wake an event_base from another thread.  This version
2503c43e99fdSEd Maste  * works by writing a byte to one end of a socketpair, so that the event_base
2504c43e99fdSEd Maste  * listening on the other end will wake up as the corresponding event
2505c43e99fdSEd Maste  * triggers */
2506c43e99fdSEd Maste static int
evthread_notify_base_default(struct event_base * base)2507c43e99fdSEd Maste evthread_notify_base_default(struct event_base *base)
2508c43e99fdSEd Maste {
2509c43e99fdSEd Maste 	char buf[1];
2510c43e99fdSEd Maste 	int r;
2511c43e99fdSEd Maste 	buf[0] = (char) 0;
2512c43e99fdSEd Maste #ifdef _WIN32
2513c43e99fdSEd Maste 	r = send(base->th_notify_fd[1], buf, 1, 0);
2514c43e99fdSEd Maste #else
2515c43e99fdSEd Maste 	r = write(base->th_notify_fd[1], buf, 1);
2516c43e99fdSEd Maste #endif
2517c43e99fdSEd Maste 	return (r < 0 && ! EVUTIL_ERR_IS_EAGAIN(errno)) ? -1 : 0;
2518c43e99fdSEd Maste }
2519c43e99fdSEd Maste 
2520c43e99fdSEd Maste #ifdef EVENT__HAVE_EVENTFD
2521c43e99fdSEd Maste /* Helper callback: wake an event_base from another thread.  This version
2522c43e99fdSEd Maste  * assumes that you have a working eventfd() implementation. */
2523c43e99fdSEd Maste static int
evthread_notify_base_eventfd(struct event_base * base)2524c43e99fdSEd Maste evthread_notify_base_eventfd(struct event_base *base)
2525c43e99fdSEd Maste {
2526c43e99fdSEd Maste 	ev_uint64_t msg = 1;
2527c43e99fdSEd Maste 	int r;
2528c43e99fdSEd Maste 	do {
2529c43e99fdSEd Maste 		r = write(base->th_notify_fd[0], (void*) &msg, sizeof(msg));
2530c43e99fdSEd Maste 	} while (r < 0 && errno == EAGAIN);
2531c43e99fdSEd Maste 
2532c43e99fdSEd Maste 	return (r < 0) ? -1 : 0;
2533c43e99fdSEd Maste }
2534c43e99fdSEd Maste #endif
2535c43e99fdSEd Maste 
2536c43e99fdSEd Maste 
2537c43e99fdSEd Maste /** Tell the thread currently running the event_loop for base (if any) that it
2538c43e99fdSEd Maste  * needs to stop waiting in its dispatch function (if it is) and process all
2539c43e99fdSEd Maste  * active callbacks. */
2540c43e99fdSEd Maste static int
evthread_notify_base(struct event_base * base)2541c43e99fdSEd Maste evthread_notify_base(struct event_base *base)
2542c43e99fdSEd Maste {
2543c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
2544c43e99fdSEd Maste 	if (!base->th_notify_fn)
2545c43e99fdSEd Maste 		return -1;
2546c43e99fdSEd Maste 	if (base->is_notify_pending)
2547c43e99fdSEd Maste 		return 0;
2548c43e99fdSEd Maste 	base->is_notify_pending = 1;
2549c43e99fdSEd Maste 	return base->th_notify_fn(base);
2550c43e99fdSEd Maste }
2551c43e99fdSEd Maste 
2552c43e99fdSEd Maste /* Implementation function to remove a timeout on a currently pending event.
2553c43e99fdSEd Maste  */
2554c43e99fdSEd Maste int
event_remove_timer_nolock_(struct event * ev)2555c43e99fdSEd Maste event_remove_timer_nolock_(struct event *ev)
2556c43e99fdSEd Maste {
2557c43e99fdSEd Maste 	struct event_base *base = ev->ev_base;
2558c43e99fdSEd Maste 
2559c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
2560c43e99fdSEd Maste 	event_debug_assert_is_setup_(ev);
2561c43e99fdSEd Maste 
2562c43e99fdSEd Maste 	event_debug(("event_remove_timer_nolock: event: %p", ev));
2563c43e99fdSEd Maste 
2564c43e99fdSEd Maste 	/* If it's not pending on a timeout, we don't need to do anything. */
2565c43e99fdSEd Maste 	if (ev->ev_flags & EVLIST_TIMEOUT) {
2566c43e99fdSEd Maste 		event_queue_remove_timeout(base, ev);
2567c43e99fdSEd Maste 		evutil_timerclear(&ev->ev_.ev_io.ev_timeout);
2568c43e99fdSEd Maste 	}
2569c43e99fdSEd Maste 
2570c43e99fdSEd Maste 	return (0);
2571c43e99fdSEd Maste }
2572c43e99fdSEd Maste 
2573c43e99fdSEd Maste int
event_remove_timer(struct event * ev)2574c43e99fdSEd Maste event_remove_timer(struct event *ev)
2575c43e99fdSEd Maste {
2576c43e99fdSEd Maste 	int res;
2577c43e99fdSEd Maste 
2578c43e99fdSEd Maste 	if (EVUTIL_FAILURE_CHECK(!ev->ev_base)) {
2579c43e99fdSEd Maste 		event_warnx("%s: event has no event_base set.", __func__);
2580c43e99fdSEd Maste 		return -1;
2581c43e99fdSEd Maste 	}
2582c43e99fdSEd Maste 
2583c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(ev->ev_base, th_base_lock);
2584c43e99fdSEd Maste 
2585c43e99fdSEd Maste 	res = event_remove_timer_nolock_(ev);
2586c43e99fdSEd Maste 
2587c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(ev->ev_base, th_base_lock);
2588c43e99fdSEd Maste 
2589c43e99fdSEd Maste 	return (res);
2590c43e99fdSEd Maste }
2591c43e99fdSEd Maste 
2592c43e99fdSEd Maste /* Implementation function to add an event.  Works just like event_add,
2593c43e99fdSEd Maste  * except: 1) it requires that we have the lock.  2) if tv_is_absolute is set,
2594c43e99fdSEd Maste  * we treat tv as an absolute time, not as an interval to add to the current
2595c43e99fdSEd Maste  * time */
2596c43e99fdSEd Maste int
event_add_nolock_(struct event * ev,const struct timeval * tv,int tv_is_absolute)2597c43e99fdSEd Maste event_add_nolock_(struct event *ev, const struct timeval *tv,
2598c43e99fdSEd Maste     int tv_is_absolute)
2599c43e99fdSEd Maste {
2600c43e99fdSEd Maste 	struct event_base *base = ev->ev_base;
2601c43e99fdSEd Maste 	int res = 0;
2602c43e99fdSEd Maste 	int notify = 0;
2603c43e99fdSEd Maste 
2604c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
2605c43e99fdSEd Maste 	event_debug_assert_is_setup_(ev);
2606c43e99fdSEd Maste 
2607c43e99fdSEd Maste 	event_debug((
2608c43e99fdSEd Maste 		 "event_add: event: %p (fd "EV_SOCK_FMT"), %s%s%s%scall %p",
2609c43e99fdSEd Maste 		 ev,
2610c43e99fdSEd Maste 		 EV_SOCK_ARG(ev->ev_fd),
2611c43e99fdSEd Maste 		 ev->ev_events & EV_READ ? "EV_READ " : " ",
2612c43e99fdSEd Maste 		 ev->ev_events & EV_WRITE ? "EV_WRITE " : " ",
2613c43e99fdSEd Maste 		 ev->ev_events & EV_CLOSED ? "EV_CLOSED " : " ",
2614c43e99fdSEd Maste 		 tv ? "EV_TIMEOUT " : " ",
2615c43e99fdSEd Maste 		 ev->ev_callback));
2616c43e99fdSEd Maste 
2617c43e99fdSEd Maste 	EVUTIL_ASSERT(!(ev->ev_flags & ~EVLIST_ALL));
2618c43e99fdSEd Maste 
2619c43e99fdSEd Maste 	if (ev->ev_flags & EVLIST_FINALIZING) {
2620c43e99fdSEd Maste 		/* XXXX debug */
2621c43e99fdSEd Maste 		return (-1);
2622c43e99fdSEd Maste 	}
2623c43e99fdSEd Maste 
2624c43e99fdSEd Maste 	/*
2625c43e99fdSEd Maste 	 * prepare for timeout insertion further below, if we get a
2626c43e99fdSEd Maste 	 * failure on any step, we should not change any state.
2627c43e99fdSEd Maste 	 */
2628c43e99fdSEd Maste 	if (tv != NULL && !(ev->ev_flags & EVLIST_TIMEOUT)) {
2629c43e99fdSEd Maste 		if (min_heap_reserve_(&base->timeheap,
2630c43e99fdSEd Maste 			1 + min_heap_size_(&base->timeheap)) == -1)
2631c43e99fdSEd Maste 			return (-1);  /* ENOMEM == errno */
2632c43e99fdSEd Maste 	}
2633c43e99fdSEd Maste 
2634c43e99fdSEd Maste 	/* If the main thread is currently executing a signal event's
2635c43e99fdSEd Maste 	 * callback, and we are not the main thread, then we want to wait
2636c43e99fdSEd Maste 	 * until the callback is done before we mess with the event, or else
2637c43e99fdSEd Maste 	 * we can race on ev_ncalls and ev_pncalls below. */
2638c43e99fdSEd Maste #ifndef EVENT__DISABLE_THREAD_SUPPORT
2639c43e99fdSEd Maste 	if (base->current_event == event_to_event_callback(ev) &&
2640c43e99fdSEd Maste 	    (ev->ev_events & EV_SIGNAL)
2641c43e99fdSEd Maste 	    && !EVBASE_IN_THREAD(base)) {
2642c43e99fdSEd Maste 		++base->current_event_waiters;
2643c43e99fdSEd Maste 		EVTHREAD_COND_WAIT(base->current_event_cond, base->th_base_lock);
2644c43e99fdSEd Maste 	}
2645c43e99fdSEd Maste #endif
2646c43e99fdSEd Maste 
2647c43e99fdSEd Maste 	if ((ev->ev_events & (EV_READ|EV_WRITE|EV_CLOSED|EV_SIGNAL)) &&
2648c43e99fdSEd Maste 	    !(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE|EVLIST_ACTIVE_LATER))) {
2649c43e99fdSEd Maste 		if (ev->ev_events & (EV_READ|EV_WRITE|EV_CLOSED))
2650c43e99fdSEd Maste 			res = evmap_io_add_(base, ev->ev_fd, ev);
2651c43e99fdSEd Maste 		else if (ev->ev_events & EV_SIGNAL)
2652c43e99fdSEd Maste 			res = evmap_signal_add_(base, (int)ev->ev_fd, ev);
2653c43e99fdSEd Maste 		if (res != -1)
2654c43e99fdSEd Maste 			event_queue_insert_inserted(base, ev);
2655c43e99fdSEd Maste 		if (res == 1) {
2656c43e99fdSEd Maste 			/* evmap says we need to notify the main thread. */
2657c43e99fdSEd Maste 			notify = 1;
2658c43e99fdSEd Maste 			res = 0;
2659c43e99fdSEd Maste 		}
2660c43e99fdSEd Maste 	}
2661c43e99fdSEd Maste 
2662c43e99fdSEd Maste 	/*
2663c43e99fdSEd Maste 	 * we should change the timeout state only if the previous event
2664c43e99fdSEd Maste 	 * addition succeeded.
2665c43e99fdSEd Maste 	 */
2666c43e99fdSEd Maste 	if (res != -1 && tv != NULL) {
2667c43e99fdSEd Maste 		struct timeval now;
2668c43e99fdSEd Maste 		int common_timeout;
2669c43e99fdSEd Maste #ifdef USE_REINSERT_TIMEOUT
2670c43e99fdSEd Maste 		int was_common;
2671c43e99fdSEd Maste 		int old_timeout_idx;
2672c43e99fdSEd Maste #endif
2673c43e99fdSEd Maste 
2674c43e99fdSEd Maste 		/*
2675c43e99fdSEd Maste 		 * for persistent timeout events, we remember the
2676c43e99fdSEd Maste 		 * timeout value and re-add the event.
2677c43e99fdSEd Maste 		 *
2678c43e99fdSEd Maste 		 * If tv_is_absolute, this was already set.
2679c43e99fdSEd Maste 		 */
2680c43e99fdSEd Maste 		if (ev->ev_closure == EV_CLOSURE_EVENT_PERSIST && !tv_is_absolute)
2681c43e99fdSEd Maste 			ev->ev_io_timeout = *tv;
2682c43e99fdSEd Maste 
2683c43e99fdSEd Maste #ifndef USE_REINSERT_TIMEOUT
2684c43e99fdSEd Maste 		if (ev->ev_flags & EVLIST_TIMEOUT) {
2685c43e99fdSEd Maste 			event_queue_remove_timeout(base, ev);
2686c43e99fdSEd Maste 		}
2687c43e99fdSEd Maste #endif
2688c43e99fdSEd Maste 
2689c43e99fdSEd Maste 		/* Check if it is active due to a timeout.  Rescheduling
2690c43e99fdSEd Maste 		 * this timeout before the callback can be executed
2691c43e99fdSEd Maste 		 * removes it from the active list. */
2692c43e99fdSEd Maste 		if ((ev->ev_flags & EVLIST_ACTIVE) &&
2693c43e99fdSEd Maste 		    (ev->ev_res & EV_TIMEOUT)) {
2694c43e99fdSEd Maste 			if (ev->ev_events & EV_SIGNAL) {
2695c43e99fdSEd Maste 				/* See if we are just active executing
2696c43e99fdSEd Maste 				 * this event in a loop
2697c43e99fdSEd Maste 				 */
2698c43e99fdSEd Maste 				if (ev->ev_ncalls && ev->ev_pncalls) {
2699c43e99fdSEd Maste 					/* Abort loop */
2700c43e99fdSEd Maste 					*ev->ev_pncalls = 0;
2701c43e99fdSEd Maste 				}
2702c43e99fdSEd Maste 			}
2703c43e99fdSEd Maste 
2704c43e99fdSEd Maste 			event_queue_remove_active(base, event_to_event_callback(ev));
2705c43e99fdSEd Maste 		}
2706c43e99fdSEd Maste 
2707c43e99fdSEd Maste 		gettime(base, &now);
2708c43e99fdSEd Maste 
2709c43e99fdSEd Maste 		common_timeout = is_common_timeout(tv, base);
2710c43e99fdSEd Maste #ifdef USE_REINSERT_TIMEOUT
2711c43e99fdSEd Maste 		was_common = is_common_timeout(&ev->ev_timeout, base);
2712c43e99fdSEd Maste 		old_timeout_idx = COMMON_TIMEOUT_IDX(&ev->ev_timeout);
2713c43e99fdSEd Maste #endif
2714c43e99fdSEd Maste 
2715c43e99fdSEd Maste 		if (tv_is_absolute) {
2716c43e99fdSEd Maste 			ev->ev_timeout = *tv;
2717c43e99fdSEd Maste 		} else if (common_timeout) {
2718c43e99fdSEd Maste 			struct timeval tmp = *tv;
2719c43e99fdSEd Maste 			tmp.tv_usec &= MICROSECONDS_MASK;
2720c43e99fdSEd Maste 			evutil_timeradd(&now, &tmp, &ev->ev_timeout);
2721c43e99fdSEd Maste 			ev->ev_timeout.tv_usec |=
2722c43e99fdSEd Maste 			    (tv->tv_usec & ~MICROSECONDS_MASK);
2723c43e99fdSEd Maste 		} else {
2724c43e99fdSEd Maste 			evutil_timeradd(&now, tv, &ev->ev_timeout);
2725c43e99fdSEd Maste 		}
2726c43e99fdSEd Maste 
2727c43e99fdSEd Maste 		event_debug((
2728c43e99fdSEd Maste 			 "event_add: event %p, timeout in %d seconds %d useconds, call %p",
2729c43e99fdSEd Maste 			 ev, (int)tv->tv_sec, (int)tv->tv_usec, ev->ev_callback));
2730c43e99fdSEd Maste 
2731c43e99fdSEd Maste #ifdef USE_REINSERT_TIMEOUT
2732c43e99fdSEd Maste 		event_queue_reinsert_timeout(base, ev, was_common, common_timeout, old_timeout_idx);
2733c43e99fdSEd Maste #else
2734c43e99fdSEd Maste 		event_queue_insert_timeout(base, ev);
2735c43e99fdSEd Maste #endif
2736c43e99fdSEd Maste 
2737c43e99fdSEd Maste 		if (common_timeout) {
2738c43e99fdSEd Maste 			struct common_timeout_list *ctl =
2739c43e99fdSEd Maste 			    get_common_timeout_list(base, &ev->ev_timeout);
2740c43e99fdSEd Maste 			if (ev == TAILQ_FIRST(&ctl->events)) {
2741c43e99fdSEd Maste 				common_timeout_schedule(ctl, &now, ev);
2742c43e99fdSEd Maste 			}
2743c43e99fdSEd Maste 		} else {
2744c43e99fdSEd Maste 			struct event* top = NULL;
2745c43e99fdSEd Maste 			/* See if the earliest timeout is now earlier than it
2746c43e99fdSEd Maste 			 * was before: if so, we will need to tell the main
2747c43e99fdSEd Maste 			 * thread to wake up earlier than it would otherwise.
2748c43e99fdSEd Maste 			 * We double check the timeout of the top element to
2749c43e99fdSEd Maste 			 * handle time distortions due to system suspension.
2750c43e99fdSEd Maste 			 */
2751c43e99fdSEd Maste 			if (min_heap_elt_is_top_(ev))
2752c43e99fdSEd Maste 				notify = 1;
2753c43e99fdSEd Maste 			else if ((top = min_heap_top_(&base->timeheap)) != NULL &&
2754c43e99fdSEd Maste 					 evutil_timercmp(&top->ev_timeout, &now, <))
2755c43e99fdSEd Maste 				notify = 1;
2756c43e99fdSEd Maste 		}
2757c43e99fdSEd Maste 	}
2758c43e99fdSEd Maste 
2759c43e99fdSEd Maste 	/* if we are not in the right thread, we need to wake up the loop */
2760c43e99fdSEd Maste 	if (res != -1 && notify && EVBASE_NEED_NOTIFY(base))
2761c43e99fdSEd Maste 		evthread_notify_base(base);
2762c43e99fdSEd Maste 
2763c43e99fdSEd Maste 	event_debug_note_add_(ev);
2764c43e99fdSEd Maste 
2765c43e99fdSEd Maste 	return (res);
2766c43e99fdSEd Maste }
2767c43e99fdSEd Maste 
2768c43e99fdSEd Maste static int
event_del_(struct event * ev,int blocking)2769c43e99fdSEd Maste event_del_(struct event *ev, int blocking)
2770c43e99fdSEd Maste {
2771c43e99fdSEd Maste 	int res;
2772*b50261e2SCy Schubert 	struct event_base *base = ev->ev_base;
2773c43e99fdSEd Maste 
2774*b50261e2SCy Schubert 	if (EVUTIL_FAILURE_CHECK(!base)) {
2775c43e99fdSEd Maste 		event_warnx("%s: event has no event_base set.", __func__);
2776c43e99fdSEd Maste 		return -1;
2777c43e99fdSEd Maste 	}
2778c43e99fdSEd Maste 
2779*b50261e2SCy Schubert 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
2780c43e99fdSEd Maste 	res = event_del_nolock_(ev, blocking);
2781*b50261e2SCy Schubert 	EVBASE_RELEASE_LOCK(base, th_base_lock);
2782c43e99fdSEd Maste 
2783c43e99fdSEd Maste 	return (res);
2784c43e99fdSEd Maste }
2785c43e99fdSEd Maste 
2786c43e99fdSEd Maste int
event_del(struct event * ev)2787c43e99fdSEd Maste event_del(struct event *ev)
2788c43e99fdSEd Maste {
2789c43e99fdSEd Maste 	return event_del_(ev, EVENT_DEL_AUTOBLOCK);
2790c43e99fdSEd Maste }
2791c43e99fdSEd Maste 
2792c43e99fdSEd Maste int
event_del_block(struct event * ev)2793c43e99fdSEd Maste event_del_block(struct event *ev)
2794c43e99fdSEd Maste {
2795c43e99fdSEd Maste 	return event_del_(ev, EVENT_DEL_BLOCK);
2796c43e99fdSEd Maste }
2797c43e99fdSEd Maste 
2798c43e99fdSEd Maste int
event_del_noblock(struct event * ev)2799c43e99fdSEd Maste event_del_noblock(struct event *ev)
2800c43e99fdSEd Maste {
2801c43e99fdSEd Maste 	return event_del_(ev, EVENT_DEL_NOBLOCK);
2802c43e99fdSEd Maste }
2803c43e99fdSEd Maste 
2804c43e99fdSEd Maste /** Helper for event_del: always called with th_base_lock held.
2805c43e99fdSEd Maste  *
2806c43e99fdSEd Maste  * "blocking" must be one of the EVENT_DEL_{BLOCK, NOBLOCK, AUTOBLOCK,
2807c43e99fdSEd Maste  * EVEN_IF_FINALIZING} values. See those for more information.
2808c43e99fdSEd Maste  */
2809c43e99fdSEd Maste int
event_del_nolock_(struct event * ev,int blocking)2810c43e99fdSEd Maste event_del_nolock_(struct event *ev, int blocking)
2811c43e99fdSEd Maste {
2812c43e99fdSEd Maste 	struct event_base *base;
2813c43e99fdSEd Maste 	int res = 0, notify = 0;
2814c43e99fdSEd Maste 
2815c43e99fdSEd Maste 	event_debug(("event_del: %p (fd "EV_SOCK_FMT"), callback %p",
2816c43e99fdSEd Maste 		ev, EV_SOCK_ARG(ev->ev_fd), ev->ev_callback));
2817c43e99fdSEd Maste 
2818c43e99fdSEd Maste 	/* An event without a base has not been added */
2819c43e99fdSEd Maste 	if (ev->ev_base == NULL)
2820c43e99fdSEd Maste 		return (-1);
2821c43e99fdSEd Maste 
2822c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(ev->ev_base);
2823c43e99fdSEd Maste 
2824c43e99fdSEd Maste 	if (blocking != EVENT_DEL_EVEN_IF_FINALIZING) {
2825c43e99fdSEd Maste 		if (ev->ev_flags & EVLIST_FINALIZING) {
2826c43e99fdSEd Maste 			/* XXXX Debug */
2827c43e99fdSEd Maste 			return 0;
2828c43e99fdSEd Maste 		}
2829c43e99fdSEd Maste 	}
2830c43e99fdSEd Maste 
2831c43e99fdSEd Maste 	base = ev->ev_base;
2832c43e99fdSEd Maste 
2833c43e99fdSEd Maste 	EVUTIL_ASSERT(!(ev->ev_flags & ~EVLIST_ALL));
2834c43e99fdSEd Maste 
2835c43e99fdSEd Maste 	/* See if we are just active executing this event in a loop */
2836c43e99fdSEd Maste 	if (ev->ev_events & EV_SIGNAL) {
2837c43e99fdSEd Maste 		if (ev->ev_ncalls && ev->ev_pncalls) {
2838c43e99fdSEd Maste 			/* Abort loop */
2839c43e99fdSEd Maste 			*ev->ev_pncalls = 0;
2840c43e99fdSEd Maste 		}
2841c43e99fdSEd Maste 	}
2842c43e99fdSEd Maste 
2843c43e99fdSEd Maste 	if (ev->ev_flags & EVLIST_TIMEOUT) {
2844c43e99fdSEd Maste 		/* NOTE: We never need to notify the main thread because of a
2845c43e99fdSEd Maste 		 * deleted timeout event: all that could happen if we don't is
2846c43e99fdSEd Maste 		 * that the dispatch loop might wake up too early.  But the
2847c43e99fdSEd Maste 		 * point of notifying the main thread _is_ to wake up the
2848c43e99fdSEd Maste 		 * dispatch loop early anyway, so we wouldn't gain anything by
2849c43e99fdSEd Maste 		 * doing it.
2850c43e99fdSEd Maste 		 */
2851c43e99fdSEd Maste 		event_queue_remove_timeout(base, ev);
2852c43e99fdSEd Maste 	}
2853c43e99fdSEd Maste 
2854c43e99fdSEd Maste 	if (ev->ev_flags & EVLIST_ACTIVE)
2855c43e99fdSEd Maste 		event_queue_remove_active(base, event_to_event_callback(ev));
2856c43e99fdSEd Maste 	else if (ev->ev_flags & EVLIST_ACTIVE_LATER)
2857c43e99fdSEd Maste 		event_queue_remove_active_later(base, event_to_event_callback(ev));
2858c43e99fdSEd Maste 
2859c43e99fdSEd Maste 	if (ev->ev_flags & EVLIST_INSERTED) {
2860c43e99fdSEd Maste 		event_queue_remove_inserted(base, ev);
2861c43e99fdSEd Maste 		if (ev->ev_events & (EV_READ|EV_WRITE|EV_CLOSED))
2862c43e99fdSEd Maste 			res = evmap_io_del_(base, ev->ev_fd, ev);
2863c43e99fdSEd Maste 		else
2864c43e99fdSEd Maste 			res = evmap_signal_del_(base, (int)ev->ev_fd, ev);
2865c43e99fdSEd Maste 		if (res == 1) {
2866c43e99fdSEd Maste 			/* evmap says we need to notify the main thread. */
2867c43e99fdSEd Maste 			notify = 1;
2868c43e99fdSEd Maste 			res = 0;
2869c43e99fdSEd Maste 		}
2870*b50261e2SCy Schubert 		/* If we do not have events, let's notify event base so it can
2871*b50261e2SCy Schubert 		 * exit without waiting */
2872*b50261e2SCy Schubert 		if (!event_haveevents(base) && !N_ACTIVE_CALLBACKS(base))
2873*b50261e2SCy Schubert 			notify = 1;
2874c43e99fdSEd Maste 	}
2875c43e99fdSEd Maste 
2876c43e99fdSEd Maste 	/* if we are not in the right thread, we need to wake up the loop */
2877c43e99fdSEd Maste 	if (res != -1 && notify && EVBASE_NEED_NOTIFY(base))
2878c43e99fdSEd Maste 		evthread_notify_base(base);
2879c43e99fdSEd Maste 
2880c43e99fdSEd Maste 	event_debug_note_del_(ev);
2881c43e99fdSEd Maste 
2882*b50261e2SCy Schubert 	/* If the main thread is currently executing this event's callback,
2883*b50261e2SCy Schubert 	 * and we are not the main thread, then we want to wait until the
2884*b50261e2SCy Schubert 	 * callback is done before returning. That way, when this function
2885*b50261e2SCy Schubert 	 * returns, it will be safe to free the user-supplied argument.
2886*b50261e2SCy Schubert 	 */
2887*b50261e2SCy Schubert #ifndef EVENT__DISABLE_THREAD_SUPPORT
2888*b50261e2SCy Schubert 	if (blocking != EVENT_DEL_NOBLOCK &&
2889*b50261e2SCy Schubert 	    base->current_event == event_to_event_callback(ev) &&
2890*b50261e2SCy Schubert 	    !EVBASE_IN_THREAD(base) &&
2891*b50261e2SCy Schubert 	    (blocking == EVENT_DEL_BLOCK || !(ev->ev_events & EV_FINALIZE))) {
2892*b50261e2SCy Schubert 		++base->current_event_waiters;
2893*b50261e2SCy Schubert 		EVTHREAD_COND_WAIT(base->current_event_cond, base->th_base_lock);
2894*b50261e2SCy Schubert 	}
2895*b50261e2SCy Schubert #endif
2896*b50261e2SCy Schubert 
2897c43e99fdSEd Maste 	return (res);
2898c43e99fdSEd Maste }
2899c43e99fdSEd Maste 
2900c43e99fdSEd Maste void
event_active(struct event * ev,int res,short ncalls)2901c43e99fdSEd Maste event_active(struct event *ev, int res, short ncalls)
2902c43e99fdSEd Maste {
2903c43e99fdSEd Maste 	if (EVUTIL_FAILURE_CHECK(!ev->ev_base)) {
2904c43e99fdSEd Maste 		event_warnx("%s: event has no event_base set.", __func__);
2905c43e99fdSEd Maste 		return;
2906c43e99fdSEd Maste 	}
2907c43e99fdSEd Maste 
2908c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(ev->ev_base, th_base_lock);
2909c43e99fdSEd Maste 
2910c43e99fdSEd Maste 	event_debug_assert_is_setup_(ev);
2911c43e99fdSEd Maste 
2912c43e99fdSEd Maste 	event_active_nolock_(ev, res, ncalls);
2913c43e99fdSEd Maste 
2914c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(ev->ev_base, th_base_lock);
2915c43e99fdSEd Maste }
2916c43e99fdSEd Maste 
2917c43e99fdSEd Maste 
2918c43e99fdSEd Maste void
event_active_nolock_(struct event * ev,int res,short ncalls)2919c43e99fdSEd Maste event_active_nolock_(struct event *ev, int res, short ncalls)
2920c43e99fdSEd Maste {
2921c43e99fdSEd Maste 	struct event_base *base;
2922c43e99fdSEd Maste 
2923c43e99fdSEd Maste 	event_debug(("event_active: %p (fd "EV_SOCK_FMT"), res %d, callback %p",
2924c43e99fdSEd Maste 		ev, EV_SOCK_ARG(ev->ev_fd), (int)res, ev->ev_callback));
2925c43e99fdSEd Maste 
2926c43e99fdSEd Maste 	base = ev->ev_base;
2927c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
2928c43e99fdSEd Maste 
2929c43e99fdSEd Maste 	if (ev->ev_flags & EVLIST_FINALIZING) {
2930c43e99fdSEd Maste 		/* XXXX debug */
2931c43e99fdSEd Maste 		return;
2932c43e99fdSEd Maste 	}
2933c43e99fdSEd Maste 
2934c43e99fdSEd Maste 	switch ((ev->ev_flags & (EVLIST_ACTIVE|EVLIST_ACTIVE_LATER))) {
2935c43e99fdSEd Maste 	default:
2936c43e99fdSEd Maste 	case EVLIST_ACTIVE|EVLIST_ACTIVE_LATER:
2937c43e99fdSEd Maste 		EVUTIL_ASSERT(0);
2938c43e99fdSEd Maste 		break;
2939c43e99fdSEd Maste 	case EVLIST_ACTIVE:
2940c43e99fdSEd Maste 		/* We get different kinds of events, add them together */
2941c43e99fdSEd Maste 		ev->ev_res |= res;
2942c43e99fdSEd Maste 		return;
2943c43e99fdSEd Maste 	case EVLIST_ACTIVE_LATER:
2944c43e99fdSEd Maste 		ev->ev_res |= res;
2945c43e99fdSEd Maste 		break;
2946c43e99fdSEd Maste 	case 0:
2947c43e99fdSEd Maste 		ev->ev_res = res;
2948c43e99fdSEd Maste 		break;
2949c43e99fdSEd Maste 	}
2950c43e99fdSEd Maste 
2951c43e99fdSEd Maste 	if (ev->ev_pri < base->event_running_priority)
2952c43e99fdSEd Maste 		base->event_continue = 1;
2953c43e99fdSEd Maste 
2954c43e99fdSEd Maste 	if (ev->ev_events & EV_SIGNAL) {
2955c43e99fdSEd Maste #ifndef EVENT__DISABLE_THREAD_SUPPORT
2956c43e99fdSEd Maste 		if (base->current_event == event_to_event_callback(ev) &&
2957c43e99fdSEd Maste 		    !EVBASE_IN_THREAD(base)) {
2958c43e99fdSEd Maste 			++base->current_event_waiters;
2959c43e99fdSEd Maste 			EVTHREAD_COND_WAIT(base->current_event_cond, base->th_base_lock);
2960c43e99fdSEd Maste 		}
2961c43e99fdSEd Maste #endif
2962c43e99fdSEd Maste 		ev->ev_ncalls = ncalls;
2963c43e99fdSEd Maste 		ev->ev_pncalls = NULL;
2964c43e99fdSEd Maste 	}
2965c43e99fdSEd Maste 
2966c43e99fdSEd Maste 	event_callback_activate_nolock_(base, event_to_event_callback(ev));
2967c43e99fdSEd Maste }
2968c43e99fdSEd Maste 
2969c43e99fdSEd Maste void
event_active_later_(struct event * ev,int res)2970c43e99fdSEd Maste event_active_later_(struct event *ev, int res)
2971c43e99fdSEd Maste {
2972c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(ev->ev_base, th_base_lock);
2973c43e99fdSEd Maste 	event_active_later_nolock_(ev, res);
2974c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(ev->ev_base, th_base_lock);
2975c43e99fdSEd Maste }
2976c43e99fdSEd Maste 
2977c43e99fdSEd Maste void
event_active_later_nolock_(struct event * ev,int res)2978c43e99fdSEd Maste event_active_later_nolock_(struct event *ev, int res)
2979c43e99fdSEd Maste {
2980c43e99fdSEd Maste 	struct event_base *base = ev->ev_base;
2981c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
2982c43e99fdSEd Maste 
2983c43e99fdSEd Maste 	if (ev->ev_flags & (EVLIST_ACTIVE|EVLIST_ACTIVE_LATER)) {
2984c43e99fdSEd Maste 		/* We get different kinds of events, add them together */
2985c43e99fdSEd Maste 		ev->ev_res |= res;
2986c43e99fdSEd Maste 		return;
2987c43e99fdSEd Maste 	}
2988c43e99fdSEd Maste 
2989c43e99fdSEd Maste 	ev->ev_res = res;
2990c43e99fdSEd Maste 
2991c43e99fdSEd Maste 	event_callback_activate_later_nolock_(base, event_to_event_callback(ev));
2992c43e99fdSEd Maste }
2993c43e99fdSEd Maste 
2994c43e99fdSEd Maste int
event_callback_activate_(struct event_base * base,struct event_callback * evcb)2995c43e99fdSEd Maste event_callback_activate_(struct event_base *base,
2996c43e99fdSEd Maste     struct event_callback *evcb)
2997c43e99fdSEd Maste {
2998c43e99fdSEd Maste 	int r;
2999c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3000c43e99fdSEd Maste 	r = event_callback_activate_nolock_(base, evcb);
3001c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3002c43e99fdSEd Maste 	return r;
3003c43e99fdSEd Maste }
3004c43e99fdSEd Maste 
3005c43e99fdSEd Maste int
event_callback_activate_nolock_(struct event_base * base,struct event_callback * evcb)3006c43e99fdSEd Maste event_callback_activate_nolock_(struct event_base *base,
3007c43e99fdSEd Maste     struct event_callback *evcb)
3008c43e99fdSEd Maste {
3009c43e99fdSEd Maste 	int r = 1;
3010c43e99fdSEd Maste 
3011c43e99fdSEd Maste 	if (evcb->evcb_flags & EVLIST_FINALIZING)
3012c43e99fdSEd Maste 		return 0;
3013c43e99fdSEd Maste 
3014c43e99fdSEd Maste 	switch (evcb->evcb_flags & (EVLIST_ACTIVE|EVLIST_ACTIVE_LATER)) {
3015c43e99fdSEd Maste 	default:
3016c43e99fdSEd Maste 		EVUTIL_ASSERT(0);
3017*b50261e2SCy Schubert 		EVUTIL_FALLTHROUGH;
3018c43e99fdSEd Maste 	case EVLIST_ACTIVE_LATER:
3019c43e99fdSEd Maste 		event_queue_remove_active_later(base, evcb);
3020c43e99fdSEd Maste 		r = 0;
3021c43e99fdSEd Maste 		break;
3022c43e99fdSEd Maste 	case EVLIST_ACTIVE:
3023c43e99fdSEd Maste 		return 0;
3024c43e99fdSEd Maste 	case 0:
3025c43e99fdSEd Maste 		break;
3026c43e99fdSEd Maste 	}
3027c43e99fdSEd Maste 
3028c43e99fdSEd Maste 	event_queue_insert_active(base, evcb);
3029c43e99fdSEd Maste 
3030c43e99fdSEd Maste 	if (EVBASE_NEED_NOTIFY(base))
3031c43e99fdSEd Maste 		evthread_notify_base(base);
3032c43e99fdSEd Maste 
3033c43e99fdSEd Maste 	return r;
3034c43e99fdSEd Maste }
3035c43e99fdSEd Maste 
3036c43e99fdSEd Maste int
event_callback_activate_later_nolock_(struct event_base * base,struct event_callback * evcb)3037c43e99fdSEd Maste event_callback_activate_later_nolock_(struct event_base *base,
3038c43e99fdSEd Maste     struct event_callback *evcb)
3039c43e99fdSEd Maste {
3040c43e99fdSEd Maste 	if (evcb->evcb_flags & (EVLIST_ACTIVE|EVLIST_ACTIVE_LATER))
3041c43e99fdSEd Maste 		return 0;
3042c43e99fdSEd Maste 
3043c43e99fdSEd Maste 	event_queue_insert_active_later(base, evcb);
3044c43e99fdSEd Maste 	if (EVBASE_NEED_NOTIFY(base))
3045c43e99fdSEd Maste 		evthread_notify_base(base);
3046c43e99fdSEd Maste 	return 1;
3047c43e99fdSEd Maste }
3048c43e99fdSEd Maste 
3049c43e99fdSEd Maste void
event_callback_init_(struct event_base * base,struct event_callback * cb)3050c43e99fdSEd Maste event_callback_init_(struct event_base *base,
3051c43e99fdSEd Maste     struct event_callback *cb)
3052c43e99fdSEd Maste {
3053c43e99fdSEd Maste 	memset(cb, 0, sizeof(*cb));
3054c43e99fdSEd Maste 	cb->evcb_pri = base->nactivequeues - 1;
3055c43e99fdSEd Maste }
3056c43e99fdSEd Maste 
3057c43e99fdSEd Maste int
event_callback_cancel_(struct event_base * base,struct event_callback * evcb)3058c43e99fdSEd Maste event_callback_cancel_(struct event_base *base,
3059c43e99fdSEd Maste     struct event_callback *evcb)
3060c43e99fdSEd Maste {
3061c43e99fdSEd Maste 	int r;
3062c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3063c43e99fdSEd Maste 	r = event_callback_cancel_nolock_(base, evcb, 0);
3064c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3065c43e99fdSEd Maste 	return r;
3066c43e99fdSEd Maste }
3067c43e99fdSEd Maste 
3068c43e99fdSEd Maste int
event_callback_cancel_nolock_(struct event_base * base,struct event_callback * evcb,int even_if_finalizing)3069c43e99fdSEd Maste event_callback_cancel_nolock_(struct event_base *base,
3070c43e99fdSEd Maste     struct event_callback *evcb, int even_if_finalizing)
3071c43e99fdSEd Maste {
3072c43e99fdSEd Maste 	if ((evcb->evcb_flags & EVLIST_FINALIZING) && !even_if_finalizing)
3073c43e99fdSEd Maste 		return 0;
3074c43e99fdSEd Maste 
3075c43e99fdSEd Maste 	if (evcb->evcb_flags & EVLIST_INIT)
3076c43e99fdSEd Maste 		return event_del_nolock_(event_callback_to_event(evcb),
3077c43e99fdSEd Maste 		    even_if_finalizing ? EVENT_DEL_EVEN_IF_FINALIZING : EVENT_DEL_AUTOBLOCK);
3078c43e99fdSEd Maste 
3079c43e99fdSEd Maste 	switch ((evcb->evcb_flags & (EVLIST_ACTIVE|EVLIST_ACTIVE_LATER))) {
3080c43e99fdSEd Maste 	default:
3081c43e99fdSEd Maste 	case EVLIST_ACTIVE|EVLIST_ACTIVE_LATER:
3082c43e99fdSEd Maste 		EVUTIL_ASSERT(0);
3083c43e99fdSEd Maste 		break;
3084c43e99fdSEd Maste 	case EVLIST_ACTIVE:
3085c43e99fdSEd Maste 		/* We get different kinds of events, add them together */
3086c43e99fdSEd Maste 		event_queue_remove_active(base, evcb);
3087c43e99fdSEd Maste 		return 0;
3088c43e99fdSEd Maste 	case EVLIST_ACTIVE_LATER:
3089c43e99fdSEd Maste 		event_queue_remove_active_later(base, evcb);
3090c43e99fdSEd Maste 		break;
3091c43e99fdSEd Maste 	case 0:
3092c43e99fdSEd Maste 		break;
3093c43e99fdSEd Maste 	}
3094c43e99fdSEd Maste 
3095c43e99fdSEd Maste 	return 0;
3096c43e99fdSEd Maste }
3097c43e99fdSEd Maste 
3098c43e99fdSEd Maste void
event_deferred_cb_init_(struct event_callback * cb,ev_uint8_t priority,deferred_cb_fn fn,void * arg)3099c43e99fdSEd Maste event_deferred_cb_init_(struct event_callback *cb, ev_uint8_t priority, deferred_cb_fn fn, void *arg)
3100c43e99fdSEd Maste {
3101c43e99fdSEd Maste 	memset(cb, 0, sizeof(*cb));
3102c43e99fdSEd Maste 	cb->evcb_cb_union.evcb_selfcb = fn;
3103c43e99fdSEd Maste 	cb->evcb_arg = arg;
3104c43e99fdSEd Maste 	cb->evcb_pri = priority;
3105c43e99fdSEd Maste 	cb->evcb_closure = EV_CLOSURE_CB_SELF;
3106c43e99fdSEd Maste }
3107c43e99fdSEd Maste 
3108c43e99fdSEd Maste void
event_deferred_cb_set_priority_(struct event_callback * cb,ev_uint8_t priority)3109c43e99fdSEd Maste event_deferred_cb_set_priority_(struct event_callback *cb, ev_uint8_t priority)
3110c43e99fdSEd Maste {
3111c43e99fdSEd Maste 	cb->evcb_pri = priority;
3112c43e99fdSEd Maste }
3113c43e99fdSEd Maste 
3114c43e99fdSEd Maste void
event_deferred_cb_cancel_(struct event_base * base,struct event_callback * cb)3115c43e99fdSEd Maste event_deferred_cb_cancel_(struct event_base *base, struct event_callback *cb)
3116c43e99fdSEd Maste {
3117c43e99fdSEd Maste 	if (!base)
3118c43e99fdSEd Maste 		base = current_base;
3119c43e99fdSEd Maste 	event_callback_cancel_(base, cb);
3120c43e99fdSEd Maste }
3121c43e99fdSEd Maste 
3122c43e99fdSEd Maste #define MAX_DEFERREDS_QUEUED 32
3123c43e99fdSEd Maste int
event_deferred_cb_schedule_(struct event_base * base,struct event_callback * cb)3124c43e99fdSEd Maste event_deferred_cb_schedule_(struct event_base *base, struct event_callback *cb)
3125c43e99fdSEd Maste {
3126c43e99fdSEd Maste 	int r = 1;
3127c43e99fdSEd Maste 	if (!base)
3128c43e99fdSEd Maste 		base = current_base;
3129c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3130c43e99fdSEd Maste 	if (base->n_deferreds_queued > MAX_DEFERREDS_QUEUED) {
3131c43e99fdSEd Maste 		r = event_callback_activate_later_nolock_(base, cb);
3132c43e99fdSEd Maste 	} else {
3133c43e99fdSEd Maste 		r = event_callback_activate_nolock_(base, cb);
3134c43e99fdSEd Maste 		if (r) {
3135c43e99fdSEd Maste 			++base->n_deferreds_queued;
3136c43e99fdSEd Maste 		}
3137c43e99fdSEd Maste 	}
3138c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3139c43e99fdSEd Maste 	return r;
3140c43e99fdSEd Maste }
3141c43e99fdSEd Maste 
3142c43e99fdSEd Maste static int
timeout_next(struct event_base * base,struct timeval ** tv_p)3143c43e99fdSEd Maste timeout_next(struct event_base *base, struct timeval **tv_p)
3144c43e99fdSEd Maste {
3145c43e99fdSEd Maste 	/* Caller must hold th_base_lock */
3146c43e99fdSEd Maste 	struct timeval now;
3147c43e99fdSEd Maste 	struct event *ev;
3148c43e99fdSEd Maste 	struct timeval *tv = *tv_p;
3149c43e99fdSEd Maste 	int res = 0;
3150c43e99fdSEd Maste 
3151c43e99fdSEd Maste 	ev = min_heap_top_(&base->timeheap);
3152c43e99fdSEd Maste 
3153c43e99fdSEd Maste 	if (ev == NULL) {
3154c43e99fdSEd Maste 		/* if no time-based events are active wait for I/O */
3155c43e99fdSEd Maste 		*tv_p = NULL;
3156c43e99fdSEd Maste 		goto out;
3157c43e99fdSEd Maste 	}
3158c43e99fdSEd Maste 
3159c43e99fdSEd Maste 	if (gettime(base, &now) == -1) {
3160c43e99fdSEd Maste 		res = -1;
3161c43e99fdSEd Maste 		goto out;
3162c43e99fdSEd Maste 	}
3163c43e99fdSEd Maste 
3164c43e99fdSEd Maste 	if (evutil_timercmp(&ev->ev_timeout, &now, <=)) {
3165c43e99fdSEd Maste 		evutil_timerclear(tv);
3166c43e99fdSEd Maste 		goto out;
3167c43e99fdSEd Maste 	}
3168c43e99fdSEd Maste 
3169c43e99fdSEd Maste 	evutil_timersub(&ev->ev_timeout, &now, tv);
3170c43e99fdSEd Maste 
3171c43e99fdSEd Maste 	EVUTIL_ASSERT(tv->tv_sec >= 0);
3172c43e99fdSEd Maste 	EVUTIL_ASSERT(tv->tv_usec >= 0);
3173c43e99fdSEd Maste 	event_debug(("timeout_next: event: %p, in %d seconds, %d useconds", ev, (int)tv->tv_sec, (int)tv->tv_usec));
3174c43e99fdSEd Maste 
3175c43e99fdSEd Maste out:
3176c43e99fdSEd Maste 	return (res);
3177c43e99fdSEd Maste }
3178c43e99fdSEd Maste 
3179c43e99fdSEd Maste /* Activate every event whose timeout has elapsed. */
3180c43e99fdSEd Maste static void
timeout_process(struct event_base * base)3181c43e99fdSEd Maste timeout_process(struct event_base *base)
3182c43e99fdSEd Maste {
3183c43e99fdSEd Maste 	/* Caller must hold lock. */
3184c43e99fdSEd Maste 	struct timeval now;
3185c43e99fdSEd Maste 	struct event *ev;
3186c43e99fdSEd Maste 
3187c43e99fdSEd Maste 	if (min_heap_empty_(&base->timeheap)) {
3188c43e99fdSEd Maste 		return;
3189c43e99fdSEd Maste 	}
3190c43e99fdSEd Maste 
3191c43e99fdSEd Maste 	gettime(base, &now);
3192c43e99fdSEd Maste 
3193c43e99fdSEd Maste 	while ((ev = min_heap_top_(&base->timeheap))) {
3194c43e99fdSEd Maste 		if (evutil_timercmp(&ev->ev_timeout, &now, >))
3195c43e99fdSEd Maste 			break;
3196c43e99fdSEd Maste 
3197c43e99fdSEd Maste 		/* delete this event from the I/O queues */
3198c43e99fdSEd Maste 		event_del_nolock_(ev, EVENT_DEL_NOBLOCK);
3199c43e99fdSEd Maste 
3200c43e99fdSEd Maste 		event_debug(("timeout_process: event: %p, call %p",
3201c43e99fdSEd Maste 			 ev, ev->ev_callback));
3202c43e99fdSEd Maste 		event_active_nolock_(ev, EV_TIMEOUT, 1);
3203c43e99fdSEd Maste 	}
3204c43e99fdSEd Maste }
3205c43e99fdSEd Maste 
3206c43e99fdSEd Maste #ifndef MAX
3207c43e99fdSEd Maste #define MAX(a,b) (((a)>(b))?(a):(b))
3208c43e99fdSEd Maste #endif
3209c43e99fdSEd Maste 
3210c43e99fdSEd Maste #define MAX_EVENT_COUNT(var, v) var = MAX(var, v)
3211c43e99fdSEd Maste 
3212c43e99fdSEd Maste /* These are a fancy way to spell
3213*b50261e2SCy Schubert      if (~flags & EVLIST_INTERNAL)
3214c43e99fdSEd Maste          base->event_count--/++;
3215c43e99fdSEd Maste */
3216c43e99fdSEd Maste #define DECR_EVENT_COUNT(base,flags) \
3217*b50261e2SCy Schubert 	((base)->event_count -= !((flags) & EVLIST_INTERNAL))
3218c43e99fdSEd Maste #define INCR_EVENT_COUNT(base,flags) do {					\
3219*b50261e2SCy Schubert 	((base)->event_count += !((flags) & EVLIST_INTERNAL));			\
3220c43e99fdSEd Maste 	MAX_EVENT_COUNT((base)->event_count_max, (base)->event_count);		\
3221c43e99fdSEd Maste } while (0)
3222c43e99fdSEd Maste 
3223c43e99fdSEd Maste static void
event_queue_remove_inserted(struct event_base * base,struct event * ev)3224c43e99fdSEd Maste event_queue_remove_inserted(struct event_base *base, struct event *ev)
3225c43e99fdSEd Maste {
3226c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
3227c43e99fdSEd Maste 	if (EVUTIL_FAILURE_CHECK(!(ev->ev_flags & EVLIST_INSERTED))) {
3228c43e99fdSEd Maste 		event_errx(1, "%s: %p(fd "EV_SOCK_FMT") not on queue %x", __func__,
3229c43e99fdSEd Maste 		    ev, EV_SOCK_ARG(ev->ev_fd), EVLIST_INSERTED);
3230c43e99fdSEd Maste 		return;
3231c43e99fdSEd Maste 	}
3232c43e99fdSEd Maste 	DECR_EVENT_COUNT(base, ev->ev_flags);
3233c43e99fdSEd Maste 	ev->ev_flags &= ~EVLIST_INSERTED;
3234c43e99fdSEd Maste }
3235c43e99fdSEd Maste static void
event_queue_remove_active(struct event_base * base,struct event_callback * evcb)3236c43e99fdSEd Maste event_queue_remove_active(struct event_base *base, struct event_callback *evcb)
3237c43e99fdSEd Maste {
3238c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
3239c43e99fdSEd Maste 	if (EVUTIL_FAILURE_CHECK(!(evcb->evcb_flags & EVLIST_ACTIVE))) {
3240c43e99fdSEd Maste 		event_errx(1, "%s: %p not on queue %x", __func__,
3241c43e99fdSEd Maste 			   evcb, EVLIST_ACTIVE);
3242c43e99fdSEd Maste 		return;
3243c43e99fdSEd Maste 	}
3244c43e99fdSEd Maste 	DECR_EVENT_COUNT(base, evcb->evcb_flags);
3245c43e99fdSEd Maste 	evcb->evcb_flags &= ~EVLIST_ACTIVE;
3246c43e99fdSEd Maste 	base->event_count_active--;
3247c43e99fdSEd Maste 
3248c43e99fdSEd Maste 	TAILQ_REMOVE(&base->activequeues[evcb->evcb_pri],
3249c43e99fdSEd Maste 	    evcb, evcb_active_next);
3250c43e99fdSEd Maste }
3251c43e99fdSEd Maste static void
event_queue_remove_active_later(struct event_base * base,struct event_callback * evcb)3252c43e99fdSEd Maste event_queue_remove_active_later(struct event_base *base, struct event_callback *evcb)
3253c43e99fdSEd Maste {
3254c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
3255c43e99fdSEd Maste 	if (EVUTIL_FAILURE_CHECK(!(evcb->evcb_flags & EVLIST_ACTIVE_LATER))) {
3256c43e99fdSEd Maste 		event_errx(1, "%s: %p not on queue %x", __func__,
3257c43e99fdSEd Maste 			   evcb, EVLIST_ACTIVE_LATER);
3258c43e99fdSEd Maste 		return;
3259c43e99fdSEd Maste 	}
3260c43e99fdSEd Maste 	DECR_EVENT_COUNT(base, evcb->evcb_flags);
3261c43e99fdSEd Maste 	evcb->evcb_flags &= ~EVLIST_ACTIVE_LATER;
3262c43e99fdSEd Maste 	base->event_count_active--;
3263c43e99fdSEd Maste 
3264c43e99fdSEd Maste 	TAILQ_REMOVE(&base->active_later_queue, evcb, evcb_active_next);
3265c43e99fdSEd Maste }
3266c43e99fdSEd Maste static void
event_queue_remove_timeout(struct event_base * base,struct event * ev)3267c43e99fdSEd Maste event_queue_remove_timeout(struct event_base *base, struct event *ev)
3268c43e99fdSEd Maste {
3269c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
3270c43e99fdSEd Maste 	if (EVUTIL_FAILURE_CHECK(!(ev->ev_flags & EVLIST_TIMEOUT))) {
3271c43e99fdSEd Maste 		event_errx(1, "%s: %p(fd "EV_SOCK_FMT") not on queue %x", __func__,
3272c43e99fdSEd Maste 		    ev, EV_SOCK_ARG(ev->ev_fd), EVLIST_TIMEOUT);
3273c43e99fdSEd Maste 		return;
3274c43e99fdSEd Maste 	}
3275c43e99fdSEd Maste 	DECR_EVENT_COUNT(base, ev->ev_flags);
3276c43e99fdSEd Maste 	ev->ev_flags &= ~EVLIST_TIMEOUT;
3277c43e99fdSEd Maste 
3278c43e99fdSEd Maste 	if (is_common_timeout(&ev->ev_timeout, base)) {
3279c43e99fdSEd Maste 		struct common_timeout_list *ctl =
3280c43e99fdSEd Maste 		    get_common_timeout_list(base, &ev->ev_timeout);
3281c43e99fdSEd Maste 		TAILQ_REMOVE(&ctl->events, ev,
3282c43e99fdSEd Maste 		    ev_timeout_pos.ev_next_with_common_timeout);
3283c43e99fdSEd Maste 	} else {
3284c43e99fdSEd Maste 		min_heap_erase_(&base->timeheap, ev);
3285c43e99fdSEd Maste 	}
3286c43e99fdSEd Maste }
3287c43e99fdSEd Maste 
3288c43e99fdSEd Maste #ifdef USE_REINSERT_TIMEOUT
3289c43e99fdSEd Maste /* Remove and reinsert 'ev' into the timeout queue. */
3290c43e99fdSEd Maste static void
event_queue_reinsert_timeout(struct event_base * base,struct event * ev,int was_common,int is_common,int old_timeout_idx)3291c43e99fdSEd Maste event_queue_reinsert_timeout(struct event_base *base, struct event *ev,
3292c43e99fdSEd Maste     int was_common, int is_common, int old_timeout_idx)
3293c43e99fdSEd Maste {
3294c43e99fdSEd Maste 	struct common_timeout_list *ctl;
3295c43e99fdSEd Maste 	if (!(ev->ev_flags & EVLIST_TIMEOUT)) {
3296c43e99fdSEd Maste 		event_queue_insert_timeout(base, ev);
3297c43e99fdSEd Maste 		return;
3298c43e99fdSEd Maste 	}
3299c43e99fdSEd Maste 
3300c43e99fdSEd Maste 	switch ((was_common<<1) | is_common) {
3301c43e99fdSEd Maste 	case 3: /* Changing from one common timeout to another */
3302c43e99fdSEd Maste 		ctl = base->common_timeout_queues[old_timeout_idx];
3303c43e99fdSEd Maste 		TAILQ_REMOVE(&ctl->events, ev,
3304c43e99fdSEd Maste 		    ev_timeout_pos.ev_next_with_common_timeout);
3305c43e99fdSEd Maste 		ctl = get_common_timeout_list(base, &ev->ev_timeout);
3306c43e99fdSEd Maste 		insert_common_timeout_inorder(ctl, ev);
3307c43e99fdSEd Maste 		break;
3308c43e99fdSEd Maste 	case 2: /* Was common; is no longer common */
3309c43e99fdSEd Maste 		ctl = base->common_timeout_queues[old_timeout_idx];
3310c43e99fdSEd Maste 		TAILQ_REMOVE(&ctl->events, ev,
3311c43e99fdSEd Maste 		    ev_timeout_pos.ev_next_with_common_timeout);
3312c43e99fdSEd Maste 		min_heap_push_(&base->timeheap, ev);
3313c43e99fdSEd Maste 		break;
3314c43e99fdSEd Maste 	case 1: /* Wasn't common; has become common. */
3315c43e99fdSEd Maste 		min_heap_erase_(&base->timeheap, ev);
3316c43e99fdSEd Maste 		ctl = get_common_timeout_list(base, &ev->ev_timeout);
3317c43e99fdSEd Maste 		insert_common_timeout_inorder(ctl, ev);
3318c43e99fdSEd Maste 		break;
3319c43e99fdSEd Maste 	case 0: /* was in heap; is still on heap. */
3320c43e99fdSEd Maste 		min_heap_adjust_(&base->timeheap, ev);
3321c43e99fdSEd Maste 		break;
3322c43e99fdSEd Maste 	default:
3323c43e99fdSEd Maste 		EVUTIL_ASSERT(0); /* unreachable */
3324c43e99fdSEd Maste 		break;
3325c43e99fdSEd Maste 	}
3326c43e99fdSEd Maste }
3327c43e99fdSEd Maste #endif
3328c43e99fdSEd Maste 
3329c43e99fdSEd Maste /* Add 'ev' to the common timeout list in 'ev'. */
3330c43e99fdSEd Maste static void
insert_common_timeout_inorder(struct common_timeout_list * ctl,struct event * ev)3331c43e99fdSEd Maste insert_common_timeout_inorder(struct common_timeout_list *ctl,
3332c43e99fdSEd Maste     struct event *ev)
3333c43e99fdSEd Maste {
3334c43e99fdSEd Maste 	struct event *e;
3335c43e99fdSEd Maste 	/* By all logic, we should just be able to append 'ev' to the end of
3336c43e99fdSEd Maste 	 * ctl->events, since the timeout on each 'ev' is set to {the common
3337c43e99fdSEd Maste 	 * timeout} + {the time when we add the event}, and so the events
3338c43e99fdSEd Maste 	 * should arrive in order of their timeeouts.  But just in case
3339c43e99fdSEd Maste 	 * there's some wacky threading issue going on, we do a search from
3340c43e99fdSEd Maste 	 * the end of 'ev' to find the right insertion point.
3341c43e99fdSEd Maste 	 */
3342c43e99fdSEd Maste 	TAILQ_FOREACH_REVERSE(e, &ctl->events,
3343c43e99fdSEd Maste 	    event_list, ev_timeout_pos.ev_next_with_common_timeout) {
3344c43e99fdSEd Maste 		/* This timercmp is a little sneaky, since both ev and e have
3345c43e99fdSEd Maste 		 * magic values in tv_usec.  Fortunately, they ought to have
3346c43e99fdSEd Maste 		 * the _same_ magic values in tv_usec.  Let's assert for that.
3347c43e99fdSEd Maste 		 */
3348c43e99fdSEd Maste 		EVUTIL_ASSERT(
3349c43e99fdSEd Maste 			is_same_common_timeout(&e->ev_timeout, &ev->ev_timeout));
3350c43e99fdSEd Maste 		if (evutil_timercmp(&ev->ev_timeout, &e->ev_timeout, >=)) {
3351c43e99fdSEd Maste 			TAILQ_INSERT_AFTER(&ctl->events, e, ev,
3352c43e99fdSEd Maste 			    ev_timeout_pos.ev_next_with_common_timeout);
3353c43e99fdSEd Maste 			return;
3354c43e99fdSEd Maste 		}
3355c43e99fdSEd Maste 	}
3356c43e99fdSEd Maste 	TAILQ_INSERT_HEAD(&ctl->events, ev,
3357c43e99fdSEd Maste 	    ev_timeout_pos.ev_next_with_common_timeout);
3358c43e99fdSEd Maste }
3359c43e99fdSEd Maste 
3360c43e99fdSEd Maste static void
event_queue_insert_inserted(struct event_base * base,struct event * ev)3361c43e99fdSEd Maste event_queue_insert_inserted(struct event_base *base, struct event *ev)
3362c43e99fdSEd Maste {
3363c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
3364c43e99fdSEd Maste 
3365c43e99fdSEd Maste 	if (EVUTIL_FAILURE_CHECK(ev->ev_flags & EVLIST_INSERTED)) {
3366c43e99fdSEd Maste 		event_errx(1, "%s: %p(fd "EV_SOCK_FMT") already inserted", __func__,
3367c43e99fdSEd Maste 		    ev, EV_SOCK_ARG(ev->ev_fd));
3368c43e99fdSEd Maste 		return;
3369c43e99fdSEd Maste 	}
3370c43e99fdSEd Maste 
3371c43e99fdSEd Maste 	INCR_EVENT_COUNT(base, ev->ev_flags);
3372c43e99fdSEd Maste 
3373c43e99fdSEd Maste 	ev->ev_flags |= EVLIST_INSERTED;
3374c43e99fdSEd Maste }
3375c43e99fdSEd Maste 
3376c43e99fdSEd Maste static void
event_queue_insert_active(struct event_base * base,struct event_callback * evcb)3377c43e99fdSEd Maste event_queue_insert_active(struct event_base *base, struct event_callback *evcb)
3378c43e99fdSEd Maste {
3379c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
3380c43e99fdSEd Maste 
3381c43e99fdSEd Maste 	if (evcb->evcb_flags & EVLIST_ACTIVE) {
3382c43e99fdSEd Maste 		/* Double insertion is possible for active events */
3383c43e99fdSEd Maste 		return;
3384c43e99fdSEd Maste 	}
3385c43e99fdSEd Maste 
3386c43e99fdSEd Maste 	INCR_EVENT_COUNT(base, evcb->evcb_flags);
3387c43e99fdSEd Maste 
3388c43e99fdSEd Maste 	evcb->evcb_flags |= EVLIST_ACTIVE;
3389c43e99fdSEd Maste 
3390c43e99fdSEd Maste 	base->event_count_active++;
3391c43e99fdSEd Maste 	MAX_EVENT_COUNT(base->event_count_active_max, base->event_count_active);
3392c43e99fdSEd Maste 	EVUTIL_ASSERT(evcb->evcb_pri < base->nactivequeues);
3393c43e99fdSEd Maste 	TAILQ_INSERT_TAIL(&base->activequeues[evcb->evcb_pri],
3394c43e99fdSEd Maste 	    evcb, evcb_active_next);
3395c43e99fdSEd Maste }
3396c43e99fdSEd Maste 
3397c43e99fdSEd Maste static void
event_queue_insert_active_later(struct event_base * base,struct event_callback * evcb)3398c43e99fdSEd Maste event_queue_insert_active_later(struct event_base *base, struct event_callback *evcb)
3399c43e99fdSEd Maste {
3400c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
3401c43e99fdSEd Maste 	if (evcb->evcb_flags & (EVLIST_ACTIVE_LATER|EVLIST_ACTIVE)) {
3402c43e99fdSEd Maste 		/* Double insertion is possible */
3403c43e99fdSEd Maste 		return;
3404c43e99fdSEd Maste 	}
3405c43e99fdSEd Maste 
3406c43e99fdSEd Maste 	INCR_EVENT_COUNT(base, evcb->evcb_flags);
3407c43e99fdSEd Maste 	evcb->evcb_flags |= EVLIST_ACTIVE_LATER;
3408c43e99fdSEd Maste 	base->event_count_active++;
3409c43e99fdSEd Maste 	MAX_EVENT_COUNT(base->event_count_active_max, base->event_count_active);
3410c43e99fdSEd Maste 	EVUTIL_ASSERT(evcb->evcb_pri < base->nactivequeues);
3411c43e99fdSEd Maste 	TAILQ_INSERT_TAIL(&base->active_later_queue, evcb, evcb_active_next);
3412c43e99fdSEd Maste }
3413c43e99fdSEd Maste 
3414c43e99fdSEd Maste static void
event_queue_insert_timeout(struct event_base * base,struct event * ev)3415c43e99fdSEd Maste event_queue_insert_timeout(struct event_base *base, struct event *ev)
3416c43e99fdSEd Maste {
3417c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
3418c43e99fdSEd Maste 
3419c43e99fdSEd Maste 	if (EVUTIL_FAILURE_CHECK(ev->ev_flags & EVLIST_TIMEOUT)) {
3420c43e99fdSEd Maste 		event_errx(1, "%s: %p(fd "EV_SOCK_FMT") already on timeout", __func__,
3421c43e99fdSEd Maste 		    ev, EV_SOCK_ARG(ev->ev_fd));
3422c43e99fdSEd Maste 		return;
3423c43e99fdSEd Maste 	}
3424c43e99fdSEd Maste 
3425c43e99fdSEd Maste 	INCR_EVENT_COUNT(base, ev->ev_flags);
3426c43e99fdSEd Maste 
3427c43e99fdSEd Maste 	ev->ev_flags |= EVLIST_TIMEOUT;
3428c43e99fdSEd Maste 
3429c43e99fdSEd Maste 	if (is_common_timeout(&ev->ev_timeout, base)) {
3430c43e99fdSEd Maste 		struct common_timeout_list *ctl =
3431c43e99fdSEd Maste 		    get_common_timeout_list(base, &ev->ev_timeout);
3432c43e99fdSEd Maste 		insert_common_timeout_inorder(ctl, ev);
3433c43e99fdSEd Maste 	} else {
3434c43e99fdSEd Maste 		min_heap_push_(&base->timeheap, ev);
3435c43e99fdSEd Maste 	}
3436c43e99fdSEd Maste }
3437c43e99fdSEd Maste 
3438c43e99fdSEd Maste static void
event_queue_make_later_events_active(struct event_base * base)3439c43e99fdSEd Maste event_queue_make_later_events_active(struct event_base *base)
3440c43e99fdSEd Maste {
3441c43e99fdSEd Maste 	struct event_callback *evcb;
3442c43e99fdSEd Maste 	EVENT_BASE_ASSERT_LOCKED(base);
3443c43e99fdSEd Maste 
3444c43e99fdSEd Maste 	while ((evcb = TAILQ_FIRST(&base->active_later_queue))) {
3445c43e99fdSEd Maste 		TAILQ_REMOVE(&base->active_later_queue, evcb, evcb_active_next);
3446c43e99fdSEd Maste 		evcb->evcb_flags = (evcb->evcb_flags & ~EVLIST_ACTIVE_LATER) | EVLIST_ACTIVE;
3447c43e99fdSEd Maste 		EVUTIL_ASSERT(evcb->evcb_pri < base->nactivequeues);
3448c43e99fdSEd Maste 		TAILQ_INSERT_TAIL(&base->activequeues[evcb->evcb_pri], evcb, evcb_active_next);
3449c43e99fdSEd Maste 		base->n_deferreds_queued += (evcb->evcb_closure == EV_CLOSURE_CB_SELF);
3450c43e99fdSEd Maste 	}
3451c43e99fdSEd Maste }
3452c43e99fdSEd Maste 
3453c43e99fdSEd Maste /* Functions for debugging */
3454c43e99fdSEd Maste 
3455c43e99fdSEd Maste const char *
event_get_version(void)3456c43e99fdSEd Maste event_get_version(void)
3457c43e99fdSEd Maste {
3458c43e99fdSEd Maste 	return (EVENT__VERSION);
3459c43e99fdSEd Maste }
3460c43e99fdSEd Maste 
3461c43e99fdSEd Maste ev_uint32_t
event_get_version_number(void)3462c43e99fdSEd Maste event_get_version_number(void)
3463c43e99fdSEd Maste {
3464c43e99fdSEd Maste 	return (EVENT__NUMERIC_VERSION);
3465c43e99fdSEd Maste }
3466c43e99fdSEd Maste 
3467c43e99fdSEd Maste /*
3468c43e99fdSEd Maste  * No thread-safe interface needed - the information should be the same
3469c43e99fdSEd Maste  * for all threads.
3470c43e99fdSEd Maste  */
3471c43e99fdSEd Maste 
3472c43e99fdSEd Maste const char *
event_get_method(void)3473c43e99fdSEd Maste event_get_method(void)
3474c43e99fdSEd Maste {
3475c43e99fdSEd Maste 	return (current_base->evsel->name);
3476c43e99fdSEd Maste }
3477c43e99fdSEd Maste 
3478c43e99fdSEd Maste #ifndef EVENT__DISABLE_MM_REPLACEMENT
3479c43e99fdSEd Maste static void *(*mm_malloc_fn_)(size_t sz) = NULL;
3480c43e99fdSEd Maste static void *(*mm_realloc_fn_)(void *p, size_t sz) = NULL;
3481c43e99fdSEd Maste static void (*mm_free_fn_)(void *p) = NULL;
3482c43e99fdSEd Maste 
3483c43e99fdSEd Maste void *
event_mm_malloc_(size_t sz)3484c43e99fdSEd Maste event_mm_malloc_(size_t sz)
3485c43e99fdSEd Maste {
3486c43e99fdSEd Maste 	if (sz == 0)
3487c43e99fdSEd Maste 		return NULL;
3488c43e99fdSEd Maste 
3489c43e99fdSEd Maste 	if (mm_malloc_fn_)
3490c43e99fdSEd Maste 		return mm_malloc_fn_(sz);
3491c43e99fdSEd Maste 	else
3492c43e99fdSEd Maste 		return malloc(sz);
3493c43e99fdSEd Maste }
3494c43e99fdSEd Maste 
3495c43e99fdSEd Maste void *
event_mm_calloc_(size_t count,size_t size)3496c43e99fdSEd Maste event_mm_calloc_(size_t count, size_t size)
3497c43e99fdSEd Maste {
3498c43e99fdSEd Maste 	if (count == 0 || size == 0)
3499c43e99fdSEd Maste 		return NULL;
3500c43e99fdSEd Maste 
3501c43e99fdSEd Maste 	if (mm_malloc_fn_) {
3502c43e99fdSEd Maste 		size_t sz = count * size;
3503c43e99fdSEd Maste 		void *p = NULL;
3504c43e99fdSEd Maste 		if (count > EV_SIZE_MAX / size)
3505c43e99fdSEd Maste 			goto error;
3506c43e99fdSEd Maste 		p = mm_malloc_fn_(sz);
3507c43e99fdSEd Maste 		if (p)
3508c43e99fdSEd Maste 			return memset(p, 0, sz);
3509c43e99fdSEd Maste 	} else {
3510c43e99fdSEd Maste 		void *p = calloc(count, size);
3511c43e99fdSEd Maste #ifdef _WIN32
3512c43e99fdSEd Maste 		/* Windows calloc doesn't reliably set ENOMEM */
3513c43e99fdSEd Maste 		if (p == NULL)
3514c43e99fdSEd Maste 			goto error;
3515c43e99fdSEd Maste #endif
3516c43e99fdSEd Maste 		return p;
3517c43e99fdSEd Maste 	}
3518c43e99fdSEd Maste 
3519c43e99fdSEd Maste error:
3520c43e99fdSEd Maste 	errno = ENOMEM;
3521c43e99fdSEd Maste 	return NULL;
3522c43e99fdSEd Maste }
3523c43e99fdSEd Maste 
3524c43e99fdSEd Maste char *
event_mm_strdup_(const char * str)3525c43e99fdSEd Maste event_mm_strdup_(const char *str)
3526c43e99fdSEd Maste {
3527c43e99fdSEd Maste 	if (!str) {
3528c43e99fdSEd Maste 		errno = EINVAL;
3529c43e99fdSEd Maste 		return NULL;
3530c43e99fdSEd Maste 	}
3531c43e99fdSEd Maste 
3532c43e99fdSEd Maste 	if (mm_malloc_fn_) {
3533c43e99fdSEd Maste 		size_t ln = strlen(str);
3534c43e99fdSEd Maste 		void *p = NULL;
3535c43e99fdSEd Maste 		if (ln == EV_SIZE_MAX)
3536c43e99fdSEd Maste 			goto error;
3537c43e99fdSEd Maste 		p = mm_malloc_fn_(ln+1);
3538c43e99fdSEd Maste 		if (p)
3539c43e99fdSEd Maste 			return memcpy(p, str, ln+1);
3540c43e99fdSEd Maste 	} else
3541c43e99fdSEd Maste #ifdef _WIN32
3542c43e99fdSEd Maste 		return _strdup(str);
3543c43e99fdSEd Maste #else
3544c43e99fdSEd Maste 		return strdup(str);
3545c43e99fdSEd Maste #endif
3546c43e99fdSEd Maste 
3547c43e99fdSEd Maste error:
3548c43e99fdSEd Maste 	errno = ENOMEM;
3549c43e99fdSEd Maste 	return NULL;
3550c43e99fdSEd Maste }
3551c43e99fdSEd Maste 
3552c43e99fdSEd Maste void *
event_mm_realloc_(void * ptr,size_t sz)3553c43e99fdSEd Maste event_mm_realloc_(void *ptr, size_t sz)
3554c43e99fdSEd Maste {
3555c43e99fdSEd Maste 	if (mm_realloc_fn_)
3556c43e99fdSEd Maste 		return mm_realloc_fn_(ptr, sz);
3557c43e99fdSEd Maste 	else
3558c43e99fdSEd Maste 		return realloc(ptr, sz);
3559c43e99fdSEd Maste }
3560c43e99fdSEd Maste 
3561c43e99fdSEd Maste void
event_mm_free_(void * ptr)3562c43e99fdSEd Maste event_mm_free_(void *ptr)
3563c43e99fdSEd Maste {
3564c43e99fdSEd Maste 	if (mm_free_fn_)
3565c43e99fdSEd Maste 		mm_free_fn_(ptr);
3566c43e99fdSEd Maste 	else
3567c43e99fdSEd Maste 		free(ptr);
3568c43e99fdSEd Maste }
3569c43e99fdSEd Maste 
3570c43e99fdSEd Maste void
event_set_mem_functions(void * (* malloc_fn)(size_t sz),void * (* realloc_fn)(void * ptr,size_t sz),void (* free_fn)(void * ptr))3571c43e99fdSEd Maste event_set_mem_functions(void *(*malloc_fn)(size_t sz),
3572c43e99fdSEd Maste 			void *(*realloc_fn)(void *ptr, size_t sz),
3573c43e99fdSEd Maste 			void (*free_fn)(void *ptr))
3574c43e99fdSEd Maste {
3575c43e99fdSEd Maste 	mm_malloc_fn_ = malloc_fn;
3576c43e99fdSEd Maste 	mm_realloc_fn_ = realloc_fn;
3577c43e99fdSEd Maste 	mm_free_fn_ = free_fn;
3578c43e99fdSEd Maste }
3579c43e99fdSEd Maste #endif
3580c43e99fdSEd Maste 
3581c43e99fdSEd Maste #ifdef EVENT__HAVE_EVENTFD
3582c43e99fdSEd Maste static void
evthread_notify_drain_eventfd(evutil_socket_t fd,short what,void * arg)3583c43e99fdSEd Maste evthread_notify_drain_eventfd(evutil_socket_t fd, short what, void *arg)
3584c43e99fdSEd Maste {
3585c43e99fdSEd Maste 	ev_uint64_t msg;
3586c43e99fdSEd Maste 	ev_ssize_t r;
3587c43e99fdSEd Maste 	struct event_base *base = arg;
3588c43e99fdSEd Maste 
3589c43e99fdSEd Maste 	r = read(fd, (void*) &msg, sizeof(msg));
3590c43e99fdSEd Maste 	if (r<0 && errno != EAGAIN) {
3591c43e99fdSEd Maste 		event_sock_warn(fd, "Error reading from eventfd");
3592c43e99fdSEd Maste 	}
3593c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3594c43e99fdSEd Maste 	base->is_notify_pending = 0;
3595c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3596c43e99fdSEd Maste }
3597c43e99fdSEd Maste #endif
3598c43e99fdSEd Maste 
3599c43e99fdSEd Maste static void
evthread_notify_drain_default(evutil_socket_t fd,short what,void * arg)3600c43e99fdSEd Maste evthread_notify_drain_default(evutil_socket_t fd, short what, void *arg)
3601c43e99fdSEd Maste {
3602c43e99fdSEd Maste 	unsigned char buf[1024];
3603c43e99fdSEd Maste 	struct event_base *base = arg;
3604c43e99fdSEd Maste #ifdef _WIN32
3605c43e99fdSEd Maste 	while (recv(fd, (char*)buf, sizeof(buf), 0) > 0)
3606c43e99fdSEd Maste 		;
3607c43e99fdSEd Maste #else
3608c43e99fdSEd Maste 	while (read(fd, (char*)buf, sizeof(buf)) > 0)
3609c43e99fdSEd Maste 		;
3610c43e99fdSEd Maste #endif
3611c43e99fdSEd Maste 
3612c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3613c43e99fdSEd Maste 	base->is_notify_pending = 0;
3614c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3615c43e99fdSEd Maste }
3616c43e99fdSEd Maste 
3617c43e99fdSEd Maste int
evthread_make_base_notifiable(struct event_base * base)3618c43e99fdSEd Maste evthread_make_base_notifiable(struct event_base *base)
3619c43e99fdSEd Maste {
3620c43e99fdSEd Maste 	int r;
3621c43e99fdSEd Maste 	if (!base)
3622c43e99fdSEd Maste 		return -1;
3623c43e99fdSEd Maste 
3624c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3625c43e99fdSEd Maste 	r = evthread_make_base_notifiable_nolock_(base);
3626c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3627c43e99fdSEd Maste 	return r;
3628c43e99fdSEd Maste }
3629c43e99fdSEd Maste 
3630c43e99fdSEd Maste static int
evthread_make_base_notifiable_nolock_(struct event_base * base)3631c43e99fdSEd Maste evthread_make_base_notifiable_nolock_(struct event_base *base)
3632c43e99fdSEd Maste {
3633c43e99fdSEd Maste 	void (*cb)(evutil_socket_t, short, void *);
3634c43e99fdSEd Maste 	int (*notify)(struct event_base *);
3635c43e99fdSEd Maste 
3636c43e99fdSEd Maste 	if (base->th_notify_fn != NULL) {
3637c43e99fdSEd Maste 		/* The base is already notifiable: we're doing fine. */
3638c43e99fdSEd Maste 		return 0;
3639c43e99fdSEd Maste 	}
3640c43e99fdSEd Maste 
3641c43e99fdSEd Maste #if defined(EVENT__HAVE_WORKING_KQUEUE)
3642c43e99fdSEd Maste 	if (base->evsel == &kqops && event_kq_add_notify_event_(base) == 0) {
3643c43e99fdSEd Maste 		base->th_notify_fn = event_kq_notify_base_;
3644c43e99fdSEd Maste 		/* No need to add an event here; the backend can wake
3645c43e99fdSEd Maste 		 * itself up just fine. */
3646c43e99fdSEd Maste 		return 0;
3647c43e99fdSEd Maste 	}
3648c43e99fdSEd Maste #endif
3649c43e99fdSEd Maste 
3650c43e99fdSEd Maste #ifdef EVENT__HAVE_EVENTFD
3651c43e99fdSEd Maste 	base->th_notify_fd[0] = evutil_eventfd_(0,
3652c43e99fdSEd Maste 	    EVUTIL_EFD_CLOEXEC|EVUTIL_EFD_NONBLOCK);
3653c43e99fdSEd Maste 	if (base->th_notify_fd[0] >= 0) {
3654c43e99fdSEd Maste 		base->th_notify_fd[1] = -1;
3655c43e99fdSEd Maste 		notify = evthread_notify_base_eventfd;
3656c43e99fdSEd Maste 		cb = evthread_notify_drain_eventfd;
3657c43e99fdSEd Maste 	} else
3658c43e99fdSEd Maste #endif
3659c43e99fdSEd Maste 	if (evutil_make_internal_pipe_(base->th_notify_fd) == 0) {
3660c43e99fdSEd Maste 		notify = evthread_notify_base_default;
3661c43e99fdSEd Maste 		cb = evthread_notify_drain_default;
3662c43e99fdSEd Maste 	} else {
3663c43e99fdSEd Maste 		return -1;
3664c43e99fdSEd Maste 	}
3665c43e99fdSEd Maste 
3666c43e99fdSEd Maste 	base->th_notify_fn = notify;
3667c43e99fdSEd Maste 
3668c43e99fdSEd Maste 	/* prepare an event that we can use for wakeup */
3669c43e99fdSEd Maste 	event_assign(&base->th_notify, base, base->th_notify_fd[0],
3670c43e99fdSEd Maste 				 EV_READ|EV_PERSIST, cb, base);
3671c43e99fdSEd Maste 
3672c43e99fdSEd Maste 	/* we need to mark this as internal event */
3673c43e99fdSEd Maste 	base->th_notify.ev_flags |= EVLIST_INTERNAL;
3674c43e99fdSEd Maste 	event_priority_set(&base->th_notify, 0);
3675c43e99fdSEd Maste 
3676c43e99fdSEd Maste 	return event_add_nolock_(&base->th_notify, NULL, 0);
3677c43e99fdSEd Maste }
3678c43e99fdSEd Maste 
3679c43e99fdSEd Maste int
event_base_foreach_event_nolock_(struct event_base * base,event_base_foreach_event_cb fn,void * arg)3680c43e99fdSEd Maste event_base_foreach_event_nolock_(struct event_base *base,
3681c43e99fdSEd Maste     event_base_foreach_event_cb fn, void *arg)
3682c43e99fdSEd Maste {
3683c43e99fdSEd Maste 	int r, i;
3684c43e99fdSEd Maste 	unsigned u;
3685c43e99fdSEd Maste 	struct event *ev;
3686c43e99fdSEd Maste 
3687c43e99fdSEd Maste 	/* Start out with all the EVLIST_INSERTED events. */
3688c43e99fdSEd Maste 	if ((r = evmap_foreach_event_(base, fn, arg)))
3689c43e99fdSEd Maste 		return r;
3690c43e99fdSEd Maste 
3691c43e99fdSEd Maste 	/* Okay, now we deal with those events that have timeouts and are in
3692c43e99fdSEd Maste 	 * the min-heap. */
3693c43e99fdSEd Maste 	for (u = 0; u < base->timeheap.n; ++u) {
3694c43e99fdSEd Maste 		ev = base->timeheap.p[u];
3695c43e99fdSEd Maste 		if (ev->ev_flags & EVLIST_INSERTED) {
3696c43e99fdSEd Maste 			/* we already processed this one */
3697c43e99fdSEd Maste 			continue;
3698c43e99fdSEd Maste 		}
3699c43e99fdSEd Maste 		if ((r = fn(base, ev, arg)))
3700c43e99fdSEd Maste 			return r;
3701c43e99fdSEd Maste 	}
3702c43e99fdSEd Maste 
3703c43e99fdSEd Maste 	/* Now for the events in one of the timeout queues.
3704c43e99fdSEd Maste 	 * the min-heap. */
3705c43e99fdSEd Maste 	for (i = 0; i < base->n_common_timeouts; ++i) {
3706c43e99fdSEd Maste 		struct common_timeout_list *ctl =
3707c43e99fdSEd Maste 		    base->common_timeout_queues[i];
3708c43e99fdSEd Maste 		TAILQ_FOREACH(ev, &ctl->events,
3709c43e99fdSEd Maste 		    ev_timeout_pos.ev_next_with_common_timeout) {
3710c43e99fdSEd Maste 			if (ev->ev_flags & EVLIST_INSERTED) {
3711c43e99fdSEd Maste 				/* we already processed this one */
3712c43e99fdSEd Maste 				continue;
3713c43e99fdSEd Maste 			}
3714c43e99fdSEd Maste 			if ((r = fn(base, ev, arg)))
3715c43e99fdSEd Maste 				return r;
3716c43e99fdSEd Maste 		}
3717c43e99fdSEd Maste 	}
3718c43e99fdSEd Maste 
3719c43e99fdSEd Maste 	/* Finally, we deal wit all the active events that we haven't touched
3720c43e99fdSEd Maste 	 * yet. */
3721c43e99fdSEd Maste 	for (i = 0; i < base->nactivequeues; ++i) {
3722c43e99fdSEd Maste 		struct event_callback *evcb;
3723c43e99fdSEd Maste 		TAILQ_FOREACH(evcb, &base->activequeues[i], evcb_active_next) {
3724c43e99fdSEd Maste 			if ((evcb->evcb_flags & (EVLIST_INIT|EVLIST_INSERTED|EVLIST_TIMEOUT)) != EVLIST_INIT) {
3725c43e99fdSEd Maste 				/* This isn't an event (evlist_init clear), or
3726c43e99fdSEd Maste 				 * we already processed it. (inserted or
3727c43e99fdSEd Maste 				 * timeout set */
3728c43e99fdSEd Maste 				continue;
3729c43e99fdSEd Maste 			}
3730c43e99fdSEd Maste 			ev = event_callback_to_event(evcb);
3731c43e99fdSEd Maste 			if ((r = fn(base, ev, arg)))
3732c43e99fdSEd Maste 				return r;
3733c43e99fdSEd Maste 		}
3734c43e99fdSEd Maste 	}
3735c43e99fdSEd Maste 
3736c43e99fdSEd Maste 	return 0;
3737c43e99fdSEd Maste }
3738c43e99fdSEd Maste 
3739c43e99fdSEd Maste /* Helper for event_base_dump_events: called on each event in the event base;
3740c43e99fdSEd Maste  * dumps only the inserted events. */
3741c43e99fdSEd Maste static int
dump_inserted_event_fn(const struct event_base * base,const struct event * e,void * arg)3742c43e99fdSEd Maste dump_inserted_event_fn(const struct event_base *base, const struct event *e, void *arg)
3743c43e99fdSEd Maste {
3744c43e99fdSEd Maste 	FILE *output = arg;
3745c43e99fdSEd Maste 	const char *gloss = (e->ev_events & EV_SIGNAL) ?
3746c43e99fdSEd Maste 	    "sig" : "fd ";
3747c43e99fdSEd Maste 
3748c43e99fdSEd Maste 	if (! (e->ev_flags & (EVLIST_INSERTED|EVLIST_TIMEOUT)))
3749c43e99fdSEd Maste 		return 0;
3750c43e99fdSEd Maste 
3751*b50261e2SCy Schubert 	fprintf(output, "  %p [%s "EV_SOCK_FMT"]%s%s%s%s%s%s%s",
3752c43e99fdSEd Maste 	    (void*)e, gloss, EV_SOCK_ARG(e->ev_fd),
3753c43e99fdSEd Maste 	    (e->ev_events&EV_READ)?" Read":"",
3754c43e99fdSEd Maste 	    (e->ev_events&EV_WRITE)?" Write":"",
3755c43e99fdSEd Maste 	    (e->ev_events&EV_CLOSED)?" EOF":"",
3756c43e99fdSEd Maste 	    (e->ev_events&EV_SIGNAL)?" Signal":"",
3757c43e99fdSEd Maste 	    (e->ev_events&EV_PERSIST)?" Persist":"",
3758*b50261e2SCy Schubert 	    (e->ev_events&EV_ET)?" ET":"",
3759c43e99fdSEd Maste 	    (e->ev_flags&EVLIST_INTERNAL)?" Internal":"");
3760c43e99fdSEd Maste 	if (e->ev_flags & EVLIST_TIMEOUT) {
3761c43e99fdSEd Maste 		struct timeval tv;
3762c43e99fdSEd Maste 		tv.tv_sec = e->ev_timeout.tv_sec;
3763c43e99fdSEd Maste 		tv.tv_usec = e->ev_timeout.tv_usec & MICROSECONDS_MASK;
3764c43e99fdSEd Maste 		evutil_timeradd(&tv, &base->tv_clock_diff, &tv);
3765c43e99fdSEd Maste 		fprintf(output, " Timeout=%ld.%06d",
3766c43e99fdSEd Maste 		    (long)tv.tv_sec, (int)(tv.tv_usec & MICROSECONDS_MASK));
3767c43e99fdSEd Maste 	}
3768c43e99fdSEd Maste 	fputc('\n', output);
3769c43e99fdSEd Maste 
3770c43e99fdSEd Maste 	return 0;
3771c43e99fdSEd Maste }
3772c43e99fdSEd Maste 
3773c43e99fdSEd Maste /* Helper for event_base_dump_events: called on each event in the event base;
3774c43e99fdSEd Maste  * dumps only the active events. */
3775c43e99fdSEd Maste static int
dump_active_event_fn(const struct event_base * base,const struct event * e,void * arg)3776c43e99fdSEd Maste dump_active_event_fn(const struct event_base *base, const struct event *e, void *arg)
3777c43e99fdSEd Maste {
3778c43e99fdSEd Maste 	FILE *output = arg;
3779c43e99fdSEd Maste 	const char *gloss = (e->ev_events & EV_SIGNAL) ?
3780c43e99fdSEd Maste 	    "sig" : "fd ";
3781c43e99fdSEd Maste 
3782c43e99fdSEd Maste 	if (! (e->ev_flags & (EVLIST_ACTIVE|EVLIST_ACTIVE_LATER)))
3783c43e99fdSEd Maste 		return 0;
3784c43e99fdSEd Maste 
3785c43e99fdSEd Maste 	fprintf(output, "  %p [%s "EV_SOCK_FMT", priority=%d]%s%s%s%s%s active%s%s\n",
3786c43e99fdSEd Maste 	    (void*)e, gloss, EV_SOCK_ARG(e->ev_fd), e->ev_pri,
3787c43e99fdSEd Maste 	    (e->ev_res&EV_READ)?" Read":"",
3788c43e99fdSEd Maste 	    (e->ev_res&EV_WRITE)?" Write":"",
3789c43e99fdSEd Maste 	    (e->ev_res&EV_CLOSED)?" EOF":"",
3790c43e99fdSEd Maste 	    (e->ev_res&EV_SIGNAL)?" Signal":"",
3791c43e99fdSEd Maste 	    (e->ev_res&EV_TIMEOUT)?" Timeout":"",
3792c43e99fdSEd Maste 	    (e->ev_flags&EVLIST_INTERNAL)?" [Internal]":"",
3793c43e99fdSEd Maste 	    (e->ev_flags&EVLIST_ACTIVE_LATER)?" [NextTime]":"");
3794c43e99fdSEd Maste 
3795c43e99fdSEd Maste 	return 0;
3796c43e99fdSEd Maste }
3797c43e99fdSEd Maste 
3798c43e99fdSEd Maste int
event_base_foreach_event(struct event_base * base,event_base_foreach_event_cb fn,void * arg)3799c43e99fdSEd Maste event_base_foreach_event(struct event_base *base,
3800c43e99fdSEd Maste     event_base_foreach_event_cb fn, void *arg)
3801c43e99fdSEd Maste {
3802c43e99fdSEd Maste 	int r;
3803c43e99fdSEd Maste 	if ((!fn) || (!base)) {
3804c43e99fdSEd Maste 		return -1;
3805c43e99fdSEd Maste 	}
3806c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3807c43e99fdSEd Maste 	r = event_base_foreach_event_nolock_(base, fn, arg);
3808c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3809c43e99fdSEd Maste 	return r;
3810c43e99fdSEd Maste }
3811c43e99fdSEd Maste 
3812c43e99fdSEd Maste 
3813c43e99fdSEd Maste void
event_base_dump_events(struct event_base * base,FILE * output)3814c43e99fdSEd Maste event_base_dump_events(struct event_base *base, FILE *output)
3815c43e99fdSEd Maste {
3816c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3817c43e99fdSEd Maste 	fprintf(output, "Inserted events:\n");
3818c43e99fdSEd Maste 	event_base_foreach_event_nolock_(base, dump_inserted_event_fn, output);
3819c43e99fdSEd Maste 
3820c43e99fdSEd Maste 	fprintf(output, "Active events:\n");
3821c43e99fdSEd Maste 	event_base_foreach_event_nolock_(base, dump_active_event_fn, output);
3822c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3823c43e99fdSEd Maste }
3824c43e99fdSEd Maste 
3825c43e99fdSEd Maste void
event_base_active_by_fd(struct event_base * base,evutil_socket_t fd,short events)3826c43e99fdSEd Maste event_base_active_by_fd(struct event_base *base, evutil_socket_t fd, short events)
3827c43e99fdSEd Maste {
3828c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3829*b50261e2SCy Schubert 
3830*b50261e2SCy Schubert 	/* Activate any non timer events */
3831*b50261e2SCy Schubert 	if (!(events & EV_TIMEOUT)) {
3832c43e99fdSEd Maste 		evmap_io_active_(base, fd, events & (EV_READ|EV_WRITE|EV_CLOSED));
3833*b50261e2SCy Schubert 	} else {
3834*b50261e2SCy Schubert 		/* If we want to activate timer events, loop and activate each event with
3835*b50261e2SCy Schubert 		 * the same fd in both the timeheap and common timeouts list */
3836*b50261e2SCy Schubert 		int i;
3837*b50261e2SCy Schubert 		unsigned u;
3838*b50261e2SCy Schubert 		struct event *ev;
3839*b50261e2SCy Schubert 
3840*b50261e2SCy Schubert 		for (u = 0; u < base->timeheap.n; ++u) {
3841*b50261e2SCy Schubert 			ev = base->timeheap.p[u];
3842*b50261e2SCy Schubert 			if (ev->ev_fd == fd) {
3843*b50261e2SCy Schubert 				event_active_nolock_(ev, EV_TIMEOUT, 1);
3844*b50261e2SCy Schubert 			}
3845*b50261e2SCy Schubert 		}
3846*b50261e2SCy Schubert 
3847*b50261e2SCy Schubert 		for (i = 0; i < base->n_common_timeouts; ++i) {
3848*b50261e2SCy Schubert 			struct common_timeout_list *ctl = base->common_timeout_queues[i];
3849*b50261e2SCy Schubert 			TAILQ_FOREACH(ev, &ctl->events,
3850*b50261e2SCy Schubert 				ev_timeout_pos.ev_next_with_common_timeout) {
3851*b50261e2SCy Schubert 				if (ev->ev_fd == fd) {
3852*b50261e2SCy Schubert 					event_active_nolock_(ev, EV_TIMEOUT, 1);
3853*b50261e2SCy Schubert 				}
3854*b50261e2SCy Schubert 			}
3855*b50261e2SCy Schubert 		}
3856*b50261e2SCy Schubert 	}
3857*b50261e2SCy Schubert 
3858c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3859c43e99fdSEd Maste }
3860c43e99fdSEd Maste 
3861c43e99fdSEd Maste void
event_base_active_by_signal(struct event_base * base,int sig)3862c43e99fdSEd Maste event_base_active_by_signal(struct event_base *base, int sig)
3863c43e99fdSEd Maste {
3864c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3865c43e99fdSEd Maste 	evmap_signal_active_(base, sig, 1);
3866c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3867c43e99fdSEd Maste }
3868c43e99fdSEd Maste 
3869c43e99fdSEd Maste 
3870c43e99fdSEd Maste void
event_base_add_virtual_(struct event_base * base)3871c43e99fdSEd Maste event_base_add_virtual_(struct event_base *base)
3872c43e99fdSEd Maste {
3873c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3874c43e99fdSEd Maste 	base->virtual_event_count++;
3875c43e99fdSEd Maste 	MAX_EVENT_COUNT(base->virtual_event_count_max, base->virtual_event_count);
3876c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3877c43e99fdSEd Maste }
3878c43e99fdSEd Maste 
3879c43e99fdSEd Maste void
event_base_del_virtual_(struct event_base * base)3880c43e99fdSEd Maste event_base_del_virtual_(struct event_base *base)
3881c43e99fdSEd Maste {
3882c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3883c43e99fdSEd Maste 	EVUTIL_ASSERT(base->virtual_event_count > 0);
3884c43e99fdSEd Maste 	base->virtual_event_count--;
3885c43e99fdSEd Maste 	if (base->virtual_event_count == 0 && EVBASE_NEED_NOTIFY(base))
3886c43e99fdSEd Maste 		evthread_notify_base(base);
3887c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3888c43e99fdSEd Maste }
3889c43e99fdSEd Maste 
3890c43e99fdSEd Maste static void
event_free_debug_globals_locks(void)3891c43e99fdSEd Maste event_free_debug_globals_locks(void)
3892c43e99fdSEd Maste {
3893c43e99fdSEd Maste #ifndef EVENT__DISABLE_THREAD_SUPPORT
3894c43e99fdSEd Maste #ifndef EVENT__DISABLE_DEBUG_MODE
3895c43e99fdSEd Maste 	if (event_debug_map_lock_ != NULL) {
3896c43e99fdSEd Maste 		EVTHREAD_FREE_LOCK(event_debug_map_lock_, 0);
3897c43e99fdSEd Maste 		event_debug_map_lock_ = NULL;
3898c43e99fdSEd Maste 		evthreadimpl_disable_lock_debugging_();
3899c43e99fdSEd Maste 	}
3900c43e99fdSEd Maste #endif /* EVENT__DISABLE_DEBUG_MODE */
3901c43e99fdSEd Maste #endif /* EVENT__DISABLE_THREAD_SUPPORT */
3902c43e99fdSEd Maste 	return;
3903c43e99fdSEd Maste }
3904c43e99fdSEd Maste 
3905c43e99fdSEd Maste static void
event_free_debug_globals(void)3906c43e99fdSEd Maste event_free_debug_globals(void)
3907c43e99fdSEd Maste {
3908c43e99fdSEd Maste 	event_free_debug_globals_locks();
3909c43e99fdSEd Maste }
3910c43e99fdSEd Maste 
3911c43e99fdSEd Maste static void
event_free_evsig_globals(void)3912c43e99fdSEd Maste event_free_evsig_globals(void)
3913c43e99fdSEd Maste {
3914c43e99fdSEd Maste 	evsig_free_globals_();
3915c43e99fdSEd Maste }
3916c43e99fdSEd Maste 
3917c43e99fdSEd Maste static void
event_free_evutil_globals(void)3918c43e99fdSEd Maste event_free_evutil_globals(void)
3919c43e99fdSEd Maste {
3920c43e99fdSEd Maste 	evutil_free_globals_();
3921c43e99fdSEd Maste }
3922c43e99fdSEd Maste 
3923c43e99fdSEd Maste static void
event_free_globals(void)3924c43e99fdSEd Maste event_free_globals(void)
3925c43e99fdSEd Maste {
3926c43e99fdSEd Maste 	event_free_debug_globals();
3927c43e99fdSEd Maste 	event_free_evsig_globals();
3928c43e99fdSEd Maste 	event_free_evutil_globals();
3929c43e99fdSEd Maste }
3930c43e99fdSEd Maste 
3931c43e99fdSEd Maste void
libevent_global_shutdown(void)3932c43e99fdSEd Maste libevent_global_shutdown(void)
3933c43e99fdSEd Maste {
3934c43e99fdSEd Maste 	event_disable_debug_mode();
3935c43e99fdSEd Maste 	event_free_globals();
3936c43e99fdSEd Maste }
3937c43e99fdSEd Maste 
3938c43e99fdSEd Maste #ifndef EVENT__DISABLE_THREAD_SUPPORT
3939c43e99fdSEd Maste int
event_global_setup_locks_(const int enable_locks)3940c43e99fdSEd Maste event_global_setup_locks_(const int enable_locks)
3941c43e99fdSEd Maste {
3942c43e99fdSEd Maste #ifndef EVENT__DISABLE_DEBUG_MODE
3943c43e99fdSEd Maste 	EVTHREAD_SETUP_GLOBAL_LOCK(event_debug_map_lock_, 0);
3944c43e99fdSEd Maste #endif
3945c43e99fdSEd Maste 	if (evsig_global_setup_locks_(enable_locks) < 0)
3946c43e99fdSEd Maste 		return -1;
3947c43e99fdSEd Maste 	if (evutil_global_setup_locks_(enable_locks) < 0)
3948c43e99fdSEd Maste 		return -1;
3949c43e99fdSEd Maste 	if (evutil_secure_rng_global_setup_locks_(enable_locks) < 0)
3950c43e99fdSEd Maste 		return -1;
3951c43e99fdSEd Maste 	return 0;
3952c43e99fdSEd Maste }
3953c43e99fdSEd Maste #endif
3954c43e99fdSEd Maste 
3955c43e99fdSEd Maste void
event_base_assert_ok_(struct event_base * base)3956c43e99fdSEd Maste event_base_assert_ok_(struct event_base *base)
3957c43e99fdSEd Maste {
3958c43e99fdSEd Maste 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
3959c43e99fdSEd Maste 	event_base_assert_ok_nolock_(base);
3960c43e99fdSEd Maste 	EVBASE_RELEASE_LOCK(base, th_base_lock);
3961c43e99fdSEd Maste }
3962c43e99fdSEd Maste 
3963c43e99fdSEd Maste void
event_base_assert_ok_nolock_(struct event_base * base)3964c43e99fdSEd Maste event_base_assert_ok_nolock_(struct event_base *base)
3965c43e99fdSEd Maste {
3966c43e99fdSEd Maste 	int i;
3967c43e99fdSEd Maste 	int count;
3968c43e99fdSEd Maste 
3969c43e99fdSEd Maste 	/* First do checks on the per-fd and per-signal lists */
3970c43e99fdSEd Maste 	evmap_check_integrity_(base);
3971c43e99fdSEd Maste 
3972c43e99fdSEd Maste 	/* Check the heap property */
3973c43e99fdSEd Maste 	for (i = 1; i < (int)base->timeheap.n; ++i) {
3974c43e99fdSEd Maste 		int parent = (i - 1) / 2;
3975c43e99fdSEd Maste 		struct event *ev, *p_ev;
3976c43e99fdSEd Maste 		ev = base->timeheap.p[i];
3977c43e99fdSEd Maste 		p_ev = base->timeheap.p[parent];
3978c43e99fdSEd Maste 		EVUTIL_ASSERT(ev->ev_flags & EVLIST_TIMEOUT);
3979c43e99fdSEd Maste 		EVUTIL_ASSERT(evutil_timercmp(&p_ev->ev_timeout, &ev->ev_timeout, <=));
3980c43e99fdSEd Maste 		EVUTIL_ASSERT(ev->ev_timeout_pos.min_heap_idx == i);
3981c43e99fdSEd Maste 	}
3982c43e99fdSEd Maste 
3983c43e99fdSEd Maste 	/* Check that the common timeouts are fine */
3984c43e99fdSEd Maste 	for (i = 0; i < base->n_common_timeouts; ++i) {
3985c43e99fdSEd Maste 		struct common_timeout_list *ctl = base->common_timeout_queues[i];
3986c43e99fdSEd Maste 		struct event *last=NULL, *ev;
3987c43e99fdSEd Maste 
3988c43e99fdSEd Maste 		EVUTIL_ASSERT_TAILQ_OK(&ctl->events, event, ev_timeout_pos.ev_next_with_common_timeout);
3989c43e99fdSEd Maste 
3990c43e99fdSEd Maste 		TAILQ_FOREACH(ev, &ctl->events, ev_timeout_pos.ev_next_with_common_timeout) {
3991c43e99fdSEd Maste 			if (last)
3992c43e99fdSEd Maste 				EVUTIL_ASSERT(evutil_timercmp(&last->ev_timeout, &ev->ev_timeout, <=));
3993c43e99fdSEd Maste 			EVUTIL_ASSERT(ev->ev_flags & EVLIST_TIMEOUT);
3994c43e99fdSEd Maste 			EVUTIL_ASSERT(is_common_timeout(&ev->ev_timeout,base));
3995c43e99fdSEd Maste 			EVUTIL_ASSERT(COMMON_TIMEOUT_IDX(&ev->ev_timeout) == i);
3996c43e99fdSEd Maste 			last = ev;
3997c43e99fdSEd Maste 		}
3998c43e99fdSEd Maste 	}
3999c43e99fdSEd Maste 
4000c43e99fdSEd Maste 	/* Check the active queues. */
4001c43e99fdSEd Maste 	count = 0;
4002c43e99fdSEd Maste 	for (i = 0; i < base->nactivequeues; ++i) {
4003c43e99fdSEd Maste 		struct event_callback *evcb;
4004c43e99fdSEd Maste 		EVUTIL_ASSERT_TAILQ_OK(&base->activequeues[i], event_callback, evcb_active_next);
4005c43e99fdSEd Maste 		TAILQ_FOREACH(evcb, &base->activequeues[i], evcb_active_next) {
4006c43e99fdSEd Maste 			EVUTIL_ASSERT((evcb->evcb_flags & (EVLIST_ACTIVE|EVLIST_ACTIVE_LATER)) == EVLIST_ACTIVE);
4007c43e99fdSEd Maste 			EVUTIL_ASSERT(evcb->evcb_pri == i);
4008c43e99fdSEd Maste 			++count;
4009c43e99fdSEd Maste 		}
4010c43e99fdSEd Maste 	}
4011c43e99fdSEd Maste 
4012c43e99fdSEd Maste 	{
4013c43e99fdSEd Maste 		struct event_callback *evcb;
4014c43e99fdSEd Maste 		TAILQ_FOREACH(evcb, &base->active_later_queue, evcb_active_next) {
4015c43e99fdSEd Maste 			EVUTIL_ASSERT((evcb->evcb_flags & (EVLIST_ACTIVE|EVLIST_ACTIVE_LATER)) == EVLIST_ACTIVE_LATER);
4016c43e99fdSEd Maste 			++count;
4017c43e99fdSEd Maste 		}
4018c43e99fdSEd Maste 	}
4019c43e99fdSEd Maste 	EVUTIL_ASSERT(count == base->event_count_active);
4020c43e99fdSEd Maste }
4021