… | |
… | |
113 | |
113 | |
114 | typedef struct ev_watcher *W; |
114 | typedef struct ev_watcher *W; |
115 | typedef struct ev_watcher_list *WL; |
115 | typedef struct ev_watcher_list *WL; |
116 | typedef struct ev_watcher_time *WT; |
116 | typedef struct ev_watcher_time *WT; |
117 | |
117 | |
118 | static ev_tstamp now_floor, mn_now, diff; /* monotonic clock */ |
118 | static int have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */ |
119 | static ev_tstamp rt_now; |
|
|
120 | static int method; |
|
|
121 | |
119 | |
122 | static int have_monotonic; /* runtime */ |
120 | /*****************************************************************************/ |
123 | |
121 | |
124 | static ev_tstamp method_fudge; /* stupid epoll-returns-early bug */ |
122 | typedef struct |
125 | static void (*method_modify)(EV_P_ int fd, int oev, int nev); |
123 | { |
126 | static void (*method_poll)(EV_P_ ev_tstamp timeout); |
124 | struct ev_watcher_list *head; |
|
|
125 | unsigned char events; |
|
|
126 | unsigned char reify; |
|
|
127 | } ANFD; |
127 | |
128 | |
128 | static int activecnt; /* number of active events */ |
129 | typedef struct |
|
|
130 | { |
|
|
131 | W w; |
|
|
132 | int events; |
|
|
133 | } ANPENDING; |
129 | |
134 | |
130 | #if EV_USE_SELECT |
135 | #ifdef EV_MULTIPLICITY |
131 | static unsigned char *vec_ri, *vec_ro, *vec_wi, *vec_wo; |
|
|
132 | static int vec_max; |
|
|
133 | #endif |
|
|
134 | |
136 | |
135 | #if EV_USEV_POLL |
137 | struct ev_loop |
136 | static struct pollfd *polls; |
138 | { |
137 | static int pollmax, pollcnt; |
139 | # define VAR(name,decl) decl; |
138 | static int *pollidxs; /* maps fds into structure indices */ |
140 | # include "ev_vars.h" |
139 | static int pollidxmax; |
141 | }; |
140 | #endif |
142 | # undef VAR |
|
|
143 | # include "ev_wrap.h" |
141 | |
144 | |
142 | #if EV_USE_EPOLL |
145 | #else |
143 | static int epoll_fd = -1; |
|
|
144 | |
146 | |
145 | static struct epoll_event *events; |
147 | # define VAR(name,decl) static decl; |
146 | static int eventmax; |
148 | # include "ev_vars.h" |
147 | #endif |
149 | # undef VAR |
148 | |
150 | |
149 | #if EV_USE_KQUEUE |
|
|
150 | static int kqueue_fd; |
|
|
151 | static struct kevent *kqueue_changes; |
|
|
152 | static int kqueue_changemax, kqueue_changecnt; |
|
|
153 | static struct kevent *kqueue_events; |
|
|
154 | static int kqueue_eventmax; |
|
|
155 | #endif |
151 | #endif |
156 | |
152 | |
157 | /*****************************************************************************/ |
153 | /*****************************************************************************/ |
158 | |
154 | |
159 | inline ev_tstamp |
155 | inline ev_tstamp |
… | |
… | |
208 | cur = newcnt; \ |
204 | cur = newcnt; \ |
209 | } |
205 | } |
210 | |
206 | |
211 | /*****************************************************************************/ |
207 | /*****************************************************************************/ |
212 | |
208 | |
213 | typedef struct |
|
|
214 | { |
|
|
215 | struct ev_watcher_list *head; |
|
|
216 | unsigned char events; |
|
|
217 | unsigned char reify; |
|
|
218 | } ANFD; |
|
|
219 | |
|
|
220 | static ANFD *anfds; |
|
|
221 | static int anfdmax; |
|
|
222 | |
|
|
223 | static void |
209 | static void |
224 | anfds_init (ANFD *base, int count) |
210 | anfds_init (ANFD *base, int count) |
225 | { |
211 | { |
226 | while (count--) |
212 | while (count--) |
227 | { |
213 | { |
… | |
… | |
230 | base->reify = 0; |
216 | base->reify = 0; |
231 | |
217 | |
232 | ++base; |
218 | ++base; |
233 | } |
219 | } |
234 | } |
220 | } |
235 | |
|
|
236 | typedef struct |
|
|
237 | { |
|
|
238 | W w; |
|
|
239 | int events; |
|
|
240 | } ANPENDING; |
|
|
241 | |
|
|
242 | static ANPENDING *pendings [NUMPRI]; |
|
|
243 | static int pendingmax [NUMPRI], pendingcnt [NUMPRI]; |
|
|
244 | |
221 | |
245 | static void |
222 | static void |
246 | event (EV_P_ W w, int events) |
223 | event (EV_P_ W w, int events) |
247 | { |
224 | { |
248 | if (w->pending) |
225 | if (w->pending) |
… | |
… | |
280 | event (EV_A_ (W)w, ev); |
257 | event (EV_A_ (W)w, ev); |
281 | } |
258 | } |
282 | } |
259 | } |
283 | |
260 | |
284 | /*****************************************************************************/ |
261 | /*****************************************************************************/ |
285 | |
|
|
286 | static int *fdchanges; |
|
|
287 | static int fdchangemax, fdchangecnt; |
|
|
288 | |
262 | |
289 | static void |
263 | static void |
290 | fd_reify (EV_P) |
264 | fd_reify (EV_P) |
291 | { |
265 | { |
292 | int i; |
266 | int i; |
… | |
… | |
366 | } |
340 | } |
367 | } |
341 | } |
368 | |
342 | |
369 | /*****************************************************************************/ |
343 | /*****************************************************************************/ |
370 | |
344 | |
371 | static struct ev_timer **timers; |
|
|
372 | static int timermax, timercnt; |
|
|
373 | |
|
|
374 | static struct ev_periodic **periodics; |
|
|
375 | static int periodicmax, periodiccnt; |
|
|
376 | |
|
|
377 | static void |
345 | static void |
378 | upheap (WT *timers, int k) |
346 | upheap (WT *heap, int k) |
379 | { |
347 | { |
380 | WT w = timers [k]; |
348 | WT w = heap [k]; |
381 | |
349 | |
382 | while (k && timers [k >> 1]->at > w->at) |
350 | while (k && heap [k >> 1]->at > w->at) |
383 | { |
351 | { |
384 | timers [k] = timers [k >> 1]; |
352 | heap [k] = heap [k >> 1]; |
385 | timers [k]->active = k + 1; |
353 | heap [k]->active = k + 1; |
386 | k >>= 1; |
354 | k >>= 1; |
387 | } |
355 | } |
388 | |
356 | |
389 | timers [k] = w; |
357 | heap [k] = w; |
390 | timers [k]->active = k + 1; |
358 | heap [k]->active = k + 1; |
391 | |
359 | |
392 | } |
360 | } |
393 | |
361 | |
394 | static void |
362 | static void |
395 | downheap (WT *timers, int N, int k) |
363 | downheap (WT *heap, int N, int k) |
396 | { |
364 | { |
397 | WT w = timers [k]; |
365 | WT w = heap [k]; |
398 | |
366 | |
399 | while (k < (N >> 1)) |
367 | while (k < (N >> 1)) |
400 | { |
368 | { |
401 | int j = k << 1; |
369 | int j = k << 1; |
402 | |
370 | |
403 | if (j + 1 < N && timers [j]->at > timers [j + 1]->at) |
371 | if (j + 1 < N && heap [j]->at > heap [j + 1]->at) |
404 | ++j; |
372 | ++j; |
405 | |
373 | |
406 | if (w->at <= timers [j]->at) |
374 | if (w->at <= heap [j]->at) |
407 | break; |
375 | break; |
408 | |
376 | |
409 | timers [k] = timers [j]; |
377 | heap [k] = heap [j]; |
410 | timers [k]->active = k + 1; |
378 | heap [k]->active = k + 1; |
411 | k = j; |
379 | k = j; |
412 | } |
380 | } |
413 | |
381 | |
414 | timers [k] = w; |
382 | heap [k] = w; |
415 | timers [k]->active = k + 1; |
383 | heap [k]->active = k + 1; |
416 | } |
384 | } |
417 | |
385 | |
418 | /*****************************************************************************/ |
386 | /*****************************************************************************/ |
419 | |
387 | |
420 | typedef struct |
388 | typedef struct |
… | |
… | |
426 | static ANSIG *signals; |
394 | static ANSIG *signals; |
427 | static int signalmax; |
395 | static int signalmax; |
428 | |
396 | |
429 | static int sigpipe [2]; |
397 | static int sigpipe [2]; |
430 | static sig_atomic_t volatile gotsig; |
398 | static sig_atomic_t volatile gotsig; |
431 | static struct ev_io sigev; |
|
|
432 | |
399 | |
433 | static void |
400 | static void |
434 | signals_init (ANSIG *base, int count) |
401 | signals_init (ANSIG *base, int count) |
435 | { |
402 | { |
436 | while (count--) |
403 | while (count--) |
… | |
… | |
486 | fcntl (sigpipe [0], F_SETFL, O_NONBLOCK); |
453 | fcntl (sigpipe [0], F_SETFL, O_NONBLOCK); |
487 | fcntl (sigpipe [1], F_SETFL, O_NONBLOCK); |
454 | fcntl (sigpipe [1], F_SETFL, O_NONBLOCK); |
488 | #endif |
455 | #endif |
489 | |
456 | |
490 | ev_io_set (&sigev, sigpipe [0], EV_READ); |
457 | ev_io_set (&sigev, sigpipe [0], EV_READ); |
491 | ev_io_start (&sigev); |
458 | ev_io_start (EV_A_ &sigev); |
492 | ev_unref (EV_A); /* child watcher should not keep loop alive */ |
459 | ev_unref (EV_A); /* child watcher should not keep loop alive */ |
493 | } |
460 | } |
494 | |
461 | |
495 | /*****************************************************************************/ |
462 | /*****************************************************************************/ |
496 | |
|
|
497 | static struct ev_idle **idles; |
|
|
498 | static int idlemax, idlecnt; |
|
|
499 | |
|
|
500 | static struct ev_prepare **prepares; |
|
|
501 | static int preparemax, preparecnt; |
|
|
502 | |
|
|
503 | static struct ev_check **checks; |
|
|
504 | static int checkmax, checkcnt; |
|
|
505 | |
|
|
506 | /*****************************************************************************/ |
|
|
507 | |
|
|
508 | static struct ev_child *childs [PID_HASHSIZE]; |
|
|
509 | static struct ev_signal childev; |
|
|
510 | |
463 | |
511 | #ifndef WIN32 |
464 | #ifndef WIN32 |
512 | |
465 | |
513 | #ifndef WCONTINUED |
466 | #ifndef WCONTINUED |
514 | # define WCONTINUED 0 |
467 | # define WCONTINUED 0 |
… | |
… | |
589 | ev_method (EV_P) |
542 | ev_method (EV_P) |
590 | { |
543 | { |
591 | return method; |
544 | return method; |
592 | } |
545 | } |
593 | |
546 | |
594 | int |
547 | static void |
595 | ev_init (EV_P_ int methods) |
548 | loop_init (EV_P_ int methods) |
596 | { |
549 | { |
597 | if (!method) |
550 | if (!method) |
598 | { |
551 | { |
599 | #if EV_USE_MONOTONIC |
552 | #if EV_USE_MONOTONIC |
600 | { |
553 | { |
… | |
… | |
605 | #endif |
558 | #endif |
606 | |
559 | |
607 | rt_now = ev_time (); |
560 | rt_now = ev_time (); |
608 | mn_now = get_clock (); |
561 | mn_now = get_clock (); |
609 | now_floor = mn_now; |
562 | now_floor = mn_now; |
610 | diff = rt_now - mn_now; |
563 | rtmn_diff = rt_now - mn_now; |
611 | |
564 | |
612 | if (pipe (sigpipe)) |
565 | if (pipe (sigpipe)) |
613 | return 0; |
566 | return 0; |
614 | |
567 | |
615 | if (methods == EVMETHOD_AUTO) |
568 | if (methods == EVMETHOD_AUTO) |
… | |
… | |
648 | } |
601 | } |
649 | |
602 | |
650 | return method; |
603 | return method; |
651 | } |
604 | } |
652 | |
605 | |
|
|
606 | #ifdef EV_MULTIPLICITY |
|
|
607 | |
|
|
608 | struct ev_loop * |
|
|
609 | ev_loop_new (int methods) |
|
|
610 | { |
|
|
611 | struct ev_loop *loop = (struct ev_loop *)calloc (1, sizeof (struct ev_loop)); |
|
|
612 | |
|
|
613 | loop_init (EV_A_ methods); |
|
|
614 | |
|
|
615 | return loop; |
|
|
616 | } |
|
|
617 | |
|
|
618 | void |
|
|
619 | ev_loop_delete (EV_P) |
|
|
620 | { |
|
|
621 | /*TODO*/ |
|
|
622 | free (loop); |
|
|
623 | } |
|
|
624 | |
|
|
625 | #else |
|
|
626 | |
|
|
627 | int |
|
|
628 | ev_init (int methods) |
|
|
629 | { |
|
|
630 | loop_init (); |
|
|
631 | } |
|
|
632 | |
|
|
633 | #endif |
|
|
634 | |
653 | /*****************************************************************************/ |
635 | /*****************************************************************************/ |
654 | |
636 | |
655 | void |
637 | void |
656 | ev_fork_prepare (void) |
638 | ev_fork_prepare (void) |
657 | { |
639 | { |
… | |
… | |
665 | } |
647 | } |
666 | |
648 | |
667 | void |
649 | void |
668 | ev_fork_child (void) |
650 | ev_fork_child (void) |
669 | { |
651 | { |
|
|
652 | /*TODO*/ |
|
|
653 | #if !EV_MULTIPLICITY |
670 | #if EV_USE_EPOLL |
654 | #if EV_USE_EPOLL |
671 | if (method == EVMETHOD_EPOLL) |
655 | if (method == EVMETHOD_EPOLL) |
672 | epoll_postfork_child (); |
656 | epoll_postfork_child (EV_A); |
673 | #endif |
657 | #endif |
674 | |
658 | |
675 | ev_io_stop (&sigev); |
659 | ev_io_stop (EV_A_ &sigev); |
676 | close (sigpipe [0]); |
660 | close (sigpipe [0]); |
677 | close (sigpipe [1]); |
661 | close (sigpipe [1]); |
678 | pipe (sigpipe); |
662 | pipe (sigpipe); |
679 | siginit (); |
663 | siginit (EV_A); |
|
|
664 | #endif |
680 | } |
665 | } |
681 | |
666 | |
682 | /*****************************************************************************/ |
667 | /*****************************************************************************/ |
683 | |
668 | |
684 | static void |
669 | static void |
… | |
… | |
714 | downheap ((WT *)timers, timercnt, 0); |
699 | downheap ((WT *)timers, timercnt, 0); |
715 | } |
700 | } |
716 | else |
701 | else |
717 | ev_timer_stop (EV_A_ w); /* nonrepeating: stop timer */ |
702 | ev_timer_stop (EV_A_ w); /* nonrepeating: stop timer */ |
718 | |
703 | |
719 | event ((W)w, EV_TIMEOUT); |
704 | event (EV_A_ (W)w, EV_TIMEOUT); |
720 | } |
705 | } |
721 | } |
706 | } |
722 | |
707 | |
723 | static void |
708 | static void |
724 | periodics_reify (EV_P) |
709 | periodics_reify (EV_P) |
… | |
… | |
740 | event (EV_A_ (W)w, EV_PERIODIC); |
725 | event (EV_A_ (W)w, EV_PERIODIC); |
741 | } |
726 | } |
742 | } |
727 | } |
743 | |
728 | |
744 | static void |
729 | static void |
745 | periodics_reschedule (EV_P_ ev_tstamp diff) |
730 | periodics_reschedule (EV_P) |
746 | { |
731 | { |
747 | int i; |
732 | int i; |
748 | |
733 | |
749 | /* adjust periodics after time jump */ |
734 | /* adjust periodics after time jump */ |
750 | for (i = 0; i < periodiccnt; ++i) |
735 | for (i = 0; i < periodiccnt; ++i) |
… | |
… | |
771 | { |
756 | { |
772 | mn_now = get_clock (); |
757 | mn_now = get_clock (); |
773 | |
758 | |
774 | if (expect_true (mn_now - now_floor < MIN_TIMEJUMP * .5)) |
759 | if (expect_true (mn_now - now_floor < MIN_TIMEJUMP * .5)) |
775 | { |
760 | { |
776 | rt_now = mn_now + diff; |
761 | rt_now = rtmn_diff + mn_now; |
777 | return 0; |
762 | return 0; |
778 | } |
763 | } |
779 | else |
764 | else |
780 | { |
765 | { |
781 | now_floor = mn_now; |
766 | now_floor = mn_now; |
… | |
… | |
792 | #if EV_USE_MONOTONIC |
777 | #if EV_USE_MONOTONIC |
793 | if (expect_true (have_monotonic)) |
778 | if (expect_true (have_monotonic)) |
794 | { |
779 | { |
795 | if (time_update_monotonic (EV_A)) |
780 | if (time_update_monotonic (EV_A)) |
796 | { |
781 | { |
797 | ev_tstamp odiff = diff; |
782 | ev_tstamp odiff = rtmn_diff; |
798 | |
783 | |
799 | for (i = 4; --i; ) /* loop a few times, before making important decisions */ |
784 | for (i = 4; --i; ) /* loop a few times, before making important decisions */ |
800 | { |
785 | { |
801 | diff = rt_now - mn_now; |
786 | rtmn_diff = rt_now - mn_now; |
802 | |
787 | |
803 | if (fabs (odiff - diff) < MIN_TIMEJUMP) |
788 | if (fabs (odiff - rtmn_diff) < MIN_TIMEJUMP) |
804 | return; /* all is well */ |
789 | return; /* all is well */ |
805 | |
790 | |
806 | rt_now = ev_time (); |
791 | rt_now = ev_time (); |
807 | mn_now = get_clock (); |
792 | mn_now = get_clock (); |
808 | now_floor = mn_now; |
793 | now_floor = mn_now; |
809 | } |
794 | } |
810 | |
795 | |
811 | periodics_reschedule (EV_A_ diff - odiff); |
796 | periodics_reschedule (EV_A); |
812 | /* no timer adjustment, as the monotonic clock doesn't jump */ |
797 | /* no timer adjustment, as the monotonic clock doesn't jump */ |
|
|
798 | /* timers_reschedule (EV_A_ rtmn_diff - odiff) */ |
813 | } |
799 | } |
814 | } |
800 | } |
815 | else |
801 | else |
816 | #endif |
802 | #endif |
817 | { |
803 | { |
818 | rt_now = ev_time (); |
804 | rt_now = ev_time (); |
819 | |
805 | |
820 | if (expect_false (mn_now > rt_now || mn_now < rt_now - MAX_BLOCKTIME - MIN_TIMEJUMP)) |
806 | if (expect_false (mn_now > rt_now || mn_now < rt_now - MAX_BLOCKTIME - MIN_TIMEJUMP)) |
821 | { |
807 | { |
822 | periodics_reschedule (EV_A_ rt_now - mn_now); |
808 | periodics_reschedule (EV_A); |
823 | |
809 | |
824 | /* adjust timers. this is easy, as the offset is the same for all */ |
810 | /* adjust timers. this is easy, as the offset is the same for all */ |
825 | for (i = 0; i < timercnt; ++i) |
811 | for (i = 0; i < timercnt; ++i) |
826 | timers [i]->at += diff; |
812 | timers [i]->at += rt_now - mn_now; |
827 | } |
813 | } |
828 | |
814 | |
829 | mn_now = rt_now; |
815 | mn_now = rt_now; |
830 | } |
816 | } |
831 | } |
817 | } |