1#include "EXTERN.h" 2#include "perl.h" 3#include "XSUB.h" 4 5#include <errno.h> 6#include <string.h> 7 8#include <sys/types.h> 9#include <sys/event.h> 10#include <sys/time.h> 11 12#include "const-c.inc" 13 14typedef int kqueue_t; 15 16struct kevent *ke2 = NULL; 17AV * ke2av = NULL; 18 19MODULE = IO::KQueue PACKAGE = IO::KQueue 20 21PROTOTYPES: DISABLE 22 23INCLUDE: const-xs.inc 24 25BOOT: 26 Newz(0, ke2, 1000, struct kevent); 27 ke2av = newAV(); 28 av_store(ke2av, 0, (newSViv(0))); 29 av_store(ke2av, 1, (newSViv(0))); 30 av_store(ke2av, 2, (newSViv(0))); 31 av_store(ke2av, 3, (newSViv(0))); 32 av_store(ke2av, 4, (newSViv(0))); 33 34kqueue_t 35new(CLASS) 36 const char * CLASS 37 CODE: 38 RETVAL = kqueue(); 39 if (RETVAL == -1) { 40 croak("kqueue() failed: %s", strerror(errno)); 41 } 42 OUTPUT: 43 RETVAL 44 45void 46EV_SET(kq, ident, filter, flags, fflags = 0, data = 0, udata = NULL) 47 kqueue_t kq 48 uintptr_t ident 49 short filter 50 u_short flags 51 u_short fflags 52 intptr_t data 53 SV * udata 54 PREINIT: 55 struct kevent ke; 56 int i; 57 PPCODE: 58 memset(&ke, 0, sizeof(struct kevent)); 59 if (udata) 60 SvREFCNT_inc(udata); 61 else 62 udata = &PL_sv_undef; 63 EV_SET(&ke, ident, filter, flags, fflags, data, udata); 64 i = kevent(kq, &ke, 1, NULL, 0, NULL); 65 if (i == -1) { 66 croak("set kevent failed: %s", strerror(errno)); 67 } 68 69void 70kevent(kq, timeout=&PL_sv_undef) 71 kqueue_t kq 72 SV * timeout 73 PREINIT: 74 int num_events, i; 75 struct timespec t; 76 struct kevent *ke = NULL; 77 struct timespec *tbuf = (struct timespec *)0; 78 I32 max_events = SvIV(get_sv("IO::KQueue::MAX_EVENTS", FALSE)); 79 PPCODE: 80 Newxz(ke, max_events, struct kevent); 81 if (ke == NULL) { 82 croak("malloc failed"); 83 } 84 85 if (timeout != &PL_sv_undef) { 86 I32 time = SvIV(timeout); 87 if (time >= 0) { 88 t.tv_sec = time / 1000; 89 t.tv_nsec = (time % 1000) * 1000000; 90 tbuf = &t; 91 } 92 } 93 94 num_events = kevent(kq, NULL, 0, ke, max_events, tbuf); 95 96 if (num_events == -1) { 97 Safefree(ke); 98 croak("kevent error: %s", strerror(errno)); 99 } 100 101 /* extend it for the number of events we have */ 102 EXTEND(SP, num_events); 103 for (i = 0; i < num_events; i++) { 104 AV * array = newAV(); 105 av_push(array, newSViv(ke[i].ident)); 106 av_push(array, newSViv(ke[i].filter)); 107 av_push(array, newSViv(ke[i].flags)); 108 av_push(array, newSViv(ke[i].fflags)); 109 av_push(array, newSViv(ke[i].data)); 110 av_push(array, SvREFCNT_inc(ke[i].udata)); 111 PUSHs(sv_2mortal(newRV_noinc((SV*)array))); 112 } 113 114 Safefree(ke); 115 116int 117kevent2(kq, timeout=&PL_sv_undef) 118 kqueue_t kq 119 SV * timeout 120 PREINIT: 121 int num_events, i; 122 struct timespec t; 123 struct timespec *tbuf = (struct timespec *)0; 124 CODE: 125 if (timeout != &PL_sv_undef) { 126 I32 time = SvIV(timeout); 127 if (time >= 0) { 128 t.tv_sec = time / 1000; 129 t.tv_nsec = (time % 1000) * 1000000; 130 tbuf = &t; 131 } 132 } 133 134 RETVAL = kevent(kq, NULL, 0, ke2, 1000, tbuf); 135 136 OUTPUT: 137 RETVAL 138 139SV* 140get_kev(kq, i) 141 kqueue_t kq 142 int i 143 PREINIT: 144 dXSTARG; 145 CODE: 146 if (i < 0 || i >= 1000) { 147 croak("Invalid kevent id: %d", i); 148 } 149 150 sv_setiv(AvARRAY(ke2av)[0], ke2[i-1].ident); 151 sv_setiv(AvARRAY(ke2av)[1], ke2[i-1].filter); 152 sv_setiv(AvARRAY(ke2av)[2], ke2[i-1].flags); 153 sv_setiv(AvARRAY(ke2av)[3], ke2[i-1].fflags); 154 sv_setiv(AvARRAY(ke2av)[4], ke2[i-1].data); 155 av_store(ke2av, 5, SvREFCNT_inc(ke2[i-1].udata)); 156 157 RETVAL = newRV_inc((SV*) ke2av); 158 159 OUTPUT: 160 RETVAL 161 162