1 /*
2 * Copyright (C) 2019-2020 Alibaba Group Holding Limited
3 */
4
5 #include <stdlib.h>
6 #include <stdint.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <aos/kernel.h>
10 #include <uservice/event.h>
11 #include <sys/select.h>
12
13 #include "internal.h"
14
15 #define FD_MASK (1UL << 31)
16
17 typedef struct event {
18 uint32_t event_id;
19 slist_t sub_list;
20
21 slist_t next;
22 } event_t;
23
24 typedef struct event_subscription {
25 event_callback_t ecb;
26 void *context;
27
28 slist_t next;
29 } event_subscription_t;
30
find_event(event_list_t * evlist,uint32_t event_id)31 static event_t *find_event(event_list_t *evlist, uint32_t event_id)
32 {
33 event_t *node;
34 slist_for_each_entry(&evlist->events, node, event_t, next) {
35 if (node->event_id == event_id) {
36 return node;
37 }
38 }
39
40 return NULL;
41 }
42
find_event_sub(event_t * ev,event_callback_t cb,void * context)43 static event_subscription_t *find_event_sub(event_t *ev, event_callback_t cb, void *context)
44 {
45 event_subscription_t *node;
46 slist_for_each_entry(&ev->sub_list, node, event_subscription_t, next) {
47 if (node->ecb == cb && node->context == context) {
48 return node;
49 }
50 }
51
52 return NULL;
53 }
54
eventlist_init(event_list_t * evlist)55 int eventlist_init(event_list_t *evlist)
56 {
57 aos_assert(evlist);
58
59 memset(evlist, 0, sizeof(event_list_t));
60 slist_init(&evlist->events);
61
62 if (aos_mutex_new(&evlist->mutex) != 0) {
63 return -1;
64 }
65
66 return 0;
67 }
68
eventlist_uninit(event_list_t * evlist)69 void eventlist_uninit(event_list_t *evlist)
70 {
71 aos_assert(evlist);
72 event_t *node;
73 slist_t *tmp_1;
74
75 aos_mutex_lock(&evlist->mutex, AOS_WAIT_FOREVER);
76
77 slist_for_each_entry_safe(&evlist->events, tmp_1, node, event_t, next) {
78 event_subscription_t *node_sub;
79 slist_t *tmp_2;
80 slist_for_each_entry_safe(&node->sub_list, tmp_2, node_sub, event_subscription_t, next) {
81 slist_del(&node_sub->next, &node->sub_list);
82 aos_free(node_sub);
83 }
84 slist_del(&node->next, &evlist->events);
85 aos_free(node);
86 }
87
88 aos_mutex_unlock(&evlist->mutex);
89
90 aos_mutex_free(&evlist->mutex);
91 }
92
__yoc_event_subscribe(event_list_t * evlist,uint32_t event_id,event_callback_t cb,void * context)93 static int __yoc_event_subscribe(event_list_t *evlist, uint32_t event_id, event_callback_t cb, void *context)
94 {
95 int ret = -1;
96
97 aos_mutex_lock(&evlist->mutex, AOS_WAIT_FOREVER);
98 event_t *ev = find_event(evlist, event_id);
99
100 if (ev == NULL) {
101 ev = (event_t *)aos_zalloc(sizeof(event_t));
102
103 if (ev != NULL) {
104 ev->event_id = event_id;
105 slist_init(&ev->sub_list);
106 slist_add(&ev->next, &evlist->events);
107 }
108 }
109
110 if (ev != NULL) {
111 event_subscription_t *e_sub;
112 e_sub = find_event_sub(ev, cb, context);
113 if (e_sub == NULL) {
114 e_sub = (event_subscription_t *)aos_zalloc(sizeof(event_subscription_t));
115
116 if (e_sub) {
117 e_sub->ecb = cb;
118 e_sub->context = context;
119 slist_add(&e_sub->next, &ev->sub_list);
120
121 ret = 0;
122 }
123 }
124 }
125
126 aos_mutex_unlock(&evlist->mutex);
127
128 return ret;
129 }
130
eventlist_subscribe_fd(event_list_t * evlist,uint32_t fd,event_callback_t cb,void * context)131 int eventlist_subscribe_fd(event_list_t *evlist, uint32_t fd, event_callback_t cb, void *context)
132 {
133 aos_assert(evlist && cb);
134 if (fd & FD_MASK) {
135 return -1;
136 }
137
138 fd |= FD_MASK;
139
140 return __yoc_event_subscribe(evlist, fd, cb, context);
141 }
142
eventlist_subscribe(event_list_t * evlist,uint32_t event_id,event_callback_t cb,void * context)143 int eventlist_subscribe(event_list_t *evlist, uint32_t event_id, event_callback_t cb, void *context)
144 {
145 aos_assert(evlist && cb);
146 if (event_id & FD_MASK) {
147 return -1;
148 }
149
150 return __yoc_event_subscribe(evlist, event_id, cb, context);
151 }
152
__yoc_event_unsubscribe(event_list_t * evlist,uint32_t event_id,event_callback_t cb,void * context)153 static int __yoc_event_unsubscribe(event_list_t *evlist, uint32_t event_id, event_callback_t cb, void *context)
154 {
155 int ret = -1;
156
157 aos_mutex_lock(&evlist->mutex, AOS_WAIT_FOREVER);
158
159 event_t *ev = find_event(evlist, event_id);
160
161 if (ev) {
162 event_subscription_t *e_sub = find_event_sub(ev, cb, context);
163
164 if (e_sub) {
165 slist_del(&e_sub->next, &ev->sub_list);
166 aos_free(e_sub);
167
168 if (slist_empty(&ev->sub_list)) {
169 slist_del(&ev->next, &evlist->events);
170 aos_free(ev);
171 }
172
173 ret = 0;
174 }
175 }
176
177 aos_mutex_unlock(&evlist->mutex);
178
179 return ret;
180 }
181
182
__yoc_event_remove(event_list_t * evlist,uint32_t event_id)183 static int __yoc_event_remove(event_list_t *evlist, uint32_t event_id)
184 {
185 int ret = -1;
186
187 aos_mutex_lock(&evlist->mutex, AOS_WAIT_FOREVER);
188
189 event_t *ev = find_event(evlist, event_id);
190
191 if (ev) {
192 event_subscription_t *node;
193 slist_t *tmp;
194 slist_for_each_entry_safe(&ev->sub_list, tmp, node, event_subscription_t, next) {
195 slist_del(&ev->next, &evlist->events);
196 aos_free(ev);
197 }
198 slist_del(&ev->next, &evlist->events);
199 aos_free(ev);
200 }
201
202 aos_mutex_unlock(&evlist->mutex);
203
204 return ret;
205 }
206
eventlist_unsubscribe_fd(event_list_t * evlist,uint32_t fd,event_callback_t cb,void * context)207 int eventlist_unsubscribe_fd(event_list_t *evlist, uint32_t fd, event_callback_t cb, void *context)
208 {
209 aos_assert(evlist && cb);
210 if (fd & FD_MASK) {
211 return -1;
212 }
213
214 fd |= FD_MASK;
215
216 return __yoc_event_unsubscribe(evlist, fd, cb, context);
217 }
218
eventlist_unsubscribe(event_list_t * evlist,uint32_t event_id,event_callback_t cb,void * context)219 int eventlist_unsubscribe(event_list_t *evlist, uint32_t event_id, event_callback_t cb, void *context)
220 {
221 aos_assert(evlist && cb);
222 if (event_id & FD_MASK) {
223 return -1;
224 }
225
226 return __yoc_event_unsubscribe(evlist, event_id, cb, context);
227 }
228
__event_publish(event_list_t * evlist,uint32_t event_id,void * data)229 static void __event_publish(event_list_t *evlist, uint32_t event_id, void *data)
230 {
231 aos_mutex_lock(&evlist->mutex, AOS_WAIT_FOREVER);
232
233 event_t *ev = find_event(evlist, event_id);
234
235 if (ev) {
236 event_subscription_t *node;
237 slist_for_each_entry(&ev->sub_list, node, event_subscription_t, next) {
238 if (node->ecb) {
239 node->ecb(ev->event_id, data, node->context);
240 }
241 }
242 }
243
244 aos_mutex_unlock(&evlist->mutex);
245 }
246
eventlist_publish(event_list_t * evlist,uint32_t event_id,void * data)247 int eventlist_publish(event_list_t *evlist, uint32_t event_id, void *data)
248 {
249 aos_assert(evlist);
250 if (event_id & FD_MASK) {
251 return -1;
252 }
253
254 __event_publish(evlist, event_id, data);
255 return 0;
256 }
257
eventlist_publish_fd(event_list_t * evlist,uint32_t fd,void * data)258 int eventlist_publish_fd(event_list_t *evlist, uint32_t fd, void *data)
259 {
260 aos_assert(evlist);
261 if (fd & FD_MASK) {
262 return -1;
263 }
264
265 fd |= FD_MASK;
266 __event_publish(evlist, fd, data);
267
268 return 0;
269 }
270
eventlist_remove(event_list_t * evlist,uint32_t event_id)271 int eventlist_remove(event_list_t *evlist, uint32_t event_id)
272 {
273 aos_assert(evlist);
274 if (event_id & FD_MASK) {
275 return -1;
276 }
277 __yoc_event_remove(evlist, event_id);
278
279 return 0;
280 }
281
eventlist_remove_fd(event_list_t * evlist,uint32_t fd)282 int eventlist_remove_fd(event_list_t *evlist, uint32_t fd)
283 {
284 aos_assert(evlist);
285 if (fd & FD_MASK) {
286 return -1;
287 }
288
289 fd |= FD_MASK;
290 __yoc_event_remove(evlist, fd);
291
292 return 0;
293 }
294
eventlist_setfd(event_list_t * evlist,void * data)295 int eventlist_setfd(event_list_t *evlist, void *data)
296 {
297 aos_assert(evlist && data);
298 int max_fd = 0;
299
300 fd_set *readfds = (fd_set *)data;
301
302 FD_ZERO(readfds);
303
304 aos_mutex_lock(&evlist->mutex, AOS_WAIT_FOREVER);
305 event_t *node;
306 slist_for_each_entry(&evlist->events, node, event_t, next) {
307 if (node->event_id > FD_MASK) {
308 uint32_t fd = node->event_id & (~FD_MASK);
309 FD_SET(fd, readfds);
310
311 if (fd > max_fd) {
312 max_fd = fd;
313 }
314 }
315 }
316 aos_mutex_unlock(&evlist->mutex);
317
318 return max_fd;
319 }
320