1 /* Kqueue(2)-based ae.c module 2 * Copyright (C) 2009 Harish Mallipeddi - [email protected] 3 * Released under the BSD license. See the COPYING file for more info. */ 4 5 #include <sys/types.h> 6 #include <sys/event.h> 7 #include <sys/time.h> 8 9 typedef struct aeApiState { 10 int kqfd; 11 struct kevent events[AE_SETSIZE]; 12 } aeApiState; 13 14 static int aeApiCreate(aeEventLoop *eventLoop) { 15 aeApiState *state = zmalloc(sizeof(aeApiState)); 16 17 if (!state) return -1; 18 state->kqfd = kqueue(); 19 if (state->kqfd == -1) return -1; 20 eventLoop->apidata = state; 21 22 return 0; 23 } 24 25 static void aeApiFree(aeEventLoop *eventLoop) { 26 aeApiState *state = eventLoop->apidata; 27 28 close(state->kqfd); 29 zfree(state); 30 } 31 32 static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) { 33 aeApiState *state = eventLoop->apidata; 34 struct kevent ke; 35 36 if (mask & AE_READABLE) { 37 EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL); 38 if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1; 39 } 40 if (mask & AE_WRITABLE) { 41 EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); 42 if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1; 43 } 44 return 0; 45 } 46 47 static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) { 48 aeApiState *state = eventLoop->apidata; 49 struct kevent ke; 50 51 if (mask & AE_READABLE) { 52 EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); 53 kevent(state->kqfd, &ke, 1, NULL, 0, NULL); 54 } 55 if (mask & AE_WRITABLE) { 56 EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); 57 kevent(state->kqfd, &ke, 1, NULL, 0, NULL); 58 } 59 } 60 61 static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) { 62 aeApiState *state = eventLoop->apidata; 63 int retval, numevents = 0; 64 65 if (tvp != NULL) { 66 struct timespec timeout; 67 timeout.tv_sec = tvp->tv_sec; 68 timeout.tv_nsec = tvp->tv_usec * 1000; 69 retval = kevent(state->kqfd, NULL, 0, state->events, AE_SETSIZE, &timeout); 70 } else { 71 retval = kevent(state->kqfd, NULL, 0, state->events, AE_SETSIZE, NULL); 72 } 73 74 if (retval > 0) { 75 int j; 76 77 numevents = retval; 78 for(j = 0; j < numevents; j++) { 79 int mask = 0; 80 struct kevent *e = state->events+j; 81 82 if (e->filter == EVFILT_READ) mask |= AE_READABLE; 83 if (e->filter == EVFILT_WRITE) mask |= AE_WRITABLE; 84 eventLoop->fired[j].fd = e->ident; 85 eventLoop->fired[j].mask = mask; 86 } 87 } 88 return numevents; 89 } 90 91 static char *aeApiName(void) { 92 return "kqueue"; 93 } 94