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; 12 } aeApiState; 13 14 static int aeApiCreate(aeEventLoop *eventLoop) { 15 aeApiState *state = zmalloc(sizeof(aeApiState)); 16 17 if (!state) return -1; 18 state->events = zmalloc(sizeof(struct kevent)*eventLoop->setsize); 19 if (!state->events) { 20 zfree(state); 21 return -1; 22 } 23 state->kqfd = kqueue(); 24 if (state->kqfd == -1) { 25 zfree(state->events); 26 zfree(state); 27 return -1; 28 } 29 eventLoop->apidata = state; 30 31 return 0; 32 } 33 34 static void aeApiFree(aeEventLoop *eventLoop) { 35 aeApiState *state = eventLoop->apidata; 36 37 close(state->kqfd); 38 zfree(state->events); 39 zfree(state); 40 } 41 42 static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask) { 43 aeApiState *state = eventLoop->apidata; 44 struct kevent ke; 45 46 if (mask & AE_READABLE) { 47 EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, NULL); 48 if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1; 49 } 50 if (mask & AE_WRITABLE) { 51 EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); 52 if (kevent(state->kqfd, &ke, 1, NULL, 0, NULL) == -1) return -1; 53 } 54 return 0; 55 } 56 57 static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask) { 58 aeApiState *state = eventLoop->apidata; 59 struct kevent ke; 60 61 if (mask & AE_READABLE) { 62 EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); 63 kevent(state->kqfd, &ke, 1, NULL, 0, NULL); 64 } 65 if (mask & AE_WRITABLE) { 66 EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); 67 kevent(state->kqfd, &ke, 1, NULL, 0, NULL); 68 } 69 } 70 71 static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) { 72 aeApiState *state = eventLoop->apidata; 73 int retval, numevents = 0; 74 75 if (tvp != NULL) { 76 struct timespec timeout; 77 timeout.tv_sec = tvp->tv_sec; 78 timeout.tv_nsec = tvp->tv_usec * 1000; 79 retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize, 80 &timeout); 81 } else { 82 retval = kevent(state->kqfd, NULL, 0, state->events, eventLoop->setsize, 83 NULL); 84 } 85 86 if (retval > 0) { 87 int j; 88 89 numevents = retval; 90 for(j = 0; j < numevents; j++) { 91 int mask = 0; 92 struct kevent *e = state->events+j; 93 94 if (e->filter == EVFILT_READ) mask |= AE_READABLE; 95 if (e->filter == EVFILT_WRITE) mask |= AE_WRITABLE; 96 eventLoop->fired[j].fd = e->ident; 97 eventLoop->fired[j].mask = mask; 98 } 99 } 100 return numevents; 101 } 102 103 static char *aeApiName(void) { 104 return "kqueue"; 105 } 106