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