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

Comparing libev/ev.c (file contents):
Revision 1.6 by root, Tue Oct 30 23:55:29 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
6#include <assert.h> 9#include <assert.h>
7#include <errno.h> 10#include <errno.h>
36static int have_monotonic; /* runtime */ 39static int have_monotonic; /* runtime */
37 40
38static ev_tstamp method_fudge; /* stupid epoll-returns-early bug */ 41static ev_tstamp method_fudge; /* stupid epoll-returns-early bug */
39static void (*method_modify)(int fd, int oev, int nev); 42static void (*method_modify)(int fd, int oev, int nev);
40static void (*method_poll)(ev_tstamp timeout); 43static void (*method_poll)(ev_tstamp timeout);
44
45/*****************************************************************************/
41 46
42ev_tstamp 47ev_tstamp
43ev_time (void) 48ev_time (void)
44{ 49{
45#if HAVE_REALTIME 50#if HAVE_REALTIME
76 base = realloc (base, sizeof (*base) * (newcnt)); \ 81 base = realloc (base, sizeof (*base) * (newcnt)); \
77 init (base + cur, newcnt - cur); \ 82 init (base + cur, newcnt - cur); \
78 cur = newcnt; \ 83 cur = newcnt; \
79 } 84 }
80 85
86/*****************************************************************************/
87
81typedef struct 88typedef struct
82{ 89{
83 struct ev_io *head; 90 struct ev_io *head;
84 unsigned char wev, rev; /* want, received event set */ 91 unsigned char wev, rev; /* want, received event set */
85} ANFD; 92} ANFD;
132 if (ev) 139 if (ev)
133 event ((struct ev_watcher *)w, ev); 140 event ((struct ev_watcher *)w, ev);
134 } 141 }
135} 142}
136 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
137static struct ev_timer **atimers; 155static struct ev_timer **atimers;
138static int atimermax, atimercnt; 156static int atimermax, atimercnt;
139 157
140static struct ev_timer **rtimers; 158static struct ev_timer **rtimers;
141static int rtimermax, rtimercnt; 159static int rtimermax, rtimercnt;
179 197
180 timers [k] = w; 198 timers [k] = w;
181 timers [k]->active = k + 1; 199 timers [k]->active = k + 1;
182} 200}
183 201
184static 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;
185static int signalmax; 211static int signalmax;
186 212
213static int sigpipe [2];
214static sig_atomic_t gotsig;
215static struct ev_io sigev;
216
187static void 217static void
188signals_init (struct ev_signal **base, int count) 218signals_init (ANSIG *base, int count)
189{ 219{
190 while (count--) 220 while (count--)
191 *base++ = 0; 221 {
222 base->head = 0;
223 base->gotsig = 0;
224 ++base;
225 }
192} 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/*****************************************************************************/
193 282
194#if HAVE_EPOLL 283#if HAVE_EPOLL
195# include "ev_epoll.c" 284# include "ev_epoll.c"
196#endif 285#endif
197#if HAVE_SELECT 286#if HAVE_SELECT
210 299
211 ev_now = ev_time (); 300 ev_now = ev_time ();
212 now = get_clock (); 301 now = get_clock ();
213 diff = ev_now - now; 302 diff = ev_now - now;
214 303
304 if (pipe (sigpipe))
305 return 0;
306
307 ev_method = EVMETHOD_NONE;
215#if HAVE_EPOLL 308#if HAVE_EPOLL
216 if (epoll_init (flags)) 309 if (ev_method == EVMETHOD_NONE) epoll_init (flags);
217 return ev_method;
218#endif 310#endif
219#if HAVE_SELECT 311#if HAVE_SELECT
220 if (select_init (flags)) 312 if (ev_method == EVMETHOD_NONE) select_init (flags);
221 return ev_method;
222#endif 313#endif
223 314
224 ev_method = EVMETHOD_NONE; 315 if (ev_method)
316 {
317 evw_init (&sigev, sigcb, 0);
318 siginit ();
319 }
320
225 return ev_method; 321 return ev_method;
226} 322}
323
324/*****************************************************************************/
227 325
228void ev_prefork (void) 326void ev_prefork (void)
229{ 327{
230} 328}
231 329
237{ 335{
238#if HAVE_EPOLL 336#if HAVE_EPOLL
239 if (ev_method == EVMETHOD_EPOLL) 337 if (ev_method == EVMETHOD_EPOLL)
240 epoll_postfork_child (); 338 epoll_postfork_child ();
241#endif 339#endif
340
341 evio_stop (&sigev);
342 close (sigpipe [0]);
343 close (sigpipe [1]);
344 pipe (sigpipe);
345 siginit ();
242} 346}
347
348/*****************************************************************************/
243 349
244static void 350static void
245fd_reify (void) 351fd_reify (void)
246{ 352{
247 int i; 353 int i;
360void ev_loop (int flags) 466void ev_loop (int flags)
361{ 467{
362 double block; 468 double block;
363 ev_loop_done = flags & EVLOOP_ONESHOT; 469 ev_loop_done = flags & EVLOOP_ONESHOT;
364 470
471 if (checkcnt)
472 {
473 queue_events (checks, checkcnt, EV_CHECK);
474 call_pending ();
475 }
476
365 do 477 do
366 { 478 {
367 /* update fd-related kernel structures */ 479 /* update fd-related kernel structures */
368 fd_reify (); 480 fd_reify ();
369 481
370 /* calculate blocking time */ 482 /* calculate blocking time */
371 if (flags & EVLOOP_NONBLOCK) 483 if (flags & EVLOOP_NONBLOCK || idlecnt)
372 block = 0.; 484 block = 0.;
373 else 485 else
374 { 486 {
375 block = MAX_BLOCKTIME; 487 block = MAX_BLOCKTIME;
376 488
392 method_poll (block); 504 method_poll (block);
393 505
394 /* update ev_now, do magic */ 506 /* update ev_now, do magic */
395 time_update (); 507 time_update ();
396 508
397 /* put pending timers into pendign queue and reschedule them */ 509 /* queue pending timers and reschedule them */
398 /* absolute timers first */ 510 /* absolute timers first */
399 timers_reify (atimers, atimercnt, ev_now); 511 timers_reify (atimers, atimercnt, ev_now);
400 /* relative timers second */ 512 /* relative timers second */
401 timers_reify (rtimers, rtimercnt, now); 513 timers_reify (rtimers, rtimercnt, now);
402 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
403 call_pending (); 522 call_pending ();
404 } 523 }
405 while (!ev_loop_done); 524 while (!ev_loop_done);
406} 525}
526
527/*****************************************************************************/
407 528
408static void 529static void
409wlist_add (struct ev_watcher_list **head, struct ev_watcher_list *elem) 530wlist_add (struct ev_watcher_list **head, struct ev_watcher_list *elem)
410{ 531{
411 elem->next = *head; 532 elem->next = *head;
441 pendings [w->pending - 1].w = 0; 562 pendings [w->pending - 1].w = 0;
442 563
443 w->active = 0; 564 w->active = 0;
444 /* nop */ 565 /* nop */
445} 566}
567
568/*****************************************************************************/
446 569
447void 570void
448evio_start (struct ev_io *w) 571evio_start (struct ev_io *w)
449{ 572{
450 if (ev_is_active (w)) 573 if (ev_is_active (w))
536 if (ev_is_active (w)) 659 if (ev_is_active (w))
537 return; 660 return;
538 661
539 ev_start ((struct ev_watcher *)w, 1); 662 ev_start ((struct ev_watcher *)w, 1);
540 array_needsize (signals, signalmax, w->signum, signals_init); 663 array_needsize (signals, signalmax, w->signum, signals_init);
541 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 }
542} 674}
543 675
544void 676void
545evsignal_stop (struct ev_signal *w) 677evsignal_stop (struct ev_signal *w)
546{ 678{
547 if (!ev_is_active (w)) 679 if (!ev_is_active (w))
548 return; 680 return;
549 681
550 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);
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];
551 ev_stop ((struct ev_watcher *)w); 718 ev_stop ((struct ev_watcher *)w);
552} 719}
553 720
554/*****************************************************************************/ 721/*****************************************************************************/
555#if 1 722#if 1
566 //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);
567 evtimer_stop (w); 734 evtimer_stop (w);
568 evtimer_start (w); 735 evtimer_start (w);
569} 736}
570 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);
748}
749
571int main (void) 750int main (void)
572{ 751{
573 struct ev_io sin; 752 struct ev_io sin;
574 753
575 ev_init (0); 754 ev_init (0);
578 evio_set (&sin, 0, EV_READ); 757 evio_set (&sin, 0, EV_READ);
579 evio_start (&sin); 758 evio_start (&sin);
580 759
581 struct ev_timer t[10000]; 760 struct ev_timer t[10000];
582 761
583#if 1 762#if 0
584 int i; 763 int i;
585 for (i = 0; i < 10000; ++i) 764 for (i = 0; i < 10000; ++i)
586 { 765 {
587 struct ev_timer *w = t + i; 766 struct ev_timer *w = t + i;
588 evw_init (w, ocb, i); 767 evw_init (w, ocb, i);
596 struct ev_timer t1; 775 struct ev_timer t1;
597 evw_init (&t1, ocb, 0); 776 evw_init (&t1, ocb, 0);
598 evtimer_set_abs (&t1, 5, 10); 777 evtimer_set_abs (&t1, 5, 10);
599 evtimer_start (&t1); 778 evtimer_start (&t1);
600 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
601 ev_loop (0); 793 ev_loop (0);
602 794
603 return 0; 795 return 0;
604} 796}
605 797

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines