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

Comparing libev/ev.c (file contents):
Revision 1.30 by root, Thu Nov 1 08:28:33 2007 UTC vs.
Revision 1.33 by root, Thu Nov 1 11:11:22 2007 UTC

58 58
59#ifndef EV_USE_EPOLL 59#ifndef EV_USE_EPOLL
60# define EV_USE_EPOLL 0 60# define EV_USE_EPOLL 0
61#endif 61#endif
62 62
63#ifndef CLOCK_REALTIME
64# define EV_USE_REALTIME 0
65#endif
63#ifndef EV_USE_REALTIME 66#ifndef EV_USE_REALTIME
64# define EV_USE_REALTIME 1 /* posix requirement, but might be slower */ 67# define EV_USE_REALTIME 1 /* posix requirement, but might be slower */
65#endif 68#endif
66 69
67#define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */ 70#define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
68#define MAX_BLOCKTIME 59.731 71#define MAX_BLOCKTIME 59.731 /* never wait longer than this time (to detetc time jumps) */
69#define PID_HASHSIZE 16 /* size of pid hahs table, must be power of two */ 72#define PID_HASHSIZE 16 /* size of pid hash table, must be power of two */
73#define CLEANUP_INTERVAL (MAX_BLOCKTIME * 5.) /* how often to try to free memory and re-check fds */
70 74
71#include "ev.h" 75#include "ev.h"
72 76
73typedef struct ev_watcher *W; 77typedef struct ev_watcher *W;
74typedef struct ev_watcher_list *WL; 78typedef struct ev_watcher_list *WL;
135/*****************************************************************************/ 139/*****************************************************************************/
136 140
137typedef struct 141typedef struct
138{ 142{
139 struct ev_io *head; 143 struct ev_io *head;
140 int events; 144 unsigned char events;
145 unsigned char reify;
141} ANFD; 146} ANFD;
142 147
143static ANFD *anfds; 148static ANFD *anfds;
144static int anfdmax; 149static int anfdmax;
145 150
148{ 153{
149 while (count--) 154 while (count--)
150 { 155 {
151 base->head = 0; 156 base->head = 0;
152 base->events = EV_NONE; 157 base->events = EV_NONE;
158 base->reify = 0;
159
153 ++base; 160 ++base;
154 } 161 }
155} 162}
156 163
157typedef struct 164typedef struct
164static int pendingmax, pendingcnt; 171static int pendingmax, pendingcnt;
165 172
166static void 173static void
167event (W w, int events) 174event (W w, int events)
168{ 175{
176 if (w->pending)
177 {
178 pendings [w->pending - 1].events |= events;
179 return;
180 }
181
169 w->pending = ++pendingcnt; 182 w->pending = ++pendingcnt;
170 array_needsize (pendings, pendingmax, pendingcnt, ); 183 array_needsize (pendings, pendingmax, pendingcnt, );
171 pendings [pendingcnt - 1].w = w; 184 pendings [pendingcnt - 1].w = w;
172 pendings [pendingcnt - 1].events = events; 185 pendings [pendingcnt - 1].events = events;
173} 186}
215 int events = 0; 228 int events = 0;
216 229
217 for (w = anfd->head; w; w = w->next) 230 for (w = anfd->head; w; w = w->next)
218 events |= w->events; 231 events |= w->events;
219 232
220 anfd->events &= ~EV_REIFY; 233 anfd->reify = 0;
221 234
222 if (anfd->events != events) 235 if (anfd->events != events)
223 { 236 {
224 method_modify (fd, anfd->events, events); 237 method_modify (fd, anfd->events, events);
225 anfd->events = events; 238 anfd->events = events;
230} 243}
231 244
232static void 245static void
233fd_change (int fd) 246fd_change (int fd)
234{ 247{
235 if (anfds [fd].events & EV_REIFY || fdchangecnt < 0) 248 if (anfds [fd].reify || fdchangecnt < 0)
236 return; 249 return;
237 250
238 anfds [fd].events |= EV_REIFY; 251 anfds [fd].reify = 1;
239 252
240 ++fdchangecnt; 253 ++fdchangecnt;
241 array_needsize (fdchanges, fdchangemax, fdchangecnt, ); 254 array_needsize (fdchanges, fdchangemax, fdchangecnt, );
242 fdchanges [fdchangecnt - 1] = fd; 255 fdchanges [fdchangecnt - 1] = fd;
243} 256}
251 for (fd = 0; fd < anfdmax; ++fd) 264 for (fd = 0; fd < anfdmax; ++fd)
252 if (anfds [fd].events) 265 if (anfds [fd].events)
253 if (fcntl (fd, F_GETFD) == -1 && errno == EBADF) 266 if (fcntl (fd, F_GETFD) == -1 && errno == EBADF)
254 while (anfds [fd].head) 267 while (anfds [fd].head)
255 { 268 {
256 event ((W)anfds [fd].head, EV_ERROR | EV_READ | EV_WRITE | EV_TIMEOUT);
257 ev_io_stop (anfds [fd].head); 269 ev_io_stop (anfds [fd].head);
270 event ((W)anfds [fd].head, EV_ERROR | EV_READ | EV_WRITE);
258 } 271 }
259} 272}
260 273
261/*****************************************************************************/ 274/*****************************************************************************/
262 275
327{ 340{
328 while (count--) 341 while (count--)
329 { 342 {
330 base->head = 0; 343 base->head = 0;
331 base->gotsig = 0; 344 base->gotsig = 0;
345
332 ++base; 346 ++base;
333 } 347 }
334} 348}
335 349
336static void 350static void
528 struct ev_timer *w = timers [0]; 542 struct ev_timer *w = timers [0];
529 543
530 /* first reschedule or stop timer */ 544 /* first reschedule or stop timer */
531 if (w->repeat) 545 if (w->repeat)
532 { 546 {
547 assert (("negative ev_timer repeat value found while processing timers", w->repeat > 0.));
533 w->at = now + w->repeat; 548 w->at = now + w->repeat;
534 assert (("timer timeout in the past, negative repeat?", w->at > now));
535 downheap ((WT *)timers, timercnt, 0); 549 downheap ((WT *)timers, timercnt, 0);
536 } 550 }
537 else 551 else
538 ev_timer_stop (w); /* nonrepeating: stop timer */ 552 ev_timer_stop (w); /* nonrepeating: stop timer */
539 553
550 564
551 /* first reschedule or stop timer */ 565 /* first reschedule or stop timer */
552 if (w->interval) 566 if (w->interval)
553 { 567 {
554 w->at += floor ((ev_now - w->at) / w->interval + 1.) * w->interval; 568 w->at += floor ((ev_now - w->at) / w->interval + 1.) * w->interval;
555 assert (("periodic timeout in the past, negative interval?", w->at > ev_now)); 569 assert (("ev_periodic timeout in the past detected while processing timers, negative interval?", w->at > ev_now));
556 downheap ((WT *)periodics, periodiccnt, 0); 570 downheap ((WT *)periodics, periodiccnt, 0);
557 } 571 }
558 else 572 else
559 ev_periodic_stop (w); /* nonrepeating: stop timer */ 573 ev_periodic_stop (w); /* nonrepeating: stop timer */
560 574
561 event ((W)w, EV_TIMEOUT); 575 event ((W)w, EV_PERIODIC);
562 } 576 }
563} 577}
564 578
565static void 579static void
566periodics_reschedule (ev_tstamp diff) 580periodics_reschedule (ev_tstamp diff)
721 head = &(*head)->next; 735 head = &(*head)->next;
722 } 736 }
723} 737}
724 738
725static void 739static void
726ev_clear (W w) 740ev_clear_pending (W w)
727{ 741{
728 if (w->pending) 742 if (w->pending)
729 { 743 {
730 pendings [w->pending - 1].w = 0; 744 pendings [w->pending - 1].w = 0;
731 w->pending = 0; 745 w->pending = 0;
751{ 765{
752 if (ev_is_active (w)) 766 if (ev_is_active (w))
753 return; 767 return;
754 768
755 int fd = w->fd; 769 int fd = w->fd;
770
771 assert (("ev_io_start called with negative fd", fd >= 0));
756 772
757 ev_start ((W)w, 1); 773 ev_start ((W)w, 1);
758 array_needsize (anfds, anfdmax, fd + 1, anfds_init); 774 array_needsize (anfds, anfdmax, fd + 1, anfds_init);
759 wlist_add ((WL *)&anfds[fd].head, (WL)w); 775 wlist_add ((WL *)&anfds[fd].head, (WL)w);
760 776
762} 778}
763 779
764void 780void
765ev_io_stop (struct ev_io *w) 781ev_io_stop (struct ev_io *w)
766{ 782{
767 ev_clear ((W)w); 783 ev_clear_pending ((W)w);
768 if (!ev_is_active (w)) 784 if (!ev_is_active (w))
769 return; 785 return;
770 786
771 wlist_del ((WL *)&anfds[w->fd].head, (WL)w); 787 wlist_del ((WL *)&anfds[w->fd].head, (WL)w);
772 ev_stop ((W)w); 788 ev_stop ((W)w);
780 if (ev_is_active (w)) 796 if (ev_is_active (w))
781 return; 797 return;
782 798
783 w->at += now; 799 w->at += now;
784 800
785 assert (("timer repeat value less than zero not allowed", w->repeat >= 0.)); 801 assert (("ev_timer_start called with negative timer repeat value", w->repeat >= 0.));
786 802
787 ev_start ((W)w, ++timercnt); 803 ev_start ((W)w, ++timercnt);
788 array_needsize (timers, timermax, timercnt, ); 804 array_needsize (timers, timermax, timercnt, );
789 timers [timercnt - 1] = w; 805 timers [timercnt - 1] = w;
790 upheap ((WT *)timers, timercnt - 1); 806 upheap ((WT *)timers, timercnt - 1);
791} 807}
792 808
793void 809void
794ev_timer_stop (struct ev_timer *w) 810ev_timer_stop (struct ev_timer *w)
795{ 811{
796 ev_clear ((W)w); 812 ev_clear_pending ((W)w);
797 if (!ev_is_active (w)) 813 if (!ev_is_active (w))
798 return; 814 return;
799 815
800 if (w->active < timercnt--) 816 if (w->active < timercnt--)
801 { 817 {
829ev_periodic_start (struct ev_periodic *w) 845ev_periodic_start (struct ev_periodic *w)
830{ 846{
831 if (ev_is_active (w)) 847 if (ev_is_active (w))
832 return; 848 return;
833 849
834 assert (("periodic interval value less than zero not allowed", w->interval >= 0.)); 850 assert (("ev_periodic_start called with negative interval value", w->interval >= 0.));
835 851
836 /* this formula differs from the one in periodic_reify because we do not always round up */ 852 /* this formula differs from the one in periodic_reify because we do not always round up */
837 if (w->interval) 853 if (w->interval)
838 w->at += ceil ((ev_now - w->at) / w->interval) * w->interval; 854 w->at += ceil ((ev_now - w->at) / w->interval) * w->interval;
839 855
844} 860}
845 861
846void 862void
847ev_periodic_stop (struct ev_periodic *w) 863ev_periodic_stop (struct ev_periodic *w)
848{ 864{
849 ev_clear ((W)w); 865 ev_clear_pending ((W)w);
850 if (!ev_is_active (w)) 866 if (!ev_is_active (w))
851 return; 867 return;
852 868
853 if (w->active < periodiccnt--) 869 if (w->active < periodiccnt--)
854 { 870 {
862void 878void
863ev_signal_start (struct ev_signal *w) 879ev_signal_start (struct ev_signal *w)
864{ 880{
865 if (ev_is_active (w)) 881 if (ev_is_active (w))
866 return; 882 return;
883
884 assert (("ev_signal_start called with illegal signal number", w->signum > 0));
867 885
868 ev_start ((W)w, 1); 886 ev_start ((W)w, 1);
869 array_needsize (signals, signalmax, w->signum, signals_init); 887 array_needsize (signals, signalmax, w->signum, signals_init);
870 wlist_add ((WL *)&signals [w->signum - 1].head, (WL)w); 888 wlist_add ((WL *)&signals [w->signum - 1].head, (WL)w);
871 889
880} 898}
881 899
882void 900void
883ev_signal_stop (struct ev_signal *w) 901ev_signal_stop (struct ev_signal *w)
884{ 902{
885 ev_clear ((W)w); 903 ev_clear_pending ((W)w);
886 if (!ev_is_active (w)) 904 if (!ev_is_active (w))
887 return; 905 return;
888 906
889 wlist_del ((WL *)&signals [w->signum - 1].head, (WL)w); 907 wlist_del ((WL *)&signals [w->signum - 1].head, (WL)w);
890 ev_stop ((W)w); 908 ev_stop ((W)w);
905} 923}
906 924
907void 925void
908ev_idle_stop (struct ev_idle *w) 926ev_idle_stop (struct ev_idle *w)
909{ 927{
910 ev_clear ((W)w); 928 ev_clear_pending ((W)w);
911 if (ev_is_active (w)) 929 if (ev_is_active (w))
912 return; 930 return;
913 931
914 idles [w->active - 1] = idles [--idlecnt]; 932 idles [w->active - 1] = idles [--idlecnt];
915 ev_stop ((W)w); 933 ev_stop ((W)w);
927} 945}
928 946
929void 947void
930ev_prepare_stop (struct ev_prepare *w) 948ev_prepare_stop (struct ev_prepare *w)
931{ 949{
932 ev_clear ((W)w); 950 ev_clear_pending ((W)w);
933 if (ev_is_active (w)) 951 if (ev_is_active (w))
934 return; 952 return;
935 953
936 prepares [w->active - 1] = prepares [--preparecnt]; 954 prepares [w->active - 1] = prepares [--preparecnt];
937 ev_stop ((W)w); 955 ev_stop ((W)w);
949} 967}
950 968
951void 969void
952ev_check_stop (struct ev_check *w) 970ev_check_stop (struct ev_check *w)
953{ 971{
954 ev_clear ((W)w); 972 ev_clear_pending ((W)w);
955 if (ev_is_active (w)) 973 if (ev_is_active (w))
956 return; 974 return;
957 975
958 checks [w->active - 1] = checks [--checkcnt]; 976 checks [w->active - 1] = checks [--checkcnt];
959 ev_stop ((W)w); 977 ev_stop ((W)w);
970} 988}
971 989
972void 990void
973ev_child_stop (struct ev_child *w) 991ev_child_stop (struct ev_child *w)
974{ 992{
975 ev_clear ((W)w); 993 ev_clear_pending ((W)w);
976 if (ev_is_active (w)) 994 if (ev_is_active (w))
977 return; 995 return;
978 996
979 wlist_del ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w); 997 wlist_del ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w);
980 ev_stop ((W)w); 998 ev_stop ((W)w);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines