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

# User Rev Content
1 root 1.1 #include <math.h>
2     #include <stdlib.h>
3 root 1.7 #include <unistd.h>
4     #include <fcntl.h>
5     #include <signal.h>
6 root 1.1
7     #include <stdio.h>
8    
9 root 1.4 #include <assert.h>
10 root 1.1 #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 root 1.6 #define HAVE_REALTIME 1
19 root 1.1 #define HAVE_EPOLL 1
20 root 1.5 #define HAVE_SELECT 1
21 root 1.1
22 root 1.4 #define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
23 root 1.1 #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 root 1.4 static ev_tstamp now, diff; /* monotonic clock */
36 root 1.1 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 root 1.5 static void (*method_modify)(int fd, int oev, int nev);
43 root 1.1 static void (*method_poll)(ev_tstamp timeout);
44    
45 root 1.8 /*****************************************************************************/
46    
47 root 1.1 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 root 1.2 int newcnt = cur ? cur << 1 : 16; \
80 root 1.1 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 root 1.8 /*****************************************************************************/
87    
88 root 1.1 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 root 1.9 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 root 1.8 /*****************************************************************************/
154    
155 root 1.4 static struct ev_timer **atimers;
156     static int atimermax, atimercnt;
157    
158     static struct ev_timer **rtimers;
159     static int rtimermax, rtimercnt;
160 root 1.1
161     static void
162 root 1.4 upheap (struct ev_timer **timers, int k)
163 root 1.1 {
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 root 1.4 downheap (struct ev_timer **timers, int N, int k)
180 root 1.1 {
181     struct ev_timer *w = timers [k];
182    
183 root 1.4 while (k < (N >> 1))
184 root 1.1 {
185     int j = k << 1;
186    
187 root 1.4 if (j + 1 < N && timers [j]->at > timers [j + 1]->at)
188 root 1.1 ++j;
189    
190     if (w->at <= timers [j]->at)
191     break;
192    
193     timers [k] = timers [j];
194 root 1.2 timers [k]->active = k + 1;
195 root 1.1 k = j;
196     }
197    
198     timers [k] = w;
199     timers [k]->active = k + 1;
200     }
201    
202 root 1.8 /*****************************************************************************/
203    
204 root 1.7 typedef struct
205     {
206     struct ev_signal *head;
207     sig_atomic_t gotsig;
208     } ANSIG;
209    
210     static ANSIG *signals;
211 root 1.4 static int signalmax;
212 root 1.1
213 root 1.7 static int sigpipe [2];
214     static sig_atomic_t gotsig;
215     static struct ev_io sigev;
216    
217 root 1.1 static void
218 root 1.7 signals_init (ANSIG *base, int count)
219 root 1.1 {
220     while (count--)
221 root 1.7 {
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 root 1.1 }
272    
273 root 1.8 /*****************************************************************************/
274    
275 root 1.9 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 root 1.1 #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 root 1.4 now = get_clock ();
302     diff = ev_now - now;
303 root 1.1
304 root 1.7 if (pipe (sigpipe))
305     return 0;
306    
307     ev_method = EVMETHOD_NONE;
308 root 1.1 #if HAVE_EPOLL
309 root 1.7 if (ev_method == EVMETHOD_NONE) epoll_init (flags);
310 root 1.1 #endif
311     #if HAVE_SELECT
312 root 1.7 if (ev_method == EVMETHOD_NONE) select_init (flags);
313 root 1.1 #endif
314    
315 root 1.7 if (ev_method)
316     {
317     evw_init (&sigev, sigcb, 0);
318     siginit ();
319     }
320    
321 root 1.1 return ev_method;
322     }
323    
324 root 1.8 /*****************************************************************************/
325    
326 root 1.1 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 root 1.5 if (ev_method == EVMETHOD_EPOLL)
338     epoll_postfork_child ();
339 root 1.1 #endif
340 root 1.7
341     evio_stop (&sigev);
342     close (sigpipe [0]);
343     close (sigpipe [1]);
344     pipe (sigpipe);
345     siginit ();
346 root 1.1 }
347    
348 root 1.8 /*****************************************************************************/
349    
350 root 1.1 static void
351 root 1.5 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 root 1.1 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 root 1.4 timers_reify (struct ev_timer **timers, int timercnt, ev_tstamp now)
397 root 1.1 {
398 root 1.4 while (timercnt && timers [0]->at <= now)
399 root 1.1 {
400     struct ev_timer *w = timers [0];
401    
402 root 1.4 /* first reschedule or stop timer */
403 root 1.1 if (w->repeat)
404     {
405     if (w->is_abs)
406 root 1.4 w->at += floor ((now - w->at) / w->repeat + 1.) * w->repeat;
407 root 1.1 else
408 root 1.4 w->at = now + w->repeat;
409    
410     assert (w->at > now);
411 root 1.1
412 root 1.4 downheap (timers, timercnt, 0);
413 root 1.1 }
414     else
415 root 1.4 {
416     evtimer_stop (w); /* nonrepeating: stop timer */
417     --timercnt; /* maybe pass by reference instead? */
418     }
419 root 1.1
420     event ((struct ev_watcher *)w, EV_TIMEOUT);
421     }
422     }
423    
424 root 1.4 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 root 1.1 int ev_loop_done;
465    
466 root 1.4 void ev_loop (int flags)
467 root 1.1 {
468     double block;
469     ev_loop_done = flags & EVLOOP_ONESHOT;
470    
471 root 1.9 if (checkcnt)
472     {
473     queue_events (checks, checkcnt, EV_CHECK);
474     call_pending ();
475     }
476    
477 root 1.1 do
478     {
479     /* update fd-related kernel structures */
480 root 1.5 fd_reify ();
481 root 1.1
482     /* calculate blocking time */
483 root 1.9 if (flags & EVLOOP_NONBLOCK || idlecnt)
484 root 1.1 block = 0.;
485     else
486     {
487 root 1.4 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 root 1.1 if (block < 0.) block = 0.;
502     }
503    
504     method_poll (block);
505    
506 root 1.4 /* update ev_now, do magic */
507     time_update ();
508    
509 root 1.9 /* queue pending timers and reschedule them */
510 root 1.4 /* absolute timers first */
511     timers_reify (atimers, atimercnt, ev_now);
512     /* relative timers second */
513     timers_reify (rtimers, rtimercnt, now);
514 root 1.1
515 root 1.9 /* 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 root 1.1 call_pending ();
523     }
524     while (!ev_loop_done);
525     }
526    
527 root 1.8 /*****************************************************************************/
528    
529 root 1.1 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 root 1.8 /*****************************************************************************/
569    
570 root 1.1 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 root 1.2 /* this formula differs from the one in timer_reify becuse we do not round up */
610 root 1.1 if (w->repeat)
611     w->at += ceil ((ev_now - w->at) / w->repeat) * w->repeat;
612 root 1.4
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 root 1.1 }
618     else
619 root 1.4 {
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 root 1.1
628     }
629    
630     void
631     evtimer_stop (struct ev_timer *w)
632     {
633     if (!ev_is_active (w))
634     return;
635    
636 root 1.4 if (w->is_abs)
637 root 1.2 {
638 root 1.4 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 root 1.2 }
652    
653 root 1.1 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 root 1.7 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 root 1.1 }
675    
676     void
677     evsignal_stop (struct ev_signal *w)
678     {
679     if (!ev_is_active (w))
680     return;
681    
682 root 1.7 wlist_del ((struct ev_watcher_list **)&signals [w->signum - 1].head, (struct ev_watcher_list *)w);
683 root 1.1 ev_stop ((struct ev_watcher *)w);
684 root 1.7
685     if (!signals [w->signum - 1].head)
686     signal (w->signum, SIG_DFL);
687 root 1.1 }
688    
689 root 1.9 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 root 1.1 /*****************************************************************************/
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 root 1.4 //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 root 1.1 }
737    
738 root 1.7 static void
739     scb (struct ev_signal *w, int revents)
740     {
741     fprintf (stderr, "signal %x,%d\n", revents, w->signum);
742     }
743    
744 root 1.9 static void
745     gcb (struct ev_signal *w, int revents)
746     {
747     fprintf (stderr, "generic %x\n", revents);
748     }
749    
750 root 1.1 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 root 1.4 struct ev_timer t[10000];
761 root 1.2
762 root 1.9 #if 0
763 root 1.2 int i;
764 root 1.4 for (i = 0; i < 10000; ++i)
765 root 1.2 {
766     struct ev_timer *w = t + i;
767     evw_init (w, ocb, i);
768 root 1.4 evtimer_set_abs (w, drand48 (), 0.99775533);
769 root 1.2 evtimer_start (w);
770     if (drand48 () < 0.5)
771     evtimer_stop (w);
772     }
773 root 1.4 #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 root 1.1
780 root 1.7 struct ev_signal sig;
781     evw_init (&sig, scb, 65535);
782     evsignal_set (&sig, SIGQUIT);
783     evsignal_start (&sig);
784    
785 root 1.9 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 root 1.1 ev_loop (0);
794    
795     return 0;
796     }
797    
798     #endif
799    
800    
801    
802