Initial support for multiple UIs
[petitboot] / discover / waiter.c
1
2 #include <poll.h>
3 #include <string.h>
4 #include <assert.h>
5
6 #include <talloc/talloc.h>
7
8 #include "waiter.h"
9
10 struct waiter {
11         int             fd;
12         int             events;
13         waiter_cb       callback;
14         void            *arg;
15 };
16
17 static struct waiter *waiters;
18 static int n_waiters;
19
20 struct waiter *waiter_register(int fd, int events,
21                 waiter_cb callback, void *arg)
22 {
23         struct waiter *waiter;
24
25         n_waiters++;
26
27         waiters = talloc_realloc(NULL, waiters, struct waiter, n_waiters);
28         waiter = &waiters[n_waiters - 1];
29
30         waiter->fd = fd;
31         waiter->events = events;
32         waiter->callback = callback;
33         waiter->arg = arg;
34
35         return 0;
36 }
37
38 void waiter_remove(struct waiter *waiter)
39 {
40         int i;
41
42         i = waiter - waiters;
43         assert(i >= 0 && i < n_waiters);
44
45         n_waiters--;
46         memmove(&waiters[i], &waiters[i+1], n_waiters - i);
47
48         waiters = talloc_realloc(NULL, waiters, struct waiter, n_waiters);
49 }
50
51 int waiter_poll(void)
52 {
53         static struct pollfd *pollfds;
54         static int n_pollfds;
55         int i, rc;
56
57         if (n_waiters > n_pollfds) {
58                 pollfds = talloc_realloc(NULL, pollfds,
59                                 struct pollfd, n_waiters);
60         }
61
62         for (i = 0; i < n_waiters; i++) {
63                 pollfds[i].fd = waiters[i].fd;
64                 pollfds[i].events = waiters[i].events;
65                 pollfds[i].revents = 0;
66         }
67
68         rc = poll(pollfds, n_waiters, -1);
69
70         if (rc <= 0)
71                 return rc;
72
73         for (i = 0; i < n_waiters; i++) {
74                 if (pollfds[i].revents) {
75                         rc = waiters[i].callback(waiters[i].arg);
76
77                         if (rc)
78                                 waiter_remove(&waiters[i]);
79                 }
80         }
81
82         return 0;
83 }