~ubuntu-branches/ubuntu/trusty/wayland/trusty-proposed

« back to all changes in this revision

Viewing changes to src/event-loop.c

  • Committer: Package Import Robot
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2013-06-06 23:22:34 UTC
  • mfrom: (5.1.2 experimental)
  • Revision ID: package-import@ubuntu.com-20130606232234-0fb2y1q6x9tyl7d2
Tags: 1.1.0-2
* Team upload.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include <signal.h>
27
27
#include <stdlib.h>
28
28
#include <string.h>
 
29
#include <fcntl.h>
29
30
#include <sys/socket.h>
30
31
#include <sys/un.h>
31
32
#include <sys/epoll.h>
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"
37
40
 
38
41
struct wl_event_loop {
39
42
        int epoll_fd;
40
43
        struct wl_list check_list;
41
44
        struct wl_list idle_list;
 
45
        struct wl_list destroy_list;
 
46
 
 
47
        struct wl_signal destroy_signal;
42
48
};
43
49
 
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);
48
53
};
49
54
 
50
55
struct wl_event_source {
52
57
        struct wl_event_loop *loop;
53
58
        struct wl_list link;
54
59
        void *data;
 
60
        int fd;
55
61
};
56
62
 
57
63
struct wl_event_source_fd {
58
64
        struct wl_event_source base;
59
 
        int fd;
60
65
        wl_event_loop_fd_func_t func;
 
66
        int fd;
61
67
};
62
68
 
63
69
static int
72
78
                mask |= WL_EVENT_READABLE;
73
79
        if (ep->events & EPOLLOUT)
74
80
                mask |= WL_EVENT_WRITABLE;
75
 
 
76
 
        return fd_source->func(fd_source->fd, mask, fd_source->base.data);
77
 
}
78
 
 
79
 
static int
80
 
wl_event_source_fd_remove(struct wl_event_source *source)
81
 
{
82
 
        struct wl_event_source_fd *fd_source =
83
 
                (struct wl_event_source_fd *) source;
84
 
        struct wl_event_loop *loop = source->loop;
85
 
        int fd;
86
 
 
87
 
        fd = fd_source->fd;
88
 
        free(source);
89
 
 
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;
 
85
 
 
86
        return fd_source->func(fd_source->fd, mask, source->data);
91
87
}
92
88
 
93
89
struct wl_event_source_interface fd_source_interface = {
94
90
        wl_event_source_fd_dispatch,
95
 
        wl_event_source_fd_remove
96
91
};
97
92
 
 
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)
 
96
{
 
97
        struct epoll_event ep;
 
98
 
 
99
        if (source->fd < 0) {
 
100
                fprintf(stderr, "could not add source\n: %m");
 
101
                free(source);
 
102
                return NULL;
 
103
        }
 
104
 
 
105
        source->loop = loop;
 
106
        source->data = data;
 
107
        wl_list_init(&source->link);
 
108
 
 
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;
 
115
 
 
116
        if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) {
 
117
                close(source->fd);
 
118
                free(source);
 
119
                return NULL;
 
120
        }
 
121
 
 
122
        return source;
 
123
}
 
124
 
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,
102
129
                     void *data)
103
130
{
104
131
        struct wl_event_source_fd *source;
105
 
        struct epoll_event ep;
106
132
 
107
133
        source = malloc(sizeof *source);
108
134
        if (source == NULL)
109
135
                return NULL;
110
136
 
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);
 
139
        source->func = func;
114
140
        source->fd = fd;
115
 
        source->func = func;
116
 
        source->base.data = data;
117
 
 
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;
124
 
 
125
 
        if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) {
126
 
                free(source);
127
 
                return NULL;
128
 
        }
129
 
 
130
 
        return &source->base;
 
141
 
 
142
        return add_source(loop, &source->base, mask, data);
131
143
}
132
144
 
133
145
WL_EXPORT int
134
146
wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask)
135
147
{
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;
140
150
 
145
155
                ep.events |= EPOLLOUT;
146
156
        ep.data.ptr = source;
147
157
 
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);
150
159
}
151
160
 
152
161
struct wl_event_source_timer {
153
162
        struct wl_event_source base;
154
 
        int fd;
155
163
        wl_event_loop_timer_func_t func;
156
164
};
157
165
 
164
172
        uint64_t expires;
165
173
        int len;
166
174
 
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);
173
181
}
174
182
 
175
 
static int
176
 
wl_event_source_timer_remove(struct wl_event_source *source)
177
 
{
178
 
        struct wl_event_source_timer *timer_source =
179
 
                (struct wl_event_source_timer *) source;
180
 
 
181
 
        close(timer_source->fd);
182
 
        free(source);
183
 
        return 0;
184
 
}
185
 
 
186
183
struct wl_event_source_interface timer_source_interface = {
187
184
        wl_event_source_timer_dispatch,
188
 
        wl_event_source_timer_remove
189
185
};
190
186
 
191
187
WL_EXPORT struct wl_event_source *
194
190
                        void *data)
195
191
{
196
192
        struct wl_event_source_timer *source;
197
 
        struct epoll_event ep;
198
193
 
199
194
        source = malloc(sizeof *source);
200
195
        if (source == NULL)
201
196
                return NULL;
202
197
 
203
198
        source->base.interface = &timer_source_interface;
204
 
        source->base.loop = loop;
205
 
        wl_list_init(&source->base.link);
206
 
 
207
 
        source->fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
208
 
        if (source->fd < 0) {
209
 
                fprintf(stderr, "could not create timerfd\n: %m");
210
 
                free(source);
211
 
                return NULL;
212
 
        }
213
 
 
 
199
        source->base.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
214
200
        source->func = func;
215
 
        source->base.data = data;
216
 
 
217
 
        memset(&ep, 0, sizeof ep);
218
 
        ep.events = EPOLLIN;
219
 
        ep.data.ptr = source;
220
 
 
221
 
        if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) {
222
 
                close(source->fd);
223
 
                free(source);
224
 
                return NULL;
225
 
        }
226
 
 
227
 
        return &source->base;
 
201
 
 
202
        return add_source(loop, &source->base, WL_EVENT_READABLE, data);
228
203
}
229
204
 
230
205
WL_EXPORT int
231
206
wl_event_source_timer_update(struct wl_event_source *source, int ms_delay)
232
207
{
233
 
        struct wl_event_source_timer *timer_source =
234
 
                (struct wl_event_source_timer *) source;
235
208
        struct itimerspec its;
236
209
 
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");
243
216
                return -1;
244
217
        }
248
221
 
249
222
struct wl_event_source_signal {
250
223
        struct wl_event_source base;
251
 
        int fd;
252
224
        int signal_number;
253
225
        wl_event_loop_signal_func_t func;
254
226
};
262
234
        struct signalfd_siginfo signal_info;
263
235
        int len;
264
236
 
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);
272
244
}
273
245
 
274
 
static int
275
 
wl_event_source_signal_remove(struct wl_event_source *source)
276
 
{
277
 
        struct wl_event_source_signal *signal_source =
278
 
                (struct wl_event_source_signal *) source;
279
 
 
280
 
        close(signal_source->fd);
281
 
        free(source);
282
 
        return 0;
283
 
}
284
 
 
285
246
struct wl_event_source_interface signal_source_interface = {
286
247
        wl_event_source_signal_dispatch,
287
 
        wl_event_source_signal_remove
288
248
};
289
249
 
290
250
WL_EXPORT struct wl_event_source *
294
254
                        void *data)
295
255
{
296
256
        struct wl_event_source_signal *source;
297
 
        struct epoll_event ep;
298
257
        sigset_t mask;
299
258
 
300
259
        source = malloc(sizeof *source);
302
261
                return NULL;
303
262
 
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;
308
265
 
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");
314
 
                free(source);
315
 
                return NULL;
316
 
        }
 
268
        source->base.fd = signalfd(-1, &mask, SFD_CLOEXEC);
317
269
        sigprocmask(SIG_BLOCK, &mask, NULL);
318
270
 
319
271
        source->func = func;
320
 
        source->base.data = data;
321
 
 
322
 
        memset(&ep, 0, sizeof ep);
323
 
        ep.events = EPOLLIN;
324
 
        ep.data.ptr = source;
325
 
 
326
 
        if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) {
327
 
                close(source->fd);
328
 
                free(source);
329
 
                return NULL;
330
 
        }
331
 
 
332
 
        return &source->base;
 
272
 
 
273
        return add_source(loop, &source->base, WL_EVENT_READABLE, data);
333
274
}
334
275
 
335
276
struct wl_event_source_idle {
337
278
        wl_event_loop_idle_func_t func;
338
279
};
339
280
 
340
 
static int
341
 
wl_event_source_idle_remove(struct wl_event_source *source)
342
 
{
343
 
        free(source);
344
 
 
345
 
        return 0;
346
 
}
347
 
 
348
281
struct wl_event_source_interface idle_source_interface = {
349
282
        NULL,
350
 
        wl_event_source_idle_remove
351
283
};
352
284
 
353
285
WL_EXPORT struct wl_event_source *
363
295
 
364
296
        source->base.interface = &idle_source_interface;
365
297
        source->base.loop = loop;
 
298
        source->base.fd = -1;
366
299
 
367
300
        source->func = func;
368
301
        source->base.data = data;
381
314
WL_EXPORT int
382
315
wl_event_source_remove(struct wl_event_source *source)
383
316
{
384
 
        if (!wl_list_empty(&source->link))
385
 
                wl_list_remove(&source->link);
386
 
 
387
 
        source->interface->remove(source);
 
317
        struct wl_event_loop *loop = source->loop;
 
318
 
 
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);
 
323
                close(source->fd);
 
324
                source->fd = -1;
 
325
        }
 
326
 
 
327
        wl_list_remove(&source->link);
 
328
        wl_list_insert(&loop->destroy_list, &source->link);
388
329
 
389
330
        return 0;
390
331
}
391
332
 
 
333
static void
 
334
wl_event_loop_process_destroy_list(struct wl_event_loop *loop)
 
335
{
 
336
        struct wl_event_source *source, *next;
 
337
 
 
338
        wl_list_for_each_safe(source, next, &loop->destroy_list, link)
 
339
                free(source);
 
340
 
 
341
        wl_list_init(&loop->destroy_list);
 
342
}
 
343
 
392
344
WL_EXPORT struct wl_event_loop *
393
345
wl_event_loop_create(void)
394
346
{
398
350
        if (loop == NULL)
399
351
                return NULL;
400
352
 
401
 
        loop->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
 
353
        loop->epoll_fd = wl_os_epoll_create_cloexec();
402
354
        if (loop->epoll_fd < 0) {
403
355
                free(loop);
404
356
                return NULL;
405
357
        }
406
358
        wl_list_init(&loop->check_list);
407
359
        wl_list_init(&loop->idle_list);
 
360
        wl_list_init(&loop->destroy_list);
 
361
 
 
362
        wl_signal_init(&loop->destroy_signal);
408
363
 
409
364
        return loop;
410
365
}
412
367
WL_EXPORT void
413
368
wl_event_loop_destroy(struct wl_event_loop *loop)
414
369
{
 
370
        wl_signal_emit(&loop->destroy_signal, loop);
 
371
 
 
372
        wl_event_loop_process_destroy_list(loop);
415
373
        close(loop->epoll_fd);
416
374
        free(loop);
417
375
}
431
389
        return n;
432
390
}
433
391
 
434
 
static void
435
 
dispatch_idle_sources(struct wl_event_loop *loop)
 
392
WL_EXPORT void
 
393
wl_event_loop_dispatch_idle(struct wl_event_loop *loop)
436
394
{
437
395
        struct wl_event_source_idle *source;
438
396
 
451
409
        struct wl_event_source *source;
452
410
        int i, count, n;
453
411
 
454
 
        dispatch_idle_sources(loop);
 
412
        wl_event_loop_dispatch_idle(loop);
455
413
 
456
414
        count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
457
415
        if (count < 0)
458
416
                return -1;
459
 
        n = 0;
 
417
 
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]);
463
422
        }
464
423
 
465
 
        while (n > 0)
 
424
        wl_event_loop_process_destroy_list(loop);
 
425
 
 
426
        do {
466
427
                n = post_dispatch_check(loop);
 
428
        } while (n > 0);
467
429
                
468
430
        return 0;
469
431
}
473
435
{
474
436
        return loop->epoll_fd;
475
437
}
 
438
 
 
439
WL_EXPORT void
 
440
wl_event_loop_add_destroy_listener(struct wl_event_loop *loop,
 
441
                                   struct wl_listener *listener)
 
442
{
 
443
        wl_signal_add(&loop->destroy_signal, listener);
 
444
}
 
445
 
 
446
WL_EXPORT struct wl_listener *
 
447
wl_event_loop_get_destroy_listener(struct wl_event_loop *loop,
 
448
                                   wl_notify_func_t notify)
 
449
{
 
450
        return wl_signal_get(&loop->destroy_signal, notify);
 
451
}
 
452