]> git.llucax.com Git - software/libev.git/blob - ev.c
implement idle and check watchers, rmeove flawed hook system
[software/libev.git] / ev.c
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