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 #include "stdinc.h"
00027 #include "fdlist.h"
00028 #include "ircd.h"
00029 #include "memory.h"
00030 #include "s_bsd.h"
00031 #include "s_log.h"
00032 #include <sys/epoll.h>
00033 #include <sys/syscall.h>
00034
00035 static fde_t efd;
00036
00037
00038
00039
00040
00041 #if defined(__stub_epoll_create) || defined(__stub___epoll_create) || defined(EPOLL_NEED_BODY)
00042
00043
00044
00045 #if !defined(__NR_epoll_create)
00046 #if defined(__ia64__)
00047 #define __NR_epoll_create 1243
00048 #define __NR_epoll_ctl 1244
00049 #define __NR_epoll_wait 1245
00050 #elif defined(__x86_64__)
00051 #define __NR_epoll_create 214
00052 #define __NR_epoll_ctl 233
00053 #define __NR_epoll_wait 232
00054 #elif defined(__sparc64__) || defined(__sparc__)
00055 #define __NR_epoll_create 193
00056 #define __NR_epoll_ctl 194
00057 #define __NR_epoll_wait 195
00058 #elif defined(__s390__) || defined(__m68k__)
00059 #define __NR_epoll_create 249
00060 #define __NR_epoll_ctl 250
00061 #define __NR_epoll_wait 251
00062 #elif defined(__ppc64__) || defined(__ppc__)
00063 #define __NR_epoll_create 236
00064 #define __NR_epoll_ctl 237
00065 #define __NR_epoll_wait 238
00066 #elif defined(__parisc__) || defined(__arm26__) || defined(__arm__)
00067 #define __NR_epoll_create 224
00068 #define __NR_epoll_ctl 225
00069 #define __NR_epoll_wait 226
00070 #elif defined(__alpha__)
00071 #define __NR_epoll_create 407
00072 #define __NR_epoll_ctl 408
00073 #define __NR_epoll_wait 409
00074 #elif defined(__sh64__)
00075 #define __NR_epoll_create 282
00076 #define __NR_epoll_ctl 283
00077 #define __NR_epoll_wait 284
00078 #elif defined(__i386__) || defined(__sh__) || defined(__m32r__) || defined(__h8300__) || defined(__frv__)
00079 #define __NR_epoll_create 254
00080 #define __NR_epoll_ctl 255
00081 #define __NR_epoll_wait 256
00082 #else
00083 #error No system call numbers defined for epoll family.
00084 #endif
00085 #endif
00086
00087 _syscall1(int, epoll_create, int, size)
00088 _syscall4(int, epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event *, event)
00089 _syscall4(int, epoll_wait, int, epfd, struct epoll_event *, pevents, int, maxevents, int, timeout)
00090
00091 #endif
00092
00093
00094
00095
00096
00097
00098
00099 void
00100 init_netio(void)
00101 {
00102 int fd;
00103
00104 if ((fd = epoll_create(hard_fdlimit)) < 0)
00105 {
00106 ilog(L_CRIT, "init_netio: Couldn't open epoll fd - %d: %s",
00107 errno, strerror(errno));
00108 exit(115);
00109 }
00110
00111 fd_open(&efd, fd, 0, "epoll file descriptor");
00112 }
00113
00114
00115
00116
00117
00118
00119
00120 void
00121 comm_setselect(fde_t *F, unsigned int type, PF *handler,
00122 void *client_data, time_t timeout)
00123 {
00124 int new_events, op;
00125 struct epoll_event ep_event;
00126
00127 if ((type & COMM_SELECT_READ))
00128 {
00129 F->read_handler = handler;
00130 F->read_data = client_data;
00131 }
00132
00133 if ((type & COMM_SELECT_WRITE))
00134 {
00135 F->write_handler = handler;
00136 F->write_data = client_data;
00137 }
00138
00139 new_events = (F->read_handler ? EPOLLIN : 0) |
00140 (F->write_handler ? EPOLLOUT : 0);
00141
00142 if (timeout != 0)
00143 F->timeout = CurrentTime + (timeout / 1000);
00144
00145 if (new_events != F->evcache)
00146 {
00147 if (new_events == 0)
00148 op = EPOLL_CTL_DEL;
00149 else if (F->evcache == 0)
00150 op = EPOLL_CTL_ADD;
00151 else
00152 op = EPOLL_CTL_MOD;
00153
00154 ep_event.events = F->evcache = new_events;
00155 ep_event.data.fd = F->fd;
00156
00157 if (epoll_ctl(efd.fd, op, F->fd, &ep_event) != 0)
00158 {
00159 ilog(L_CRIT, "comm_setselect: epoll_ctl() failed: %s", strerror(errno));
00160 abort();
00161 }
00162 }
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 void
00174 comm_select(void)
00175 {
00176 struct epoll_event ep_fdlist[128];
00177 int num, i;
00178 PF *hdl;
00179 fde_t *F;
00180
00181 num = epoll_wait(efd.fd, ep_fdlist, 128, SELECT_DELAY);
00182
00183 set_time();
00184
00185 if (num < 0)
00186 {
00187 #ifdef HAVE_USLEEP
00188 usleep(50000);
00189 #endif
00190 return;
00191 }
00192
00193 for (i = 0; i < num; i++)
00194 {
00195 F = lookup_fd(ep_fdlist[i].data.fd);
00196 if (F == NULL || !F->flags.open)
00197 continue;
00198
00199 if ((ep_fdlist[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR)))
00200 if ((hdl = F->read_handler) != NULL)
00201 {
00202 F->read_handler = NULL;
00203 hdl(F, F->read_data);
00204 if (!F->flags.open)
00205 continue;
00206 }
00207
00208 if ((ep_fdlist[i].events & (EPOLLOUT | EPOLLHUP | EPOLLERR)))
00209 if ((hdl = F->write_handler) != NULL)
00210 {
00211 F->write_handler = NULL;
00212 hdl(F, F->write_data);
00213 if (!F->flags.open)
00214 continue;
00215 }
00216
00217 comm_setselect(F, 0, NULL, NULL, 0);
00218 }
00219 }