… | |
… | |
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 int have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */ |
|
|
119 | |
118 | /*****************************************************************************/ |
120 | /*****************************************************************************/ |
119 | |
121 | |
120 | typedef struct |
122 | typedef struct |
121 | { |
123 | { |
122 | struct ev_watcher_list *head; |
124 | struct ev_watcher_list *head; |
… | |
… | |
129 | W w; |
131 | W w; |
130 | int events; |
132 | int events; |
131 | } ANPENDING; |
133 | } ANPENDING; |
132 | |
134 | |
133 | #ifdef EV_MULTIPLICITY |
135 | #ifdef EV_MULTIPLICITY |
|
|
136 | |
134 | struct ev_loop |
137 | struct ev_loop |
135 | { |
138 | { |
136 | # define VAR(name,decl) decl |
139 | # define VAR(name,decl) decl; |
137 | # include "ev_vars.h" |
140 | # include "ev_vars.h" |
138 | }; |
141 | }; |
|
|
142 | # undef VAR |
|
|
143 | # include "ev_wrap.h" |
|
|
144 | |
139 | #else |
145 | #else |
|
|
146 | |
140 | # define VAR(name,decl) static decl |
147 | # define VAR(name,decl) static decl; |
141 | # include "ev_vars.h" |
148 | # include "ev_vars.h" |
142 | #endif |
|
|
143 | #undef VAR |
149 | # undef VAR |
|
|
150 | |
|
|
151 | #endif |
144 | |
152 | |
145 | /*****************************************************************************/ |
153 | /*****************************************************************************/ |
146 | |
154 | |
147 | inline ev_tstamp |
155 | inline ev_tstamp |
148 | ev_time (void) |
156 | ev_time (void) |
… | |
… | |
333 | } |
341 | } |
334 | |
342 | |
335 | /*****************************************************************************/ |
343 | /*****************************************************************************/ |
336 | |
344 | |
337 | static void |
345 | static void |
338 | upheap (WT *timers, int k) |
346 | upheap (WT *heap, int k) |
339 | { |
347 | { |
340 | WT w = timers [k]; |
348 | WT w = heap [k]; |
341 | |
349 | |
342 | while (k && timers [k >> 1]->at > w->at) |
350 | while (k && heap [k >> 1]->at > w->at) |
343 | { |
351 | { |
344 | timers [k] = timers [k >> 1]; |
352 | heap [k] = heap [k >> 1]; |
345 | timers [k]->active = k + 1; |
353 | heap [k]->active = k + 1; |
346 | k >>= 1; |
354 | k >>= 1; |
347 | } |
355 | } |
348 | |
356 | |
349 | timers [k] = w; |
357 | heap [k] = w; |
350 | timers [k]->active = k + 1; |
358 | heap [k]->active = k + 1; |
351 | |
359 | |
352 | } |
360 | } |
353 | |
361 | |
354 | static void |
362 | static void |
355 | downheap (WT *timers, int N, int k) |
363 | downheap (WT *heap, int N, int k) |
356 | { |
364 | { |
357 | WT w = timers [k]; |
365 | WT w = heap [k]; |
358 | |
366 | |
359 | while (k < (N >> 1)) |
367 | while (k < (N >> 1)) |
360 | { |
368 | { |
361 | int j = k << 1; |
369 | int j = k << 1; |
362 | |
370 | |
363 | if (j + 1 < N && timers [j]->at > timers [j + 1]->at) |
371 | if (j + 1 < N && heap [j]->at > heap [j + 1]->at) |
364 | ++j; |
372 | ++j; |
365 | |
373 | |
366 | if (w->at <= timers [j]->at) |
374 | if (w->at <= heap [j]->at) |
367 | break; |
375 | break; |
368 | |
376 | |
369 | timers [k] = timers [j]; |
377 | heap [k] = heap [j]; |
370 | timers [k]->active = k + 1; |
378 | heap [k]->active = k + 1; |
371 | k = j; |
379 | k = j; |
372 | } |
380 | } |
373 | |
381 | |
374 | timers [k] = w; |
382 | heap [k] = w; |
375 | timers [k]->active = k + 1; |
383 | heap [k]->active = k + 1; |
376 | } |
384 | } |
377 | |
385 | |
378 | /*****************************************************************************/ |
386 | /*****************************************************************************/ |
379 | |
387 | |
380 | typedef struct |
388 | typedef struct |
… | |
… | |
445 | fcntl (sigpipe [0], F_SETFL, O_NONBLOCK); |
453 | fcntl (sigpipe [0], F_SETFL, O_NONBLOCK); |
446 | fcntl (sigpipe [1], F_SETFL, O_NONBLOCK); |
454 | fcntl (sigpipe [1], F_SETFL, O_NONBLOCK); |
447 | #endif |
455 | #endif |
448 | |
456 | |
449 | ev_io_set (&sigev, sigpipe [0], EV_READ); |
457 | ev_io_set (&sigev, sigpipe [0], EV_READ); |
450 | ev_io_start (&sigev); |
458 | ev_io_start (EV_A_ &sigev); |
451 | ev_unref (EV_A); /* child watcher should not keep loop alive */ |
459 | ev_unref (EV_A); /* child watcher should not keep loop alive */ |
452 | } |
460 | } |
453 | |
461 | |
454 | /*****************************************************************************/ |
462 | /*****************************************************************************/ |
455 | |
463 | |
… | |
… | |
534 | ev_method (EV_P) |
542 | ev_method (EV_P) |
535 | { |
543 | { |
536 | return method; |
544 | return method; |
537 | } |
545 | } |
538 | |
546 | |
539 | int |
547 | static void |
540 | ev_init (EV_P_ int methods) |
548 | loop_init (EV_P_ int methods) |
541 | { |
549 | { |
542 | #ifdef EV_MULTIPLICITY |
|
|
543 | memset (loop, 0, sizeof (struct ev_loop)); |
|
|
544 | #endif |
|
|
545 | |
|
|
546 | if (!method) |
550 | if (!method) |
547 | { |
551 | { |
548 | #if EV_USE_MONOTONIC |
552 | #if EV_USE_MONOTONIC |
549 | { |
553 | { |
550 | struct timespec ts; |
554 | struct timespec ts; |
… | |
… | |
554 | #endif |
558 | #endif |
555 | |
559 | |
556 | rt_now = ev_time (); |
560 | rt_now = ev_time (); |
557 | mn_now = get_clock (); |
561 | mn_now = get_clock (); |
558 | now_floor = mn_now; |
562 | now_floor = mn_now; |
559 | diff = rt_now - mn_now; |
563 | rtmn_diff = rt_now - mn_now; |
560 | |
564 | |
561 | if (pipe (sigpipe)) |
565 | if (pipe (sigpipe)) |
562 | return 0; |
566 | return 0; |
563 | |
567 | |
564 | if (methods == EVMETHOD_AUTO) |
568 | if (methods == EVMETHOD_AUTO) |
… | |
… | |
597 | } |
601 | } |
598 | |
602 | |
599 | return method; |
603 | return method; |
600 | } |
604 | } |
601 | |
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 | |
602 | /*****************************************************************************/ |
635 | /*****************************************************************************/ |
603 | |
636 | |
604 | void |
637 | void |
605 | ev_fork_prepare (void) |
638 | ev_fork_prepare (void) |
606 | { |
639 | { |
… | |
… | |
614 | } |
647 | } |
615 | |
648 | |
616 | void |
649 | void |
617 | ev_fork_child (void) |
650 | ev_fork_child (void) |
618 | { |
651 | { |
|
|
652 | /*TODO*/ |
|
|
653 | #if !EV_MULTIPLICITY |
619 | #if EV_USE_EPOLL |
654 | #if EV_USE_EPOLL |
620 | if (method == EVMETHOD_EPOLL) |
655 | if (method == EVMETHOD_EPOLL) |
621 | epoll_postfork_child (); |
656 | epoll_postfork_child (EV_A); |
622 | #endif |
657 | #endif |
623 | |
658 | |
624 | ev_io_stop (&sigev); |
659 | ev_io_stop (EV_A_ &sigev); |
625 | close (sigpipe [0]); |
660 | close (sigpipe [0]); |
626 | close (sigpipe [1]); |
661 | close (sigpipe [1]); |
627 | pipe (sigpipe); |
662 | pipe (sigpipe); |
628 | siginit (); |
663 | siginit (EV_A); |
|
|
664 | #endif |
629 | } |
665 | } |
630 | |
666 | |
631 | /*****************************************************************************/ |
667 | /*****************************************************************************/ |
632 | |
668 | |
633 | static void |
669 | static void |
… | |
… | |
663 | downheap ((WT *)timers, timercnt, 0); |
699 | downheap ((WT *)timers, timercnt, 0); |
664 | } |
700 | } |
665 | else |
701 | else |
666 | ev_timer_stop (EV_A_ w); /* nonrepeating: stop timer */ |
702 | ev_timer_stop (EV_A_ w); /* nonrepeating: stop timer */ |
667 | |
703 | |
668 | event ((W)w, EV_TIMEOUT); |
704 | event (EV_A_ (W)w, EV_TIMEOUT); |
669 | } |
705 | } |
670 | } |
706 | } |
671 | |
707 | |
672 | static void |
708 | static void |
673 | periodics_reify (EV_P) |
709 | periodics_reify (EV_P) |
… | |
… | |
689 | event (EV_A_ (W)w, EV_PERIODIC); |
725 | event (EV_A_ (W)w, EV_PERIODIC); |
690 | } |
726 | } |
691 | } |
727 | } |
692 | |
728 | |
693 | static void |
729 | static void |
694 | periodics_reschedule (EV_P_ ev_tstamp diff) |
730 | periodics_reschedule (EV_P) |
695 | { |
731 | { |
696 | int i; |
732 | int i; |
697 | |
733 | |
698 | /* adjust periodics after time jump */ |
734 | /* adjust periodics after time jump */ |
699 | for (i = 0; i < periodiccnt; ++i) |
735 | for (i = 0; i < periodiccnt; ++i) |
… | |
… | |
720 | { |
756 | { |
721 | mn_now = get_clock (); |
757 | mn_now = get_clock (); |
722 | |
758 | |
723 | if (expect_true (mn_now - now_floor < MIN_TIMEJUMP * .5)) |
759 | if (expect_true (mn_now - now_floor < MIN_TIMEJUMP * .5)) |
724 | { |
760 | { |
725 | rt_now = mn_now + diff; |
761 | rt_now = rtmn_diff + mn_now; |
726 | return 0; |
762 | return 0; |
727 | } |
763 | } |
728 | else |
764 | else |
729 | { |
765 | { |
730 | now_floor = mn_now; |
766 | now_floor = mn_now; |
… | |
… | |
741 | #if EV_USE_MONOTONIC |
777 | #if EV_USE_MONOTONIC |
742 | if (expect_true (have_monotonic)) |
778 | if (expect_true (have_monotonic)) |
743 | { |
779 | { |
744 | if (time_update_monotonic (EV_A)) |
780 | if (time_update_monotonic (EV_A)) |
745 | { |
781 | { |
746 | ev_tstamp odiff = diff; |
782 | ev_tstamp odiff = rtmn_diff; |
747 | |
783 | |
748 | 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 */ |
749 | { |
785 | { |
750 | diff = rt_now - mn_now; |
786 | rtmn_diff = rt_now - mn_now; |
751 | |
787 | |
752 | if (fabs (odiff - diff) < MIN_TIMEJUMP) |
788 | if (fabs (odiff - rtmn_diff) < MIN_TIMEJUMP) |
753 | return; /* all is well */ |
789 | return; /* all is well */ |
754 | |
790 | |
755 | rt_now = ev_time (); |
791 | rt_now = ev_time (); |
756 | mn_now = get_clock (); |
792 | mn_now = get_clock (); |
757 | now_floor = mn_now; |
793 | now_floor = mn_now; |
758 | } |
794 | } |
759 | |
795 | |
760 | periodics_reschedule (EV_A_ diff - odiff); |
796 | periodics_reschedule (EV_A); |
761 | /* 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) */ |
762 | } |
799 | } |
763 | } |
800 | } |
764 | else |
801 | else |
765 | #endif |
802 | #endif |
766 | { |
803 | { |
767 | rt_now = ev_time (); |
804 | rt_now = ev_time (); |
768 | |
805 | |
769 | 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)) |
770 | { |
807 | { |
771 | periodics_reschedule (EV_A_ rt_now - mn_now); |
808 | periodics_reschedule (EV_A); |
772 | |
809 | |
773 | /* 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 */ |
774 | for (i = 0; i < timercnt; ++i) |
811 | for (i = 0; i < timercnt; ++i) |
775 | timers [i]->at += diff; |
812 | timers [i]->at += rt_now - mn_now; |
776 | } |
813 | } |
777 | |
814 | |
778 | mn_now = rt_now; |
815 | mn_now = rt_now; |
779 | } |
816 | } |
780 | } |
817 | } |