... | ... |
@@ -39,6 +39,7 @@ |
39 | 39 |
# 2004-12-19 amd64 transformed in x86_64 (andrei) |
40 | 40 |
# 2005-04-27 alpha support added (andrei) |
41 | 41 |
# 2005-06-01 use $(LOCALBASE) instead of /usr/{local,pkg} (andrei) |
42 |
+# 2006-06-26 numeric OSREL & HAVE_KQUEUE added to the *BSD (andrei) |
|
42 | 43 |
|
43 | 44 |
|
44 | 45 |
# check if already included/exported |
... | ... |
@@ -55,7 +56,7 @@ MAIN_NAME=ser |
55 | 56 |
VERSION = 0 |
56 | 57 |
PATCHLEVEL = 10 |
57 | 58 |
SUBLEVEL = 99 |
58 |
-EXTRAVERSION = -dev8-new_tcp |
|
59 |
+EXTRAVERSION = -dev9-new_tcp |
|
59 | 60 |
|
60 | 61 |
RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) |
61 | 62 |
OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]") |
... | ... |
@@ -63,6 +64,13 @@ ARCH = $(shell uname -m |sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ |
63 | 64 |
-e s/armv4l/arm/ -e "s/Power Macintosh/ppc/" -e "s/cobalt/mips2/" \ |
64 | 65 |
-e s/amd64/x86_64/ ) |
65 | 66 |
OSREL = $(shell uname -r) |
67 |
+# numerical version (good for comparisons: A.B.C => A*1000000+B*1000+C) |
|
68 |
+OSREL_N= $(shell echo $(OSREL) | sed -e 's/^[^0-9]*//' \ |
|
69 |
+ -e 's/^\([0-9][0-9]*\(\.[0-9][0-9]*\)*\).*$$/\1/g' | \ |
|
70 |
+ (IFS=. read A B C ; R=0; \ |
|
71 |
+ [ -n "$$A" ] && R=`expr $$R \* 1000 + $$A` && \ |
|
72 |
+ [ -n "$$B" ] && R=`expr $$R \* 1000 + $$B` && \ |
|
73 |
+ [ -n "$$C" ] && R=`expr $$R \* 1000 + $$C`; echo $$R ) ) |
|
66 | 74 |
|
67 | 75 |
# TLS support |
68 | 76 |
TLS ?= |
... | ... |
@@ -913,14 +921,17 @@ ifeq ($(OS), linux) |
913 | 921 |
DEFS+= -DUSE_SYSV_SEM # try posix sems |
914 | 922 |
found_lock_method=yes |
915 | 923 |
endif |
916 |
- # check for 2.6 |
|
917 |
- ifneq ($(shell echo "$(OSREL)"|grep "^2\.6\."),) |
|
924 |
+ # check for >= 2.5.44 |
|
925 |
+ ifeq ($(shell [ $(OSREL_N) -ge 2005044 ] && echo has_epoll), has_epoll) |
|
918 | 926 |
ifeq ($(NO_EPOLL),) |
919 | 927 |
DEFS+=-DHAVE_EPOLL |
920 | 928 |
endif |
921 | 929 |
endif |
922 |
- ifeq ($(NO_SIGIO),) |
|
923 |
- DEFS+=-DHAVE_SIGIO_RT |
|
930 |
+ # check for >= 2.2.0 |
|
931 |
+ ifeq ($(shell [ $(OSREL_N) -ge 2002000 ] && echo has_sigio), has_sigio) |
|
932 |
+ ifeq ($(NO_SIGIO),) |
|
933 |
+ DEFS+=-DHAVE_SIGIO_RT |
|
934 |
+ endif |
|
924 | 935 |
endif |
925 | 936 |
ifeq ($(NO_SELECT),) |
926 | 937 |
DEFS+=-DHAVE_SELECT |
... | ... |
@@ -971,6 +982,12 @@ ifeq ($(OS), freebsd) |
971 | 982 |
else |
972 | 983 |
LIBS= -lfl #dlopen is in libc |
973 | 984 |
endif |
985 |
+ # check for ver >= 4.1 |
|
986 |
+ ifeq ($(shell [ $(OSREL_N) -gt 4001 ] && echo has_kqueue), has_kqueue) |
|
987 |
+ ifeq ($(NO_KQUEUE),) |
|
988 |
+ DEFS+=-DHAVE_KQUEUE |
|
989 |
+ endif |
|
990 |
+ endif |
|
974 | 991 |
ifeq ($(NO_SELECT),) |
975 | 992 |
DEFS+=-DHAVE_SELECT |
976 | 993 |
endif |
... | ... |
@@ -984,6 +1001,12 @@ ifeq ($(OS), openbsd) |
984 | 1001 |
DEFS+= -DUSE_PTHREAD_MUTEX # try pthread sems |
985 | 1002 |
found_lock_method=yes |
986 | 1003 |
endif |
1004 |
+ # check for ver >= 3.7 |
|
1005 |
+ ifeq ($(shell [ $(OSREL_N) -ge 3007 ] && echo has_kqueue), has_kqueue) |
|
1006 |
+ ifeq ($(NO_KQUEUE),) |
|
1007 |
+ DEFS+=-DHAVE_KQUEUE |
|
1008 |
+ endif |
|
1009 |
+ endif |
|
987 | 1010 |
ifeq ($(NO_SELECT),) |
988 | 1011 |
DEFS+=-DHAVE_SELECT |
989 | 1012 |
endif |
... | ... |
@@ -1016,6 +1039,13 @@ ifeq ($(OS), netbsd) |
1016 | 1039 |
DEFS+= -DUSE_SYSV_SEM # try pthread sems |
1017 | 1040 |
found_lock_method=yes |
1018 | 1041 |
endif |
1042 |
+ # check for ver >= 2.0.0 |
|
1043 |
+$(warning OSREL_N=$(OSREL_N) , OSREL=$(OSREL) ) |
|
1044 |
+ ifeq ($(shell [ $(OSREL_N) -ge 2000000 ] && echo has_kqueue), has_kqueue) |
|
1045 |
+ ifeq ($(NO_KQUEUE),) |
|
1046 |
+ DEFS+=-DHAVE_KQUEUE |
|
1047 |
+ endif |
|
1048 |
+ endif |
|
1019 | 1049 |
ifeq ($(NO_SELECT),) |
1020 | 1050 |
DEFS+=-DHAVE_SELECT |
1021 | 1051 |
endif |
... | ... |
@@ -32,6 +32,7 @@ |
32 | 32 |
* History: |
33 | 33 |
* -------- |
34 | 34 |
* 2005-06-15 created by andrei |
35 |
+ * 2005-06-26 added kqueue (andrei) |
|
35 | 36 |
*/ |
36 | 37 |
|
37 | 38 |
|
... | ... |
@@ -216,6 +217,33 @@ static void destroy_epoll(io_wait_h* h) |
216 | 217 |
|
217 | 218 |
|
218 | 219 |
|
220 |
+#ifdef HAVE_KQUEUE |
|
221 |
+/* kqueue specific init |
|
222 |
+ * returns -1 on error, 0 on success */ |
|
223 |
+static int init_kqueue(io_wait_h* h) |
|
224 |
+{ |
|
225 |
+ h->kq_fd=kqueue(); |
|
226 |
+ if (h->kq_fd==-1){ |
|
227 |
+ LOG(L_ERR, "ERROR: init_kqueue: kqueue: %s [%d]\n", |
|
228 |
+ strerror(errno), errno); |
|
229 |
+ return -1; |
|
230 |
+ } |
|
231 |
+ return 0; |
|
232 |
+} |
|
233 |
+ |
|
234 |
+ |
|
235 |
+ |
|
236 |
+static void destroy_kqueue(io_wait_h* h) |
|
237 |
+{ |
|
238 |
+ if (h->kq_fd!=-1){ |
|
239 |
+ close(h->kq_fd); |
|
240 |
+ h->kq_fd=-1; |
|
241 |
+ } |
|
242 |
+} |
|
243 |
+#endif |
|
244 |
+ |
|
245 |
+ |
|
246 |
+ |
|
219 | 247 |
#ifdef HAVE_SELECT |
220 | 248 |
static int init_select(io_wait_h* h) |
221 | 249 |
{ |
... | ... |
@@ -284,10 +312,10 @@ char* check_poll_method(enum poll_types poll_method) |
284 | 312 |
break; |
285 | 313 |
case POLL_EPOLL_LT: |
286 | 314 |
case POLL_EPOLL_ET: |
287 |
- /* only on 2.6 + */ |
|
288 | 315 |
#ifndef HAVE_EPOLL |
289 | 316 |
ret="epoll not supported, try re-compiling with -DHAVE_EPOLL"; |
290 | 317 |
#else |
318 |
+ /* only on 2.6 + */ |
|
291 | 319 |
if (os_ver<0x020542) /* if ver < 2.5.66 */ |
292 | 320 |
ret="epoll not supported on kernels < 2.6"; |
293 | 321 |
#endif |
... | ... |
@@ -296,8 +324,30 @@ char* check_poll_method(enum poll_types poll_method) |
296 | 324 |
#ifndef HAVE_SIGIO_RT |
297 | 325 |
ret="sigio_rt not supported, try re-compiling with" |
298 | 326 |
" -DHAVE_SIGIO_RT"; |
327 |
+#else |
|
328 |
+ /* only on 2.2 + ?? */ |
|
329 |
+ if (os_ver<0x020200) /* if ver < 2.2.0 */ |
|
330 |
+ ret="epoll not supported on kernels < 2.2 (?)"; |
|
299 | 331 |
#endif |
300 | 332 |
break; |
333 |
+ case POLL_KQUEUE: |
|
334 |
+#ifndef HAVE_KQUEUE |
|
335 |
+ ret="kqueue not supported, try re-compiling with -DHAVE_KQUEUE"; |
|
336 |
+#else |
|
337 |
+ /* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD ???, Darwin ??? FIXME */ |
|
338 |
+ #ifdef __OS_freebsd |
|
339 |
+ if (os_ver<0x0401) /* if ver < 4.1 */ |
|
340 |
+ ret="kqueue not supported on FreeBSD < 4.1"; |
|
341 |
+ #elif defined (__OS_netbsd) |
|
342 |
+ if (os_ver<0x020000) /* if ver < 2.0 */ |
|
343 |
+ ret="kqueue not supported on NetBSD < 2.0"; |
|
344 |
+ #elif defined (__OS_openbsd) |
|
345 |
+ if (os_ver<0x0307) /* if ver < 3.7 ??? */ |
|
346 |
+ ret="kqueue not supported on OpenBSD < 3.7 (?)"; |
|
347 |
+ #endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */ |
|
348 |
+#endif |
|
349 |
+ break; |
|
350 |
+ |
|
301 | 351 |
default: |
302 | 352 |
ret="unknown not supported method"; |
303 | 353 |
} |
... | ... |
@@ -318,8 +368,22 @@ enum poll_types choose_poll_method() |
318 | 368 |
poll_method=POLL_EPOLL_LT; /* or POLL_EPOLL_ET */ |
319 | 369 |
|
320 | 370 |
#endif |
371 |
+#ifdef HAVE_KQUEUE |
|
372 |
+ if (poll_method==0) |
|
373 |
+ /* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD ???, Darwin ??? FIXME */ |
|
374 |
+ #ifdef __OS_freebsd |
|
375 |
+ if (os_ver>=0x0401) /* if ver >= 4.1 */ |
|
376 |
+ #elif defined (__OS_netbsd) |
|
377 |
+ if (os_ver>=0x020000) /* if ver >= 2.0 */ |
|
378 |
+ #elif defined (__OS_openbsd) |
|
379 |
+ if (os_ver>=0x0307) /* if ver >= 3.7 */ |
|
380 |
+ #endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */ |
|
381 |
+ poll_method=POLL_KQUEUE; |
|
382 |
+#endif |
|
321 | 383 |
#ifdef HAVE_SIGIO_RT |
322 |
- if (poll_method==0) poll_method=POLL_SIGIO_RT; |
|
384 |
+ if (poll_method==0) |
|
385 |
+ if (os_ver>=0x020200) /* if ver >= 2.2.0 */ |
|
386 |
+ poll_method=POLL_SIGIO_RT; |
|
323 | 387 |
#endif |
324 | 388 |
if (poll_method==0) poll_method=POLL_POLL; |
325 | 389 |
return poll_method; |
... | ... |
@@ -369,7 +433,9 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method) |
369 | 433 |
#ifdef HAVE_EPOLL |
370 | 434 |
h->epfd=-1; |
371 | 435 |
#endif |
372 |
- |
|
436 |
+#ifdef HAVE_KQUEUE |
|
437 |
+ h->kq_fd=-1; |
|
438 |
+#endif |
|
373 | 439 |
poll_err=check_poll_method(poll_method); |
374 | 440 |
|
375 | 441 |
/* set an appropiate poll method */ |
... | ... |
@@ -445,6 +511,32 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method) |
445 | 511 |
goto error; |
446 | 512 |
} |
447 | 513 |
break; |
514 |
+#endif |
|
515 |
+#ifdef HAVE_KQUEUE |
|
516 |
+ case POLL_KQUEUE: |
|
517 |
+ h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->max_fd_no); |
|
518 |
+ if (h->kq_array==0){ |
|
519 |
+ LOG(L_CRIT, "ERROR: init_io_wait: could not alloc" |
|
520 |
+ " kqueue event array\n"); |
|
521 |
+ goto error; |
|
522 |
+ } |
|
523 |
+ h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE; |
|
524 |
+ h->kq_changes=local_malloc(sizeof(*(h->kq_changes))* |
|
525 |
+ h->kq_changes_size); |
|
526 |
+ if (h->kq_changes==0){ |
|
527 |
+ LOG(L_CRIT, "ERROR: init_io_wait: could not alloc" |
|
528 |
+ " kqueue changes array\n"); |
|
529 |
+ goto error; |
|
530 |
+ } |
|
531 |
+ h->kq_nchanges=0; |
|
532 |
+ memset((void*)h->kq_array, 0, sizeof(*(h->kq_array))*h->max_fd_no); |
|
533 |
+ memset((void*)h->kq_changes, 0, |
|
534 |
+ sizeof(*(h->kq_changes))* h->kq_changes_size); |
|
535 |
+ if (init_kqueue(h)<0){ |
|
536 |
+ LOG(L_CRIT, "ERROR: init_io_wait: kqueue init failed\n"); |
|
537 |
+ goto error; |
|
538 |
+ } |
|
539 |
+ break; |
|
448 | 540 |
#endif |
449 | 541 |
default: |
450 | 542 |
LOG(L_CRIT, "BUG: init_io_wait: unknown/unsupported poll" |
... | ... |
@@ -473,6 +565,19 @@ void destroy_io_wait(io_wait_h* h) |
473 | 565 |
} |
474 | 566 |
break; |
475 | 567 |
#endif |
568 |
+#ifdef HAVE_KQUEUE |
|
569 |
+ case POLL_KQUEUE: |
|
570 |
+ destroy_kqueue(h); |
|
571 |
+ if (h->kq_array){ |
|
572 |
+ local_free(h->kq_array); |
|
573 |
+ h->kq_array=0; |
|
574 |
+ } |
|
575 |
+ if (h->kq_changes){ |
|
576 |
+ local_free(h->kq_changes); |
|
577 |
+ h->kq_changes=0; |
|
578 |
+ } |
|
579 |
+ break; |
|
580 |
+#endif |
|
476 | 581 |
#ifdef HAVE_SIGIO_RT |
477 | 582 |
case POLL_SIGIO_RT: |
478 | 583 |
destroy_sigio(h); |
... | ... |
@@ -46,6 +46,7 @@ |
46 | 46 |
* History: |
47 | 47 |
* -------- |
48 | 48 |
* 2005-06-13 created by andrei |
49 |
+ * 2005-06-26 added kqueue (andrei) |
|
49 | 50 |
*/ |
50 | 51 |
|
51 | 52 |
|
... | ... |
@@ -64,6 +65,11 @@ |
64 | 65 |
#ifdef HAVE_EPOLL |
65 | 66 |
#include <sys/epoll.h> |
66 | 67 |
#endif |
68 |
+#ifdef HAVE_KQUEUE |
|
69 |
+#include <sys/types.h> /* needed on freebsd */ |
|
70 |
+#include <sys/event.h> |
|
71 |
+#include <sys/time.h> |
|
72 |
+#endif |
|
67 | 73 |
#ifdef HAVE_SELECT |
68 | 74 |
/* needed on openbsd for select*/ |
69 | 75 |
#include <sys/time.h> |
... | ... |
@@ -103,6 +109,19 @@ struct fd_map{ |
103 | 109 |
}; |
104 | 110 |
|
105 | 111 |
|
112 |
+#ifdef HAVE_KQUEUE |
|
113 |
+#ifndef KQ_CHANGES_ARRAY_SIZE |
|
114 |
+#define KQ_CHANGES_ARRAY_SIZE 128 |
|
115 |
+ |
|
116 |
+#ifdef __OS_netbsd |
|
117 |
+#define KEV_UDATA_CAST (intptr_t) |
|
118 |
+#else |
|
119 |
+#define KEV_UDATA_CAST |
|
120 |
+#endif |
|
121 |
+ |
|
122 |
+#endif |
|
123 |
+#endif |
|
124 |
+ |
|
106 | 125 |
|
107 | 126 |
/* handler structure */ |
108 | 127 |
struct io_wait_handler{ |
... | ... |
@@ -114,6 +133,13 @@ struct io_wait_handler{ |
114 | 133 |
sigset_t sset; /* signal mask for sigio & sigrtmin */ |
115 | 134 |
int signo; /* real time signal used */ |
116 | 135 |
#endif |
136 |
+#ifdef HAVE_KQUEUE |
|
137 |
+ struct kevent* kq_array; /* used for the eventlist*/ |
|
138 |
+ struct kevent* kq_changes; /* used for the changelist */ |
|
139 |
+ size_t kq_nchanges; |
|
140 |
+ size_t kq_changes_size; /* size of the changes array */ |
|
141 |
+ int kq_fd; |
|
142 |
+#endif |
|
117 | 143 |
#ifdef HAVE_SELECT |
118 | 144 |
fd_set master_set; |
119 | 145 |
int max_fd_select; /* maximum select used fd */ |
... | ... |
@@ -185,6 +211,43 @@ int handle_io(struct fd_map* fm, int idx); |
185 | 211 |
|
186 | 212 |
|
187 | 213 |
|
214 |
+#ifdef HAVE_KQUEUE |
|
215 |
+/* |
|
216 |
+ * kqueue specific function: register a change |
|
217 |
+ * (adds a change to the kevent change array, and if full flushes it first) |
|
218 |
+ * returns: -1 on error, 0 on success |
|
219 |
+ */ |
|
220 |
+static inline int kq_ev_change(io_wait_h* h, int fd, int filter, int flag, |
|
221 |
+ void* data) |
|
222 |
+{ |
|
223 |
+ int n; |
|
224 |
+ struct timespec tspec; |
|
225 |
+ |
|
226 |
+ if (h->kq_nchanges>=h->kq_changes_size){ |
|
227 |
+ /* changes array full ! */ |
|
228 |
+ LOG(L_WARN, "WARNING: kq_ev_change: kqueue changes array full" |
|
229 |
+ " trying to flush...\n"); |
|
230 |
+ tspec.tv_sec=0; |
|
231 |
+ tspec.tv_nsec=0; |
|
232 |
+again: |
|
233 |
+ n=kevent(h->kq_fd, h->kq_changes, h->kq_nchanges, 0, 0, &tspec); |
|
234 |
+ if (n==-1){ |
|
235 |
+ if (errno==EINTR) goto again; |
|
236 |
+ LOG(L_ERR, "ERROR: io_watch_add: kevent flush changes " |
|
237 |
+ " failed: %s [%d]\n", strerror(errno), errno); |
|
238 |
+ return -1; |
|
239 |
+ } |
|
240 |
+ h->kq_nchanges=0; /* changes array is empty */ |
|
241 |
+ } |
|
242 |
+ EV_SET(&h->kq_changes[h->kq_nchanges], fd, filter, flag, 0, 0, |
|
243 |
+ KEV_UDATA_CAST data); |
|
244 |
+ h->kq_nchanges++; |
|
245 |
+ return 0; |
|
246 |
+} |
|
247 |
+#endif |
|
248 |
+ |
|
249 |
+ |
|
250 |
+ |
|
188 | 251 |
/* generic io_watch_add function |
189 | 252 |
* returns 0 on success, -1 on error |
190 | 253 |
* |
... | ... |
@@ -235,7 +298,7 @@ inline static int io_watch_add( io_wait_h* h, |
235 | 298 |
LOG(L_CRIT, "BUG: io_watch_add: fd is -1!\n"); |
236 | 299 |
goto error; |
237 | 300 |
} |
238 |
- /* add it to the poll fd array */ |
|
301 |
+ /* check if not too big */ |
|
239 | 302 |
if (h->fd_no>=h->max_fd_no){ |
240 | 303 |
LOG(L_CRIT, "ERROR: io_watch_add: maximum fd number exceeded:" |
241 | 304 |
" %d/%d\n", h->fd_no, h->max_fd_no); |
... | ... |
@@ -320,6 +383,12 @@ again2: |
320 | 383 |
goto error; |
321 | 384 |
} |
322 | 385 |
break; |
386 |
+#endif |
|
387 |
+#ifdef HAVE_KQUEUE |
|
388 |
+ case POLL_KQUEUE: |
|
389 |
+ if (kq_ev_change(h, fd, EVFILT_READ, EV_ADD, e)==-1) |
|
390 |
+ goto error; |
|
391 |
+ break; |
|
323 | 392 |
#endif |
324 | 393 |
default: |
325 | 394 |
LOG(L_CRIT, "BUG: io_watch_add: no support for poll method " |
... | ... |
@@ -328,7 +397,7 @@ again2: |
328 | 397 |
goto error; |
329 | 398 |
} |
330 | 399 |
|
331 |
- h->fd_no++; /* "activate" changes, for epoll it |
|
400 |
+ h->fd_no++; /* "activate" changes, for epoll/kqueue/devpoll it |
|
332 | 401 |
has only informative value */ |
333 | 402 |
return 0; |
334 | 403 |
error: |
... | ... |
@@ -339,12 +408,19 @@ error: |
339 | 408 |
|
340 | 409 |
|
341 | 410 |
|
342 |
-/* parameters: fd and index in the fd_array |
|
343 |
- * if index==-1, it fd_array will be searched for the corresponding fd |
|
344 |
- * entry (slower but unavoidable in some cases) |
|
345 |
- * index is not used (no fd_arry) for epoll, /dev/poll and kqueue |
|
411 |
+#define IO_FD_CLOSING 16 |
|
412 |
+/* parameters: h - handler |
|
413 |
+ * fd - file descriptor |
|
414 |
+ * index - index in the fd_array if known, -1 if not |
|
415 |
+ * (if index==-1 fd_array will be searched for the |
|
416 |
+ * corresponding fd* entry -- slower but unavoidable in |
|
417 |
+ * some cases). index is not used (no fd_array) for epoll, |
|
418 |
+ * /dev/poll and kqueue |
|
419 |
+ * flags - optimization flags, e.g. IO_FD_CLOSING, the fd was |
|
420 |
+ * or will shortly be closed, in some cases we can avoid |
|
421 |
+ * extra remove operations (e.g.: epoll, kqueue, sigio) |
|
346 | 422 |
* returns 0 if ok, -1 on error */ |
347 |
-inline static int io_watch_del(io_wait_h* h, int fd, int idx) |
|
423 |
+inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags) |
|
348 | 424 |
{ |
349 | 425 |
|
350 | 426 |
#define fix_fd_array \ |
... | ... |
@@ -416,11 +492,21 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx) |
416 | 492 |
#ifdef HAVE_EPOLL |
417 | 493 |
case POLL_EPOLL_LT: |
418 | 494 |
case POLL_EPOLL_ET: |
419 |
- n=epoll_ctl(h->epfd, EPOLL_CTL_DEL, fd, &ep_event); |
|
420 |
- if (n==-1){ |
|
421 |
- LOG(L_ERR, "ERROR: io_watch_del: removing fd from" |
|
422 |
- " epoll list failed: %s [%d]\n", strerror(errno), errno); |
|
423 |
- goto error; |
|
495 |
+ if (!(flags & IO_FD_CLOSING)){ |
|
496 |
+ n=epoll_ctl(h->epfd, EPOLL_CTL_DEL, fd, &ep_event); |
|
497 |
+ if (n==-1){ |
|
498 |
+ LOG(L_ERR, "ERROR: io_watch_del: removing fd from epoll " |
|
499 |
+ "list failed: %s [%d]\n", strerror(errno), errno); |
|
500 |
+ goto error; |
|
501 |
+ } |
|
502 |
+ } |
|
503 |
+ break; |
|
504 |
+#endif |
|
505 |
+#ifdef HAVE_KQUEUE |
|
506 |
+ case POLL_KQUEUE: |
|
507 |
+ if (!(flags & IO_FD_CLOSING)){ |
|
508 |
+ if (kq_ev_change(h, fd, EVFILT_READ, EV_DELETE, 0)==-1) |
|
509 |
+ goto error; |
|
424 | 510 |
} |
425 | 511 |
break; |
426 | 512 |
#endif |
... | ... |
@@ -528,7 +614,7 @@ again: |
528 | 614 |
if (n==-1){ |
529 | 615 |
if (errno==EINTR) goto again; /* signal, ignore it */ |
530 | 616 |
else{ |
531 |
- LOG(L_ERR, "ERROR:io_wait_loop_epoll_et: epoll_wait:" |
|
617 |
+ LOG(L_ERR, "ERROR:io_wait_loop_epoll: epoll_wait:" |
|
532 | 618 |
" %s [%d]\n", strerror(errno), errno); |
533 | 619 |
goto error; |
534 | 620 |
} |
... | ... |
@@ -544,6 +630,47 @@ error: |
544 | 630 |
|
545 | 631 |
|
546 | 632 |
|
633 |
+#ifdef HAVE_KQUEUE |
|
634 |
+inline static int io_wait_loop_kqueue(io_wait_h* h, int t, int repeat) |
|
635 |
+{ |
|
636 |
+ int n, r; |
|
637 |
+ struct timespec tspec; |
|
638 |
+ |
|
639 |
+ tspec.tv_sec=t; |
|
640 |
+ tspec.tv_nsec=0; |
|
641 |
+again: |
|
642 |
+ n=kevent(h->kq_fd, h->kq_changes, h->kq_nchanges, h->kq_array, |
|
643 |
+ h->fd_no, &tspec); |
|
644 |
+ if (n==-1){ |
|
645 |
+ if (errno==EINTR) goto again; /* signal, ignore it */ |
|
646 |
+ else{ |
|
647 |
+ LOG(L_ERR, "ERROR: io_wait_loop_kqueue: kevent:" |
|
648 |
+ " %s [%d]\n", strerror(errno), errno); |
|
649 |
+ goto error; |
|
650 |
+ } |
|
651 |
+ } |
|
652 |
+ h->kq_nchanges=0; /* reset changes array */ |
|
653 |
+ for (r=0; r<n; r++){ |
|
654 |
+ if (h->kq_array[r].flags & EV_ERROR){ |
|
655 |
+ /* error in changes: we ignore it, it can be caused by |
|
656 |
+ trying to remove an already closed fd: race between |
|
657 |
+ adding smething to the changes array, close() and |
|
658 |
+ applying the changes */ |
|
659 |
+ LOG(L_INFO, "INFO: io_wait_loop_kqueue: kevent error on " |
|
660 |
+ "fd %d: %s [%d]\n", h->kq_array[r].ident, |
|
661 |
+ strerror(h->kq_array[r].data), |
|
662 |
+ h->kq_array[r].data); |
|
663 |
+ }else /* READ/EOF */ |
|
664 |
+ while((handle_io((struct fd_map*)h->kq_array[r].udata, -1)>0) |
|
665 |
+ && repeat); |
|
666 |
+ } |
|
667 |
+error: |
|
668 |
+ return n; |
|
669 |
+} |
|
670 |
+#endif |
|
671 |
+ |
|
672 |
+ |
|
673 |
+ |
|
547 | 674 |
#ifdef HAVE_SIGIO_RT |
548 | 675 |
/* sigio rt version has no repeat (it doesn't make sense)*/ |
549 | 676 |
inline static int io_wait_loop_sigio_rt(io_wait_h* h, int t) |
... | ... |
@@ -54,6 +54,7 @@ |
54 | 54 |
* 2004-11-08 dropped find_tcp_si and replaced with find_si (andrei) |
55 | 55 |
* 2005-06-07 new tcp optimized code, supports epoll (LT), sigio + real time |
56 | 56 |
* signals, poll & select (andrei) |
57 |
+ * 2005-06-26 *bsd kqueue support (andrei) |
|
57 | 58 |
*/ |
58 | 59 |
|
59 | 60 |
|
... | ... |
@@ -1073,7 +1074,7 @@ inline static int handle_tcpconn_ev(struct tcp_connection* tcpconn, int fd_i) |
1073 | 1074 |
} |
1074 | 1075 |
/* pass it to child, so remove it from the io watch list */ |
1075 | 1076 |
DBG("handle_tcpconn_ev: data available on %p %d\n", tcpconn, tcpconn->s); |
1076 |
- if (io_watch_del(&io_h, tcpconn->s, fd_i)==-1) goto error; |
|
1077 |
+ if (io_watch_del(&io_h, tcpconn->s, fd_i, 0)==-1) goto error; |
|
1077 | 1078 |
tcpconn_ref(tcpconn); /* refcnt ++ */ |
1078 | 1079 |
if (send2child(tcpconn)<0){ |
1079 | 1080 |
LOG(L_ERR,"ERROR: handle_tcpconn_ev: no children available\n"); |
... | ... |
@@ -1126,8 +1127,8 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i) |
1126 | 1127 |
DBG("DBG: handle_tcp_child: dead tcp child %d (pid %d, no %d)" |
1127 | 1128 |
" (shutting down?)\n", (int)(tcp_c-&tcp_children[0]), |
1128 | 1129 |
tcp_c->pid, tcp_c->proc_no ); |
1129 |
- /* don't listen on it any more */ |
|
1130 |
- io_watch_del(&io_h, tcp_c->unix_sock, fd_i); |
|
1130 |
+ /* don't listen on it any more */ |
|
1131 |
+ io_watch_del(&io_h, tcp_c->unix_sock, fd_i, 0); |
|
1131 | 1132 |
goto error; /* eof. so no more io here, it's ok to return error */ |
1132 | 1133 |
}else if (bytes<0){ |
1133 | 1134 |
/* EAGAIN is ok if we try to empty the buffer |
... | ... |
@@ -1186,9 +1187,9 @@ inline static int handle_tcp_child(struct tcp_child* tcp_c, int fd_i) |
1186 | 1187 |
tcp_c->busy--; |
1187 | 1188 |
/* main doesn't listen on it => we don't have to delete it |
1188 | 1189 |
if (tcpconn->s!=-1) |
1189 |
- io_watch_del(&io_h, tcpconn->s, -1); |
|
1190 |
+ io_watch_del(&io_h, tcpconn->s, -1, IO_FD_CLOSING); |
|
1190 | 1191 |
*/ |
1191 |
- tcpconn_destroy(tcpconn); |
|
1192 |
+ tcpconn_destroy(tcpconn); /* closes also the fd */ |
|
1192 | 1193 |
break; |
1193 | 1194 |
default: |
1194 | 1195 |
LOG(L_CRIT, "BUG: handle_tcp_child: unknown cmd %d" |
... | ... |
@@ -1244,7 +1245,7 @@ inline static int handle_ser_child(struct process_table* p, int fd_i) |
1244 | 1245 |
DBG("DBG: handle_ser_child: dead child %d, pid %d" |
1245 | 1246 |
" (shutting down?)\n", (int)(p-&pt[0]), p->pid); |
1246 | 1247 |
/* don't listen on it any more */ |
1247 |
- io_watch_del(&io_h, p->unix_sock, fd_i); |
|
1248 |
+ io_watch_del(&io_h, p->unix_sock, fd_i, 0); |
|
1248 | 1249 |
goto error; /* child dead => no further io events from it */ |
1249 | 1250 |
}else if (bytes<0){ |
1250 | 1251 |
/* EAGAIN is ok if we try to empty the buffer |
... | ... |
@@ -1283,8 +1284,8 @@ inline static int handle_ser_child(struct process_table* p, int fd_i) |
1283 | 1284 |
switch(cmd){ |
1284 | 1285 |
case CONN_ERROR: |
1285 | 1286 |
if (tcpconn->s!=-1) |
1286 |
- io_watch_del(&io_h, tcpconn->s, -1); |
|
1287 |
- tcpconn_destroy(tcpconn); |
|
1287 |
+ io_watch_del(&io_h, tcpconn->s, -1, IO_FD_CLOSING); |
|
1288 |
+ tcpconn_destroy(tcpconn); /* will close also the fd */ |
|
1288 | 1289 |
break; |
1289 | 1290 |
case CONN_GET_FD: |
1290 | 1291 |
/* send the requested FD */ |
... | ... |
@@ -1391,7 +1392,7 @@ static void tcpconn_timeout() |
1391 | 1392 |
#endif |
1392 | 1393 |
_tcpconn_rm(c); |
1393 | 1394 |
if (fd>0) { |
1394 |
- io_watch_del(&io_h, fd, -1); |
|
1395 |
+ io_watch_del(&io_h, fd, -1, IO_FD_CLOSING); |
|
1395 | 1396 |
close(fd); |
1396 | 1397 |
} |
1397 | 1398 |
} |
... | ... |
@@ -1506,6 +1507,14 @@ void tcp_main_loop() |
1506 | 1507 |
tcpconn_timeout(); |
1507 | 1508 |
} |
1508 | 1509 |
break; |
1510 |
+#endif |
|
1511 |
+#ifdef HAVE_KQUEUE |
|
1512 |
+ case POLL_KQUEUE: |
|
1513 |
+ while(1){ |
|
1514 |
+ io_wait_loop_kqueue(&io_h, TCP_MAIN_SELECT_TIMEOUT, 0); |
|
1515 |
+ tcpconn_timeout(); |
|
1516 |
+ } |
|
1517 |
+ break; |
|
1509 | 1518 |
#endif |
1510 | 1519 |
default: |
1511 | 1520 |
LOG(L_CRIT, "BUG: tcp_main_loop: no support for poll method " |
... | ... |
@@ -35,6 +35,7 @@ |
35 | 35 |
* 2004-07-05 udp_rcv_loop: drop packets with 0 src port + error msg. |
36 | 36 |
* cleanups (andrei) |
37 | 37 |
* 2005-03-10 multicast options are now set for all the udp sockets (andrei) |
38 |
+ * 2005-06-26 failure to set mcast options is not an error anymore (andrei) |
|
38 | 39 |
*/ |
39 | 40 |
|
40 | 41 |
|
... | ... |
@@ -319,32 +320,30 @@ int udp_init(struct socket_info* sock_info) |
319 | 320 |
if (addr->s.sa_family==AF_INET){ |
320 | 321 |
if (setsockopt(sock_info->socket, IPPROTO_IP, IP_MULTICAST_LOOP, |
321 | 322 |
&mcast_loopback, sizeof(mcast_loopback))==-1){ |
322 |
- LOG(L_ERR, "ERROR: udp_init: setsockopt(IP_MULTICAST_LOOP): %s\n", |
|
323 |
- strerror(errno)); |
|
324 |
- goto error; |
|
323 |
+ LOG(L_WARN, "WARNING: udp_init: setsockopt(IP_MULTICAST_LOOP):" |
|
324 |
+ " %s\n", strerror(errno)); |
|
325 |
+ /* it's only a warning because we might get this error if the |
|
326 |
+ network interface doesn't support multicasting -- andrei */ |
|
325 | 327 |
} |
326 | 328 |
if (mcast_ttl>=0){ |
327 | 329 |
if (setsockopt(sock_info->socket, IPPROTO_IP, IP_MULTICAST_TTL, |
328 | 330 |
&mcast_ttl, sizeof(mcast_ttl))==-1){ |
329 |
- LOG(L_ERR, "ERROR: udp_init: setsockopt (IP_MULTICAST_TTL):" |
|
331 |
+ LOG(L_WARN, "WARNING: udp_init: setsockopt (IP_MULTICAST_TTL):" |
|
330 | 332 |
" %s\n", strerror(errno)); |
331 |
- goto error; |
|
332 | 333 |
} |
333 | 334 |
} |
334 | 335 |
#ifdef USE_IPV6 |
335 | 336 |
} else if (addr->s.sa_family==AF_INET6){ |
336 | 337 |
if (setsockopt(sock_info->socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, |
337 | 338 |
&mcast_loopback, sizeof(mcast_loopback))==-1){ |
338 |
- LOG(L_ERR, "ERROR: udp_init: setsockopt (IPV6_MULTICAST_LOOP):" |
|
339 |
+ LOG(L_WARN, "WARNING: udp_init: setsockopt (IPV6_MULTICAST_LOOP):" |
|
339 | 340 |
" %s\n", strerror(errno)); |
340 |
- goto error; |
|
341 | 341 |
} |
342 | 342 |
if (mcast_ttl>=0){ |
343 | 343 |
if (setsockopt(sock_info->socket, IPPROTO_IP, IPV6_MULTICAST_HOPS, |
344 | 344 |
&mcast_ttl, sizeof(mcast_ttl))==-1){ |
345 |
- LOG(L_ERR, "ERROR: udp_init: setssckopt (IPV6_MULTICAST_HOPS):" |
|
346 |
- " %s\n", strerror(errno)); |
|
347 |
- goto error; |
|
345 |
+ LOG(L_WARN, "WARNING: udp_init: setssckopt " |
|
346 |
+ "(IPV6_MULTICAST_HOPS): %s\n", strerror(errno)); |
|
348 | 347 |
} |
349 | 348 |
} |
350 | 349 |
#endif /* USE_IPV6*/ |