34
35
#include <unistd.h>
35
36
#include <assert.h>
36
37
#include "wayland-server.h"
38
#include "wayland-private.h"
39
#include "wayland-os.h"
38
41
struct wl_event_loop {
40
43
struct wl_list check_list;
41
44
struct wl_list idle_list;
45
struct wl_list destroy_list;
47
struct wl_signal destroy_signal;
44
50
struct wl_event_source_interface {
45
51
int (*dispatch)(struct wl_event_source *source,
46
52
struct epoll_event *ep);
47
int (*remove)(struct wl_event_source *source);
50
55
struct wl_event_source {
72
78
mask |= WL_EVENT_READABLE;
73
79
if (ep->events & EPOLLOUT)
74
80
mask |= WL_EVENT_WRITABLE;
76
return fd_source->func(fd_source->fd, mask, fd_source->base.data);
80
wl_event_source_fd_remove(struct wl_event_source *source)
82
struct wl_event_source_fd *fd_source =
83
(struct wl_event_source_fd *) source;
84
struct wl_event_loop *loop = source->loop;
90
return epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, fd, NULL);
81
if (ep->events & EPOLLHUP)
82
mask |= WL_EVENT_HANGUP;
83
if (ep->events & EPOLLERR)
84
mask |= WL_EVENT_ERROR;
86
return fd_source->func(fd_source->fd, mask, source->data);
93
89
struct wl_event_source_interface fd_source_interface = {
94
90
wl_event_source_fd_dispatch,
95
wl_event_source_fd_remove
93
static struct wl_event_source *
94
add_source(struct wl_event_loop *loop,
95
struct wl_event_source *source, uint32_t mask, void *data)
97
struct epoll_event ep;
100
fprintf(stderr, "could not add source\n: %m");
107
wl_list_init(&source->link);
109
memset(&ep, 0, sizeof ep);
110
if (mask & WL_EVENT_READABLE)
111
ep.events |= EPOLLIN;
112
if (mask & WL_EVENT_WRITABLE)
113
ep.events |= EPOLLOUT;
114
ep.data.ptr = source;
116
if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) {
98
125
WL_EXPORT struct wl_event_source *
99
126
wl_event_loop_add_fd(struct wl_event_loop *loop,
100
127
int fd, uint32_t mask,
104
131
struct wl_event_source_fd *source;
105
struct epoll_event ep;
107
133
source = malloc(sizeof *source);
108
134
if (source == NULL)
111
137
source->base.interface = &fd_source_interface;
112
source->base.loop = loop;
113
wl_list_init(&source->base.link);
138
source->base.fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
116
source->base.data = data;
118
memset(&ep, 0, sizeof ep);
119
if (mask & WL_EVENT_READABLE)
120
ep.events |= EPOLLIN;
121
if (mask & WL_EVENT_WRITABLE)
122
ep.events |= EPOLLOUT;
123
ep.data.ptr = source;
125
if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) {
130
return &source->base;
142
return add_source(loop, &source->base, mask, data);
134
146
wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask)
136
struct wl_event_source_fd *fd_source =
137
(struct wl_event_source_fd *) source;
138
148
struct wl_event_loop *loop = source->loop;
139
149
struct epoll_event ep;
145
155
ep.events |= EPOLLOUT;
146
156
ep.data.ptr = source;
148
return epoll_ctl(loop->epoll_fd,
149
EPOLL_CTL_MOD, fd_source->fd, &ep);
158
return epoll_ctl(loop->epoll_fd, EPOLL_CTL_MOD, source->fd, &ep);
152
161
struct wl_event_source_timer {
153
162
struct wl_event_source base;
155
163
wl_event_loop_timer_func_t func;
164
172
uint64_t expires;
167
len = read(timer_source->fd, &expires, sizeof expires);
175
len = read(source->fd, &expires, sizeof expires);
168
176
if (len != sizeof expires)
169
177
/* Is there anything we can do here? Will this ever happen? */
170
178
fprintf(stderr, "timerfd read error: %m\n");
172
180
return timer_source->func(timer_source->base.data);
176
wl_event_source_timer_remove(struct wl_event_source *source)
178
struct wl_event_source_timer *timer_source =
179
(struct wl_event_source_timer *) source;
181
close(timer_source->fd);
186
183
struct wl_event_source_interface timer_source_interface = {
187
184
wl_event_source_timer_dispatch,
188
wl_event_source_timer_remove
191
187
WL_EXPORT struct wl_event_source *
196
192
struct wl_event_source_timer *source;
197
struct epoll_event ep;
199
194
source = malloc(sizeof *source);
200
195
if (source == NULL)
203
198
source->base.interface = &timer_source_interface;
204
source->base.loop = loop;
205
wl_list_init(&source->base.link);
207
source->fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
208
if (source->fd < 0) {
209
fprintf(stderr, "could not create timerfd\n: %m");
199
source->base.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
214
200
source->func = func;
215
source->base.data = data;
217
memset(&ep, 0, sizeof ep);
219
ep.data.ptr = source;
221
if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) {
227
return &source->base;
202
return add_source(loop, &source->base, WL_EVENT_READABLE, data);
231
206
wl_event_source_timer_update(struct wl_event_source *source, int ms_delay)
233
struct wl_event_source_timer *timer_source =
234
(struct wl_event_source_timer *) source;
235
208
struct itimerspec its;
237
210
its.it_interval.tv_sec = 0;
238
211
its.it_interval.tv_nsec = 0;
239
212
its.it_value.tv_sec = ms_delay / 1000;
240
213
its.it_value.tv_nsec = (ms_delay % 1000) * 1000 * 1000;
241
if (timerfd_settime(timer_source->fd, 0, &its, NULL) < 0) {
214
if (timerfd_settime(source->fd, 0, &its, NULL) < 0) {
242
215
fprintf(stderr, "could not set timerfd\n: %m");
262
234
struct signalfd_siginfo signal_info;
265
len = read(signal_source->fd, &signal_info, sizeof signal_info);
237
len = read(source->fd, &signal_info, sizeof signal_info);
266
238
if (len != sizeof signal_info)
267
239
/* Is there anything we can do here? Will this ever happen? */
268
240
fprintf(stderr, "signalfd read error: %m\n");
271
243
signal_source->base.data);
275
wl_event_source_signal_remove(struct wl_event_source *source)
277
struct wl_event_source_signal *signal_source =
278
(struct wl_event_source_signal *) source;
280
close(signal_source->fd);
285
246
struct wl_event_source_interface signal_source_interface = {
286
247
wl_event_source_signal_dispatch,
287
wl_event_source_signal_remove
290
250
WL_EXPORT struct wl_event_source *
304
263
source->base.interface = &signal_source_interface;
305
source->base.loop = loop;
306
wl_list_init(&source->base.link);
307
264
source->signal_number = signal_number;
309
266
sigemptyset(&mask);
310
267
sigaddset(&mask, signal_number);
311
source->fd = signalfd(-1, &mask, SFD_CLOEXEC);
312
if (source->fd < 0) {
313
fprintf(stderr, "could not create fd to watch signal\n: %m");
268
source->base.fd = signalfd(-1, &mask, SFD_CLOEXEC);
317
269
sigprocmask(SIG_BLOCK, &mask, NULL);
319
271
source->func = func;
320
source->base.data = data;
322
memset(&ep, 0, sizeof ep);
324
ep.data.ptr = source;
326
if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) {
332
return &source->base;
273
return add_source(loop, &source->base, WL_EVENT_READABLE, data);
335
276
struct wl_event_source_idle {
337
278
wl_event_loop_idle_func_t func;
341
wl_event_source_idle_remove(struct wl_event_source *source)
348
281
struct wl_event_source_interface idle_source_interface = {
350
wl_event_source_idle_remove
353
285
WL_EXPORT struct wl_event_source *
382
315
wl_event_source_remove(struct wl_event_source *source)
384
if (!wl_list_empty(&source->link))
385
wl_list_remove(&source->link);
387
source->interface->remove(source);
317
struct wl_event_loop *loop = source->loop;
319
/* We need to explicitly remove the fd, since closing the fd
320
* isn't enough in case we've dup'ed the fd. */
321
if (source->fd >= 0) {
322
epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, source->fd, NULL);
327
wl_list_remove(&source->link);
328
wl_list_insert(&loop->destroy_list, &source->link);
334
wl_event_loop_process_destroy_list(struct wl_event_loop *loop)
336
struct wl_event_source *source, *next;
338
wl_list_for_each_safe(source, next, &loop->destroy_list, link)
341
wl_list_init(&loop->destroy_list);
392
344
WL_EXPORT struct wl_event_loop *
393
345
wl_event_loop_create(void)
398
350
if (loop == NULL)
401
loop->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
353
loop->epoll_fd = wl_os_epoll_create_cloexec();
402
354
if (loop->epoll_fd < 0) {
406
358
wl_list_init(&loop->check_list);
407
359
wl_list_init(&loop->idle_list);
360
wl_list_init(&loop->destroy_list);
362
wl_signal_init(&loop->destroy_signal);
451
409
struct wl_event_source *source;
454
dispatch_idle_sources(loop);
412
wl_event_loop_dispatch_idle(loop);
456
414
count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
460
418
for (i = 0; i < count; i++) {
461
419
source = ep[i].data.ptr;
462
n += source->interface->dispatch(source, &ep[i]);
420
if (source->fd != -1)
421
source->interface->dispatch(source, &ep[i]);
424
wl_event_loop_process_destroy_list(loop);
466
427
n = post_dispatch_check(loop);
474
436
return loop->epoll_fd;
440
wl_event_loop_add_destroy_listener(struct wl_event_loop *loop,
441
struct wl_listener *listener)
443
wl_signal_add(&loop->destroy_signal, listener);
446
WL_EXPORT struct wl_listener *
447
wl_event_loop_get_destroy_listener(struct wl_event_loop *loop,
448
wl_notify_func_t notify)
450
return wl_signal_get(&loop->destroy_signal, notify);