ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/ev.c
(Generate patch)

Comparing libev/ev.c (file contents):
Revision 1.2 by root, Tue Oct 30 21:42:12 2007 UTC vs.
Revision 1.9 by root, Wed Oct 31 07:24:17 2007 UTC

1#include <math.h> 1#include <math.h>
2#include <stdlib.h> 2#include <stdlib.h>
3#include <unistd.h>
4#include <fcntl.h>
5#include <signal.h>
3 6
4#include <stdio.h> 7#include <stdio.h>
5 8
9#include <assert.h>
6#include <errno.h> 10#include <errno.h>
7#include <sys/time.h> 11#include <sys/time.h>
8#include <time.h> 12#include <time.h>
9 13
10#ifdef CLOCK_MONOTONIC 14#ifdef CLOCK_MONOTONIC
11# define HAVE_MONOTONIC 1 15# define HAVE_MONOTONIC 1
12#endif 16#endif
13 17
18#define HAVE_REALTIME 1
14#define HAVE_EPOLL 1 19#define HAVE_EPOLL 1
15#define HAVE_REALTIME 1
16#define HAVE_SELECT 0 20#define HAVE_SELECT 1
17 21
22#define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
18#define MAX_BLOCKTIME 60. 23#define MAX_BLOCKTIME 60.
19 24
20#include "ev.h" 25#include "ev.h"
21 26
22struct ev_watcher { 27struct ev_watcher {
25 30
26struct ev_watcher_list { 31struct ev_watcher_list {
27 EV_WATCHER_LIST (ev_watcher_list); 32 EV_WATCHER_LIST (ev_watcher_list);
28}; 33};
29 34
35static ev_tstamp now, diff; /* monotonic clock */
30ev_tstamp ev_now; 36ev_tstamp ev_now;
31int ev_method; 37int ev_method;
32 38
33static int have_monotonic; /* runtime */ 39static int have_monotonic; /* runtime */
34 40
35static ev_tstamp method_fudge; /* stupid epoll-returns-early bug */ 41static ev_tstamp method_fudge; /* stupid epoll-returns-early bug */
36static void (*method_reify)(void); 42static void (*method_modify)(int fd, int oev, int nev);
37static void (*method_poll)(ev_tstamp timeout); 43static void (*method_poll)(ev_tstamp timeout);
44
45/*****************************************************************************/
38 46
39ev_tstamp 47ev_tstamp
40ev_time (void) 48ev_time (void)
41{ 49{
42#if HAVE_REALTIME 50#if HAVE_REALTIME
73 base = realloc (base, sizeof (*base) * (newcnt)); \ 81 base = realloc (base, sizeof (*base) * (newcnt)); \
74 init (base + cur, newcnt - cur); \ 82 init (base + cur, newcnt - cur); \
75 cur = newcnt; \ 83 cur = newcnt; \
76 } 84 }
77 85
86/*****************************************************************************/
87
78typedef struct 88typedef struct
79{ 89{
80 struct ev_io *head; 90 struct ev_io *head;
81 unsigned char wev, rev; /* want, received event set */ 91 unsigned char wev, rev; /* want, received event set */
82} ANFD; 92} ANFD;
129 if (ev) 139 if (ev)
130 event ((struct ev_watcher *)w, ev); 140 event ((struct ev_watcher *)w, ev);
131 } 141 }
132} 142}
133 143
144static void
145queue_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
134static struct ev_timer **timers; 155static struct ev_timer **atimers;
135static int timermax, timercnt; 156static int atimermax, atimercnt;
136 157
158static struct ev_timer **rtimers;
159static int rtimermax, rtimercnt;
160
137static void 161static void
138upheap (int k) 162upheap (struct ev_timer **timers, int k)
139{ 163{
140 struct ev_timer *w = timers [k]; 164 struct ev_timer *w = timers [k];
141 165
142 while (k && timers [k >> 1]->at > w->at) 166 while (k && timers [k >> 1]->at > w->at)
143 { 167 {
150 timers [k]->active = k + 1; 174 timers [k]->active = k + 1;
151 175
152} 176}
153 177
154static void 178static void
155downheap (int k) 179downheap (struct ev_timer **timers, int N, int k)
156{ 180{
157 struct ev_timer *w = timers [k]; 181 struct ev_timer *w = timers [k];
158 182
159 while (k < (timercnt >> 1)) 183 while (k < (N >> 1))
160 { 184 {
161 int j = k << 1; 185 int j = k << 1;
162 186
163 if (j + 1 < timercnt && timers [j]->at > timers [j + 1]->at) 187 if (j + 1 < N && timers [j]->at > timers [j + 1]->at)
164 ++j; 188 ++j;
165 189
166 if (w->at <= timers [j]->at) 190 if (w->at <= timers [j]->at)
167 break; 191 break;
168 192
173 197
174 timers [k] = w; 198 timers [k] = w;
175 timers [k]->active = k + 1; 199 timers [k]->active = k + 1;
176} 200}
177 201
178static struct ev_signal **signals; 202/*****************************************************************************/
203
204typedef struct
205{
206 struct ev_signal *head;
207 sig_atomic_t gotsig;
208} ANSIG;
209
210static ANSIG *signals;
179static int signalmax, signalcnt; 211static int signalmax;
180 212
213static int sigpipe [2];
214static sig_atomic_t gotsig;
215static struct ev_io sigev;
216
181static void 217static void
182signals_init (struct ev_signal **base, int count) 218signals_init (ANSIG *base, int count)
183{ 219{
184 while (count--) 220 while (count--)
185 *base++ = 0; 221 {
222 base->head = 0;
223 base->gotsig = 0;
224 ++base;
225 }
186} 226}
227
228static void
229sighandler (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
240static void
241sigcb (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
259static void
260siginit (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
275static struct ev_idle **idles;
276static int idlemax, idlecnt;
277
278static struct ev_check **checks;
279static int checkmax, checkcnt;
280
281/*****************************************************************************/
187 282
188#if HAVE_EPOLL 283#if HAVE_EPOLL
189# include "ev_epoll.c" 284# include "ev_epoll.c"
190#endif 285#endif
191#if HAVE_SELECT 286#if HAVE_SELECT
201 have_monotonic = 1; 296 have_monotonic = 1;
202 } 297 }
203#endif 298#endif
204 299
205 ev_now = ev_time (); 300 ev_now = ev_time ();
301 now = get_clock ();
302 diff = ev_now - now;
206 303
304 if (pipe (sigpipe))
305 return 0;
306
307 ev_method = EVMETHOD_NONE;
207#if HAVE_EPOLL 308#if HAVE_EPOLL
208 if (epoll_init (flags)) 309 if (ev_method == EVMETHOD_NONE) epoll_init (flags);
209 return ev_method;
210#endif 310#endif
211#if HAVE_SELECT 311#if HAVE_SELECT
212 if (select_init (flags)) 312 if (ev_method == EVMETHOD_NONE) select_init (flags);
213 return ev_method;
214#endif 313#endif
215 314
216 ev_method = EVMETHOD_NONE; 315 if (ev_method)
316 {
317 evw_init (&sigev, sigcb, 0);
318 siginit ();
319 }
320
217 return ev_method; 321 return ev_method;
218} 322}
219 323
324/*****************************************************************************/
325
220void ev_prefork (void) 326void ev_prefork (void)
221{ 327{
222} 328}
223 329
224void ev_postfork_parent (void) 330void ev_postfork_parent (void)
226} 332}
227 333
228void ev_postfork_child (void) 334void ev_postfork_child (void)
229{ 335{
230#if HAVE_EPOLL 336#if HAVE_EPOLL
337 if (ev_method == EVMETHOD_EPOLL)
231 epoll_postfork_child (); 338 epoll_postfork_child ();
232#endif 339#endif
340
341 evio_stop (&sigev);
342 close (sigpipe [0]);
343 close (sigpipe [1]);
344 pipe (sigpipe);
345 siginit ();
346}
347
348/*****************************************************************************/
349
350static void
351fd_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;
233} 374}
234 375
235static void 376static void
236call_pending () 377call_pending ()
237{ 378{
250 391
251 pendingcnt = 0; 392 pendingcnt = 0;
252} 393}
253 394
254static void 395static void
255timer_reify (void) 396timers_reify (struct ev_timer **timers, int timercnt, ev_tstamp now)
256{ 397{
257 while (timercnt && timers [0]->at <= ev_now) 398 while (timercnt && timers [0]->at <= now)
258 { 399 {
259 struct ev_timer *w = timers [0]; 400 struct ev_timer *w = timers [0];
260 401
261 fprintf (stderr, "0 %f, %d c%d\n", w->at, w->active, timercnt);//D
262 /* first reschedule timer */ 402 /* first reschedule or stop timer */
263 if (w->repeat) 403 if (w->repeat)
264 { 404 {
265 fprintf (stderr, "a %f now %f repeat %f, %f\n", w->at, ev_now, w->repeat, w->repeat *1e30);//D
266 if (w->is_abs) 405 if (w->is_abs)
267 w->at += ceil ((ev_now - w->at) / w->repeat + 1.) * w->repeat; 406 w->at += floor ((now - w->at) / w->repeat + 1.) * w->repeat;
268 else 407 else
269 w->at = ev_now + w->repeat; 408 w->at = now + w->repeat;
270 409
271 fprintf (stderr, "b %f\n", w->at);//D 410 assert (w->at > now);
272 411
273 downheap (0); 412 downheap (timers, timercnt, 0);
274 } 413 }
275 else 414 else
276 { 415 {
277 fprintf (stderr, "c %f, %d c%d\n", w->at, w->active, timercnt);//D
278 evtimer_stop (w); /* nonrepeating: stop timer */ 416 evtimer_stop (w); /* nonrepeating: stop timer */
417 --timercnt; /* maybe pass by reference instead? */
279 } 418 }
280 419
281 event ((struct ev_watcher *)w, EV_TIMEOUT); 420 event ((struct ev_watcher *)w, EV_TIMEOUT);
282 } 421 }
283} 422}
284 423
424static void
425time_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
285int ev_loop_done; 464int ev_loop_done;
286 465
287int ev_loop (int flags) 466void ev_loop (int flags)
288{ 467{
289 double block; 468 double block;
290 ev_loop_done = flags & EVLOOP_ONESHOT; 469 ev_loop_done = flags & EVLOOP_ONESHOT;
291 470
471 if (checkcnt)
472 {
473 queue_events (checks, checkcnt, EV_CHECK);
474 call_pending ();
475 }
476
292 do 477 do
293 { 478 {
294 /* update fd-related kernel structures */ 479 /* update fd-related kernel structures */
295 method_reify (); fdchangecnt = 0; 480 fd_reify ();
296 481
297 /* calculate blocking time */ 482 /* calculate blocking time */
298 ev_now = ev_time ();
299
300 if (flags & EVLOOP_NONBLOCK) 483 if (flags & EVLOOP_NONBLOCK || idlecnt)
301 block = 0.; 484 block = 0.;
302 else if (!timercnt)
303 block = MAX_BLOCKTIME;
304 else 485 else
305 { 486 {
487 block = MAX_BLOCKTIME;
488
489 if (rtimercnt)
490 {
306 block = timers [0]->at - ev_now + method_fudge; 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
307 if (block < 0.) block = 0.; 501 if (block < 0.) block = 0.;
308 else if (block > MAX_BLOCKTIME) block = MAX_BLOCKTIME;
309 } 502 }
310 503
311 fprintf (stderr, "block %f\n", block);//D
312 method_poll (block); 504 method_poll (block);
313 505
506 /* update ev_now, do magic */
507 time_update ();
508
314 /* put pending timers into pendign queue and reschedule them */ 509 /* queue pending timers and reschedule them */
315 timer_reify (); 510 /* absolute timers first */
511 timers_reify (atimers, atimercnt, ev_now);
512 /* relative timers second */
513 timers_reify (rtimers, rtimercnt, now);
316 514
317 ev_now = ev_time (); 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
318 call_pending (); 522 call_pending ();
319 } 523 }
320 while (!ev_loop_done); 524 while (!ev_loop_done);
321} 525}
526
527/*****************************************************************************/
322 528
323static void 529static void
324wlist_add (struct ev_watcher_list **head, struct ev_watcher_list *elem) 530wlist_add (struct ev_watcher_list **head, struct ev_watcher_list *elem)
325{ 531{
326 elem->next = *head; 532 elem->next = *head;
356 pendings [w->pending - 1].w = 0; 562 pendings [w->pending - 1].w = 0;
357 563
358 w->active = 0; 564 w->active = 0;
359 /* nop */ 565 /* nop */
360} 566}
567
568/*****************************************************************************/
361 569
362void 570void
363evio_start (struct ev_io *w) 571evio_start (struct ev_io *w)
364{ 572{
365 if (ev_is_active (w)) 573 if (ev_is_active (w))
394evtimer_start (struct ev_timer *w) 602evtimer_start (struct ev_timer *w)
395{ 603{
396 if (ev_is_active (w)) 604 if (ev_is_active (w))
397 return; 605 return;
398 606
399 fprintf (stderr, "t1 %f a %d\n", w->at, w->is_abs);//D
400 if (w->is_abs) 607 if (w->is_abs)
401 { 608 {
402 /* this formula differs from the one in timer_reify becuse we do not round up */ 609 /* this formula differs from the one in timer_reify becuse we do not round up */
403 if (w->repeat) 610 if (w->repeat)
404 w->at += ceil ((ev_now - w->at) / w->repeat) * 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);
405 } 617 }
406 else 618 else
619 {
407 w->at += ev_now; 620 w->at += now;
408 fprintf (stderr, "t2 %f a %d\n", w->at, w->is_abs);//D
409 621
410 ev_start ((struct ev_watcher *)w, ++timercnt); 622 ev_start ((struct ev_watcher *)w, ++rtimercnt);
411 array_needsize (timers, timermax, timercnt, ); 623 array_needsize (rtimers, rtimermax, rtimercnt, );
412 timers [timercnt - 1] = w; 624 rtimers [rtimercnt - 1] = w;
413 upheap (timercnt - 1); 625 upheap (rtimers, rtimercnt - 1);
626 }
627
414} 628}
415 629
416void 630void
417evtimer_stop (struct ev_timer *w) 631evtimer_stop (struct ev_timer *w)
418{ 632{
419 fprintf (stderr, "-topping %d, %d\n", w->active, timercnt);//D
420 if (!ev_is_active (w)) 633 if (!ev_is_active (w))
421 return; 634 return;
422 635
423 fprintf (stderr, "stopping %d, %d\n", w->active, timercnt);//D 636 if (w->is_abs)
637 {
424 if (w->active < timercnt) 638 if (w->active < atimercnt--)
425 { 639 {
426 timers [w->active - 1] = timers [--timercnt]; 640 atimers [w->active - 1] = atimers [atimercnt];
427 downheap (w->active - 1); 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 }
428 } 651 }
429 652
430 ev_stop ((struct ev_watcher *)w); 653 ev_stop ((struct ev_watcher *)w);
431} 654}
432 655
436 if (ev_is_active (w)) 659 if (ev_is_active (w))
437 return; 660 return;
438 661
439 ev_start ((struct ev_watcher *)w, 1); 662 ev_start ((struct ev_watcher *)w, 1);
440 array_needsize (signals, signalmax, w->signum, signals_init); 663 array_needsize (signals, signalmax, w->signum, signals_init);
441 wlist_add ((struct ev_watcher_list **)&signals [w->signum - 1], (struct ev_watcher_list *)w); 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 }
442} 674}
443 675
444void 676void
445evsignal_stop (struct ev_signal *w) 677evsignal_stop (struct ev_signal *w)
446{ 678{
447 if (!ev_is_active (w)) 679 if (!ev_is_active (w))
448 return; 680 return;
449 681
450 wlist_del ((struct ev_watcher_list **)&signals [w->signum - 1], (struct ev_watcher_list *)w); 682 wlist_del ((struct ev_watcher_list **)&signals [w->signum - 1].head, (struct ev_watcher_list *)w);
451 ev_stop ((struct ev_watcher *)w); 683 ev_stop ((struct ev_watcher *)w);
684
685 if (!signals [w->signum - 1].head)
686 signal (w->signum, SIG_DFL);
687}
688
689void 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
699void evidle_stop (struct ev_idle *w)
700{
701 idles [w->active - 1] = idles [--idlecnt];
702 ev_stop ((struct ev_watcher *)w);
703}
704
705void 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
715void evcheck_stop (struct ev_check *w)
716{
717 checks [w->active - 1] = checks [--checkcnt];
718 ev_stop ((struct ev_watcher *)w);
452} 719}
453 720
454/*****************************************************************************/ 721/*****************************************************************************/
455#if 1 722#if 1
456 723
461} 728}
462 729
463static void 730static void
464ocb (struct ev_timer *w, int revents) 731ocb (struct ev_timer *w, int revents)
465{ 732{
466 fprintf (stderr, "timer %f,%f (%x) (%f) d%p\n", w->at, w->repeat, revents, w->at - ev_time (), w->data); 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
738static void
739scb (struct ev_signal *w, int revents)
740{
741 fprintf (stderr, "signal %x,%d\n", revents, w->signum);
742}
743
744static void
745gcb (struct ev_signal *w, int revents)
746{
747 fprintf (stderr, "generic %x\n", revents);
467} 748}
468 749
469int main (void) 750int main (void)
470{ 751{
471 struct ev_io sin; 752 struct ev_io sin;
474 755
475 evw_init (&sin, sin_cb, 55); 756 evw_init (&sin, sin_cb, 55);
476 evio_set (&sin, 0, EV_READ); 757 evio_set (&sin, 0, EV_READ);
477 evio_start (&sin); 758 evio_start (&sin);
478 759
479 struct ev_timer t[1000]; 760 struct ev_timer t[10000];
480 761
762#if 0
481 int i; 763 int i;
482 for (i = 0; i < 1000; ++i) 764 for (i = 0; i < 10000; ++i)
483 { 765 {
484 struct ev_timer *w = t + i; 766 struct ev_timer *w = t + i;
485 evw_init (w, ocb, i); 767 evw_init (w, ocb, i);
486 evtimer_set_rel (w, drand48 (), 0); 768 evtimer_set_abs (w, drand48 (), 0.99775533);
487 evtimer_start (w); 769 evtimer_start (w);
488 if (drand48 () < 0.5) 770 if (drand48 () < 0.5)
489 evtimer_stop (w); 771 evtimer_stop (w);
490 } 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);
491 792
492 ev_loop (0); 793 ev_loop (0);
493 794
494 return 0; 795 return 0;
495} 796}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines