]>
jfr.im git - irc/quakenet/newserv.git/blob - core/events-kqueue.c
2 * events.c: the event handling core, kqueue() version
12 #include "../lib/array.h"
18 * OK, for the kqueue() version we just keep an array (indexed by fd)
19 * of what we put in the kqueue() so we can remove it later. This is only
20 * required because the deregisterhandler() call doesn't include the
21 * "events" field, thus the kqueue filter used is unknown.
23 * We have a seperate fixed array addqueue() for stuff we're adding to
24 * the queue; this gets flushed if it's full or held over until we
25 * next call handleevents().
28 #define UPDATEQUEUESIZE 100
30 struct kevent addqueue
[UPDATEQUEUESIZE
];
31 struct kevent
*eventfds
;
42 /* How many fds are currently registered */
45 void eventstats(int hooknum
, void *arg
);
50 eventadds
=eventdels
=eventexes
=0;
54 registerhook(HOOK_CORE_STATSREQUEST
, &eventstats
);
58 deregisterhook(HOOK_CORE_STATSREQUEST
, &eventstats
);
64 * Given the number of a new file descriptor, makes sure that the array
65 * will be big enough to deal with it.
68 void checkindex(unsigned index
) {
75 while (maxfds
<=index
) {
79 eventfds
=(struct kevent
*)realloc((void *)eventfds
,maxfds
*sizeof(struct kevent
));
80 memset(&eventfds
[oldmax
],0,(maxfds
-oldmax
)*sizeof(struct kevent
));
85 * Create a kevent structure and put it on the list to be added next
86 * time kevent() is called. If that list is full, we call kevent()
89 * We pass the handler in as the udata field to the kernel, this way
90 * we don't have to hunt for it when the kernel throws the kevent back
94 int registerhandler(int fd
, short events
, FDHandler handler
) {
97 /* Check that it's not already registered */
98 if (eventfds
[fd
].filter
!=0) {
102 eventfds
[fd
].ident
=fd
;
103 if (events
& POLLIN
) {
104 eventfds
[fd
].filter
=EVFILT_READ
;
106 eventfds
[fd
].filter
=EVFILT_WRITE
;
108 eventfds
[fd
].flags
=EV_ADD
;
109 eventfds
[fd
].fflags
=0;
111 eventfds
[fd
].udata
=(void *)handler
;
113 /* Error("core",ERR_DEBUG,"Adding fd %d filter %d",fd,eventfds[fd].filter); */
115 if (updates
>=UPDATEQUEUESIZE
) {
116 kevent(kq
, addqueue
, updates
, NULL
, 0, NULL
);
120 addqueue
[updates
++]=eventfds
[fd
];
128 * deregisterhandler():
129 * Removes the fd's kevent from the kqueue. Note that if we're
130 * going to be closing the fd, it will automatically be removed
131 * from the queue so we don't have to do anything except the close().
134 int deregisterhandler(int fd
, int doclose
) {
137 if (updates
>=UPDATEQUEUESIZE
) {
138 kevent(kq
, addqueue
, updates
, NULL
, 0, NULL
);
142 eventfds
[fd
].flags
=EV_DELETE
;
143 addqueue
[updates
++]=eventfds
[fd
];
145 /* Error("core",ERR_DEBUG,"Deleting fd %d filter %d",fd,eventfds[fd].filter); */
152 eventfds
[fd
].filter
=0;
159 * Call kevent() and handle and call appropiate handlers
160 * for any sockets that come up.
162 * This is O(n) in the number of fds returned, rather than the number
163 * of fds polled as in the poll() case.
166 int handleevents(int timeout
) {
169 struct kevent theevents
[100];
172 ts
.tv_sec
=(timeout
/1000);
173 ts
.tv_nsec
=(timeout%1000
)*1000000;
175 res
=kevent(kq
, addqueue
, updates
, theevents
, 100, &ts
);
182 for (i
=0;i
<res
;i
++) {
185 /* If EV_ERROR is set it's a failed addition of a kevent to the queue.
186 * This shouldn't happen so we flag a warning. */
187 if(theevents
[i
].flags
& EV_ERROR
) {
188 Error("core",ERR_WARNING
,"Got EV_ERROR return from kqueue: fd %d filter %d error %d",theevents
[i
].ident
,theevents
[i
].filter
,theevents
[i
].data
);
190 /* Otherwise, translate the result into poll() format.. */
191 if(theevents
[i
].filter
==EVFILT_READ
) {
192 if (theevents
[i
].data
>0) {
196 if (theevents
[i
].data
>0) {
201 if (theevents
[i
].flags
& EV_EOF
|| theevents
[i
].data
<0) {
205 /* Call the handler */
206 ((FDHandler
)(theevents
[i
].udata
))(theevents
[i
].ident
, revents
);
213 void eventstats(int hooknum
, void *arg
) {
215 long level
=(long) arg
;
218 sprintf(buf
,"Events :%7d fds registered, %7d fds deregistered",eventadds
,eventdels
);
219 triggerhook(HOOK_CORE_STATSREPLY
,(void *)buf
);
220 sprintf(buf
,"Events :%7d events triggered, %6d fds active",eventexes
,regfds
);
221 triggerhook(HOOK_CORE_STATSREPLY
,(void *)buf
);