af4a616105c6bb1e5b7b0385bd1e4abc9d3509cc
[src/app-framework-binder.git] / src / utils-upoll.c
1 /*
2  * Copyright 2016 IoT.bzh
3  * Author: José Bollo <jose.bollo@iot.bzh>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <sys/epoll.h>
19 #include <pthread.h>
20 #include <stdlib.h>
21 #include <errno.h>
22 #include <unistd.h>
23 #include <assert.h>
24
25 #include "utils-upoll.h"
26
27
28 struct upoll
29 {
30         int fd;
31         void (*process)(void *closure, int fd, uint32_t events);
32         void *closure;
33         struct upoll *next;
34 };
35
36 static int pollfd = 0;
37 static struct upoll *head = NULL;
38 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
39
40 int upoll_is_valid(struct upoll *upoll)
41 {
42         struct upoll *it = head;
43         while (it != NULL) {
44                 if (it == upoll)
45                         return 1;
46                 it = it->next;
47         }
48         return 0;
49 }
50
51 struct upoll *upoll_open(int fd, uint32_t events, void (*process)(void *closure, int fd, uint32_t events), void *closure)
52 {
53         struct epoll_event e;
54         struct upoll *result;
55         int rc;
56
57         /* opens the epoll stream */
58         if (pollfd == 0) {
59                 pollfd = epoll_create1(EPOLL_CLOEXEC);
60                 if (pollfd == 0) {
61                         pollfd = dup(0);
62                         close(0);
63                 }
64                 if (pollfd < 0) {
65                         pollfd = 0;
66                         return NULL;
67                 }
68         }
69
70         /* allocates */
71         result = malloc(sizeof *result);
72         if (result == NULL)
73                 return NULL;
74
75         /* init */
76         result->fd = fd;
77         result->process = process;
78         result->closure = closure;
79         pthread_mutex_lock(&mutex);
80         result->next = head;
81         head = result;
82         pthread_mutex_unlock(&mutex);
83
84         /* records */
85         e.events = events;
86         e.data.ptr = result;
87         rc = epoll_ctl(pollfd, EPOLL_CTL_ADD, fd, &e);
88         if (rc == 0)
89                 return result;
90
91         /* revert on error */
92         rc = errno;
93         upoll_close(result);
94         errno = rc;
95         return NULL;
96 }
97
98 int upoll_update(struct upoll *upoll, uint32_t events)
99 {
100         struct epoll_event e;
101
102         assert(pollfd != 0);
103         assert(upoll_is_valid(upoll));
104
105         e.events = events;
106         e.data.ptr = upoll;
107         return epoll_ctl(pollfd, EPOLL_CTL_MOD, upoll->fd, &e);
108 }
109
110 void upoll_close(struct upoll *upoll)
111 {
112         struct upoll **it;
113
114         assert(pollfd != 0);
115         assert(upoll_is_valid(upoll));
116
117         epoll_ctl(pollfd, EPOLL_CTL_DEL, upoll->fd, NULL);
118         pthread_mutex_lock(&mutex);
119         it = &head;
120         while (*it != upoll)
121                 it = &(*it)->next;
122         *it = upoll->next;
123         pthread_mutex_unlock(&mutex);
124         free(upoll);
125 }
126
127 void upoll_wait(int timeout)
128 {
129         int rc;
130         struct epoll_event e;
131         struct upoll *upoll;
132
133         if (pollfd == 0)
134                 return;
135
136         rc = epoll_wait(pollfd, &e, 1, timeout);
137         if (rc == 1) {
138                 upoll = e.data.ptr;
139                 upoll->process(upoll->closure, upoll->fd, e.events);
140         }
141 }
142