2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
8 * Sun elects to license this software under the BSD license.
9 * See README for more details.
12 #pragma ident "%Z%%M% %I% %E% SMI"
25 static struct eloop_data eloop
;
27 * Initialize global event loop data - must be called before any other eloop_*
28 * function. user_data is a pointer to global data structure and will be passed
29 * as eloop_ctx to signal handlers.
32 eloop_init(void *user_data
)
34 (void) memset(&eloop
, 0, sizeof (eloop
));
35 eloop
.user_data
= user_data
;
39 * Register handler for read event
42 eloop_register_read_sock(int sock
,
43 void (*handler
)(int sock
, void *eloop_ctx
,
44 void *sock_ctx
), void *eloop_data
, void *user_data
)
46 struct eloop_sock
*tmp
;
48 tmp
= reallocarray(eloop
.readers
, eloop
.reader_count
+ 1,
49 sizeof(struct eloop_sock
));
53 tmp
[eloop
.reader_count
].sock
= sock
;
54 tmp
[eloop
.reader_count
].eloop_data
= eloop_data
;
55 tmp
[eloop
.reader_count
].user_data
= user_data
;
56 tmp
[eloop
.reader_count
].handler
= handler
;
59 if (sock
> eloop
.max_sock
)
60 eloop
.max_sock
= sock
;
66 eloop_unregister_read_sock(int sock
)
70 if (eloop
.readers
== NULL
|| eloop
.reader_count
== 0)
73 for (i
= 0; i
< eloop
.reader_count
; i
++) {
74 if (eloop
.readers
[i
].sock
== sock
)
77 if (i
== eloop
.reader_count
)
79 if (i
!= eloop
.reader_count
- 1) {
80 (void) memmove(&eloop
.readers
[i
], &eloop
.readers
[i
+ 1],
81 (eloop
.reader_count
- i
- 1) *
82 sizeof (struct eloop_sock
));
88 * Register timeout routines
91 eloop_register_timeout(unsigned int secs
, unsigned int usecs
,
92 void (*handler
)(void *eloop_ctx
, void *timeout_ctx
),
93 void *eloop_data
, void *user_data
)
95 struct eloop_timeout
*timeout
, *tmp
, *prev
;
97 timeout
= (struct eloop_timeout
*)malloc(sizeof (*timeout
));
100 (void) gettimeofday(&timeout
->time
, NULL
);
101 timeout
->time
.tv_sec
+= secs
;
102 timeout
->time
.tv_usec
+= usecs
;
103 while (timeout
->time
.tv_usec
>= 1000000) {
104 timeout
->time
.tv_sec
++;
105 timeout
->time
.tv_usec
-= 1000000;
107 timeout
->eloop_data
= eloop_data
;
108 timeout
->user_data
= user_data
;
109 timeout
->handler
= handler
;
110 timeout
->next
= NULL
;
112 if (eloop
.timeout
== NULL
) {
113 eloop
.timeout
= timeout
;
119 while (tmp
!= NULL
) {
120 if (timercmp(&timeout
->time
, &tmp
->time
, < /* */))
127 timeout
->next
= eloop
.timeout
;
128 eloop
.timeout
= timeout
;
130 timeout
->next
= prev
->next
;
131 prev
->next
= timeout
;
138 * Cancel timeouts matching <handler,eloop_data,user_data>.
139 * ELOOP_ALL_CTX can be used as a wildcard for cancelling all timeouts
140 * regardless of eloop_data/user_data.
143 eloop_cancel_timeout(void (*handler
)(void *eloop_ctx
, void *sock_ctx
),
144 void *eloop_data
, void *user_data
)
146 struct eloop_timeout
*timeout
, *prev
, *next
;
149 timeout
= eloop
.timeout
;
150 while (timeout
!= NULL
) {
151 next
= timeout
->next
;
153 if (timeout
->handler
== handler
&&
154 (timeout
->eloop_data
== eloop_data
||
155 eloop_data
== ELOOP_ALL_CTX
) &&
156 (timeout
->user_data
== user_data
||
157 user_data
== ELOOP_ALL_CTX
)) {
159 eloop
.timeout
= next
;
170 static void eloop_handle_signal(int sig
)
175 for (i
= 0; i
< eloop
.signal_count
; i
++) {
176 if (eloop
.signals
[i
].sig
== sig
) {
177 eloop
.signals
[i
].signaled
++;
183 static void eloop_process_pending_signals(void)
187 if (eloop
.signaled
== 0)
191 for (i
= 0; i
< eloop
.signal_count
; i
++) {
192 if (eloop
.signals
[i
].signaled
) {
193 eloop
.signals
[i
].signaled
= 0;
194 eloop
.signals
[i
].handler(eloop
.signals
[i
].sig
,
195 eloop
.user_data
, eloop
.signals
[i
].user_data
);
201 * Register handler for signal.
202 * Note: signals are 'global' events and there is no local eloop_data pointer
203 * like with other handlers. The (global) pointer given to eloop_init() will be
204 * used as eloop_ctx for signal handlers.
207 eloop_register_signal(int sig
,
208 void (*handler
)(int sig
, void *eloop_ctx
, void *signal_ctx
),
211 struct eloop_signal
*tmp
;
213 tmp
= (struct eloop_signal
*)
214 reallocarray(eloop
.signals
, eloop
.signal_count
+ 1,
215 sizeof(struct eloop_signal
));
219 tmp
[eloop
.signal_count
].sig
= sig
;
220 tmp
[eloop
.signal_count
].user_data
= user_data
;
221 tmp
[eloop
.signal_count
].handler
= handler
;
222 tmp
[eloop
.signal_count
].signaled
= 0;
223 eloop
.signal_count
++;
225 (void) signal(sig
, eloop_handle_signal
);
231 * Start event loop and continue running as long as there are any registered
237 struct pollfd pfds
[MAX_POLLFDS
]; /* array of polled fd */
240 struct timeval tv
, now
;
242 default_t
= 5 * 1000; /* 5 seconds */
243 while (!eloop
.terminate
&&
244 (eloop
.timeout
|| eloop
.reader_count
> 0)) {
246 (void) gettimeofday(&now
, NULL
);
247 if (timercmp(&now
, &eloop
.timeout
->time
, < /* */))
248 timersub(&eloop
.timeout
->time
, &now
, &tv
);
250 tv
.tv_sec
= tv
.tv_usec
= 0;
253 t
= (eloop
.timeout
== NULL
?
254 default_t
: (tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000));
255 for (i
= 0; i
< eloop
.reader_count
; i
++) {
256 pfds
[i
].fd
= eloop
.readers
[i
].sock
;
257 pfds
[i
].events
= POLLIN
| POLLPRI
;
259 res
= poll(pfds
, eloop
.reader_count
, t
);
260 if (res
< 0 && errno
!= EINTR
)
263 eloop_process_pending_signals();
265 /* check if some registered timeouts have occurred */
267 struct eloop_timeout
*tmp
;
269 (void) gettimeofday(&now
, NULL
);
270 if (!timercmp(&now
, &eloop
.timeout
->time
, < /* */)) {
272 eloop
.timeout
= eloop
.timeout
->next
;
273 tmp
->handler(tmp
->eloop_data
, tmp
->user_data
);
282 for (i
= 0; i
< eloop
.reader_count
; i
++) {
283 if (pfds
[i
].revents
) {
284 eloop
.readers
[i
].handler(
285 eloop
.readers
[i
].sock
,
286 eloop
.readers
[i
].eloop_data
,
287 eloop
.readers
[i
].user_data
);
294 * Terminate event loop even if there are registered events.
297 eloop_terminate(void)
304 * Free any reserved resources. After calling eloop_destoy(), other eloop_*
305 * functions must not be called before re-running eloop_init().
310 struct eloop_timeout
*timeout
, *prev
;
312 timeout
= eloop
.timeout
;
313 while (timeout
!= NULL
) {
315 timeout
= timeout
->next
;