ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/ev.c
Revision: 1.9
Committed: Wed Oct 31 07:24:17 2007 UTC (16 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.8: +79 -28 lines
Log Message:
implement idle and check watchers, rmeove flawed hook system

File Contents

# Content
1 #include <math.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <signal.h>
6
7 #include <stdio.h>
8
9 #include <assert.h>
10 #include <errno.h>
11 #include <sys/time.h>
12 #include <time.h>
13
14 #ifdef CLOCK_MONOTONIC
15 # define HAVE_MONOTONIC 1
16 #endif
17
18 #define HAVE_REALTIME 1
19 #define HAVE_EPOLL 1
20 #define HAVE_SELECT 1
21
22 #define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
23 #define MAX_BLOCKTIME 60.
24
25 #include "ev.h"
26
27 struct ev_watcher {
28 EV_WATCHER (ev_watcher);
29 };
30
31 struct ev_watcher_list {
32 EV_WATCHER_LIST (ev_watcher_list);
33 };
34
35 static ev_tstamp now, diff; /* monotonic clock */
36 ev_tstamp ev_now;
37 int ev_method;
38
39 static int have_monotonic; /* runtime */
40
41 static ev_tstamp method_fudge; /* stupid epoll-returns-early bug */
42 static void (*method_modify)(int fd, int oev, int nev);
43 static void (*method_poll)(ev_tstamp timeout);
44
45 /*****************************************************************************/
46
47 ev_tstamp
48 ev_time (void)
49 {
50 #if HAVE_REALTIME
51 struct timespec ts;
52 clock_gettime (CLOCK_REALTIME, &ts);
53 return ts.tv_sec + ts.tv_nsec * 1e-9;
54 #else
55 struct timeval tv;
56 gettimeofday (&tv, 0);
57 return tv.tv_sec + tv.tv_usec * 1e-6;
58 #endif
59 }
60
61 static ev_tstamp
62 get_clock (void)
63 {
64 #if HAVE_MONOTONIC
65 if (have_monotonic)
66 {
67 struct timespec ts;
68 clock_gettime (CLOCK_MONOTONIC, &ts);
69 return ts.tv_sec + ts.tv_nsec * 1e-9;
70 }
71 #endif
72
73 return ev_time ();
74 }
75
76 #define array_needsize(base,cur,cnt,init) \
77 if ((cnt) > cur) \
78 { \
79 int newcnt = cur ? cur << 1 : 16; \
80 fprintf (stderr, "resize(" # base ") from %d to %d\n", cur, newcnt);\
81 base = realloc (base, sizeof (*base) * (newcnt)); \
82 init (base + cur, newcnt - cur); \
83 cur = newcnt; \
84 }
85
86 /*****************************************************************************/
87
88 typedef struct
89 {
90 struct ev_io *head;
91 unsigned char wev, rev; /* want, received event set */
92 } ANFD;
93
94 static ANFD *anfds;
95 static int anfdmax;
96
97 static int *fdchanges;
98 static int fdchangemax, fdchangecnt;
99
100 static void
101 anfds_init (ANFD *base, int count)
102 {
103 while (count--)
104 {
105 base->head = 0;
106 base->wev = base->rev = EV_NONE;
107 ++base;
108 }
109 }
110
111 typedef struct
112 {
113 struct ev_watcher *w;
114 int events;
115 } ANPENDING;
116
117 static ANPENDING *pendings;
118 static int pendingmax, pendingcnt;
119
120 static void
121 event (struct ev_watcher *w, int events)
122 {
123 w->pending = ++pendingcnt;
124 array_needsize (pendings, pendingmax, pendingcnt, );
125 pendings [pendingcnt - 1].w = w;
126 pendings [pendingcnt - 1].events = events;
127 }
128
129 static void
130 fd_event (int fd, int events)
131 {
132 ANFD *anfd = anfds + fd;
133 struct ev_io *w;
134
135 for (w = anfd->head; w; w = w->next)
136 {
137 int ev = w->events & events;
138
139 if (ev)
140 event ((struct ev_watcher *)w, ev);
141 }
142 }
143
144 static void
145 queue_events (struct ev_watcher **events, int eventcnt, int type)
146 {
147 int i;
148
149 for (i = 0; i < eventcnt; ++i)
150 event (events [i], type);
151 }
152
153 /*****************************************************************************/
154
155 static struct ev_timer **atimers;
156 static int atimermax, atimercnt;
157
158 static struct ev_timer **rtimers;
159 static int rtimermax, rtimercnt;
160
161 static void
162 upheap (struct ev_timer **timers, int k)
163 {
164 struct ev_timer *w = timers [k];
165
166 while (k && timers [k >> 1]->at > w->at)
167 {
168 timers [k] = timers [k >> 1];
169 timers [k]->active = k + 1;
170 k >>= 1;
171 }
172
173 timers [k] = w;
174 timers [k]->active = k + 1;
175
176 }
177
178 static void
179 downheap (struct ev_timer **timers, int N, int k)
180 {
181 struct ev_timer *w = timers [k];
182
183 while (k < (N >> 1))
184 {
185 int j = k << 1;
186
187 if (j + 1 < N && timers [j]->at > timers [j + 1]->at)
188 ++j;
189
190 if (w->at <= timers [j]->at)
191 break;
192
193 timers [k] = timers [j];
194 timers [k]->active = k + 1;
195 k = j;
196 }
197
198 timers [k] = w;
199 timers [k]->active = k + 1;
200 }
201
202 /*****************************************************************************/
203
204 typedef struct
205 {
206 struct ev_signal *head;
207 sig_atomic_t gotsig;
208 } ANSIG;
209
210 static ANSIG *signals;
211 static int signalmax;
212
213 static int sigpipe [2];
214 static sig_atomic_t gotsig;
215 static struct ev_io sigev;
216
217 static void
218 signals_init (ANSIG *base, int count)
219 {
220 while (count--)
221 {
222 base->head = 0;
223 base->gotsig = 0;
224 ++base;
225 }
226 }
227
228 static void
229 sighandler (int signum)
230 {
231 signals [signum - 1].gotsig = 1;
232
233 if (!gotsig)
234 {
235 gotsig = 1;
236 write (sigpipe [1], &gotsig, 1);
237 }
238 }
239
240 static void
241 sigcb (struct ev_io *iow, int revents)
242 {
243 struct ev_signal *w;
244 int sig;
245
246 gotsig = 0;
247 read (sigpipe [0], &revents, 1);
248
249 for (sig = signalmax; sig--; )
250 if (signals [sig].gotsig)
251 {
252 signals [sig].gotsig = 0;
253
254 for (w = signals [sig].head; w; w = w->next)
255 event ((struct ev_watcher *)w, EV_SIGNAL);
256 }
257 }
258
259 static void
260 siginit (void)
261 {
262 fcntl (sigpipe [0], F_SETFD, FD_CLOEXEC);
263 fcntl (sigpipe [1], F_SETFD, FD_CLOEXEC);
264
265 /* rather than sort out wether we really need nb, set it */
266 fcntl (sigpipe [0], F_SETFL, O_NONBLOCK);
267 fcntl (sigpipe [1], F_SETFL, O_NONBLOCK);
268
269 evio_set (&sigev, sigpipe [0], EV_READ);
270 evio_start (&sigev);
271 }
272
273 /*****************************************************************************/
274
275 static struct ev_idle **idles;
276 static int idlemax, idlecnt;
277
278 static struct ev_check **checks;
279 static int checkmax, checkcnt;
280
281 /*****************************************************************************/
282
283 #if HAVE_EPOLL
284 # include "ev_epoll.c"
285 #endif
286 #if HAVE_SELECT
287 # include "ev_select.c"
288 #endif
289
290 int ev_init (int flags)
291 {
292 #if HAVE_MONOTONIC
293 {
294 struct timespec ts;
295 if (!clock_gettime (CLOCK_MONOTONIC, &ts))
296 have_monotonic = 1;
297 }
298 #endif
299
300 ev_now = ev_time ();
301 now = get_clock ();
302 diff = ev_now - now;
303
304 if (pipe (sigpipe))
305 return 0;
306
307 ev_method = EVMETHOD_NONE;
308 #if HAVE_EPOLL
309 if (ev_method == EVMETHOD_NONE) epoll_init (flags);
310 #endif
311 #if HAVE_SELECT
312 if (ev_method == EVMETHOD_NONE) select_init (flags);
313 #endif
314
315 if (ev_method)
316 {
317 evw_init (&sigev, sigcb, 0);
318 siginit ();
319 }
320
321 return ev_method;
322 }
323
324 /*****************************************************************************/
325
326 void ev_prefork (void)
327 {
328 }
329
330 void ev_postfork_parent (void)
331 {
332 }
333
334 void ev_postfork_child (void)
335 {
336 #if HAVE_EPOLL
337 if (ev_method == EVMETHOD_EPOLL)
338 epoll_postfork_child ();
339 #endif
340
341 evio_stop (&sigev);
342 close (sigpipe [0]);
343 close (sigpipe [1]);
344 pipe (sigpipe);
345 siginit ();
346 }
347
348 /*****************************************************************************/
349
350 static void
351 fd_reify (void)
352 {
353 int i;
354
355 for (i = 0; i < fdchangecnt; ++i)
356 {
357 int fd = fdchanges [i];
358 ANFD *anfd = anfds + fd;
359 struct ev_io *w;
360
361 int wev = 0;
362
363 for (w = anfd->head; w; w = w->next)
364 wev |= w->events;
365
366 if (anfd->wev != wev)
367 {
368 method_modify (fd, anfd->wev, wev);
369 anfd->wev = wev;
370 }
371 }
372
373 fdchangecnt = 0;
374 }
375
376 static void
377 call_pending ()
378 {
379 int i;
380
381 for (i = 0; i < pendingcnt; ++i)
382 {
383 ANPENDING *p = pendings + i;
384
385 if (p->w)
386 {
387 p->w->pending = 0;
388 p->w->cb (p->w, p->events);
389 }
390 }
391
392 pendingcnt = 0;
393 }
394
395 static void
396 timers_reify (struct ev_timer **timers, int timercnt, ev_tstamp now)
397 {
398 while (timercnt && timers [0]->at <= now)
399 {
400 struct ev_timer *w = timers [0];
401
402 /* first reschedule or stop timer */
403 if (w->repeat)
404 {
405 if (w->is_abs)
406 w->at += floor ((now - w->at) / w->repeat + 1.) * w->repeat;
407 else
408 w->at = now + w->repeat;
409
410 assert (w->at > now);
411
412 downheap (timers, timercnt, 0);
413 }
414 else
415 {
416 evtimer_stop (w); /* nonrepeating: stop timer */
417 --timercnt; /* maybe pass by reference instead? */
418 }
419
420 event ((struct ev_watcher *)w, EV_TIMEOUT);
421 }
422 }
423
424 static void
425 time_update ()
426 {
427 int i;
428 ev_now = ev_time ();
429
430 if (have_monotonic)
431 {
432 ev_tstamp odiff = diff;
433
434 /* detecting time jumps is much more difficult */
435 for (i = 2; --i; ) /* loop a few times, before making important decisions */
436 {
437 now = get_clock ();
438 diff = ev_now - now;
439
440 if (fabs (odiff - diff) < MIN_TIMEJUMP)
441 return; /* all is well */
442
443 ev_now = ev_time ();
444 }
445
446 /* time jump detected, reschedule atimers */
447 for (i = 0; i < atimercnt; ++i)
448 {
449 struct ev_timer *w = atimers [i];
450 w->at += ceil ((ev_now - w->at) / w->repeat + 1.) * w->repeat;
451 }
452 }
453 else
454 {
455 if (now > ev_now || now < ev_now - MAX_BLOCKTIME - MIN_TIMEJUMP)
456 /* time jump detected, adjust rtimers */
457 for (i = 0; i < rtimercnt; ++i)
458 rtimers [i]->at += ev_now - now;
459
460 now = ev_now;
461 }
462 }
463
464 int ev_loop_done;
465
466 void ev_loop (int flags)
467 {
468 double block;
469 ev_loop_done = flags & EVLOOP_ONESHOT;
470
471 if (checkcnt)
472 {
473 queue_events (checks, checkcnt, EV_CHECK);
474 call_pending ();
475 }
476
477 do
478 {
479 /* update fd-related kernel structures */
480 fd_reify ();
481
482 /* calculate blocking time */
483 if (flags & EVLOOP_NONBLOCK || idlecnt)
484 block = 0.;
485 else
486 {
487 block = MAX_BLOCKTIME;
488
489 if (rtimercnt)
490 {
491 ev_tstamp to = rtimers [0]->at - get_clock () + method_fudge;
492 if (block > to) block = to;
493 }
494
495 if (atimercnt)
496 {
497 ev_tstamp to = atimers [0]->at - ev_time () + method_fudge;
498 if (block > to) block = to;
499 }
500
501 if (block < 0.) block = 0.;
502 }
503
504 method_poll (block);
505
506 /* update ev_now, do magic */
507 time_update ();
508
509 /* queue pending timers and reschedule them */
510 /* absolute timers first */
511 timers_reify (atimers, atimercnt, ev_now);
512 /* relative timers second */
513 timers_reify (rtimers, rtimercnt, now);
514
515 /* queue idle watchers unless io or timers are pending */
516 if (!pendingcnt)
517 queue_events (idles, idlecnt, EV_IDLE);
518
519 /* queue check and possibly idle watchers */
520 queue_events (checks, checkcnt, EV_CHECK);
521
522 call_pending ();
523 }
524 while (!ev_loop_done);
525 }
526
527 /*****************************************************************************/
528
529 static void
530 wlist_add (struct ev_watcher_list **head, struct ev_watcher_list *elem)
531 {
532 elem->next = *head;
533 *head = elem;
534 }
535
536 static void
537 wlist_del (struct ev_watcher_list **head, struct ev_watcher_list *elem)
538 {
539 while (*head)
540 {
541 if (*head == elem)
542 {
543 *head = elem->next;
544 return;
545 }
546
547 head = &(*head)->next;
548 }
549 }
550
551 static void
552 ev_start (struct ev_watcher *w, int active)
553 {
554 w->pending = 0;
555 w->active = active;
556 }
557
558 static void
559 ev_stop (struct ev_watcher *w)
560 {
561 if (w->pending)
562 pendings [w->pending - 1].w = 0;
563
564 w->active = 0;
565 /* nop */
566 }
567
568 /*****************************************************************************/
569
570 void
571 evio_start (struct ev_io *w)
572 {
573 if (ev_is_active (w))
574 return;
575
576 int fd = w->fd;
577
578 ev_start ((struct ev_watcher *)w, 1);
579 array_needsize (anfds, anfdmax, fd + 1, anfds_init);
580 wlist_add ((struct ev_watcher_list **)&anfds[fd].head, (struct ev_watcher_list *)w);
581
582 ++fdchangecnt;
583 array_needsize (fdchanges, fdchangemax, fdchangecnt, );
584 fdchanges [fdchangecnt - 1] = fd;
585 }
586
587 void
588 evio_stop (struct ev_io *w)
589 {
590 if (!ev_is_active (w))
591 return;
592
593 wlist_del ((struct ev_watcher_list **)&anfds[w->fd].head, (struct ev_watcher_list *)w);
594 ev_stop ((struct ev_watcher *)w);
595
596 ++fdchangecnt;
597 array_needsize (fdchanges, fdchangemax, fdchangecnt, );
598 fdchanges [fdchangecnt - 1] = w->fd;
599 }
600
601 void
602 evtimer_start (struct ev_timer *w)
603 {
604 if (ev_is_active (w))
605 return;
606
607 if (w->is_abs)
608 {
609 /* this formula differs from the one in timer_reify becuse we do not round up */
610 if (w->repeat)
611 w->at += ceil ((ev_now - w->at) / w->repeat) * w->repeat;
612
613 ev_start ((struct ev_watcher *)w, ++atimercnt);
614 array_needsize (atimers, atimermax, atimercnt, );
615 atimers [atimercnt - 1] = w;
616 upheap (atimers, atimercnt - 1);
617 }
618 else
619 {
620 w->at += now;
621
622 ev_start ((struct ev_watcher *)w, ++rtimercnt);
623 array_needsize (rtimers, rtimermax, rtimercnt, );
624 rtimers [rtimercnt - 1] = w;
625 upheap (rtimers, rtimercnt - 1);
626 }
627
628 }
629
630 void
631 evtimer_stop (struct ev_timer *w)
632 {
633 if (!ev_is_active (w))
634 return;
635
636 if (w->is_abs)
637 {
638 if (w->active < atimercnt--)
639 {
640 atimers [w->active - 1] = atimers [atimercnt];
641 downheap (atimers, atimercnt, w->active - 1);
642 }
643 }
644 else
645 {
646 if (w->active < rtimercnt--)
647 {
648 rtimers [w->active - 1] = rtimers [rtimercnt];
649 downheap (rtimers, rtimercnt, w->active - 1);
650 }
651 }
652
653 ev_stop ((struct ev_watcher *)w);
654 }
655
656 void
657 evsignal_start (struct ev_signal *w)
658 {
659 if (ev_is_active (w))
660 return;
661
662 ev_start ((struct ev_watcher *)w, 1);
663 array_needsize (signals, signalmax, w->signum, signals_init);
664 wlist_add ((struct ev_watcher_list **)&signals [w->signum - 1].head, (struct ev_watcher_list *)w);
665
666 if (!w->next)
667 {
668 struct sigaction sa;
669 sa.sa_handler = sighandler;
670 sigfillset (&sa.sa_mask);
671 sa.sa_flags = 0;
672 sigaction (w->signum, &sa, 0);
673 }
674 }
675
676 void
677 evsignal_stop (struct ev_signal *w)
678 {
679 if (!ev_is_active (w))
680 return;
681
682 wlist_del ((struct ev_watcher_list **)&signals [w->signum - 1].head, (struct ev_watcher_list *)w);
683 ev_stop ((struct ev_watcher *)w);
684
685 if (!signals [w->signum - 1].head)
686 signal (w->signum, SIG_DFL);
687 }
688
689 void evidle_start (struct ev_idle *w)
690 {
691 if (ev_is_active (w))
692 return;
693
694 ev_start ((struct ev_watcher *)w, ++idlecnt);
695 array_needsize (idles, idlemax, idlecnt, );
696 idles [idlecnt - 1] = w;
697 }
698
699 void evidle_stop (struct ev_idle *w)
700 {
701 idles [w->active - 1] = idles [--idlecnt];
702 ev_stop ((struct ev_watcher *)w);
703 }
704
705 void evcheck_start (struct ev_check *w)
706 {
707 if (ev_is_active (w))
708 return;
709
710 ev_start ((struct ev_watcher *)w, ++checkcnt);
711 array_needsize (checks, checkmax, checkcnt, );
712 checks [checkcnt - 1] = w;
713 }
714
715 void evcheck_stop (struct ev_check *w)
716 {
717 checks [w->active - 1] = checks [--checkcnt];
718 ev_stop ((struct ev_watcher *)w);
719 }
720
721 /*****************************************************************************/
722 #if 1
723
724 static void
725 sin_cb (struct ev_io *w, int revents)
726 {
727 fprintf (stderr, "sin %d, revents %d\n", w->fd, revents);
728 }
729
730 static void
731 ocb (struct ev_timer *w, int revents)
732 {
733 //fprintf (stderr, "timer %f,%f (%x) (%f) d%p\n", w->at, w->repeat, revents, w->at - ev_time (), w->data);
734 evtimer_stop (w);
735 evtimer_start (w);
736 }
737
738 static void
739 scb (struct ev_signal *w, int revents)
740 {
741 fprintf (stderr, "signal %x,%d\n", revents, w->signum);
742 }
743
744 static void
745 gcb (struct ev_signal *w, int revents)
746 {
747 fprintf (stderr, "generic %x\n", revents);
748 }
749
750 int main (void)
751 {
752 struct ev_io sin;
753
754 ev_init (0);
755
756 evw_init (&sin, sin_cb, 55);
757 evio_set (&sin, 0, EV_READ);
758 evio_start (&sin);
759
760 struct ev_timer t[10000];
761
762 #if 0
763 int i;
764 for (i = 0; i < 10000; ++i)
765 {
766 struct ev_timer *w = t + i;
767 evw_init (w, ocb, i);
768 evtimer_set_abs (w, drand48 (), 0.99775533);
769 evtimer_start (w);
770 if (drand48 () < 0.5)
771 evtimer_stop (w);
772 }
773 #endif
774
775 struct ev_timer t1;
776 evw_init (&t1, ocb, 0);
777 evtimer_set_abs (&t1, 5, 10);
778 evtimer_start (&t1);
779
780 struct ev_signal sig;
781 evw_init (&sig, scb, 65535);
782 evsignal_set (&sig, SIGQUIT);
783 evsignal_start (&sig);
784
785 struct ev_check cw;
786 evw_init (&cw, gcb, 0);
787 evcheck_start (&cw);
788
789 struct ev_idle iw;
790 evw_init (&iw, gcb, 0);
791 evidle_start (&iw);
792
793 ev_loop (0);
794
795 return 0;
796 }
797
798 #endif
799
800
801
802