00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #ifndef _io_wait_h
00053 #define _io_wait_h
00054
00055 #include <errno.h>
00056 #include <string.h>
00057 #ifdef HAVE_SIGIO_RT
00058 #define __USE_GNU
00059 #include <sys/types.h>
00060 #include <sys/socket.h>
00061 #include <signal.h>
00062 #endif
00063
00064 #define _GNU_SOURCE
00065 #include <sys/poll.h>
00066 #include <fcntl.h>
00067
00068 #ifdef HAVE_EPOLL
00069 #include <sys/epoll.h>
00070 #endif
00071 #ifdef HAVE_KQUEUE
00072 #include <sys/types.h>
00073 #include <sys/event.h>
00074 #include <sys/time.h>
00075 #endif
00076 #ifdef HAVE_DEVPOLL
00077 #include <sys/devpoll.h>
00078 #endif
00079 #ifdef HAVE_SELECT
00080
00081 #include <sys/time.h>
00082 #include <sys/types.h>
00083 #include <unistd.h>
00084
00085 #include <sys/select.h>
00086 #endif
00087
00088 #include "dprint.h"
00089
00090 #include "poll_types.h"
00091 #ifdef HAVE_SIGIO_RT
00092 #include "pt.h"
00093 #endif
00094
00095 #include "compiler_opt.h"
00096
00097
00098 #ifdef HAVE_EPOLL
00099
00100 #if defined POLLRDHUP && ! defined EPOLLRDHUP
00101 #define EPOLLRDHUP POLLRDHUP
00102 #endif
00103 #endif
00104
00105
00106 extern int _os_ver;
00107
00108
00109 #if 0
00110 enum fd_types;
00111
00112
00113 #endif
00114
00115 #ifndef FD_TYPE_DEFINED
00116 typedef int fd_type;
00117 #define FD_TYPE_DEFINED
00118 #endif
00119
00120
00121
00122 struct fd_map{
00123 int fd;
00124 fd_type type;
00125 void* data;
00126 short events;
00127 };
00128
00129
00130 #ifdef HAVE_KQUEUE
00131 #ifndef KQ_CHANGES_ARRAY_SIZE
00132 #define KQ_CHANGES_ARRAY_SIZE 256
00133
00134 #ifdef __OS_netbsd
00135 #define KEV_UDATA_CAST (intptr_t)
00136 #else
00137 #define KEV_UDATA_CAST
00138 #endif
00139
00140 #endif
00141 #endif
00142
00143
00144
00145 struct io_wait_handler{
00146 enum poll_types poll_method;
00147 int flags;
00148 struct fd_map* fd_hash;
00149 int fd_no;
00150
00151 int max_fd_no;
00152
00153
00154
00155 struct pollfd* fd_array;
00156 int crt_fd_array_idx;
00157
00158
00159 #ifdef HAVE_EPOLL
00160 int epfd;
00161 struct epoll_event* ep_array;
00162 #endif
00163 #ifdef HAVE_SIGIO_RT
00164 sigset_t sset;
00165 int signo;
00166 #endif
00167 #ifdef HAVE_KQUEUE
00168 int kq_fd;
00169 struct kevent* kq_array;
00170 struct kevent* kq_changes;
00171 size_t kq_nchanges;
00172 size_t kq_changes_size;
00173 #endif
00174 #ifdef HAVE_DEVPOLL
00175 int dpoll_fd;
00176 #endif
00177 #ifdef HAVE_SELECT
00178 fd_set master_rset;
00179 fd_set master_wset;
00180 int max_fd_select;
00181 #endif
00182 };
00183
00184 typedef struct io_wait_handler io_wait_h;
00185
00186
00187
00188 #define get_fd_map(h, fd) (&(h)->fd_hash[(fd)])
00189
00190
00191 #define unhash_fd_map(pfm) \
00192 do{ \
00193 (pfm)->type=0 ; \
00194 (pfm)->fd=-1; \
00195 }while(0)
00196
00197
00198 static inline struct fd_map* hash_fd_map( io_wait_h* h,
00199 int fd,
00200 short events,
00201 fd_type type,
00202 void* data)
00203 {
00204 h->fd_hash[fd].fd=fd;
00205 h->fd_hash[fd].events=events;
00206 h->fd_hash[fd].type=type;
00207 h->fd_hash[fd].data=data;
00208 return &h->fd_hash[fd];
00209 }
00210
00211
00212
00213 #ifdef HANDLE_IO_INLINE
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 inline static int handle_io(struct fd_map* fm, short events, int idx);
00229 #else
00230 int handle_io(struct fd_map* fm, short events, int idx);
00231 #endif
00232
00233
00234
00235 #ifdef HAVE_KQUEUE
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 static inline int kq_ev_change(io_wait_h* h, int fd, int filter, int flag,
00246 void* data)
00247 {
00248 int n;
00249 struct timespec tspec;
00250
00251 if (h->kq_nchanges>=h->kq_changes_size){
00252
00253 LOG(L_WARN, "WARNING: kq_ev_change: kqueue changes array full"
00254 " trying to flush...\n");
00255 tspec.tv_sec=0;
00256 tspec.tv_nsec=0;
00257 again:
00258 n=kevent(h->kq_fd, h->kq_changes, h->kq_nchanges, 0, 0, &tspec);
00259 if (n==-1){
00260 if (errno==EINTR) goto again;
00261 LOG(L_ERR, "ERROR: io_watch_add: kevent flush changes "
00262 " failed: %s [%d]\n", strerror(errno), errno);
00263 return -1;
00264 }
00265 h->kq_nchanges=0;
00266 }
00267 EV_SET(&h->kq_changes[h->kq_nchanges], fd, filter, flag, 0, 0,
00268 KEV_UDATA_CAST data);
00269 h->kq_nchanges++;
00270 return 0;
00271 }
00272 #endif
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 inline static int io_watch_add( io_wait_h* h,
00294 int fd,
00295 short events,
00296 fd_type type,
00297 void* data)
00298 {
00299
00300
00301 #define fd_array_setup(ev) \
00302 do{ \
00303 h->fd_array[h->fd_no].fd=fd; \
00304 h->fd_array[h->fd_no].events=(ev); \
00305 h->fd_array[h->fd_no].revents=0; \
00306 }while(0)
00307
00308 #define set_fd_flags(f) \
00309 do{ \
00310 flags=fcntl(fd, F_GETFL); \
00311 if (flags==-1){ \
00312 LOG(L_ERR, "ERROR: io_watch_add: fnctl: GETFL failed:" \
00313 " %s [%d]\n", strerror(errno), errno); \
00314 goto error; \
00315 } \
00316 if (fcntl(fd, F_SETFL, flags|(f))==-1){ \
00317 LOG(L_ERR, "ERROR: io_watch_add: fnctl: SETFL" \
00318 " failed: %s [%d]\n", strerror(errno), errno); \
00319 goto error; \
00320 } \
00321 }while(0)
00322
00323
00324 struct fd_map* e;
00325 int flags;
00326 #ifdef HAVE_EPOLL
00327 struct epoll_event ep_event;
00328 #endif
00329 #ifdef HAVE_DEVPOLL
00330 struct pollfd pfd;
00331 #endif
00332 #if defined(HAVE_SIGIO_RT) || defined (HAVE_EPOLL)
00333 int n;
00334 #endif
00335 #if defined(HAVE_SIGIO_RT)
00336 int idx;
00337 int check_io;
00338 struct pollfd pf;
00339
00340 check_io=0;
00341
00342 idx=-1;
00343 #endif
00344 e=0;
00345
00346 if (unlikely(fd==-1)){
00347 LOG(L_CRIT, "BUG: io_watch_add: fd is -1!\n");
00348 goto error;
00349 }
00350 if (unlikely((events&(POLLIN|POLLOUT))==0)){
00351 LOG(L_CRIT, "BUG: io_watch_add: invalid events: 0x%0x\n", events);
00352 goto error;
00353 }
00354
00355 if (unlikely(h->fd_no>=h->max_fd_no)){
00356 LOG(L_CRIT, "ERROR: io_watch_add: maximum fd number exceeded:"
00357 " %d/%d\n", h->fd_no, h->max_fd_no);
00358 goto error;
00359 }
00360 DBG("DBG: io_watch_add(%p, %d, %d, %p), fd_no=%d\n",
00361 h, fd, type, data, h->fd_no);
00362
00363 e=get_fd_map(h, fd);
00364 if (unlikely(e && (e->type!=0 ))){
00365 LOG(L_ERR, "ERROR: io_watch_add: trying to overwrite entry %d"
00366 " watched for %x in the hash(%d, %d, %p) with (%d, %d, %p)\n",
00367 fd, events, e->fd, e->type, e->data, fd, type, data);
00368 e=0;
00369 goto error;
00370 }
00371
00372 if (unlikely((e=hash_fd_map(h, fd, events, type, data))==0)){
00373 LOG(L_ERR, "ERROR: io_watch_add: failed to hash the fd %d\n", fd);
00374 goto error;
00375 }
00376 switch(h->poll_method){
00377 case POLL_POLL:
00378 #ifdef POLLRDHUP
00379
00380 events|=((int)!(events & POLLIN) - 1) & POLLRDHUP;
00381 #endif
00382 fd_array_setup(events);
00383 set_fd_flags(O_NONBLOCK);
00384 break;
00385 #ifdef HAVE_SELECT
00386 case POLL_SELECT:
00387 fd_array_setup(events);
00388 if (likely(events & POLLIN))
00389 FD_SET(fd, &h->master_rset);
00390 if (unlikely(events & POLLOUT))
00391 FD_SET(fd, &h->master_wset);
00392 if (h->max_fd_select<fd) h->max_fd_select=fd;
00393 break;
00394 #endif
00395 #ifdef HAVE_SIGIO_RT
00396 case POLL_SIGIO_RT:
00397 fd_array_setup(events);
00398
00399
00400
00401
00402
00403 if (fcntl(fd, F_SETOWN, my_pid())==-1){
00404 LOG(L_ERR, "ERROR: io_watch_add: fnctl: SETOWN"
00405 " failed: %s [%d]\n", strerror(errno), errno);
00406 goto error;
00407 }
00408 if (fcntl(fd, F_SETSIG, h->signo)==-1){
00409 LOG(L_ERR, "ERROR: io_watch_add: fnctl: SETSIG"
00410 " failed: %s [%d]\n", strerror(errno), errno);
00411 goto error;
00412 }
00413
00414 set_fd_flags(O_ASYNC| O_NONBLOCK);
00415 #ifdef EXTRA_DEBUG
00416 DBG("io_watch_add: sigio_rt on f %d, signal %d to pid %d\n",
00417 fd, h->signo, my_pid());
00418 #endif
00419
00420
00421
00422
00423
00424
00425 idx=h->fd_no;
00426 check_io=1;
00427 break;
00428 #endif
00429 #ifdef HAVE_EPOLL
00430 case POLL_EPOLL_LT:
00431 ep_event.events=
00432 #ifdef POLLRDHUP
00433
00434 ((EPOLLIN|EPOLLRDHUP) & ((int)!(events & POLLIN)-1) ) |
00435 #else
00436 (EPOLLIN & ((int)!(events & POLLIN)-1) ) |
00437 #endif
00438 (EPOLLOUT & ((int)!(events & POLLOUT)-1) );
00439 ep_event.data.ptr=e;
00440 again1:
00441 n=epoll_ctl(h->epfd, EPOLL_CTL_ADD, fd, &ep_event);
00442 if (unlikely(n==-1)){
00443 if (errno==EAGAIN) goto again1;
00444 LOG(L_ERR, "ERROR: io_watch_add: epoll_ctl failed: %s [%d]\n",
00445 strerror(errno), errno);
00446 goto error;
00447 }
00448 break;
00449 case POLL_EPOLL_ET:
00450 set_fd_flags(O_NONBLOCK);
00451 ep_event.events=
00452 #ifdef POLLRDHUP
00453
00454 ((EPOLLIN|EPOLLRDHUP) & ((int)!(events & POLLIN)-1) ) |
00455 #else
00456 (EPOLLIN & ((int)!(events & POLLIN)-1) ) |
00457 #endif
00458 (EPOLLOUT & ((int)!(events & POLLOUT)-1) ) |
00459 EPOLLET;
00460 ep_event.data.ptr=e;
00461 again2:
00462 n=epoll_ctl(h->epfd, EPOLL_CTL_ADD, fd, &ep_event);
00463 if (unlikely(n==-1)){
00464 if (errno==EAGAIN) goto again2;
00465 LOG(L_ERR, "ERROR: io_watch_add: epoll_ctl failed: %s [%d]\n",
00466 strerror(errno), errno);
00467 goto error;
00468 }
00469 break;
00470 #endif
00471 #ifdef HAVE_KQUEUE
00472 case POLL_KQUEUE:
00473 if (likely( events & POLLIN)){
00474 if (unlikely(kq_ev_change(h, fd, EVFILT_READ, EV_ADD, e)==-1))
00475 goto error;
00476 }
00477 if (unlikely( events & POLLOUT)){
00478 if (unlikely(kq_ev_change(h, fd, EVFILT_WRITE, EV_ADD, e)==-1))
00479 {
00480 if (likely(events & POLLIN)){
00481 kq_ev_change(h, fd, EVFILT_READ, EV_DELETE, 0);
00482 }
00483 }
00484 goto error;
00485 }
00486 break;
00487 #endif
00488 #ifdef HAVE_DEVPOLL
00489 case POLL_DEVPOLL:
00490 pfd.fd=fd;
00491 pfd.events=events;
00492 pfd.revents=0;
00493 again_devpoll:
00494 if (write(h->dpoll_fd, &pfd, sizeof(pfd))==-1){
00495 if (errno==EAGAIN) goto again_devpoll;
00496 LOG(L_ERR, "ERROR: io_watch_add: /dev/poll write failed:"
00497 "%s [%d]\n", strerror(errno), errno);
00498 goto error;
00499 }
00500 break;
00501 #endif
00502
00503 default:
00504 LOG(L_CRIT, "BUG: io_watch_add: no support for poll method "
00505 " %s (%d)\n", poll_method_str[h->poll_method],
00506 h->poll_method);
00507 goto error;
00508 }
00509
00510 h->fd_no++;
00511
00512 #if defined(HAVE_SIGIO_RT)
00513 if (check_io){
00514
00515 pf.fd=fd;
00516 pf.events=events;
00517 check_io_again:
00518 n=0;
00519 while(e->type && ((n=poll(&pf, 1, 0))>0) &&
00520 (handle_io(e, pf.revents, idx)>0) &&
00521 (pf.revents & (e->events|POLLERR|POLLHUP)));
00522 if (unlikely(e->type && (n==-1))){
00523 if (errno==EINTR) goto check_io_again;
00524 LOG(L_ERR, "ERROR: io_watch_add: check_io poll: %s [%d]\n",
00525 strerror(errno), errno);
00526 }
00527 }
00528 #endif
00529 return 0;
00530 error:
00531 if (e) unhash_fd_map(e);
00532 return -1;
00533 #undef fd_array_setup
00534 #undef set_fd_flags
00535 }
00536
00537
00538
00539 #define IO_FD_CLOSING 16
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
00552 {
00553
00554 #define fix_fd_array \
00555 do{\
00556 if (unlikely(idx==-1)){ \
00557 \
00558 for (idx=0; (idx<h->fd_no) && \
00559 (h->fd_array[idx].fd!=fd); idx++); \
00560 } \
00561 if (likely(idx<h->fd_no)){ \
00562 memmove(&h->fd_array[idx], &h->fd_array[idx+1], \
00563 (h->fd_no-(idx+1))*sizeof(*(h->fd_array))); \
00564 if ((idx<=h->crt_fd_array_idx) && (h->crt_fd_array_idx>=0)) \
00565 h->crt_fd_array_idx--; \
00566 } \
00567 }while(0)
00568
00569 struct fd_map* e;
00570 int events;
00571 #ifdef HAVE_EPOLL
00572 int n;
00573 struct epoll_event ep_event;
00574 #endif
00575 #ifdef HAVE_DEVPOLL
00576 struct pollfd pfd;
00577 #endif
00578 #ifdef HAVE_SIGIO_RT
00579 int fd_flags;
00580 #endif
00581
00582 if (unlikely((fd<0) || (fd>=h->max_fd_no))){
00583 LOG(L_CRIT, "BUG: io_watch_del: invalid fd %d, not in [0, %d) \n",
00584 fd, h->fd_no);
00585 goto error;
00586 }
00587 DBG("DBG: io_watch_del (%p, %d, %d, 0x%x) fd_no=%d called\n",
00588 h, fd, idx, flags, h->fd_no);
00589 e=get_fd_map(h, fd);
00590
00591 if (unlikely(e==0)){
00592 LOG(L_CRIT, "BUG: io_watch_del: no corresponding hash entry for %d\n",
00593 fd);
00594 goto error;
00595 }
00596 if (unlikely(e->type==0 )){
00597 LOG(L_ERR, "ERROR: io_watch_del: trying to delete already erased"
00598 " entry %d in the hash(%d, %d, %p) flags %x)\n",
00599 fd, e->fd, e->type, e->data, flags);
00600 goto error;
00601 }
00602 events=e->events;
00603 unhash_fd_map(e);
00604
00605 switch(h->poll_method){
00606 case POLL_POLL:
00607 fix_fd_array;
00608 break;
00609 #ifdef HAVE_SELECT
00610 case POLL_SELECT:
00611 if (likely(events & POLLIN))
00612 FD_CLR(fd, &h->master_rset);
00613 if (unlikely(events & POLLOUT))
00614 FD_CLR(fd, &h->master_wset);
00615 if (unlikely(h->max_fd_select && (h->max_fd_select==fd)))
00616
00617 h->max_fd_select--;
00618 fix_fd_array;
00619 break;
00620 #endif
00621 #ifdef HAVE_SIGIO_RT
00622 case POLL_SIGIO_RT:
00623 fix_fd_array;
00624
00625
00626
00627
00628
00629
00630
00631
00632 fd_flags=fcntl(fd, F_GETFL);
00633 if (unlikely(fd_flags==-1)){
00634 LOG(L_ERR, "ERROR: io_watch_del: fnctl: GETFL failed:"
00635 " %s [%d]\n", strerror(errno), errno);
00636 goto error;
00637 }
00638 if (unlikely(fcntl(fd, F_SETFL, fd_flags&(~O_ASYNC))==-1)){
00639 LOG(L_ERR, "ERROR: io_watch_del: fnctl: SETFL"
00640 " failed: %s [%d]\n", strerror(errno), errno);
00641 goto error;
00642 }
00643 break;
00644 #endif
00645 #ifdef HAVE_EPOLL
00646 case POLL_EPOLL_LT:
00647 case POLL_EPOLL_ET:
00648
00649
00650
00651
00652
00653 #ifdef EPOLL_NO_CLOSE_BUG
00654 if (!(flags & IO_FD_CLOSING)){
00655 #endif
00656 again_epoll:
00657 n=epoll_ctl(h->epfd, EPOLL_CTL_DEL, fd, &ep_event);
00658 if (unlikely(n==-1)){
00659 if (errno==EAGAIN) goto again_epoll;
00660 LOG(L_ERR, "ERROR: io_watch_del: removing fd from epoll "
00661 "list failed: %s [%d]\n", strerror(errno), errno);
00662 goto error;
00663 }
00664 #ifdef EPOLL_NO_CLOSE_BUG
00665 }
00666 #endif
00667 break;
00668 #endif
00669 #ifdef HAVE_KQUEUE
00670 case POLL_KQUEUE:
00671 if (!(flags & IO_FD_CLOSING)){
00672 if (likely(events & POLLIN)){
00673 if (unlikely(kq_ev_change(h, fd, EVFILT_READ,
00674 EV_DELETE, 0) ==-1)){
00675
00676 if (events & POLLOUT){
00677 kq_ev_change(h, fd, EVFILT_WRITE, EV_DELETE, 0);
00678 }
00679 goto error;
00680 }
00681 }
00682 if (unlikely(events & POLLOUT)){
00683 if (unlikely(kq_ev_change(h, fd, EVFILT_WRITE,
00684 EV_DELETE, 0) ==-1))
00685 goto error;
00686 }
00687 }
00688 break;
00689 #endif
00690 #ifdef HAVE_DEVPOLL
00691 case POLL_DEVPOLL:
00692
00693
00694 pfd.fd=fd;
00695 pfd.events=POLLREMOVE;
00696 pfd.revents=0;
00697 again_devpoll:
00698 if (write(h->dpoll_fd, &pfd, sizeof(pfd))==-1){
00699 if (errno==EINTR) goto again_devpoll;
00700 LOG(L_ERR, "ERROR: io_watch_del: removing fd from "
00701 "/dev/poll failed: %s [%d]\n",
00702 strerror(errno), errno);
00703 goto error;
00704 }
00705 break;
00706 #endif
00707 default:
00708 LOG(L_CRIT, "BUG: io_watch_del: no support for poll method "
00709 " %s (%d)\n", poll_method_str[h->poll_method],
00710 h->poll_method);
00711 goto error;
00712 }
00713 h->fd_no--;
00714 return 0;
00715 error:
00716 return -1;
00717 #undef fix_fd_array
00718 }
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731 inline static int io_watch_chg(io_wait_h* h, int fd, short events, int idx )
00732 {
00733
00734 #define fd_array_chg(ev) \
00735 do{\
00736 if (unlikely(idx==-1)){ \
00737 \
00738 for (idx=0; (idx<h->fd_no) && \
00739 (h->fd_array[idx].fd!=fd); idx++); \
00740 } \
00741 if (likely(idx<h->fd_no)){ \
00742 h->fd_array[idx].events=(ev); \
00743 } \
00744 }while(0)
00745
00746 struct fd_map* e;
00747 int add_events;
00748 int del_events;
00749 #ifdef HAVE_DEVPOLL
00750 struct pollfd pfd;
00751 #endif
00752 #ifdef HAVE_EPOLL
00753 int n;
00754 struct epoll_event ep_event;
00755 #endif
00756
00757 if (unlikely((fd<0) || (fd>=h->max_fd_no))){
00758 LOG(L_CRIT, "BUG: io_watch_chg: invalid fd %d, not in [0, %d) \n",
00759 fd, h->fd_no);
00760 goto error;
00761 }
00762 if (unlikely((events&(POLLIN|POLLOUT))==0)){
00763 LOG(L_CRIT, "BUG: io_watch_chg: invalid events: 0x%0x\n", events);
00764 goto error;
00765 }
00766 DBG("DBG: io_watch_chg (%p, %d, 0x%x, 0x%x) fd_no=%d called\n",
00767 h, fd, events, idx, h->fd_no);
00768 e=get_fd_map(h, fd);
00769
00770 if (unlikely(e==0)){
00771 LOG(L_CRIT, "BUG: io_watch_chg: no corresponding hash entry for %d\n",
00772 fd);
00773 goto error;
00774 }
00775 if (unlikely(e->type==0 )){
00776 LOG(L_ERR, "ERROR: io_watch_chg: trying to change an already erased"
00777 " entry %d in the hash(%d, %d, %p) )\n",
00778 fd, e->fd, e->type, e->data);
00779 goto error;
00780 }
00781
00782 add_events=events & ~e->events;
00783 del_events=e->events & ~events;
00784 e->events=events;
00785 switch(h->poll_method){
00786 case POLL_POLL:
00787 #ifdef POLLRDHUP
00788
00789 events|=((int)!(events & POLLIN) - 1) & POLLRDHUP;
00790 #endif
00791 fd_array_chg(events);
00792 break;
00793 #ifdef HAVE_SELECT
00794 case POLL_SELECT:
00795 fd_array_chg(events);
00796 if (unlikely(del_events & POLLIN))
00797 FD_CLR(fd, &h->master_rset);
00798 else if (unlikely(add_events & POLLIN))
00799 FD_SET(fd, &h->master_rset);
00800 if (likely(del_events & POLLOUT))
00801 FD_CLR(fd, &h->master_wset);
00802 else if (likely(add_events & POLLOUT))
00803 FD_SET(fd, &h->master_wset);
00804 break;
00805 #endif
00806 #ifdef HAVE_SIGIO_RT
00807 case POLL_SIGIO_RT:
00808 fd_array_chg(events);
00809
00810
00811 break;
00812 #endif
00813 #ifdef HAVE_EPOLL
00814 case POLL_EPOLL_LT:
00815 ep_event.events=
00816 #ifdef POLLRDHUP
00817
00818 ((EPOLLIN|EPOLLRDHUP) & ((int)!(events & POLLIN)-1) ) |
00819 #else
00820 (EPOLLIN & ((int)!(events & POLLIN)-1) ) |
00821 #endif
00822 (EPOLLOUT & ((int)!(events & POLLOUT)-1) );
00823 ep_event.data.ptr=e;
00824 again_epoll_lt:
00825 n=epoll_ctl(h->epfd, EPOLL_CTL_MOD, fd, &ep_event);
00826 if (unlikely(n==-1)){
00827 if (errno==EAGAIN) goto again_epoll_lt;
00828 LOG(L_ERR, "ERROR: io_watch_chg: modifying epoll events"
00829 " failed: %s [%d]\n", strerror(errno), errno);
00830 goto error;
00831 }
00832 break;
00833 case POLL_EPOLL_ET:
00834 ep_event.events=
00835 #ifdef POLLRDHUP
00836
00837 ((EPOLLIN|EPOLLRDHUP) & ((int)!(events & POLLIN)-1) ) |
00838 #else
00839 (EPOLLIN & ((int)!(events & POLLIN)-1) ) |
00840 #endif
00841 (EPOLLOUT & ((int)!(events & POLLOUT)-1) ) |
00842 EPOLLET;
00843 ep_event.data.ptr=e;
00844 again_epoll_et:
00845 n=epoll_ctl(h->epfd, EPOLL_CTL_MOD, fd, &ep_event);
00846 if (unlikely(n==-1)){
00847 if (errno==EAGAIN) goto again_epoll_et;
00848 LOG(L_ERR, "ERROR: io_watch_chg: modifying epoll events"
00849 " failed: %s [%d]\n", strerror(errno), errno);
00850 goto error;
00851 }
00852 break;
00853 #endif
00854 #ifdef HAVE_KQUEUE
00855 case POLL_KQUEUE:
00856 if (unlikely(del_events & POLLIN)){
00857 if (unlikely(kq_ev_change(h, fd, EVFILT_READ,
00858 EV_DELETE, 0) ==-1))
00859 goto error;
00860 }else if (unlikely(add_events & POLLIN)){
00861 if (unlikely(kq_ev_change(h, fd, EVFILT_READ, EV_ADD, e) ==-1))
00862 goto error;
00863 }
00864 if (likely(del_events & POLLOUT)){
00865 if (unlikely(kq_ev_change(h, fd, EVFILT_WRITE,
00866 EV_DELETE, 0) ==-1))
00867 goto error;
00868 }else if (likely(add_events & POLLOUT)){
00869 if (unlikely(kq_ev_change(h, fd, EVFILT_WRITE, EV_ADD, e)==-1))
00870 goto error;
00871 }
00872 break;
00873 #endif
00874 #ifdef HAVE_DEVPOLL
00875 case POLL_DEVPOLL:
00876
00877
00878 pfd.fd=fd;
00879 pfd.events=POLLREMOVE;
00880 pfd.revents=0;
00881 again_devpoll1:
00882 if (unlikely(write(h->dpoll_fd, &pfd, sizeof(pfd))==-1)){
00883 if (errno==EINTR) goto again_devpoll1;
00884 LOG(L_ERR, "ERROR: io_watch_chg: removing fd from "
00885 "/dev/poll failed: %s [%d]\n",
00886 strerror(errno), errno);
00887 goto error;
00888 }
00889 again_devpoll2:
00890 pfd.events=events;
00891 pfd.revents=0;
00892 if (unlikely(write(h->dpoll_fd, &pfd, sizeof(pfd))==-1)){
00893 if (errno==EINTR) goto again_devpoll2;
00894 LOG(L_ERR, "ERROR: io_watch_chg: re-adding fd to "
00895 "/dev/poll failed: %s [%d]\n",
00896 strerror(errno), errno);
00897 goto error;
00898 }
00899 break;
00900 #endif
00901 default:
00902 LOG(L_CRIT, "BUG: io_watch_chg: no support for poll method "
00903 " %s (%d)\n", poll_method_str[h->poll_method],
00904 h->poll_method);
00905 goto error;
00906 }
00907 return 0;
00908 error:
00909 return -1;
00910 #undef fix_fd_array
00911 }
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922 inline static int io_wait_loop_poll(io_wait_h* h, int t, int repeat)
00923 {
00924 int n, r;
00925 int ret;
00926 struct fd_map* fm;
00927
00928 again:
00929 ret=n=poll(h->fd_array, h->fd_no, t*1000);
00930 if (n==-1){
00931 if (errno==EINTR) goto again;
00932 else{
00933 LOG(L_ERR, "ERROR:io_wait_loop_poll: poll: %s [%d]\n",
00934 strerror(errno), errno);
00935 goto error;
00936 }
00937 }
00938 for (r=0; (r<h->fd_no) && n; r++){
00939 fm=get_fd_map(h, h->fd_array[r].fd);
00940 if (h->fd_array[r].revents & (fm->events|POLLERR|POLLHUP)){
00941 n--;
00942
00943 if (unlikely((h->fd_array[r].fd >= h->max_fd_no)||
00944 (h->fd_array[r].fd < 0))){
00945 LOG(L_CRIT, "BUG: io_wait_loop_poll: bad fd %d "
00946 "(no in the 0 - %d range)\n",
00947 h->fd_array[r].fd, h->max_fd_no);
00948
00949 h->fd_array[r].events=0;
00950 continue;
00951 }
00952 h->crt_fd_array_idx=r;
00953
00954
00955
00956 while(fm->type &&
00957 (handle_io(fm, h->fd_array[r].revents, r) > 0) &&
00958 repeat && ((fm->events|POLLERR|POLLHUP) &
00959 h->fd_array[r].revents));
00960 r=h->crt_fd_array_idx;
00961
00962 }
00963 }
00964 error:
00965 return ret;
00966 }
00967
00968
00969
00970 #ifdef HAVE_SELECT
00971
00972 inline static int io_wait_loop_select(io_wait_h* h, int t, int repeat)
00973 {
00974 fd_set sel_rset;
00975 fd_set sel_wset;
00976 int n, ret;
00977 struct timeval timeout;
00978 int r;
00979 struct fd_map* fm;
00980 int revents;
00981
00982 again:
00983 sel_rset=h->master_rset;
00984 sel_wset=h->master_wset;
00985 timeout.tv_sec=t;
00986 timeout.tv_usec=0;
00987 ret=n=select(h->max_fd_select+1, &sel_rset, &sel_wset, 0, &timeout);
00988 if (n<0){
00989 if (errno==EINTR) goto again;
00990 LOG(L_ERR, "ERROR: io_wait_loop_select: select: %s [%d]\n",
00991 strerror(errno), errno);
00992 n=0;
00993
00994 }
00995
00996 for(r=0; (r<h->fd_no) && n; r++){
00997 revents=0;
00998 if (likely(FD_ISSET(h->fd_array[r].fd, &sel_rset)))
00999 revents|=POLLIN;
01000 if (unlikely(FD_ISSET(h->fd_array[r].fd, &sel_wset)))
01001 revents|=POLLOUT;
01002 if (unlikely(revents)){
01003 h->crt_fd_array_idx=r;
01004 fm=get_fd_map(h, h->fd_array[r].fd);
01005 while(fm->type && (fm->events & revents) &&
01006 (handle_io(fm, revents, r)>0) && repeat);
01007 r=h->crt_fd_array_idx;
01008
01009 n--;
01010 }
01011 };
01012 return ret;
01013 }
01014 #endif
01015
01016
01017
01018 #ifdef HAVE_EPOLL
01019 inline static int io_wait_loop_epoll(io_wait_h* h, int t, int repeat)
01020 {
01021 int n, r;
01022 struct fd_map* fm;
01023 int revents;
01024
01025 again:
01026 n=epoll_wait(h->epfd, h->ep_array, h->fd_no, t*1000);
01027 if (unlikely(n==-1)){
01028 if (errno==EINTR) goto again;
01029 else{
01030 LOG(L_ERR, "ERROR:io_wait_loop_epoll: "
01031 "epoll_wait(%d, %p, %d, %d): %s [%d]\n",
01032 h->epfd, h->ep_array, h->fd_no, t*1000,
01033 strerror(errno), errno);
01034 goto error;
01035 }
01036 }
01037 #if 0
01038 if (n>1){
01039 for(r=0; r<n; r++){
01040 LOG(L_ERR, "WARNING: ep_array[%d]= %x, %p\n",
01041 r, h->ep_array[r].events, h->ep_array[r].data.ptr);
01042 }
01043 }
01044 #endif
01045 for (r=0; r<n; r++){
01046 revents= (POLLIN & (!(h->ep_array[r].events & (EPOLLIN|EPOLLPRI))
01047 -1)) |
01048 (POLLOUT & (!(h->ep_array[r].events & EPOLLOUT)-1)) |
01049 (POLLERR & (!(h->ep_array[r].events & EPOLLERR)-1)) |
01050 (POLLHUP & (!(h->ep_array[r].events & EPOLLHUP)-1))
01051 #ifdef POLLRDHUP
01052 | (POLLRDHUP & (!(h->ep_array[r].events & EPOLLRDHUP)-1))
01053 #endif
01054 ;
01055 if (likely(revents)){
01056 fm=(struct fd_map*)h->ep_array[r].data.ptr;
01057 while(fm->type && ((fm->events|POLLERR|POLLHUP) & revents) &&
01058 (handle_io(fm, revents, -1)>0) && repeat);
01059 }else{
01060 LOG(L_ERR, "ERROR:io_wait_loop_epoll: unexpected event %x"
01061 " on %d/%d, data=%p\n", h->ep_array[r].events,
01062 r+1, n, h->ep_array[r].data.ptr);
01063 }
01064 }
01065 error:
01066 return n;
01067 }
01068 #endif
01069
01070
01071
01072 #ifdef HAVE_KQUEUE
01073 inline static int io_wait_loop_kqueue(io_wait_h* h, int t, int repeat)
01074 {
01075 int n, r;
01076 struct timespec tspec;
01077 struct fd_map* fm;
01078 int revents;
01079
01080 tspec.tv_sec=t;
01081 tspec.tv_nsec=0;
01082 again:
01083 n=kevent(h->kq_fd, h->kq_changes, h->kq_nchanges, h->kq_array,
01084 h->fd_no, &tspec);
01085 if (unlikely(n==-1)){
01086 if (errno==EINTR) goto again;
01087 else{
01088 LOG(L_ERR, "ERROR: io_wait_loop_kqueue: kevent:"
01089 " %s [%d]\n", strerror(errno), errno);
01090 goto error;
01091 }
01092 }
01093 h->kq_nchanges=0;
01094 for (r=0; r<n; r++){
01095 #ifdef EXTRA_DEBUG
01096 DBG("DBG: kqueue: event %d/%d: fd=%d, udata=%lx, flags=0x%x\n",
01097 r, n, h->kq_array[r].ident, (long)h->kq_array[r].udata,
01098 h->kq_array[r].flags);
01099 #endif
01100 #if 0
01101 if (unlikely(h->kq_array[r].flags & EV_ERROR)){
01102
01103
01104
01105
01106 LOG(L_INFO, "INFO: io_wait_loop_kqueue: kevent error on "
01107 "fd %ld: %s [%ld]\n", h->kq_array[r].ident,
01108 strerror(h->kq_array[r].data),
01109 (long)h->kq_array[r].data);
01110 }else{
01111 #endif
01112 fm=(struct fd_map*)h->kq_array[r].udata;
01113 if (likely(h->kq_array[r].filter==EVFILT_READ)){
01114 revents=POLLIN |
01115 (((int)!(h->kq_array[r].flags & EV_EOF)-1)&POLLHUP);
01116 while(fm->type && (fm->events & revents) &&
01117 (handle_io(fm, revents, -1)>0) && repeat);
01118 }else if (h->kq_array[r].filter==EVFILT_WRITE){
01119 revents=POLLOUT |
01120 (((int)!(h->kq_array[r].flags & EV_EOF)-1)&POLLHUP);
01121 while(fm->type && (fm->events & revents) &&
01122 (handle_io(fm, revents, -1)>0) && repeat);
01123 }
01124
01125 }
01126 error:
01127 return n;
01128 }
01129 #endif
01130
01131
01132
01133 #ifdef HAVE_SIGIO_RT
01134
01135 inline static int io_wait_loop_sigio_rt(io_wait_h* h, int t)
01136 {
01137 int n;
01138 int ret;
01139 struct timespec ts;
01140 siginfo_t siginfo;
01141 int sigio_band;
01142 int sigio_fd;
01143 struct fd_map* fm;
01144 int revents;
01145 #ifdef SIGINFO64_WORKARROUND
01146 int* pi;
01147 #endif
01148
01149
01150 ret=1;
01151 ts.tv_sec=t;
01152 ts.tv_nsec=0;
01153 if (unlikely(!sigismember(&h->sset, h->signo) ||
01154 !sigismember(&h->sset, SIGIO))) {
01155 LOG(L_CRIT, "BUG: io_wait_loop_sigio_rt: the signal mask"
01156 " is not properly set!\n");
01157 goto error;
01158 }
01159 again:
01160 n=sigtimedwait(&h->sset, &siginfo, &ts);
01161 if (unlikely(n==-1)){
01162 if (errno==EINTR) goto again;
01163 else if (errno==EAGAIN){
01164 ret=0;
01165 goto end;
01166 }else{
01167 LOG(L_ERR, "ERROR: io_wait_loop_sigio_rt: sigtimed_wait"
01168 " %s [%d]\n", strerror(errno), errno);
01169 goto error;
01170 }
01171 }
01172 if (likely(n!=SIGIO)){
01173 #ifdef SIGINFO64_WORKARROUND
01174
01175
01176
01177
01178
01179
01180
01181
01182 if ((_os_ver<0x020605) && (sizeof(siginfo.si_band)>sizeof(int))){
01183 pi=(int*)(void*)&siginfo.si_band;
01184 sigio_band=*pi;
01185 sigio_fd=*(pi+1);
01186 }else
01187 #endif
01188 {
01189 sigio_band=siginfo.si_band;
01190 sigio_fd=siginfo.si_fd;
01191 }
01192 if (unlikely(siginfo.si_code==SI_SIGIO)){
01193
01194 LOG(L_WARN, "WARNING: io_wait_loop_sigio_rt: old style sigio"
01195 " interface\n");
01196 fm=get_fd_map(h, sigio_fd);
01197
01198
01199 if (fm->type)
01200 handle_io(fm, POLLIN|POLLOUT, -1);
01201 }else{
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213 #ifdef EXTRA_DEBUG
01214 DBG("io_wait_loop_sigio_rt: siginfo: signal=%d (%d),"
01215 " si_code=%d, si_band=0x%x,"
01216 " si_fd=%d\n",
01217 siginfo.si_signo, n, siginfo.si_code,
01218 (unsigned)sigio_band,
01219 sigio_fd);
01220 #endif
01221
01222
01223
01224 if (likely(sigio_band)){
01225 fm=get_fd_map(h, sigio_fd);
01226 revents=sigio_band;
01227
01228 revents |= (!(revents & POLLPRI)-1) & POLLIN;
01229
01230
01231
01232 if (fm->type && ((fm->events|POLLERR|POLLHUP) & revents))
01233 handle_io(fm, revents, -1);
01234 else
01235 DBG("WARNING: io_wait_loop_sigio_rt: ignoring event"
01236 " %x on fd %d, watching for %x, si_code=%x "
01237 "(fm->type=%d, fm->fd=%d, fm->data=%p)\n",
01238 sigio_band, sigio_fd, fm->events, siginfo.si_code,
01239 fm->type, fm->fd, fm->data);
01240 }else{
01241 LOG(L_ERR, "ERROR: io_wait_loop_sigio_rt: unexpected event"
01242 " on fd %d: %x\n", sigio_fd, sigio_band);
01243 }
01244 }
01245 }else{
01246
01247
01248 LOG(L_WARN, "WARNING: io_wait_loop_sigio_rt: signal queue overflowed"
01249 "- falling back to poll\n");
01250
01251
01252
01253 if (signal(h->signo, SIG_IGN)==SIG_ERR){
01254 LOG(L_CRIT, "BUG: do_poll: couldn't reset signal to IGN\n");
01255 }
01256
01257 if (signal(h->signo, SIG_DFL)==SIG_ERR){
01258 LOG(L_CRIT, "BUG: do_poll: couldn't reset signal to DFL\n");
01259 }
01260
01261 ret=io_wait_loop_poll(h, -1, 1);
01262 }
01263 end:
01264 return ret;
01265 error:
01266 return -1;
01267 }
01268 #endif
01269
01270
01271
01272 #ifdef HAVE_DEVPOLL
01273 inline static int io_wait_loop_devpoll(io_wait_h* h, int t, int repeat)
01274 {
01275 int n, r;
01276 int ret;
01277 struct dvpoll dpoll;
01278 struct fd_map* fm;
01279
01280 dpoll.dp_timeout=t*1000;
01281 dpoll.dp_nfds=h->fd_no;
01282 dpoll.dp_fds=h->fd_array;
01283 again:
01284 ret=n=ioctl(h->dpoll_fd, DP_POLL, &dpoll);
01285 if (unlikely(n==-1)){
01286 if (errno==EINTR) goto again;
01287 else{
01288 LOG(L_ERR, "ERROR:io_wait_loop_devpoll: ioctl: %s [%d]\n",
01289 strerror(errno), errno);
01290 goto error;
01291 }
01292 }
01293 for (r=0; r< n; r++){
01294 if (h->fd_array[r].revents & (POLLNVAL|POLLERR)){
01295 LOG(L_ERR, "ERROR: io_wait_loop_devpoll: pollinval returned"
01296 " for fd %d, revents=%x\n",
01297 h->fd_array[r].fd, h->fd_array[r].revents);
01298 }
01299
01300 fm=get_fd_map(h, h->fd_array[r].fd);
01301 while(fm->type && (fm->events & h->fd_array[r].revents) &&
01302 (handle_io(fm, h->fd_array[r].revents, r) > 0) && repeat);
01303 }
01304 error:
01305 return ret;
01306 }
01307 #endif
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319 int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method);
01320
01321
01322 void destroy_io_wait(io_wait_h* h);
01323
01324
01325 #endif