ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/s_bsd_epoll.c
Revision: 33
Committed: Sun Oct 2 20:50:00 2005 UTC (18 years, 5 months ago) by knight
Content type: text/x-csrc
File size: 5835 byte(s)
Log Message:
- svn:keywords

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * s_bsd_epoll.c: Linux epoll() compatible network routines.
4     *
5     * Copyright (C) 2002-2005 Hybrid Development Team
6     * Based also on work of Adrian Chadd, Aaron Sethman and others.
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21     * USA
22     *
23 knight 31 * $Id$
24 adx 30 */
25    
26     #include "stdinc.h"
27     #include "fdlist.h"
28     #include "ircd.h"
29     #include "memory.h"
30     #include "s_bsd.h"
31     #include "s_log.h"
32     #include <sys/epoll.h>
33     #include <sys/syscall.h>
34    
35     static fde_t efd;
36    
37     /* Thanks to ircu for the following ifdefs. */
38    
39     /* The GNU C library may have a valid header but stub implementations
40     * of the epoll system calls. If so, provide our own. */
41     #if defined(__stub_epoll_create) || defined(__stub___epoll_create) || defined(EPOLL_NEED_BODY)
42    
43     /* Oh, did we mention that some glibc releases do not even define the
44     * syscall numbers? */
45     #if !defined(__NR_epoll_create)
46     #if defined(__ia64__)
47     #define __NR_epoll_create 1243
48     #define __NR_epoll_ctl 1244
49     #define __NR_epoll_wait 1245
50     #elif defined(__x86_64__)
51     #define __NR_epoll_create 214
52     #define __NR_epoll_ctl 233
53     #define __NR_epoll_wait 232
54     #elif defined(__sparc64__) || defined(__sparc__)
55     #define __NR_epoll_create 193
56     #define __NR_epoll_ctl 194
57     #define __NR_epoll_wait 195
58     #elif defined(__s390__) || defined(__m68k__)
59     #define __NR_epoll_create 249
60     #define __NR_epoll_ctl 250
61     #define __NR_epoll_wait 251
62     #elif defined(__ppc64__) || defined(__ppc__)
63     #define __NR_epoll_create 236
64     #define __NR_epoll_ctl 237
65     #define __NR_epoll_wait 238
66     #elif defined(__parisc__) || defined(__arm26__) || defined(__arm__)
67     #define __NR_epoll_create 224
68     #define __NR_epoll_ctl 225
69     #define __NR_epoll_wait 226
70     #elif defined(__alpha__)
71     #define __NR_epoll_create 407
72     #define __NR_epoll_ctl 408
73     #define __NR_epoll_wait 409
74     #elif defined(__sh64__)
75     #define __NR_epoll_create 282
76     #define __NR_epoll_ctl 283
77     #define __NR_epoll_wait 284
78     #elif defined(__i386__) || defined(__sh__) || defined(__m32r__) || defined(__h8300__) || defined(__frv__)
79     #define __NR_epoll_create 254
80     #define __NR_epoll_ctl 255
81     #define __NR_epoll_wait 256
82     #else /* cpu types */
83     #error No system call numbers defined for epoll family.
84     #endif /* cpu types */
85     #endif /* !defined(__NR_epoll_create) */
86    
87     _syscall1(int, epoll_create, int, size)
88     _syscall4(int, epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event *, event)
89     _syscall4(int, epoll_wait, int, epfd, struct epoll_event *, pevents, int, maxevents, int, timeout)
90    
91     #endif /* epoll_create defined as stub */
92    
93     /*
94     * init_netio
95     *
96     * This is a needed exported function which will be called to initialise
97     * the network loop code.
98     */
99     void
100     init_netio(void)
101     {
102     int fd;
103    
104     if ((fd = epoll_create(hard_fdlimit)) < 0)
105     {
106     ilog(L_CRIT, "init_netio: Couldn't open epoll fd - %d: %s",
107     errno, strerror(errno));
108     exit(115); /* Whee! */
109     }
110    
111     fd_open(&efd, fd, 0, "epoll file descriptor");
112     }
113    
114     /*
115     * comm_setselect
116     *
117     * This is a needed exported function which will be called to register
118     * and deregister interest in a pending IO state for a given FD.
119     */
120     void
121     comm_setselect(fde_t *F, unsigned int type, PF *handler,
122     void *client_data, time_t timeout)
123     {
124     int new_events, op;
125     struct epoll_event ep_event;
126    
127     if ((type & COMM_SELECT_READ))
128     {
129     F->read_handler = handler;
130     F->read_data = client_data;
131     }
132    
133     if ((type & COMM_SELECT_WRITE))
134     {
135     F->write_handler = handler;
136     F->write_data = client_data;
137     }
138    
139     new_events = (F->read_handler ? EPOLLIN : 0) |
140     (F->write_handler ? EPOLLOUT : 0);
141    
142     if (timeout != 0)
143     F->timeout = CurrentTime + (timeout / 1000);
144    
145     if (new_events != F->evcache)
146     {
147     if (new_events == 0)
148     op = EPOLL_CTL_DEL;
149     else if (F->evcache == 0)
150     op = EPOLL_CTL_ADD;
151     else
152     op = EPOLL_CTL_MOD;
153    
154     ep_event.events = F->evcache = new_events;
155     ep_event.data.fd = F->fd;
156    
157     if (epoll_ctl(efd.fd, op, F->fd, &ep_event) != 0)
158     {
159     ilog(L_CRIT, "comm_setselect: epoll_ctl() failed: %s", strerror(errno));
160     abort();
161     }
162     }
163     }
164    
165     /*
166     * comm_select()
167     *
168     * Called to do the new-style IO, courtesy of of squid (like most of this
169     * new IO code). This routine handles the stuff we've hidden in
170     * comm_setselect and fd_table[] and calls callbacks for IO ready
171     * events.
172     */
173     void
174     comm_select(void)
175     {
176     struct epoll_event ep_fdlist[128];
177     int num, i;
178     PF *hdl;
179     fde_t *F;
180    
181     num = epoll_wait(efd.fd, ep_fdlist, 128, SELECT_DELAY);
182    
183     set_time();
184    
185     if (num < 0)
186     {
187     #ifdef HAVE_USLEEP
188     usleep(50000); /* avoid 99% CPU in comm_select */
189     #endif
190     return;
191     }
192    
193     for (i = 0; i < num; i++)
194     {
195     F = lookup_fd(ep_fdlist[i].data.fd);
196     if (F == NULL || !F->flags.open)
197     continue;
198    
199     if ((ep_fdlist[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR)))
200     if ((hdl = F->read_handler) != NULL)
201     {
202     F->read_handler = NULL;
203     hdl(F, F->read_data);
204     if (!F->flags.open)
205     continue;
206     }
207    
208     if ((ep_fdlist[i].events & (EPOLLOUT | EPOLLHUP | EPOLLERR)))
209     if ((hdl = F->write_handler) != NULL)
210     {
211     F->write_handler = NULL;
212     hdl(F, F->write_data);
213     if (!F->flags.open)
214     continue;
215     }
216    
217     comm_setselect(F, 0, NULL, NULL, 0);
218     }
219     }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision