Fix memmove size
[petitboot] / lib / waiter / 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],
47                 (n_waiters - i) * sizeof(waiters[0]));
48
49         waiters = talloc_realloc(NULL, waiters, struct waiter, n_waiters);
50 }
51
52 int waiter_poll(void)
53 {
54         static struct pollfd *pollfds;
55         static int n_pollfds;
56         int i, rc;
57
58         if (n_waiters != n_pollfds) {
59                 pollfds = talloc_realloc(NULL, pollfds,
60                                 struct pollfd, n_waiters);
61                 n_pollfds = n_waiters;
62         }
63
64         for (i = 0; i < n_waiters; i++) {
65                 pollfds[i].fd = waiters[i].fd;
66                 pollfds[i].events = waiters[i].events;
67                 pollfds[i].revents = 0;
68         }
69
70         rc = poll(pollfds, n_waiters, -1);
71
72         if (rc <= 0)
73                 return rc;
74
75         for (i = 0; i < n_waiters; i++) {
76                 if (pollfds[i].revents) {
77                         rc = waiters[i].callback(waiters[i].arg);
78
79                         if (rc)
80                                 waiter_remove(&waiters[i]);
81                 }
82         }
83
84         return 0;
85 }