xref: /aosp_15_r20/external/wayland/src/event-loop.c (revision 84e872a0dc482bffdb63672969dd03a827d67c73)
1*84e872a0SLloyd Pique /*
2*84e872a0SLloyd Pique  * Copyright © 2008 Kristian Høgsberg
3*84e872a0SLloyd Pique  *
4*84e872a0SLloyd Pique  * Permission is hereby granted, free of charge, to any person obtaining
5*84e872a0SLloyd Pique  * a copy of this software and associated documentation files (the
6*84e872a0SLloyd Pique  * "Software"), to deal in the Software without restriction, including
7*84e872a0SLloyd Pique  * without limitation the rights to use, copy, modify, merge, publish,
8*84e872a0SLloyd Pique  * distribute, sublicense, and/or sell copies of the Software, and to
9*84e872a0SLloyd Pique  * permit persons to whom the Software is furnished to do so, subject to
10*84e872a0SLloyd Pique  * the following conditions:
11*84e872a0SLloyd Pique  *
12*84e872a0SLloyd Pique  * The above copyright notice and this permission notice (including the
13*84e872a0SLloyd Pique  * next paragraph) shall be included in all copies or substantial
14*84e872a0SLloyd Pique  * portions of the Software.
15*84e872a0SLloyd Pique  *
16*84e872a0SLloyd Pique  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17*84e872a0SLloyd Pique  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*84e872a0SLloyd Pique  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19*84e872a0SLloyd Pique  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20*84e872a0SLloyd Pique  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21*84e872a0SLloyd Pique  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22*84e872a0SLloyd Pique  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23*84e872a0SLloyd Pique  * SOFTWARE.
24*84e872a0SLloyd Pique  */
25*84e872a0SLloyd Pique 
26*84e872a0SLloyd Pique #include <assert.h>
27*84e872a0SLloyd Pique #include <stddef.h>
28*84e872a0SLloyd Pique #include <stdio.h>
29*84e872a0SLloyd Pique #include <errno.h>
30*84e872a0SLloyd Pique #include <signal.h>
31*84e872a0SLloyd Pique #include <stdlib.h>
32*84e872a0SLloyd Pique #include <stdint.h>
33*84e872a0SLloyd Pique #include <stdbool.h>
34*84e872a0SLloyd Pique #include <string.h>
35*84e872a0SLloyd Pique #include <fcntl.h>
36*84e872a0SLloyd Pique #include <sys/socket.h>
37*84e872a0SLloyd Pique #include <sys/un.h>
38*84e872a0SLloyd Pique #include <sys/epoll.h>
39*84e872a0SLloyd Pique #include <sys/signalfd.h>
40*84e872a0SLloyd Pique #include <sys/timerfd.h>
41*84e872a0SLloyd Pique #include <unistd.h>
42*84e872a0SLloyd Pique #include "wayland-util.h"
43*84e872a0SLloyd Pique #include "wayland-private.h"
44*84e872a0SLloyd Pique #include "wayland-server-core.h"
45*84e872a0SLloyd Pique #include "wayland-os.h"
46*84e872a0SLloyd Pique 
47*84e872a0SLloyd Pique /** \cond INTERNAL */
48*84e872a0SLloyd Pique 
49*84e872a0SLloyd Pique #define TIMER_REMOVED -2
50*84e872a0SLloyd Pique 
51*84e872a0SLloyd Pique struct wl_event_loop;
52*84e872a0SLloyd Pique struct wl_event_source_interface;
53*84e872a0SLloyd Pique struct wl_event_source_timer;
54*84e872a0SLloyd Pique 
55*84e872a0SLloyd Pique struct wl_event_source {
56*84e872a0SLloyd Pique 	struct wl_event_source_interface *interface;
57*84e872a0SLloyd Pique 	struct wl_event_loop *loop;
58*84e872a0SLloyd Pique 	struct wl_list link;
59*84e872a0SLloyd Pique 	void *data;
60*84e872a0SLloyd Pique 	int fd;
61*84e872a0SLloyd Pique };
62*84e872a0SLloyd Pique 
63*84e872a0SLloyd Pique struct wl_timer_heap {
64*84e872a0SLloyd Pique 	struct wl_event_source base;
65*84e872a0SLloyd Pique 	/* pointers to the user-visible event sources */
66*84e872a0SLloyd Pique 	struct wl_event_source_timer **data;
67*84e872a0SLloyd Pique 	int space, active, count;
68*84e872a0SLloyd Pique };
69*84e872a0SLloyd Pique 
70*84e872a0SLloyd Pique struct wl_event_loop {
71*84e872a0SLloyd Pique 	int epoll_fd;
72*84e872a0SLloyd Pique 	struct wl_list check_list;
73*84e872a0SLloyd Pique 	struct wl_list idle_list;
74*84e872a0SLloyd Pique 	struct wl_list destroy_list;
75*84e872a0SLloyd Pique 
76*84e872a0SLloyd Pique 	struct wl_signal destroy_signal;
77*84e872a0SLloyd Pique 
78*84e872a0SLloyd Pique 	struct wl_timer_heap timers;
79*84e872a0SLloyd Pique };
80*84e872a0SLloyd Pique 
81*84e872a0SLloyd Pique struct wl_event_source_interface {
82*84e872a0SLloyd Pique 	int (*dispatch)(struct wl_event_source *source,
83*84e872a0SLloyd Pique 			struct epoll_event *ep);
84*84e872a0SLloyd Pique };
85*84e872a0SLloyd Pique 
86*84e872a0SLloyd Pique 
87*84e872a0SLloyd Pique struct wl_event_source_fd {
88*84e872a0SLloyd Pique 	struct wl_event_source base;
89*84e872a0SLloyd Pique 	wl_event_loop_fd_func_t func;
90*84e872a0SLloyd Pique 	int fd;
91*84e872a0SLloyd Pique };
92*84e872a0SLloyd Pique 
93*84e872a0SLloyd Pique /** \endcond */
94*84e872a0SLloyd Pique 
95*84e872a0SLloyd Pique static int
wl_event_source_fd_dispatch(struct wl_event_source * source,struct epoll_event * ep)96*84e872a0SLloyd Pique wl_event_source_fd_dispatch(struct wl_event_source *source,
97*84e872a0SLloyd Pique 			    struct epoll_event *ep)
98*84e872a0SLloyd Pique {
99*84e872a0SLloyd Pique 	struct wl_event_source_fd *fd_source = (struct wl_event_source_fd *) source;
100*84e872a0SLloyd Pique 	uint32_t mask;
101*84e872a0SLloyd Pique 
102*84e872a0SLloyd Pique 	mask = 0;
103*84e872a0SLloyd Pique 	if (ep->events & EPOLLIN)
104*84e872a0SLloyd Pique 		mask |= WL_EVENT_READABLE;
105*84e872a0SLloyd Pique 	if (ep->events & EPOLLOUT)
106*84e872a0SLloyd Pique 		mask |= WL_EVENT_WRITABLE;
107*84e872a0SLloyd Pique 	if (ep->events & EPOLLHUP)
108*84e872a0SLloyd Pique 		mask |= WL_EVENT_HANGUP;
109*84e872a0SLloyd Pique 	if (ep->events & EPOLLERR)
110*84e872a0SLloyd Pique 		mask |= WL_EVENT_ERROR;
111*84e872a0SLloyd Pique 
112*84e872a0SLloyd Pique 	return fd_source->func(fd_source->fd, mask, source->data);
113*84e872a0SLloyd Pique }
114*84e872a0SLloyd Pique 
115*84e872a0SLloyd Pique struct wl_event_source_interface fd_source_interface = {
116*84e872a0SLloyd Pique 	wl_event_source_fd_dispatch,
117*84e872a0SLloyd Pique };
118*84e872a0SLloyd Pique 
119*84e872a0SLloyd Pique static struct wl_event_source *
add_source(struct wl_event_loop * loop,struct wl_event_source * source,uint32_t mask,void * data)120*84e872a0SLloyd Pique add_source(struct wl_event_loop *loop,
121*84e872a0SLloyd Pique 	   struct wl_event_source *source, uint32_t mask, void *data)
122*84e872a0SLloyd Pique {
123*84e872a0SLloyd Pique 	struct epoll_event ep;
124*84e872a0SLloyd Pique 
125*84e872a0SLloyd Pique 	if (source->fd < 0) {
126*84e872a0SLloyd Pique 		free(source);
127*84e872a0SLloyd Pique 		return NULL;
128*84e872a0SLloyd Pique 	}
129*84e872a0SLloyd Pique 
130*84e872a0SLloyd Pique 	source->loop = loop;
131*84e872a0SLloyd Pique 	source->data = data;
132*84e872a0SLloyd Pique 	wl_list_init(&source->link);
133*84e872a0SLloyd Pique 
134*84e872a0SLloyd Pique 	memset(&ep, 0, sizeof ep);
135*84e872a0SLloyd Pique 	if (mask & WL_EVENT_READABLE)
136*84e872a0SLloyd Pique 		ep.events |= EPOLLIN;
137*84e872a0SLloyd Pique 	if (mask & WL_EVENT_WRITABLE)
138*84e872a0SLloyd Pique 		ep.events |= EPOLLOUT;
139*84e872a0SLloyd Pique 	ep.data.ptr = source;
140*84e872a0SLloyd Pique 
141*84e872a0SLloyd Pique 	if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) {
142*84e872a0SLloyd Pique 		close(source->fd);
143*84e872a0SLloyd Pique 		free(source);
144*84e872a0SLloyd Pique 		return NULL;
145*84e872a0SLloyd Pique 	}
146*84e872a0SLloyd Pique 
147*84e872a0SLloyd Pique 	return source;
148*84e872a0SLloyd Pique }
149*84e872a0SLloyd Pique 
150*84e872a0SLloyd Pique /** Create a file descriptor event source
151*84e872a0SLloyd Pique  *
152*84e872a0SLloyd Pique  * \param loop The event loop that will process the new source.
153*84e872a0SLloyd Pique  * \param fd The file descriptor to watch.
154*84e872a0SLloyd Pique  * \param mask A bitwise-or of which events to watch for: \c WL_EVENT_READABLE,
155*84e872a0SLloyd Pique  * \c WL_EVENT_WRITABLE.
156*84e872a0SLloyd Pique  * \param func The file descriptor dispatch function.
157*84e872a0SLloyd Pique  * \param data User data.
158*84e872a0SLloyd Pique  * \return A new file descriptor event source.
159*84e872a0SLloyd Pique  *
160*84e872a0SLloyd Pique  * The given file descriptor is initially watched for the events given in
161*84e872a0SLloyd Pique  * \c mask. This can be changed as needed with wl_event_source_fd_update().
162*84e872a0SLloyd Pique  *
163*84e872a0SLloyd Pique  * If it is possible that program execution causes the file descriptor to be
164*84e872a0SLloyd Pique  * read while leaving the data in a buffer without actually processing it,
165*84e872a0SLloyd Pique  * it may be necessary to register the file descriptor source to be re-checked,
166*84e872a0SLloyd Pique  * see wl_event_source_check(). This will ensure that the dispatch function
167*84e872a0SLloyd Pique  * gets called even if the file descriptor is not readable or writable
168*84e872a0SLloyd Pique  * anymore. This is especially useful with IPC libraries that automatically
169*84e872a0SLloyd Pique  * buffer incoming data, possibly as a side-effect of other operations.
170*84e872a0SLloyd Pique  *
171*84e872a0SLloyd Pique  * \sa wl_event_loop_fd_func_t
172*84e872a0SLloyd Pique  * \memberof wl_event_source
173*84e872a0SLloyd Pique  */
174*84e872a0SLloyd Pique WL_EXPORT struct wl_event_source *
wl_event_loop_add_fd(struct wl_event_loop * loop,int fd,uint32_t mask,wl_event_loop_fd_func_t func,void * data)175*84e872a0SLloyd Pique wl_event_loop_add_fd(struct wl_event_loop *loop,
176*84e872a0SLloyd Pique 		     int fd, uint32_t mask,
177*84e872a0SLloyd Pique 		     wl_event_loop_fd_func_t func,
178*84e872a0SLloyd Pique 		     void *data)
179*84e872a0SLloyd Pique {
180*84e872a0SLloyd Pique 	struct wl_event_source_fd *source;
181*84e872a0SLloyd Pique 
182*84e872a0SLloyd Pique 	source = zalloc(sizeof *source);
183*84e872a0SLloyd Pique 	if (source == NULL)
184*84e872a0SLloyd Pique 		return NULL;
185*84e872a0SLloyd Pique 
186*84e872a0SLloyd Pique 	source->base.interface = &fd_source_interface;
187*84e872a0SLloyd Pique 	source->base.fd = wl_os_dupfd_cloexec(fd, 0);
188*84e872a0SLloyd Pique 	source->func = func;
189*84e872a0SLloyd Pique 	source->fd = fd;
190*84e872a0SLloyd Pique 
191*84e872a0SLloyd Pique 	return add_source(loop, &source->base, mask, data);
192*84e872a0SLloyd Pique }
193*84e872a0SLloyd Pique 
194*84e872a0SLloyd Pique /** Update a file descriptor source's event mask
195*84e872a0SLloyd Pique  *
196*84e872a0SLloyd Pique  * \param source The file descriptor event source to update.
197*84e872a0SLloyd Pique  * \param mask The new mask, a bitwise-or of: \c WL_EVENT_READABLE,
198*84e872a0SLloyd Pique  * \c WL_EVENT_WRITABLE.
199*84e872a0SLloyd Pique  * \return 0 on success, -1 on failure.
200*84e872a0SLloyd Pique  *
201*84e872a0SLloyd Pique  * This changes which events, readable and/or writable, cause the dispatch
202*84e872a0SLloyd Pique  * callback to be called on.
203*84e872a0SLloyd Pique  *
204*84e872a0SLloyd Pique  * File descriptors are usually writable to begin with, so they do not need to
205*84e872a0SLloyd Pique  * be polled for writable until a write actually fails. When a write fails,
206*84e872a0SLloyd Pique  * the event mask can be changed to poll for readable and writable, delivering
207*84e872a0SLloyd Pique  * a dispatch callback when it is possible to write more. Once all data has
208*84e872a0SLloyd Pique  * been written, the mask can be changed to poll only for readable to avoid
209*84e872a0SLloyd Pique  * busy-looping on dispatch.
210*84e872a0SLloyd Pique  *
211*84e872a0SLloyd Pique  * \sa wl_event_loop_add_fd()
212*84e872a0SLloyd Pique  * \memberof wl_event_source
213*84e872a0SLloyd Pique  */
214*84e872a0SLloyd Pique WL_EXPORT int
wl_event_source_fd_update(struct wl_event_source * source,uint32_t mask)215*84e872a0SLloyd Pique wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask)
216*84e872a0SLloyd Pique {
217*84e872a0SLloyd Pique 	struct wl_event_loop *loop = source->loop;
218*84e872a0SLloyd Pique 	struct epoll_event ep;
219*84e872a0SLloyd Pique 
220*84e872a0SLloyd Pique 	memset(&ep, 0, sizeof ep);
221*84e872a0SLloyd Pique 	if (mask & WL_EVENT_READABLE)
222*84e872a0SLloyd Pique 		ep.events |= EPOLLIN;
223*84e872a0SLloyd Pique 	if (mask & WL_EVENT_WRITABLE)
224*84e872a0SLloyd Pique 		ep.events |= EPOLLOUT;
225*84e872a0SLloyd Pique 	ep.data.ptr = source;
226*84e872a0SLloyd Pique 
227*84e872a0SLloyd Pique 	return epoll_ctl(loop->epoll_fd, EPOLL_CTL_MOD, source->fd, &ep);
228*84e872a0SLloyd Pique }
229*84e872a0SLloyd Pique 
230*84e872a0SLloyd Pique /** \cond INTERNAL */
231*84e872a0SLloyd Pique 
232*84e872a0SLloyd Pique struct wl_event_source_timer {
233*84e872a0SLloyd Pique 	struct wl_event_source base;
234*84e872a0SLloyd Pique 	wl_event_loop_timer_func_t func;
235*84e872a0SLloyd Pique 	struct wl_event_source_timer *next_due;
236*84e872a0SLloyd Pique 	struct timespec deadline;
237*84e872a0SLloyd Pique 	int heap_idx;
238*84e872a0SLloyd Pique };
239*84e872a0SLloyd Pique 
240*84e872a0SLloyd Pique static int
noop_dispatch(struct wl_event_source * source,struct epoll_event * ep)241*84e872a0SLloyd Pique noop_dispatch(struct wl_event_source *source,
242*84e872a0SLloyd Pique 	      struct epoll_event *ep) {
243*84e872a0SLloyd Pique 	return 0;
244*84e872a0SLloyd Pique }
245*84e872a0SLloyd Pique 
246*84e872a0SLloyd Pique struct wl_event_source_interface timer_heap_source_interface = {
247*84e872a0SLloyd Pique 	noop_dispatch,
248*84e872a0SLloyd Pique };
249*84e872a0SLloyd Pique 
250*84e872a0SLloyd Pique static bool
time_lt(struct timespec ta,struct timespec tb)251*84e872a0SLloyd Pique time_lt(struct timespec ta, struct timespec tb)
252*84e872a0SLloyd Pique {
253*84e872a0SLloyd Pique 	if (ta.tv_sec != tb.tv_sec) {
254*84e872a0SLloyd Pique 		return ta.tv_sec < tb.tv_sec;
255*84e872a0SLloyd Pique 	}
256*84e872a0SLloyd Pique 	return ta.tv_nsec < tb.tv_nsec;
257*84e872a0SLloyd Pique }
258*84e872a0SLloyd Pique 
259*84e872a0SLloyd Pique static int
set_timer(int timerfd,struct timespec deadline)260*84e872a0SLloyd Pique set_timer(int timerfd, struct timespec deadline) {
261*84e872a0SLloyd Pique 	struct itimerspec its;
262*84e872a0SLloyd Pique 
263*84e872a0SLloyd Pique 	its.it_interval.tv_sec = 0;
264*84e872a0SLloyd Pique 	its.it_interval.tv_nsec = 0;
265*84e872a0SLloyd Pique 	its.it_value = deadline;
266*84e872a0SLloyd Pique 	return timerfd_settime(timerfd, TFD_TIMER_ABSTIME, &its, NULL);
267*84e872a0SLloyd Pique }
268*84e872a0SLloyd Pique 
269*84e872a0SLloyd Pique static int
clear_timer(int timerfd)270*84e872a0SLloyd Pique clear_timer(int timerfd)
271*84e872a0SLloyd Pique {
272*84e872a0SLloyd Pique 	struct itimerspec its;
273*84e872a0SLloyd Pique 
274*84e872a0SLloyd Pique 	its.it_interval.tv_sec = 0;
275*84e872a0SLloyd Pique 	its.it_interval.tv_nsec = 0;
276*84e872a0SLloyd Pique 	its.it_value.tv_sec = 0;
277*84e872a0SLloyd Pique 	its.it_value.tv_nsec = 0;
278*84e872a0SLloyd Pique 	return timerfd_settime(timerfd, 0, &its, NULL);
279*84e872a0SLloyd Pique }
280*84e872a0SLloyd Pique 
281*84e872a0SLloyd Pique static void
wl_timer_heap_init(struct wl_timer_heap * timers,struct wl_event_loop * loop)282*84e872a0SLloyd Pique wl_timer_heap_init(struct wl_timer_heap *timers, struct wl_event_loop *loop)
283*84e872a0SLloyd Pique {
284*84e872a0SLloyd Pique 	timers->base.fd = -1;
285*84e872a0SLloyd Pique 	timers->base.data = NULL;
286*84e872a0SLloyd Pique 	wl_list_init(&timers->base.link);
287*84e872a0SLloyd Pique 	timers->base.interface = &timer_heap_source_interface;
288*84e872a0SLloyd Pique 	timers->base.loop = loop;
289*84e872a0SLloyd Pique 
290*84e872a0SLloyd Pique 	loop->timers.data = NULL;
291*84e872a0SLloyd Pique 	loop->timers.active = 0;
292*84e872a0SLloyd Pique 	loop->timers.space = 0;
293*84e872a0SLloyd Pique 	loop->timers.count = 0;
294*84e872a0SLloyd Pique }
295*84e872a0SLloyd Pique 
296*84e872a0SLloyd Pique static void
wl_timer_heap_release(struct wl_timer_heap * timers)297*84e872a0SLloyd Pique wl_timer_heap_release(struct wl_timer_heap *timers)
298*84e872a0SLloyd Pique {
299*84e872a0SLloyd Pique 	if (timers->base.fd != -1) {
300*84e872a0SLloyd Pique 		close(timers->base.fd);
301*84e872a0SLloyd Pique 	}
302*84e872a0SLloyd Pique 	free(timers->data);
303*84e872a0SLloyd Pique }
304*84e872a0SLloyd Pique 
305*84e872a0SLloyd Pique static int
wl_timer_heap_ensure_timerfd(struct wl_timer_heap * timers)306*84e872a0SLloyd Pique wl_timer_heap_ensure_timerfd(struct wl_timer_heap *timers)
307*84e872a0SLloyd Pique {
308*84e872a0SLloyd Pique 	struct epoll_event ep;
309*84e872a0SLloyd Pique 	int timer_fd;
310*84e872a0SLloyd Pique 
311*84e872a0SLloyd Pique 	if (timers->base.fd != -1)
312*84e872a0SLloyd Pique 		return 0;
313*84e872a0SLloyd Pique 
314*84e872a0SLloyd Pique 	memset(&ep, 0, sizeof ep);
315*84e872a0SLloyd Pique 	ep.events = EPOLLIN;
316*84e872a0SLloyd Pique 	ep.data.ptr = timers;
317*84e872a0SLloyd Pique 
318*84e872a0SLloyd Pique 	timer_fd = timerfd_create(CLOCK_MONOTONIC,
319*84e872a0SLloyd Pique 				  TFD_CLOEXEC | TFD_NONBLOCK);
320*84e872a0SLloyd Pique 	if (timer_fd < 0)
321*84e872a0SLloyd Pique 		return -1;
322*84e872a0SLloyd Pique 
323*84e872a0SLloyd Pique 	if (epoll_ctl(timers->base.loop->epoll_fd,
324*84e872a0SLloyd Pique 		      EPOLL_CTL_ADD, timer_fd, &ep) < 0) {
325*84e872a0SLloyd Pique 		close(timer_fd);
326*84e872a0SLloyd Pique 		return -1;
327*84e872a0SLloyd Pique 	}
328*84e872a0SLloyd Pique 
329*84e872a0SLloyd Pique 	timers->base.fd = timer_fd;
330*84e872a0SLloyd Pique 	return 0;
331*84e872a0SLloyd Pique }
332*84e872a0SLloyd Pique 
333*84e872a0SLloyd Pique static int
wl_timer_heap_reserve(struct wl_timer_heap * timers)334*84e872a0SLloyd Pique wl_timer_heap_reserve(struct wl_timer_heap *timers)
335*84e872a0SLloyd Pique {
336*84e872a0SLloyd Pique 	struct wl_event_source_timer **n;
337*84e872a0SLloyd Pique 	int new_space;
338*84e872a0SLloyd Pique 
339*84e872a0SLloyd Pique 	if (timers->count + 1 > timers->space) {
340*84e872a0SLloyd Pique 		new_space = timers->space >= 8 ? timers->space * 2 : 8;
341*84e872a0SLloyd Pique 		n = realloc(timers->data, (size_t)new_space * sizeof(*n));
342*84e872a0SLloyd Pique 		if (!n) {
343*84e872a0SLloyd Pique 			wl_log("Allocation failure when expanding timer list\n");
344*84e872a0SLloyd Pique 			return -1;
345*84e872a0SLloyd Pique 		}
346*84e872a0SLloyd Pique 		timers->data = n;
347*84e872a0SLloyd Pique 		timers->space = new_space;
348*84e872a0SLloyd Pique 	}
349*84e872a0SLloyd Pique 
350*84e872a0SLloyd Pique 	timers->count++;
351*84e872a0SLloyd Pique 	return 0;
352*84e872a0SLloyd Pique }
353*84e872a0SLloyd Pique 
354*84e872a0SLloyd Pique static void
wl_timer_heap_unreserve(struct wl_timer_heap * timers)355*84e872a0SLloyd Pique wl_timer_heap_unreserve(struct wl_timer_heap *timers)
356*84e872a0SLloyd Pique {
357*84e872a0SLloyd Pique 	struct wl_event_source_timer **n;
358*84e872a0SLloyd Pique 
359*84e872a0SLloyd Pique 	timers->count--;
360*84e872a0SLloyd Pique 
361*84e872a0SLloyd Pique 	if (timers->space >= 16 && timers->space >= 4 * timers->count) {
362*84e872a0SLloyd Pique 		n = realloc(timers->data, (size_t)timers->space / 2 * sizeof(*n));
363*84e872a0SLloyd Pique 		if (!n) {
364*84e872a0SLloyd Pique 			wl_log("Reallocation failure when shrinking timer list\n");
365*84e872a0SLloyd Pique 			return;
366*84e872a0SLloyd Pique 		}
367*84e872a0SLloyd Pique 		timers->data = n;
368*84e872a0SLloyd Pique 		timers->space = timers->space / 2;
369*84e872a0SLloyd Pique 	}
370*84e872a0SLloyd Pique }
371*84e872a0SLloyd Pique 
372*84e872a0SLloyd Pique static int
heap_set(struct wl_event_source_timer ** data,struct wl_event_source_timer * a,int idx)373*84e872a0SLloyd Pique heap_set(struct wl_event_source_timer **data,
374*84e872a0SLloyd Pique 	 struct wl_event_source_timer *a,
375*84e872a0SLloyd Pique 	 int idx)
376*84e872a0SLloyd Pique {
377*84e872a0SLloyd Pique 	int tmp;
378*84e872a0SLloyd Pique 
379*84e872a0SLloyd Pique 	tmp = a->heap_idx;
380*84e872a0SLloyd Pique 	a->heap_idx = idx;
381*84e872a0SLloyd Pique 	data[a->heap_idx] = a;
382*84e872a0SLloyd Pique 
383*84e872a0SLloyd Pique 	return tmp;
384*84e872a0SLloyd Pique }
385*84e872a0SLloyd Pique 
386*84e872a0SLloyd Pique static void
heap_sift_down(struct wl_event_source_timer ** data,int num_active,struct wl_event_source_timer * source)387*84e872a0SLloyd Pique heap_sift_down(struct wl_event_source_timer **data,
388*84e872a0SLloyd Pique 	       int num_active,
389*84e872a0SLloyd Pique 	       struct wl_event_source_timer *source)
390*84e872a0SLloyd Pique {
391*84e872a0SLloyd Pique 	struct wl_event_source_timer *child, *other_child;
392*84e872a0SLloyd Pique 	int cursor_idx;
393*84e872a0SLloyd Pique 	struct timespec key;
394*84e872a0SLloyd Pique 
395*84e872a0SLloyd Pique 	cursor_idx = source->heap_idx;
396*84e872a0SLloyd Pique 	key = source->deadline;
397*84e872a0SLloyd Pique 	while (1) {
398*84e872a0SLloyd Pique 		int lchild_idx = cursor_idx * 2 + 1;
399*84e872a0SLloyd Pique 
400*84e872a0SLloyd Pique 		if (lchild_idx >= num_active) {
401*84e872a0SLloyd Pique 			break;
402*84e872a0SLloyd Pique 		}
403*84e872a0SLloyd Pique 
404*84e872a0SLloyd Pique 		child = data[lchild_idx];
405*84e872a0SLloyd Pique 		if (lchild_idx + 1 < num_active) {
406*84e872a0SLloyd Pique 			other_child = data[lchild_idx + 1];
407*84e872a0SLloyd Pique 			if (time_lt(other_child->deadline, child->deadline))
408*84e872a0SLloyd Pique 				child = other_child;
409*84e872a0SLloyd Pique 		}
410*84e872a0SLloyd Pique 
411*84e872a0SLloyd Pique 		if (time_lt(child->deadline, key))
412*84e872a0SLloyd Pique 			cursor_idx = heap_set(data, child, cursor_idx);
413*84e872a0SLloyd Pique 		else
414*84e872a0SLloyd Pique 			break;
415*84e872a0SLloyd Pique 	}
416*84e872a0SLloyd Pique 
417*84e872a0SLloyd Pique 	heap_set(data, source, cursor_idx);
418*84e872a0SLloyd Pique }
419*84e872a0SLloyd Pique 
420*84e872a0SLloyd Pique static void
heap_sift_up(struct wl_event_source_timer ** data,struct wl_event_source_timer * source)421*84e872a0SLloyd Pique heap_sift_up(struct wl_event_source_timer **data,
422*84e872a0SLloyd Pique 	     struct wl_event_source_timer *source)
423*84e872a0SLloyd Pique {
424*84e872a0SLloyd Pique 	int cursor_idx;
425*84e872a0SLloyd Pique 	struct timespec key;
426*84e872a0SLloyd Pique 
427*84e872a0SLloyd Pique 	cursor_idx = source->heap_idx;
428*84e872a0SLloyd Pique 	key = source->deadline;
429*84e872a0SLloyd Pique 	while (cursor_idx > 0) {
430*84e872a0SLloyd Pique 		struct wl_event_source_timer *parent =
431*84e872a0SLloyd Pique 			data[(cursor_idx - 1) / 2];
432*84e872a0SLloyd Pique 
433*84e872a0SLloyd Pique 		if (time_lt(key, parent->deadline))
434*84e872a0SLloyd Pique 			cursor_idx = heap_set(data, parent, cursor_idx);
435*84e872a0SLloyd Pique 		else
436*84e872a0SLloyd Pique 			break;
437*84e872a0SLloyd Pique 	}
438*84e872a0SLloyd Pique 	heap_set(data, source, cursor_idx);
439*84e872a0SLloyd Pique }
440*84e872a0SLloyd Pique 
441*84e872a0SLloyd Pique /* requires timer be armed */
442*84e872a0SLloyd Pique static void
wl_timer_heap_disarm(struct wl_timer_heap * timers,struct wl_event_source_timer * source)443*84e872a0SLloyd Pique wl_timer_heap_disarm(struct wl_timer_heap *timers,
444*84e872a0SLloyd Pique 		     struct wl_event_source_timer *source)
445*84e872a0SLloyd Pique {
446*84e872a0SLloyd Pique 	struct wl_event_source_timer *last_end_evt;
447*84e872a0SLloyd Pique 	int old_source_idx;
448*84e872a0SLloyd Pique 
449*84e872a0SLloyd Pique 	assert(source->heap_idx >= 0);
450*84e872a0SLloyd Pique 
451*84e872a0SLloyd Pique 	old_source_idx = source->heap_idx;
452*84e872a0SLloyd Pique 	source->heap_idx = -1;
453*84e872a0SLloyd Pique 	source->deadline.tv_sec = 0;
454*84e872a0SLloyd Pique 	source->deadline.tv_nsec = 0;
455*84e872a0SLloyd Pique 
456*84e872a0SLloyd Pique 	last_end_evt = timers->data[timers->active - 1];
457*84e872a0SLloyd Pique 	timers->data[timers->active - 1] = NULL;
458*84e872a0SLloyd Pique 	timers->active--;
459*84e872a0SLloyd Pique 
460*84e872a0SLloyd Pique 	if (old_source_idx == timers->active)
461*84e872a0SLloyd Pique 		return;
462*84e872a0SLloyd Pique 
463*84e872a0SLloyd Pique 	timers->data[old_source_idx] = last_end_evt;
464*84e872a0SLloyd Pique 	last_end_evt->heap_idx = old_source_idx;
465*84e872a0SLloyd Pique 
466*84e872a0SLloyd Pique 	/* Move the displaced (active) element to its proper place.
467*84e872a0SLloyd Pique 	 * Only one of sift-down and sift-up will have any effect */
468*84e872a0SLloyd Pique 	heap_sift_down(timers->data, timers->active, last_end_evt);
469*84e872a0SLloyd Pique 	heap_sift_up(timers->data, last_end_evt);
470*84e872a0SLloyd Pique }
471*84e872a0SLloyd Pique 
472*84e872a0SLloyd Pique /* requires timer be disarmed */
473*84e872a0SLloyd Pique static void
wl_timer_heap_arm(struct wl_timer_heap * timers,struct wl_event_source_timer * source,struct timespec deadline)474*84e872a0SLloyd Pique wl_timer_heap_arm(struct wl_timer_heap *timers,
475*84e872a0SLloyd Pique 		  struct wl_event_source_timer *source,
476*84e872a0SLloyd Pique 		  struct timespec deadline)
477*84e872a0SLloyd Pique {
478*84e872a0SLloyd Pique 	assert(source->heap_idx == -1);
479*84e872a0SLloyd Pique 
480*84e872a0SLloyd Pique 	source->deadline = deadline;
481*84e872a0SLloyd Pique 	timers->data[timers->active] = source;
482*84e872a0SLloyd Pique 	source->heap_idx = timers->active;
483*84e872a0SLloyd Pique 	timers->active++;
484*84e872a0SLloyd Pique 	heap_sift_up(timers->data, source);
485*84e872a0SLloyd Pique }
486*84e872a0SLloyd Pique 
487*84e872a0SLloyd Pique 
488*84e872a0SLloyd Pique static int
wl_timer_heap_dispatch(struct wl_timer_heap * timers)489*84e872a0SLloyd Pique wl_timer_heap_dispatch(struct wl_timer_heap *timers)
490*84e872a0SLloyd Pique {
491*84e872a0SLloyd Pique 	struct timespec now;
492*84e872a0SLloyd Pique 	struct wl_event_source_timer *root;
493*84e872a0SLloyd Pique 	struct wl_event_source_timer *list_cursor = NULL, *list_tail = NULL;
494*84e872a0SLloyd Pique 
495*84e872a0SLloyd Pique 	clock_gettime(CLOCK_MONOTONIC, &now);
496*84e872a0SLloyd Pique 
497*84e872a0SLloyd Pique 	while (timers->active > 0) {
498*84e872a0SLloyd Pique 		root = timers->data[0];
499*84e872a0SLloyd Pique 		if (time_lt(now, root->deadline))
500*84e872a0SLloyd Pique 			break;
501*84e872a0SLloyd Pique 
502*84e872a0SLloyd Pique 		wl_timer_heap_disarm(timers, root);
503*84e872a0SLloyd Pique 
504*84e872a0SLloyd Pique 		if (list_cursor == NULL)
505*84e872a0SLloyd Pique 			list_cursor = root;
506*84e872a0SLloyd Pique 		else
507*84e872a0SLloyd Pique 			list_tail->next_due = root;
508*84e872a0SLloyd Pique 		list_tail = root;
509*84e872a0SLloyd Pique 	}
510*84e872a0SLloyd Pique 	if (list_tail)
511*84e872a0SLloyd Pique 		list_tail->next_due = NULL;
512*84e872a0SLloyd Pique 
513*84e872a0SLloyd Pique 	if (timers->active > 0) {
514*84e872a0SLloyd Pique 		if (set_timer(timers->base.fd, timers->data[0]->deadline) < 0)
515*84e872a0SLloyd Pique 			return -1;
516*84e872a0SLloyd Pique 	} else {
517*84e872a0SLloyd Pique 		if (clear_timer(timers->base.fd) < 0)
518*84e872a0SLloyd Pique 			return -1;
519*84e872a0SLloyd Pique 	}
520*84e872a0SLloyd Pique 
521*84e872a0SLloyd Pique 	/* Execute precisely the functions for events before `now`, in order.
522*84e872a0SLloyd Pique 	 * Because wl_event_loop_dispatch ignores return codes, do the same
523*84e872a0SLloyd Pique 	 * here as well */
524*84e872a0SLloyd Pique 	for (; list_cursor; list_cursor = list_cursor->next_due) {
525*84e872a0SLloyd Pique 		if (list_cursor->base.fd != TIMER_REMOVED)
526*84e872a0SLloyd Pique 			list_cursor->func(list_cursor->base.data);
527*84e872a0SLloyd Pique 	}
528*84e872a0SLloyd Pique 
529*84e872a0SLloyd Pique 	return 0;
530*84e872a0SLloyd Pique }
531*84e872a0SLloyd Pique 
532*84e872a0SLloyd Pique static int
wl_event_source_timer_dispatch(struct wl_event_source * source,struct epoll_event * ep)533*84e872a0SLloyd Pique wl_event_source_timer_dispatch(struct wl_event_source *source,
534*84e872a0SLloyd Pique 			       struct epoll_event *ep)
535*84e872a0SLloyd Pique {
536*84e872a0SLloyd Pique 	struct wl_event_source_timer *timer;
537*84e872a0SLloyd Pique 
538*84e872a0SLloyd Pique 	timer = wl_container_of(source, timer, base);
539*84e872a0SLloyd Pique 	return timer->func(timer->base.data);
540*84e872a0SLloyd Pique }
541*84e872a0SLloyd Pique 
542*84e872a0SLloyd Pique struct wl_event_source_interface timer_source_interface = {
543*84e872a0SLloyd Pique 	wl_event_source_timer_dispatch,
544*84e872a0SLloyd Pique };
545*84e872a0SLloyd Pique 
546*84e872a0SLloyd Pique /** \endcond */
547*84e872a0SLloyd Pique 
548*84e872a0SLloyd Pique /** Create a timer event source
549*84e872a0SLloyd Pique  *
550*84e872a0SLloyd Pique  * \param loop The event loop that will process the new source.
551*84e872a0SLloyd Pique  * \param func The timer dispatch function.
552*84e872a0SLloyd Pique  * \param data User data.
553*84e872a0SLloyd Pique  * \return A new timer event source.
554*84e872a0SLloyd Pique  *
555*84e872a0SLloyd Pique  * The timer is initially disarmed. It needs to be armed with a call to
556*84e872a0SLloyd Pique  * wl_event_source_timer_update() before it can trigger a dispatch call.
557*84e872a0SLloyd Pique  *
558*84e872a0SLloyd Pique  * \sa wl_event_loop_timer_func_t
559*84e872a0SLloyd Pique  * \memberof wl_event_source
560*84e872a0SLloyd Pique  */
561*84e872a0SLloyd Pique WL_EXPORT struct wl_event_source *
wl_event_loop_add_timer(struct wl_event_loop * loop,wl_event_loop_timer_func_t func,void * data)562*84e872a0SLloyd Pique wl_event_loop_add_timer(struct wl_event_loop *loop,
563*84e872a0SLloyd Pique 			wl_event_loop_timer_func_t func,
564*84e872a0SLloyd Pique 			void *data)
565*84e872a0SLloyd Pique {
566*84e872a0SLloyd Pique 	struct wl_event_source_timer *source;
567*84e872a0SLloyd Pique 
568*84e872a0SLloyd Pique 	if (wl_timer_heap_ensure_timerfd(&loop->timers) < 0)
569*84e872a0SLloyd Pique 		return NULL;
570*84e872a0SLloyd Pique 
571*84e872a0SLloyd Pique 	source = zalloc(sizeof *source);
572*84e872a0SLloyd Pique 	if (source == NULL)
573*84e872a0SLloyd Pique 		return NULL;
574*84e872a0SLloyd Pique 
575*84e872a0SLloyd Pique 	source->base.interface = &timer_source_interface;
576*84e872a0SLloyd Pique 	source->base.fd = -1;
577*84e872a0SLloyd Pique 	source->func = func;
578*84e872a0SLloyd Pique 	source->base.loop = loop;
579*84e872a0SLloyd Pique 	source->base.data = data;
580*84e872a0SLloyd Pique 	wl_list_init(&source->base.link);
581*84e872a0SLloyd Pique 	source->next_due = NULL;
582*84e872a0SLloyd Pique 	source->deadline.tv_sec = 0;
583*84e872a0SLloyd Pique 	source->deadline.tv_nsec = 0;
584*84e872a0SLloyd Pique 	source->heap_idx = -1;
585*84e872a0SLloyd Pique 
586*84e872a0SLloyd Pique 	if (wl_timer_heap_reserve(&loop->timers) < 0) {
587*84e872a0SLloyd Pique 		free(source);
588*84e872a0SLloyd Pique 		return NULL;
589*84e872a0SLloyd Pique 	}
590*84e872a0SLloyd Pique 
591*84e872a0SLloyd Pique 	return &source->base;
592*84e872a0SLloyd Pique }
593*84e872a0SLloyd Pique 
594*84e872a0SLloyd Pique /** Arm or disarm a timer
595*84e872a0SLloyd Pique  *
596*84e872a0SLloyd Pique  * \param source The timer event source to modify.
597*84e872a0SLloyd Pique  * \param ms_delay The timeout in milliseconds.
598*84e872a0SLloyd Pique  * \return 0 on success, -1 on failure.
599*84e872a0SLloyd Pique  *
600*84e872a0SLloyd Pique  * If the timeout is zero, the timer is disarmed.
601*84e872a0SLloyd Pique  *
602*84e872a0SLloyd Pique  * If the timeout is non-zero, the timer is set to expire after the given
603*84e872a0SLloyd Pique  * timeout in milliseconds. When the timer expires, the dispatch function
604*84e872a0SLloyd Pique  * set with wl_event_loop_add_timer() is called once from
605*84e872a0SLloyd Pique  * wl_event_loop_dispatch(). If another dispatch is desired after another
606*84e872a0SLloyd Pique  * expiry, wl_event_source_timer_update() needs to be called again.
607*84e872a0SLloyd Pique  *
608*84e872a0SLloyd Pique  * \memberof wl_event_source
609*84e872a0SLloyd Pique  */
610*84e872a0SLloyd Pique WL_EXPORT int
wl_event_source_timer_update(struct wl_event_source * source,int ms_delay)611*84e872a0SLloyd Pique wl_event_source_timer_update(struct wl_event_source *source, int ms_delay)
612*84e872a0SLloyd Pique {
613*84e872a0SLloyd Pique 	struct wl_event_source_timer *tsource =
614*84e872a0SLloyd Pique 		wl_container_of(source, tsource, base);
615*84e872a0SLloyd Pique 	struct wl_timer_heap *timers = &tsource->base.loop->timers;
616*84e872a0SLloyd Pique 
617*84e872a0SLloyd Pique 	if (ms_delay > 0) {
618*84e872a0SLloyd Pique 		struct timespec deadline;
619*84e872a0SLloyd Pique 
620*84e872a0SLloyd Pique 		clock_gettime(CLOCK_MONOTONIC, &deadline);
621*84e872a0SLloyd Pique 
622*84e872a0SLloyd Pique 		deadline.tv_nsec += (ms_delay % 1000) * 1000000L;
623*84e872a0SLloyd Pique 		deadline.tv_sec += ms_delay / 1000;
624*84e872a0SLloyd Pique 		if (deadline.tv_nsec >= 1000000000L) {
625*84e872a0SLloyd Pique 			deadline.tv_nsec -= 1000000000L;
626*84e872a0SLloyd Pique 			deadline.tv_sec += 1;
627*84e872a0SLloyd Pique 		}
628*84e872a0SLloyd Pique 
629*84e872a0SLloyd Pique 		if (tsource->heap_idx == -1) {
630*84e872a0SLloyd Pique 			wl_timer_heap_arm(timers, tsource, deadline);
631*84e872a0SLloyd Pique 		} else if (time_lt(deadline, tsource->deadline)) {
632*84e872a0SLloyd Pique 			tsource->deadline = deadline;
633*84e872a0SLloyd Pique 			heap_sift_up(timers->data, tsource);
634*84e872a0SLloyd Pique 		} else {
635*84e872a0SLloyd Pique 			tsource->deadline = deadline;
636*84e872a0SLloyd Pique 			heap_sift_down(timers->data, timers->active, tsource);
637*84e872a0SLloyd Pique 		}
638*84e872a0SLloyd Pique 
639*84e872a0SLloyd Pique 		if (tsource->heap_idx == 0) {
640*84e872a0SLloyd Pique 			/* Only update the timerfd if the new deadline is
641*84e872a0SLloyd Pique 			 * the earliest */
642*84e872a0SLloyd Pique 			if (set_timer(timers->base.fd, deadline) < 0)
643*84e872a0SLloyd Pique 				return -1;
644*84e872a0SLloyd Pique 		}
645*84e872a0SLloyd Pique 	} else {
646*84e872a0SLloyd Pique 		if (tsource->heap_idx == -1)
647*84e872a0SLloyd Pique 			return 0;
648*84e872a0SLloyd Pique 		wl_timer_heap_disarm(timers, tsource);
649*84e872a0SLloyd Pique 
650*84e872a0SLloyd Pique 		if (timers->active == 0) {
651*84e872a0SLloyd Pique 			/* Only update the timerfd if this was the last
652*84e872a0SLloyd Pique 			 * active timer */
653*84e872a0SLloyd Pique 			if (clear_timer(timers->base.fd) < 0)
654*84e872a0SLloyd Pique 				return -1;
655*84e872a0SLloyd Pique 		}
656*84e872a0SLloyd Pique 	}
657*84e872a0SLloyd Pique 
658*84e872a0SLloyd Pique 	return 0;
659*84e872a0SLloyd Pique }
660*84e872a0SLloyd Pique 
661*84e872a0SLloyd Pique /** \cond INTERNAL */
662*84e872a0SLloyd Pique 
663*84e872a0SLloyd Pique struct wl_event_source_signal {
664*84e872a0SLloyd Pique 	struct wl_event_source base;
665*84e872a0SLloyd Pique 	int signal_number;
666*84e872a0SLloyd Pique 	wl_event_loop_signal_func_t func;
667*84e872a0SLloyd Pique };
668*84e872a0SLloyd Pique 
669*84e872a0SLloyd Pique /** \endcond */
670*84e872a0SLloyd Pique 
671*84e872a0SLloyd Pique static int
wl_event_source_signal_dispatch(struct wl_event_source * source,struct epoll_event * ep)672*84e872a0SLloyd Pique wl_event_source_signal_dispatch(struct wl_event_source *source,
673*84e872a0SLloyd Pique 				struct epoll_event *ep)
674*84e872a0SLloyd Pique {
675*84e872a0SLloyd Pique 	struct wl_event_source_signal *signal_source =
676*84e872a0SLloyd Pique 		(struct wl_event_source_signal *) source;
677*84e872a0SLloyd Pique 	struct signalfd_siginfo signal_info;
678*84e872a0SLloyd Pique 	int len;
679*84e872a0SLloyd Pique 
680*84e872a0SLloyd Pique 	len = read(source->fd, &signal_info, sizeof signal_info);
681*84e872a0SLloyd Pique 	if (!(len == -1 && errno == EAGAIN) && len != sizeof signal_info)
682*84e872a0SLloyd Pique 		/* Is there anything we can do here?  Will this ever happen? */
683*84e872a0SLloyd Pique 		wl_log("signalfd read error: %s\n", strerror(errno));
684*84e872a0SLloyd Pique 
685*84e872a0SLloyd Pique 	return signal_source->func(signal_source->signal_number,
686*84e872a0SLloyd Pique 				   signal_source->base.data);
687*84e872a0SLloyd Pique }
688*84e872a0SLloyd Pique 
689*84e872a0SLloyd Pique struct wl_event_source_interface signal_source_interface = {
690*84e872a0SLloyd Pique 	wl_event_source_signal_dispatch,
691*84e872a0SLloyd Pique };
692*84e872a0SLloyd Pique 
693*84e872a0SLloyd Pique /** Create a POSIX signal event source
694*84e872a0SLloyd Pique  *
695*84e872a0SLloyd Pique  * \param loop The event loop that will process the new source.
696*84e872a0SLloyd Pique  * \param signal_number Number of the signal to watch for.
697*84e872a0SLloyd Pique  * \param func The signal dispatch function.
698*84e872a0SLloyd Pique  * \param data User data.
699*84e872a0SLloyd Pique  * \return A new signal event source.
700*84e872a0SLloyd Pique  *
701*84e872a0SLloyd Pique  * This function blocks the normal delivery of the given signal in the calling
702*84e872a0SLloyd Pique  * thread, and creates a "watch" for it. Signal delivery no longer happens
703*84e872a0SLloyd Pique  * asynchronously, but by wl_event_loop_dispatch() calling the dispatch
704*84e872a0SLloyd Pique  * callback function \c func.
705*84e872a0SLloyd Pique  *
706*84e872a0SLloyd Pique  * It is the caller's responsibility to ensure that all other threads have
707*84e872a0SLloyd Pique  * also blocked the signal.
708*84e872a0SLloyd Pique  *
709*84e872a0SLloyd Pique  * \sa wl_event_loop_signal_func_t
710*84e872a0SLloyd Pique  * \memberof wl_event_source
711*84e872a0SLloyd Pique  */
712*84e872a0SLloyd Pique WL_EXPORT struct wl_event_source *
wl_event_loop_add_signal(struct wl_event_loop * loop,int signal_number,wl_event_loop_signal_func_t func,void * data)713*84e872a0SLloyd Pique wl_event_loop_add_signal(struct wl_event_loop *loop,
714*84e872a0SLloyd Pique 			 int signal_number,
715*84e872a0SLloyd Pique 			 wl_event_loop_signal_func_t func,
716*84e872a0SLloyd Pique 			 void *data)
717*84e872a0SLloyd Pique {
718*84e872a0SLloyd Pique 	struct wl_event_source_signal *source;
719*84e872a0SLloyd Pique 	sigset_t mask;
720*84e872a0SLloyd Pique 
721*84e872a0SLloyd Pique 	source = zalloc(sizeof *source);
722*84e872a0SLloyd Pique 	if (source == NULL)
723*84e872a0SLloyd Pique 		return NULL;
724*84e872a0SLloyd Pique 
725*84e872a0SLloyd Pique 	source->base.interface = &signal_source_interface;
726*84e872a0SLloyd Pique 	source->signal_number = signal_number;
727*84e872a0SLloyd Pique 
728*84e872a0SLloyd Pique 	sigemptyset(&mask);
729*84e872a0SLloyd Pique 	sigaddset(&mask, signal_number);
730*84e872a0SLloyd Pique 	source->base.fd = signalfd(-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK);
731*84e872a0SLloyd Pique 	sigprocmask(SIG_BLOCK, &mask, NULL);
732*84e872a0SLloyd Pique 
733*84e872a0SLloyd Pique 	source->func = func;
734*84e872a0SLloyd Pique 
735*84e872a0SLloyd Pique 	return add_source(loop, &source->base, WL_EVENT_READABLE, data);
736*84e872a0SLloyd Pique }
737*84e872a0SLloyd Pique 
738*84e872a0SLloyd Pique /** \cond INTERNAL */
739*84e872a0SLloyd Pique 
740*84e872a0SLloyd Pique struct wl_event_source_idle {
741*84e872a0SLloyd Pique 	struct wl_event_source base;
742*84e872a0SLloyd Pique 	wl_event_loop_idle_func_t func;
743*84e872a0SLloyd Pique };
744*84e872a0SLloyd Pique 
745*84e872a0SLloyd Pique /** \endcond */
746*84e872a0SLloyd Pique 
747*84e872a0SLloyd Pique struct wl_event_source_interface idle_source_interface = {
748*84e872a0SLloyd Pique 	NULL,
749*84e872a0SLloyd Pique };
750*84e872a0SLloyd Pique 
751*84e872a0SLloyd Pique /** Create an idle task
752*84e872a0SLloyd Pique  *
753*84e872a0SLloyd Pique  * \param loop The event loop that will process the new task.
754*84e872a0SLloyd Pique  * \param func The idle task dispatch function.
755*84e872a0SLloyd Pique  * \param data User data.
756*84e872a0SLloyd Pique  * \return A new idle task (an event source).
757*84e872a0SLloyd Pique  *
758*84e872a0SLloyd Pique  * Idle tasks are dispatched before wl_event_loop_dispatch() goes to sleep.
759*84e872a0SLloyd Pique  * See wl_event_loop_dispatch() for more details.
760*84e872a0SLloyd Pique  *
761*84e872a0SLloyd Pique  * Idle tasks fire once, and are automatically destroyed right after the
762*84e872a0SLloyd Pique  * callback function has been called.
763*84e872a0SLloyd Pique  *
764*84e872a0SLloyd Pique  * An idle task can be cancelled before the callback has been called by
765*84e872a0SLloyd Pique  * wl_event_source_remove(). Calling wl_event_source_remove() after or from
766*84e872a0SLloyd Pique  * within the callback results in undefined behaviour.
767*84e872a0SLloyd Pique  *
768*84e872a0SLloyd Pique  * \sa wl_event_loop_idle_func_t
769*84e872a0SLloyd Pique  * \memberof wl_event_source
770*84e872a0SLloyd Pique  */
771*84e872a0SLloyd Pique WL_EXPORT struct wl_event_source *
wl_event_loop_add_idle(struct wl_event_loop * loop,wl_event_loop_idle_func_t func,void * data)772*84e872a0SLloyd Pique wl_event_loop_add_idle(struct wl_event_loop *loop,
773*84e872a0SLloyd Pique 		       wl_event_loop_idle_func_t func,
774*84e872a0SLloyd Pique 		       void *data)
775*84e872a0SLloyd Pique {
776*84e872a0SLloyd Pique 	struct wl_event_source_idle *source;
777*84e872a0SLloyd Pique 
778*84e872a0SLloyd Pique 	source = zalloc(sizeof *source);
779*84e872a0SLloyd Pique 	if (source == NULL)
780*84e872a0SLloyd Pique 		return NULL;
781*84e872a0SLloyd Pique 
782*84e872a0SLloyd Pique 	source->base.interface = &idle_source_interface;
783*84e872a0SLloyd Pique 	source->base.loop = loop;
784*84e872a0SLloyd Pique 	source->base.fd = -1;
785*84e872a0SLloyd Pique 
786*84e872a0SLloyd Pique 	source->func = func;
787*84e872a0SLloyd Pique 	source->base.data = data;
788*84e872a0SLloyd Pique 
789*84e872a0SLloyd Pique 	wl_list_insert(loop->idle_list.prev, &source->base.link);
790*84e872a0SLloyd Pique 
791*84e872a0SLloyd Pique 	return &source->base;
792*84e872a0SLloyd Pique }
793*84e872a0SLloyd Pique 
794*84e872a0SLloyd Pique /** Mark event source to be re-checked
795*84e872a0SLloyd Pique  *
796*84e872a0SLloyd Pique  * \param source The event source to be re-checked.
797*84e872a0SLloyd Pique  *
798*84e872a0SLloyd Pique  * This function permanently marks the event source to be re-checked after
799*84e872a0SLloyd Pique  * the normal dispatch of sources in wl_event_loop_dispatch(). Re-checking
800*84e872a0SLloyd Pique  * will keep iterating over all such event sources until the dispatch
801*84e872a0SLloyd Pique  * function for them all returns zero.
802*84e872a0SLloyd Pique  *
803*84e872a0SLloyd Pique  * Re-checking is used on sources that may become ready to dispatch as a
804*84e872a0SLloyd Pique  * side-effect of dispatching themselves or other event sources, including idle
805*84e872a0SLloyd Pique  * sources. Re-checking ensures all the incoming events have been fully drained
806*84e872a0SLloyd Pique  * before wl_event_loop_dispatch() returns.
807*84e872a0SLloyd Pique  *
808*84e872a0SLloyd Pique  * \memberof wl_event_source
809*84e872a0SLloyd Pique  */
810*84e872a0SLloyd Pique WL_EXPORT void
wl_event_source_check(struct wl_event_source * source)811*84e872a0SLloyd Pique wl_event_source_check(struct wl_event_source *source)
812*84e872a0SLloyd Pique {
813*84e872a0SLloyd Pique 	wl_list_insert(source->loop->check_list.prev, &source->link);
814*84e872a0SLloyd Pique }
815*84e872a0SLloyd Pique 
816*84e872a0SLloyd Pique /** Remove an event source from its event loop
817*84e872a0SLloyd Pique  *
818*84e872a0SLloyd Pique  * \param source The event source to be removed.
819*84e872a0SLloyd Pique  * \return Zero.
820*84e872a0SLloyd Pique  *
821*84e872a0SLloyd Pique  * The event source is removed from the event loop it was created for,
822*84e872a0SLloyd Pique  * and is effectively destroyed. This invalidates \c source .
823*84e872a0SLloyd Pique  * The dispatch function of the source will no longer be called through this
824*84e872a0SLloyd Pique  * source.
825*84e872a0SLloyd Pique  *
826*84e872a0SLloyd Pique  * \memberof wl_event_source
827*84e872a0SLloyd Pique  */
828*84e872a0SLloyd Pique WL_EXPORT int
wl_event_source_remove(struct wl_event_source * source)829*84e872a0SLloyd Pique wl_event_source_remove(struct wl_event_source *source)
830*84e872a0SLloyd Pique {
831*84e872a0SLloyd Pique 	struct wl_event_loop *loop = source->loop;
832*84e872a0SLloyd Pique 
833*84e872a0SLloyd Pique 	/* We need to explicitly remove the fd, since closing the fd
834*84e872a0SLloyd Pique 	 * isn't enough in case we've dup'ed the fd. */
835*84e872a0SLloyd Pique 	if (source->fd >= 0) {
836*84e872a0SLloyd Pique 		epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, source->fd, NULL);
837*84e872a0SLloyd Pique 		close(source->fd);
838*84e872a0SLloyd Pique 		source->fd = -1;
839*84e872a0SLloyd Pique 	}
840*84e872a0SLloyd Pique 
841*84e872a0SLloyd Pique 	if (source->interface == &timer_source_interface &&
842*84e872a0SLloyd Pique 	    source->fd != TIMER_REMOVED) {
843*84e872a0SLloyd Pique 		/* Disarm the timer (and the loop's timerfd, if necessary),
844*84e872a0SLloyd Pique 		 * before removing its space in the loop timer heap */
845*84e872a0SLloyd Pique 		wl_event_source_timer_update(source, 0);
846*84e872a0SLloyd Pique 		wl_timer_heap_unreserve(&loop->timers);
847*84e872a0SLloyd Pique 		/* Set the fd field to to indicate that the timer should NOT
848*84e872a0SLloyd Pique 		 * be dispatched in `wl_event_loop_dispatch` */
849*84e872a0SLloyd Pique 		source->fd = TIMER_REMOVED;
850*84e872a0SLloyd Pique 	}
851*84e872a0SLloyd Pique 
852*84e872a0SLloyd Pique 	wl_list_remove(&source->link);
853*84e872a0SLloyd Pique 	wl_list_insert(&loop->destroy_list, &source->link);
854*84e872a0SLloyd Pique 
855*84e872a0SLloyd Pique 	return 0;
856*84e872a0SLloyd Pique }
857*84e872a0SLloyd Pique 
858*84e872a0SLloyd Pique static void
wl_event_loop_process_destroy_list(struct wl_event_loop * loop)859*84e872a0SLloyd Pique wl_event_loop_process_destroy_list(struct wl_event_loop *loop)
860*84e872a0SLloyd Pique {
861*84e872a0SLloyd Pique 	struct wl_event_source *source, *next;
862*84e872a0SLloyd Pique 
863*84e872a0SLloyd Pique 	wl_list_for_each_safe(source, next, &loop->destroy_list, link)
864*84e872a0SLloyd Pique 		free(source);
865*84e872a0SLloyd Pique 
866*84e872a0SLloyd Pique 	wl_list_init(&loop->destroy_list);
867*84e872a0SLloyd Pique }
868*84e872a0SLloyd Pique 
869*84e872a0SLloyd Pique /** Create a new event loop context
870*84e872a0SLloyd Pique  *
871*84e872a0SLloyd Pique  * \return A new event loop context object.
872*84e872a0SLloyd Pique  *
873*84e872a0SLloyd Pique  * This creates a new event loop context. Initially this context is empty.
874*84e872a0SLloyd Pique  * Event sources need to be explicitly added to it.
875*84e872a0SLloyd Pique  *
876*84e872a0SLloyd Pique  * Normally the event loop is run by calling wl_event_loop_dispatch() in
877*84e872a0SLloyd Pique  * a loop until the program terminates. Alternatively, an event loop can be
878*84e872a0SLloyd Pique  * embedded in another event loop by its file descriptor, see
879*84e872a0SLloyd Pique  * wl_event_loop_get_fd().
880*84e872a0SLloyd Pique  *
881*84e872a0SLloyd Pique  * \memberof wl_event_loop
882*84e872a0SLloyd Pique  */
883*84e872a0SLloyd Pique WL_EXPORT struct wl_event_loop *
wl_event_loop_create(void)884*84e872a0SLloyd Pique wl_event_loop_create(void)
885*84e872a0SLloyd Pique {
886*84e872a0SLloyd Pique 	struct wl_event_loop *loop;
887*84e872a0SLloyd Pique 
888*84e872a0SLloyd Pique 	loop = zalloc(sizeof *loop);
889*84e872a0SLloyd Pique 	if (loop == NULL)
890*84e872a0SLloyd Pique 		return NULL;
891*84e872a0SLloyd Pique 
892*84e872a0SLloyd Pique 	loop->epoll_fd = wl_os_epoll_create_cloexec();
893*84e872a0SLloyd Pique 	if (loop->epoll_fd < 0) {
894*84e872a0SLloyd Pique 		free(loop);
895*84e872a0SLloyd Pique 		return NULL;
896*84e872a0SLloyd Pique 	}
897*84e872a0SLloyd Pique 	wl_list_init(&loop->check_list);
898*84e872a0SLloyd Pique 	wl_list_init(&loop->idle_list);
899*84e872a0SLloyd Pique 	wl_list_init(&loop->destroy_list);
900*84e872a0SLloyd Pique 
901*84e872a0SLloyd Pique 	wl_signal_init(&loop->destroy_signal);
902*84e872a0SLloyd Pique 
903*84e872a0SLloyd Pique 	wl_timer_heap_init(&loop->timers, loop);
904*84e872a0SLloyd Pique 
905*84e872a0SLloyd Pique 	return loop;
906*84e872a0SLloyd Pique }
907*84e872a0SLloyd Pique 
908*84e872a0SLloyd Pique /** Destroy an event loop context
909*84e872a0SLloyd Pique  *
910*84e872a0SLloyd Pique  * \param loop The event loop to be destroyed.
911*84e872a0SLloyd Pique  *
912*84e872a0SLloyd Pique  * This emits the event loop destroy signal, closes the event loop file
913*84e872a0SLloyd Pique  * descriptor, and frees \c loop.
914*84e872a0SLloyd Pique  *
915*84e872a0SLloyd Pique  * If the event loop has existing sources, those cannot be safely removed
916*84e872a0SLloyd Pique  * afterwards. Therefore one must call wl_event_source_remove() on all
917*84e872a0SLloyd Pique  * event sources before destroying the event loop context.
918*84e872a0SLloyd Pique  *
919*84e872a0SLloyd Pique  * \memberof wl_event_loop
920*84e872a0SLloyd Pique  */
921*84e872a0SLloyd Pique WL_EXPORT void
wl_event_loop_destroy(struct wl_event_loop * loop)922*84e872a0SLloyd Pique wl_event_loop_destroy(struct wl_event_loop *loop)
923*84e872a0SLloyd Pique {
924*84e872a0SLloyd Pique 	wl_signal_emit(&loop->destroy_signal, loop);
925*84e872a0SLloyd Pique 
926*84e872a0SLloyd Pique 	wl_event_loop_process_destroy_list(loop);
927*84e872a0SLloyd Pique 	wl_timer_heap_release(&loop->timers);
928*84e872a0SLloyd Pique 	close(loop->epoll_fd);
929*84e872a0SLloyd Pique 	free(loop);
930*84e872a0SLloyd Pique }
931*84e872a0SLloyd Pique 
932*84e872a0SLloyd Pique static bool
post_dispatch_check(struct wl_event_loop * loop)933*84e872a0SLloyd Pique post_dispatch_check(struct wl_event_loop *loop)
934*84e872a0SLloyd Pique {
935*84e872a0SLloyd Pique 	struct epoll_event ep;
936*84e872a0SLloyd Pique 	struct wl_event_source *source, *next;
937*84e872a0SLloyd Pique 	bool needs_recheck = false;
938*84e872a0SLloyd Pique 
939*84e872a0SLloyd Pique 	ep.events = 0;
940*84e872a0SLloyd Pique 	wl_list_for_each_safe(source, next, &loop->check_list, link) {
941*84e872a0SLloyd Pique 		int dispatch_result;
942*84e872a0SLloyd Pique 
943*84e872a0SLloyd Pique 		dispatch_result = source->interface->dispatch(source, &ep);
944*84e872a0SLloyd Pique 		if (dispatch_result < 0) {
945*84e872a0SLloyd Pique 			wl_log("Source dispatch function returned negative value!\n");
946*84e872a0SLloyd Pique 			wl_log("This would previously accidentally suppress a follow-up dispatch\n");
947*84e872a0SLloyd Pique 		}
948*84e872a0SLloyd Pique 		needs_recheck |= dispatch_result != 0;
949*84e872a0SLloyd Pique 	}
950*84e872a0SLloyd Pique 
951*84e872a0SLloyd Pique 	return needs_recheck;
952*84e872a0SLloyd Pique }
953*84e872a0SLloyd Pique 
954*84e872a0SLloyd Pique /** Dispatch the idle sources
955*84e872a0SLloyd Pique  *
956*84e872a0SLloyd Pique  * \param loop The event loop whose idle sources are dispatched.
957*84e872a0SLloyd Pique  *
958*84e872a0SLloyd Pique  * \sa wl_event_loop_add_idle()
959*84e872a0SLloyd Pique  * \memberof wl_event_loop
960*84e872a0SLloyd Pique  */
961*84e872a0SLloyd Pique WL_EXPORT void
wl_event_loop_dispatch_idle(struct wl_event_loop * loop)962*84e872a0SLloyd Pique wl_event_loop_dispatch_idle(struct wl_event_loop *loop)
963*84e872a0SLloyd Pique {
964*84e872a0SLloyd Pique 	struct wl_event_source_idle *source;
965*84e872a0SLloyd Pique 
966*84e872a0SLloyd Pique 	while (!wl_list_empty(&loop->idle_list)) {
967*84e872a0SLloyd Pique 		source = wl_container_of(loop->idle_list.next,
968*84e872a0SLloyd Pique 					 source, base.link);
969*84e872a0SLloyd Pique 		source->func(source->base.data);
970*84e872a0SLloyd Pique 		wl_event_source_remove(&source->base);
971*84e872a0SLloyd Pique 	}
972*84e872a0SLloyd Pique }
973*84e872a0SLloyd Pique 
974*84e872a0SLloyd Pique /** Wait for events and dispatch them
975*84e872a0SLloyd Pique  *
976*84e872a0SLloyd Pique  * \param loop The event loop whose sources to wait for.
977*84e872a0SLloyd Pique  * \param timeout The polling timeout in milliseconds.
978*84e872a0SLloyd Pique  * \return 0 for success, -1 for polling (or timer update) error.
979*84e872a0SLloyd Pique  *
980*84e872a0SLloyd Pique  * All the associated event sources are polled. This function blocks until
981*84e872a0SLloyd Pique  * any event source delivers an event (idle sources excluded), or the timeout
982*84e872a0SLloyd Pique  * expires. A timeout of -1 disables the timeout, causing the function to block
983*84e872a0SLloyd Pique  * indefinitely. A timeout of zero causes the poll to always return immediately.
984*84e872a0SLloyd Pique  *
985*84e872a0SLloyd Pique  * All idle sources are dispatched before blocking. An idle source is destroyed
986*84e872a0SLloyd Pique  * when it is dispatched. After blocking, all other ready sources are
987*84e872a0SLloyd Pique  * dispatched. Then, idle sources are dispatched again, in case the dispatched
988*84e872a0SLloyd Pique  * events created idle sources. Finally, all sources marked with
989*84e872a0SLloyd Pique  * wl_event_source_check() are dispatched in a loop until their dispatch
990*84e872a0SLloyd Pique  * functions all return zero.
991*84e872a0SLloyd Pique  *
992*84e872a0SLloyd Pique  * \memberof wl_event_loop
993*84e872a0SLloyd Pique  */
994*84e872a0SLloyd Pique WL_EXPORT int
wl_event_loop_dispatch(struct wl_event_loop * loop,int timeout)995*84e872a0SLloyd Pique wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout)
996*84e872a0SLloyd Pique {
997*84e872a0SLloyd Pique 	struct epoll_event ep[32];
998*84e872a0SLloyd Pique 	struct wl_event_source *source;
999*84e872a0SLloyd Pique 	int i, count;
1000*84e872a0SLloyd Pique 	bool has_timers = false;
1001*84e872a0SLloyd Pique 
1002*84e872a0SLloyd Pique 	wl_event_loop_dispatch_idle(loop);
1003*84e872a0SLloyd Pique 
1004*84e872a0SLloyd Pique 	count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
1005*84e872a0SLloyd Pique 	if (count < 0)
1006*84e872a0SLloyd Pique 		return -1;
1007*84e872a0SLloyd Pique 
1008*84e872a0SLloyd Pique 	for (i = 0; i < count; i++) {
1009*84e872a0SLloyd Pique 		source = ep[i].data.ptr;
1010*84e872a0SLloyd Pique 		if (source == &loop->timers.base)
1011*84e872a0SLloyd Pique 			has_timers = true;
1012*84e872a0SLloyd Pique 	}
1013*84e872a0SLloyd Pique 
1014*84e872a0SLloyd Pique 	if (has_timers) {
1015*84e872a0SLloyd Pique 		/* Dispatch timer sources before non-timer sources, so that
1016*84e872a0SLloyd Pique 		 * the non-timer sources can not cancel (by calling
1017*84e872a0SLloyd Pique 		 * `wl_event_source_timer_update`) the dispatching of the timers
1018*84e872a0SLloyd Pique 		 * (Note that timer sources also can't cancel pending non-timer
1019*84e872a0SLloyd Pique 		 * sources, since epoll_wait has already been called) */
1020*84e872a0SLloyd Pique 		if (wl_timer_heap_dispatch(&loop->timers) < 0)
1021*84e872a0SLloyd Pique 			return -1;
1022*84e872a0SLloyd Pique 	}
1023*84e872a0SLloyd Pique 
1024*84e872a0SLloyd Pique 	for (i = 0; i < count; i++) {
1025*84e872a0SLloyd Pique 		source = ep[i].data.ptr;
1026*84e872a0SLloyd Pique 		if (source->fd != -1)
1027*84e872a0SLloyd Pique 			source->interface->dispatch(source, &ep[i]);
1028*84e872a0SLloyd Pique 	}
1029*84e872a0SLloyd Pique 
1030*84e872a0SLloyd Pique 	wl_event_loop_process_destroy_list(loop);
1031*84e872a0SLloyd Pique 
1032*84e872a0SLloyd Pique 	wl_event_loop_dispatch_idle(loop);
1033*84e872a0SLloyd Pique 
1034*84e872a0SLloyd Pique 	while (post_dispatch_check(loop));
1035*84e872a0SLloyd Pique 
1036*84e872a0SLloyd Pique 	return 0;
1037*84e872a0SLloyd Pique }
1038*84e872a0SLloyd Pique 
1039*84e872a0SLloyd Pique /** Get the event loop file descriptor
1040*84e872a0SLloyd Pique  *
1041*84e872a0SLloyd Pique  * \param loop The event loop context.
1042*84e872a0SLloyd Pique  * \return The aggregate file descriptor.
1043*84e872a0SLloyd Pique  *
1044*84e872a0SLloyd Pique  * This function returns the aggregate file descriptor, that represents all
1045*84e872a0SLloyd Pique  * the event sources (idle sources excluded) associated with the given event
1046*84e872a0SLloyd Pique  * loop context. When any event source makes an event available, it will be
1047*84e872a0SLloyd Pique  * reflected in the aggregate file descriptor.
1048*84e872a0SLloyd Pique  *
1049*84e872a0SLloyd Pique  * When the aggregate file descriptor delivers an event, one can call
1050*84e872a0SLloyd Pique  * wl_event_loop_dispatch() on the event loop context to dispatch all the
1051*84e872a0SLloyd Pique  * available events.
1052*84e872a0SLloyd Pique  *
1053*84e872a0SLloyd Pique  * \memberof wl_event_loop
1054*84e872a0SLloyd Pique  */
1055*84e872a0SLloyd Pique WL_EXPORT int
wl_event_loop_get_fd(struct wl_event_loop * loop)1056*84e872a0SLloyd Pique wl_event_loop_get_fd(struct wl_event_loop *loop)
1057*84e872a0SLloyd Pique {
1058*84e872a0SLloyd Pique 	return loop->epoll_fd;
1059*84e872a0SLloyd Pique }
1060*84e872a0SLloyd Pique 
1061*84e872a0SLloyd Pique /** Register a destroy listener for an event loop context
1062*84e872a0SLloyd Pique  *
1063*84e872a0SLloyd Pique  * \param loop The event loop context whose destruction to listen for.
1064*84e872a0SLloyd Pique  * \param listener The listener with the callback to be called.
1065*84e872a0SLloyd Pique  *
1066*84e872a0SLloyd Pique  * \sa wl_listener
1067*84e872a0SLloyd Pique  * \memberof wl_event_loop
1068*84e872a0SLloyd Pique  */
1069*84e872a0SLloyd Pique WL_EXPORT void
wl_event_loop_add_destroy_listener(struct wl_event_loop * loop,struct wl_listener * listener)1070*84e872a0SLloyd Pique wl_event_loop_add_destroy_listener(struct wl_event_loop *loop,
1071*84e872a0SLloyd Pique 				   struct wl_listener *listener)
1072*84e872a0SLloyd Pique {
1073*84e872a0SLloyd Pique 	wl_signal_add(&loop->destroy_signal, listener);
1074*84e872a0SLloyd Pique }
1075*84e872a0SLloyd Pique 
1076*84e872a0SLloyd Pique /** Get the listener struct for the specified callback
1077*84e872a0SLloyd Pique  *
1078*84e872a0SLloyd Pique  * \param loop The event loop context to inspect.
1079*84e872a0SLloyd Pique  * \param notify The destroy callback to find.
1080*84e872a0SLloyd Pique  * \return The wl_listener registered to the event loop context with
1081*84e872a0SLloyd Pique  * the given callback pointer.
1082*84e872a0SLloyd Pique  *
1083*84e872a0SLloyd Pique  * \memberof wl_event_loop
1084*84e872a0SLloyd Pique  */
1085*84e872a0SLloyd Pique WL_EXPORT struct wl_listener *
wl_event_loop_get_destroy_listener(struct wl_event_loop * loop,wl_notify_func_t notify)1086*84e872a0SLloyd Pique wl_event_loop_get_destroy_listener(struct wl_event_loop *loop,
1087*84e872a0SLloyd Pique 				   wl_notify_func_t notify)
1088*84e872a0SLloyd Pique {
1089*84e872a0SLloyd Pique 	return wl_signal_get(&loop->destroy_signal, notify);
1090*84e872a0SLloyd Pique }
1091