1 | #include <math.h> |
1 | #include <math.h> |
2 | #include <stdlib.h> |
2 | #include <stdlib.h> |
|
|
3 | #include <unistd.h> |
|
|
4 | #include <fcntl.h> |
|
|
5 | #include <signal.h> |
3 | |
6 | |
4 | #include <stdio.h> |
7 | #include <stdio.h> |
5 | |
8 | |
6 | #include <assert.h> |
9 | #include <assert.h> |
7 | #include <errno.h> |
10 | #include <errno.h> |
… | |
… | |
10 | |
13 | |
11 | #ifdef CLOCK_MONOTONIC |
14 | #ifdef CLOCK_MONOTONIC |
12 | # define HAVE_MONOTONIC 1 |
15 | # define HAVE_MONOTONIC 1 |
13 | #endif |
16 | #endif |
14 | |
17 | |
|
|
18 | #define HAVE_REALTIME 1 |
15 | #define HAVE_EPOLL 1 |
19 | #define HAVE_EPOLL 1 |
16 | #define HAVE_REALTIME 1 |
|
|
17 | #define HAVE_SELECT 0 |
20 | #define HAVE_SELECT 1 |
18 | |
21 | |
19 | #define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */ |
22 | #define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */ |
20 | #define MAX_BLOCKTIME 60. |
23 | #define MAX_BLOCKTIME 60. |
21 | |
24 | |
22 | #include "ev.h" |
25 | #include "ev.h" |
… | |
… | |
34 | int ev_method; |
37 | int ev_method; |
35 | |
38 | |
36 | static int have_monotonic; /* runtime */ |
39 | static int have_monotonic; /* runtime */ |
37 | |
40 | |
38 | static ev_tstamp method_fudge; /* stupid epoll-returns-early bug */ |
41 | static ev_tstamp method_fudge; /* stupid epoll-returns-early bug */ |
39 | static void (*method_reify)(void); |
42 | static void (*method_modify)(int fd, int oev, int nev); |
40 | static void (*method_poll)(ev_tstamp timeout); |
43 | static void (*method_poll)(ev_tstamp timeout); |
41 | |
44 | |
42 | ev_tstamp |
45 | ev_tstamp |
43 | ev_time (void) |
46 | ev_time (void) |
44 | { |
47 | { |
… | |
… | |
179 | |
182 | |
180 | timers [k] = w; |
183 | timers [k] = w; |
181 | timers [k]->active = k + 1; |
184 | timers [k]->active = k + 1; |
182 | } |
185 | } |
183 | |
186 | |
184 | static struct ev_signal **signals; |
187 | typedef struct |
|
|
188 | { |
|
|
189 | struct ev_signal *head; |
|
|
190 | sig_atomic_t gotsig; |
|
|
191 | } ANSIG; |
|
|
192 | |
|
|
193 | static ANSIG *signals; |
185 | static int signalmax; |
194 | static int signalmax; |
186 | |
195 | |
|
|
196 | static int sigpipe [2]; |
|
|
197 | static sig_atomic_t gotsig; |
|
|
198 | static struct ev_io sigev; |
|
|
199 | |
187 | static void |
200 | static void |
188 | signals_init (struct ev_signal **base, int count) |
201 | signals_init (ANSIG *base, int count) |
189 | { |
202 | { |
190 | while (count--) |
203 | while (count--) |
191 | *base++ = 0; |
204 | { |
|
|
205 | base->head = 0; |
|
|
206 | base->gotsig = 0; |
|
|
207 | ++base; |
|
|
208 | } |
|
|
209 | } |
|
|
210 | |
|
|
211 | static void |
|
|
212 | sighandler (int signum) |
|
|
213 | { |
|
|
214 | signals [signum - 1].gotsig = 1; |
|
|
215 | |
|
|
216 | if (!gotsig) |
|
|
217 | { |
|
|
218 | gotsig = 1; |
|
|
219 | write (sigpipe [1], &gotsig, 1); |
|
|
220 | } |
|
|
221 | } |
|
|
222 | |
|
|
223 | static void |
|
|
224 | sigcb (struct ev_io *iow, int revents) |
|
|
225 | { |
|
|
226 | struct ev_signal *w; |
|
|
227 | int sig; |
|
|
228 | |
|
|
229 | gotsig = 0; |
|
|
230 | read (sigpipe [0], &revents, 1); |
|
|
231 | |
|
|
232 | for (sig = signalmax; sig--; ) |
|
|
233 | if (signals [sig].gotsig) |
|
|
234 | { |
|
|
235 | signals [sig].gotsig = 0; |
|
|
236 | |
|
|
237 | for (w = signals [sig].head; w; w = w->next) |
|
|
238 | event ((struct ev_watcher *)w, EV_SIGNAL); |
|
|
239 | } |
|
|
240 | } |
|
|
241 | |
|
|
242 | static void |
|
|
243 | siginit (void) |
|
|
244 | { |
|
|
245 | fcntl (sigpipe [0], F_SETFD, FD_CLOEXEC); |
|
|
246 | fcntl (sigpipe [1], F_SETFD, FD_CLOEXEC); |
|
|
247 | |
|
|
248 | /* rather than sort out wether we really need nb, set it */ |
|
|
249 | fcntl (sigpipe [0], F_SETFL, O_NONBLOCK); |
|
|
250 | fcntl (sigpipe [1], F_SETFL, O_NONBLOCK); |
|
|
251 | |
|
|
252 | evio_set (&sigev, sigpipe [0], EV_READ); |
|
|
253 | evio_start (&sigev); |
192 | } |
254 | } |
193 | |
255 | |
194 | #if HAVE_EPOLL |
256 | #if HAVE_EPOLL |
195 | # include "ev_epoll.c" |
257 | # include "ev_epoll.c" |
196 | #endif |
258 | #endif |
… | |
… | |
210 | |
272 | |
211 | ev_now = ev_time (); |
273 | ev_now = ev_time (); |
212 | now = get_clock (); |
274 | now = get_clock (); |
213 | diff = ev_now - now; |
275 | diff = ev_now - now; |
214 | |
276 | |
|
|
277 | if (pipe (sigpipe)) |
|
|
278 | return 0; |
|
|
279 | |
|
|
280 | ev_method = EVMETHOD_NONE; |
215 | #if HAVE_EPOLL |
281 | #if HAVE_EPOLL |
216 | if (epoll_init (flags)) |
282 | if (ev_method == EVMETHOD_NONE) epoll_init (flags); |
217 | return ev_method; |
|
|
218 | #endif |
283 | #endif |
219 | #if HAVE_SELECT |
284 | #if HAVE_SELECT |
220 | if (select_init (flags)) |
285 | if (ev_method == EVMETHOD_NONE) select_init (flags); |
221 | return ev_method; |
|
|
222 | #endif |
286 | #endif |
223 | |
287 | |
224 | ev_method = EVMETHOD_NONE; |
288 | if (ev_method) |
|
|
289 | { |
|
|
290 | evw_init (&sigev, sigcb, 0); |
|
|
291 | siginit (); |
|
|
292 | } |
|
|
293 | |
225 | return ev_method; |
294 | return ev_method; |
226 | } |
295 | } |
227 | |
296 | |
228 | void ev_prefork (void) |
297 | void ev_prefork (void) |
229 | { |
298 | { |
… | |
… | |
234 | } |
303 | } |
235 | |
304 | |
236 | void ev_postfork_child (void) |
305 | void ev_postfork_child (void) |
237 | { |
306 | { |
238 | #if HAVE_EPOLL |
307 | #if HAVE_EPOLL |
|
|
308 | if (ev_method == EVMETHOD_EPOLL) |
239 | epoll_postfork_child (); |
309 | epoll_postfork_child (); |
240 | #endif |
310 | #endif |
|
|
311 | |
|
|
312 | evio_stop (&sigev); |
|
|
313 | close (sigpipe [0]); |
|
|
314 | close (sigpipe [1]); |
|
|
315 | pipe (sigpipe); |
|
|
316 | siginit (); |
|
|
317 | } |
|
|
318 | |
|
|
319 | static void |
|
|
320 | fd_reify (void) |
|
|
321 | { |
|
|
322 | int i; |
|
|
323 | |
|
|
324 | for (i = 0; i < fdchangecnt; ++i) |
|
|
325 | { |
|
|
326 | int fd = fdchanges [i]; |
|
|
327 | ANFD *anfd = anfds + fd; |
|
|
328 | struct ev_io *w; |
|
|
329 | |
|
|
330 | int wev = 0; |
|
|
331 | |
|
|
332 | for (w = anfd->head; w; w = w->next) |
|
|
333 | wev |= w->events; |
|
|
334 | |
|
|
335 | if (anfd->wev != wev) |
|
|
336 | { |
|
|
337 | method_modify (fd, anfd->wev, wev); |
|
|
338 | anfd->wev = wev; |
|
|
339 | } |
|
|
340 | } |
|
|
341 | |
|
|
342 | fdchangecnt = 0; |
241 | } |
343 | } |
242 | |
344 | |
243 | static void |
345 | static void |
244 | call_pending () |
346 | call_pending () |
245 | { |
347 | { |
… | |
… | |
336 | ev_loop_done = flags & EVLOOP_ONESHOT; |
438 | ev_loop_done = flags & EVLOOP_ONESHOT; |
337 | |
439 | |
338 | do |
440 | do |
339 | { |
441 | { |
340 | /* update fd-related kernel structures */ |
442 | /* update fd-related kernel structures */ |
341 | method_reify (); fdchangecnt = 0; |
443 | fd_reify (); |
342 | |
444 | |
343 | /* calculate blocking time */ |
445 | /* calculate blocking time */ |
344 | if (flags & EVLOOP_NONBLOCK) |
446 | if (flags & EVLOOP_NONBLOCK) |
345 | block = 0.; |
447 | block = 0.; |
346 | else |
448 | else |
… | |
… | |
509 | if (ev_is_active (w)) |
611 | if (ev_is_active (w)) |
510 | return; |
612 | return; |
511 | |
613 | |
512 | ev_start ((struct ev_watcher *)w, 1); |
614 | ev_start ((struct ev_watcher *)w, 1); |
513 | array_needsize (signals, signalmax, w->signum, signals_init); |
615 | array_needsize (signals, signalmax, w->signum, signals_init); |
514 | wlist_add ((struct ev_watcher_list **)&signals [w->signum - 1], (struct ev_watcher_list *)w); |
616 | wlist_add ((struct ev_watcher_list **)&signals [w->signum - 1].head, (struct ev_watcher_list *)w); |
|
|
617 | |
|
|
618 | if (!w->next) |
|
|
619 | { |
|
|
620 | struct sigaction sa; |
|
|
621 | sa.sa_handler = sighandler; |
|
|
622 | sigfillset (&sa.sa_mask); |
|
|
623 | sa.sa_flags = 0; |
|
|
624 | sigaction (w->signum, &sa, 0); |
|
|
625 | } |
515 | } |
626 | } |
516 | |
627 | |
517 | void |
628 | void |
518 | evsignal_stop (struct ev_signal *w) |
629 | evsignal_stop (struct ev_signal *w) |
519 | { |
630 | { |
520 | if (!ev_is_active (w)) |
631 | if (!ev_is_active (w)) |
521 | return; |
632 | return; |
522 | |
633 | |
523 | wlist_del ((struct ev_watcher_list **)&signals [w->signum - 1], (struct ev_watcher_list *)w); |
634 | wlist_del ((struct ev_watcher_list **)&signals [w->signum - 1].head, (struct ev_watcher_list *)w); |
524 | ev_stop ((struct ev_watcher *)w); |
635 | ev_stop ((struct ev_watcher *)w); |
|
|
636 | |
|
|
637 | if (!signals [w->signum - 1].head) |
|
|
638 | signal (w->signum, SIG_DFL); |
525 | } |
639 | } |
526 | |
640 | |
527 | /*****************************************************************************/ |
641 | /*****************************************************************************/ |
528 | #if 1 |
642 | #if 1 |
529 | |
643 | |
… | |
… | |
539 | //fprintf (stderr, "timer %f,%f (%x) (%f) d%p\n", w->at, w->repeat, revents, w->at - ev_time (), w->data); |
653 | //fprintf (stderr, "timer %f,%f (%x) (%f) d%p\n", w->at, w->repeat, revents, w->at - ev_time (), w->data); |
540 | evtimer_stop (w); |
654 | evtimer_stop (w); |
541 | evtimer_start (w); |
655 | evtimer_start (w); |
542 | } |
656 | } |
543 | |
657 | |
|
|
658 | static void |
|
|
659 | scb (struct ev_signal *w, int revents) |
|
|
660 | { |
|
|
661 | fprintf (stderr, "signal %x,%d\n", revents, w->signum); |
|
|
662 | } |
|
|
663 | |
544 | int main (void) |
664 | int main (void) |
545 | { |
665 | { |
546 | struct ev_io sin; |
666 | struct ev_io sin; |
547 | |
667 | |
548 | ev_init (0); |
668 | ev_init (0); |
… | |
… | |
551 | evio_set (&sin, 0, EV_READ); |
671 | evio_set (&sin, 0, EV_READ); |
552 | evio_start (&sin); |
672 | evio_start (&sin); |
553 | |
673 | |
554 | struct ev_timer t[10000]; |
674 | struct ev_timer t[10000]; |
555 | |
675 | |
556 | #if 1 |
676 | #if 0 |
557 | int i; |
677 | int i; |
558 | for (i = 0; i < 10000; ++i) |
678 | for (i = 0; i < 10000; ++i) |
559 | { |
679 | { |
560 | struct ev_timer *w = t + i; |
680 | struct ev_timer *w = t + i; |
561 | evw_init (w, ocb, i); |
681 | evw_init (w, ocb, i); |
… | |
… | |
569 | struct ev_timer t1; |
689 | struct ev_timer t1; |
570 | evw_init (&t1, ocb, 0); |
690 | evw_init (&t1, ocb, 0); |
571 | evtimer_set_abs (&t1, 5, 10); |
691 | evtimer_set_abs (&t1, 5, 10); |
572 | evtimer_start (&t1); |
692 | evtimer_start (&t1); |
573 | |
693 | |
|
|
694 | struct ev_signal sig; |
|
|
695 | evw_init (&sig, scb, 65535); |
|
|
696 | evsignal_set (&sig, SIGQUIT); |
|
|
697 | evsignal_start (&sig); |
|
|
698 | |
574 | ev_loop (0); |
699 | ev_loop (0); |
575 | |
700 | |
576 | return 0; |
701 | return 0; |
577 | } |
702 | } |
578 | |
703 | |