Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2005 iptelorg GmbH |
3 | | * |
4 | | * This file is part of opensips, a free SIP server. |
5 | | * |
6 | | * opensips is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU General Public License as published by |
8 | | * the Free Software Foundation; either version 2 of the License, or |
9 | | * (at your option) any later version |
10 | | * |
11 | | * opensips is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | * |
20 | | * History: |
21 | | * -------- |
22 | | * 2005-06-15 created by andrei |
23 | | * 2005-06-26 added kqueue (andrei) |
24 | | * 2005-07-04 added /dev/poll (andrei) |
25 | | */ |
26 | | |
27 | | /*! |
28 | | * \file |
29 | | * \brief OpenSIPS TCP IO wait common functions |
30 | | */ |
31 | | |
32 | | |
33 | | #ifdef HAVE_EPOLL |
34 | | #include <unistd.h> /* close() */ |
35 | | #endif |
36 | | #ifdef HAVE_DEVPOLL |
37 | | #include <sys/types.h> /* open */ |
38 | | #include <sys/stat.h> |
39 | | #include <fcntl.h> |
40 | | #include <unistd.h> /* close, ioctl */ |
41 | | #endif |
42 | | |
43 | | #include <sys/utsname.h> /* uname() */ |
44 | | #include <stdlib.h> /* strtol() */ |
45 | | #include "io_wait.h" |
46 | | |
47 | | |
48 | | #include "mem/mem.h" |
49 | | |
50 | | #ifndef local_malloc |
51 | 0 | #define local_malloc pkg_malloc |
52 | | #endif |
53 | | #ifndef local_free |
54 | 0 | #define local_free pkg_free |
55 | | #endif |
56 | | |
57 | | char* poll_support="poll" |
58 | | #ifdef HAVE_EPOLL |
59 | | ", epoll" |
60 | | #endif |
61 | | #ifdef HAVE_SIGIO_RT |
62 | | ", sigio_rt" |
63 | | #endif |
64 | | #ifdef HAVE_SELECT |
65 | | ", select" |
66 | | #endif |
67 | | #ifdef HAVE_KQUEUE |
68 | | ", kqueue" |
69 | | #endif |
70 | | #ifdef HAVE_DEVPOLL |
71 | | ", /dev/poll" |
72 | | #endif |
73 | | ; |
74 | | |
75 | | /*! supported poll methods */ |
76 | | char* poll_method_str[POLL_END]={ "none", "poll", "epoll", |
77 | | "sigio_rt", "select", "kqueue", "/dev/poll" |
78 | | }; |
79 | | |
80 | | #ifdef HAVE_SIGIO_RT |
81 | | static int _sigio_init=0; |
82 | | static int _sigio_crt_rtsig; |
83 | | static sigset_t _sigio_rtsig_used; |
84 | | #endif |
85 | | |
86 | | |
87 | | |
88 | | #ifdef HAVE_SIGIO_RT |
89 | | /*! |
90 | | * \brief sigio specific init |
91 | | * \param h IO handle |
92 | | * \param rsig real time signal |
93 | | * \return returns -1 on error, 0 on success |
94 | | */ |
95 | | static int init_sigio(io_wait_h* h, int rsig) |
96 | 0 | { |
97 | 0 | int r; |
98 | 0 | int n; |
99 | 0 | int signo; |
100 | 0 | int start_sig; |
101 | 0 | sigset_t oldset; |
102 | |
|
103 | 0 | if (!_sigio_init){ |
104 | 0 | _sigio_init=1; |
105 | 0 | _sigio_crt_rtsig=SIGRTMIN; |
106 | 0 | sigemptyset(&_sigio_rtsig_used); |
107 | 0 | } |
108 | 0 | h->signo=0; |
109 | |
|
110 | 0 | if (rsig==0){ |
111 | 0 | start_sig=_sigio_crt_rtsig; |
112 | 0 | n=SIGRTMAX-SIGRTMIN; |
113 | 0 | }else{ |
114 | 0 | if ((rsig < SIGRTMIN) || (rsig >SIGRTMAX)){ |
115 | 0 | LM_CRIT("real time signal %d out of" |
116 | 0 | " range [%d, %d]\n", rsig, SIGRTMIN, SIGRTMAX); |
117 | 0 | goto error; |
118 | 0 | } |
119 | 0 | start_sig=rsig; |
120 | 0 | n=0; |
121 | 0 | } |
122 | | |
123 | 0 | sigemptyset(&h->sset); |
124 | 0 | sigemptyset(&oldset); |
125 | 0 | retry1: |
126 | | /* get current block mask */ |
127 | 0 | if (sigprocmask(SIG_BLOCK, &h->sset, &oldset )==-1){ |
128 | 0 | if (errno==EINTR) goto retry1; |
129 | 0 | LM_ERR("1st sigprocmask failed: %s [%d]\n", |
130 | 0 | strerror(errno), errno); |
131 | | /* try to continue */ |
132 | 0 | } |
133 | | |
134 | 0 | for (r=start_sig; r<=(n+start_sig); r++){ |
135 | 0 | signo=(r>SIGRTMAX)?r-SIGRTMAX+SIGRTMIN:r; |
136 | 0 | if (! sigismember(&_sigio_rtsig_used, signo) && |
137 | 0 | ! sigismember(&oldset, signo)){ |
138 | 0 | sigaddset(&_sigio_rtsig_used, signo); |
139 | 0 | h->signo=signo; |
140 | 0 | _sigio_crt_rtsig=(signo<SIGRTMAX)?signo+1:SIGRTMIN; |
141 | 0 | break; |
142 | 0 | } |
143 | 0 | } |
144 | |
|
145 | 0 | if (h->signo==0){ |
146 | 0 | LM_CRIT("init_sigio: %s\n", |
147 | 0 | rsig?"could not assign requested real-time signal": |
148 | 0 | "out of real-time signals"); |
149 | 0 | goto error; |
150 | 0 | } |
151 | | |
152 | 0 | LM_DBG("trying signal %d... \n", h->signo); |
153 | |
|
154 | 0 | if (sigaddset(&h->sset, h->signo)==-1){ |
155 | 0 | LM_ERR("sigaddset failed for %d: %s [%d]\n", |
156 | 0 | h->signo, strerror(errno), errno); |
157 | 0 | goto error; |
158 | 0 | } |
159 | 0 | if (sigaddset(&h->sset, SIGIO)==-1){ |
160 | 0 | LM_ERR("sigaddset failed for %d: %s [%d]\n", |
161 | 0 | SIGIO, strerror(errno), errno); |
162 | 0 | goto error; |
163 | 0 | } |
164 | 0 | retry: |
165 | 0 | if (sigprocmask(SIG_BLOCK, &h->sset, 0)==-1){ |
166 | 0 | if (errno==EINTR) goto retry; |
167 | 0 | LM_ERR("sigprocmask failed: %s [%d]\n", |
168 | 0 | strerror(errno), errno); |
169 | 0 | goto error; |
170 | 0 | } |
171 | 0 | return 0; |
172 | 0 | error: |
173 | 0 | h->signo=0; |
174 | 0 | sigemptyset(&h->sset); |
175 | 0 | return -1; |
176 | 0 | } |
177 | | |
178 | | |
179 | | |
180 | | /*! |
181 | | * \brief sigio specific destroy |
182 | | * \param h IO handle |
183 | | */ |
184 | | static void destroy_sigio(io_wait_h* h) |
185 | 0 | { |
186 | 0 | if (h->signo){ |
187 | 0 | sigprocmask(SIG_UNBLOCK, &h->sset, 0); |
188 | 0 | sigemptyset(&h->sset); |
189 | 0 | sigdelset(&_sigio_rtsig_used, h->signo); |
190 | 0 | h->signo=0; |
191 | 0 | } |
192 | 0 | } |
193 | | #endif |
194 | | |
195 | | |
196 | | |
197 | | #ifdef HAVE_EPOLL |
198 | | /*! |
199 | | * \brief epoll specific init |
200 | | * \param h IO handle |
201 | | * \return -1 on error, 0 on success |
202 | | */ |
203 | | static int init_epoll(io_wait_h* h) |
204 | 0 | { |
205 | 0 | again: |
206 | 0 | h->epfd=epoll_create(h->max_fd_no); |
207 | 0 | if (h->epfd==-1){ |
208 | 0 | if (errno==EINTR) goto again; |
209 | 0 | LM_ERR("epoll_create: %s [%d]\n", |
210 | 0 | strerror(errno), errno); |
211 | 0 | return -1; |
212 | 0 | } |
213 | 0 | return 0; |
214 | 0 | } |
215 | | |
216 | | /*! |
217 | | * \brief epoll specific destroy |
218 | | * \param h IO handle |
219 | | */ |
220 | | static void destroy_epoll(io_wait_h* h) |
221 | 0 | { |
222 | 0 | if (h->epfd!=-1){ |
223 | 0 | close(h->epfd); |
224 | 0 | h->epfd=-1; |
225 | 0 | } |
226 | 0 | } |
227 | | #endif |
228 | | |
229 | | |
230 | | |
231 | | #ifdef HAVE_KQUEUE |
232 | | /*! |
233 | | * \brief kqueue specific init |
234 | | * \param h IO handle |
235 | | * \return -1 on error, 0 on success |
236 | | */ |
237 | | static int init_kqueue(io_wait_h* h) |
238 | | { |
239 | | again: |
240 | | h->kq_fd=kqueue(); |
241 | | if (h->kq_fd==-1){ |
242 | | if (errno==EINTR) goto again; |
243 | | LM_ERR("kqueue: %s [%d]\n", |
244 | | strerror(errno), errno); |
245 | | return -1; |
246 | | } |
247 | | return 0; |
248 | | } |
249 | | |
250 | | |
251 | | /*! |
252 | | * \brief kqueue specific destroy |
253 | | * \param h IO handle |
254 | | */ |
255 | | static void destroy_kqueue(io_wait_h* h) |
256 | | { |
257 | | if (h->kq_fd!=-1){ |
258 | | close(h->kq_fd); |
259 | | h->kq_fd=-1; |
260 | | } |
261 | | } |
262 | | #endif |
263 | | |
264 | | |
265 | | |
266 | | #ifdef HAVE_DEVPOLL |
267 | | /*! |
268 | | * \brief /dev/poll specific init |
269 | | * \param h IO handle |
270 | | * \return -1 on error, 0 on success */ |
271 | | static int init_devpoll(io_wait_h* h) |
272 | | { |
273 | | again: |
274 | | h->dpoll_fd=open("/dev/poll", O_RDWR); |
275 | | if (h->dpoll_fd==-1){ |
276 | | if (errno==EINTR) goto again; |
277 | | LM_ERR("open: %s [%d]\n", |
278 | | strerror(errno), errno); |
279 | | return -1; |
280 | | } |
281 | | return 0; |
282 | | } |
283 | | |
284 | | |
285 | | /*! |
286 | | * \brief dev/poll specific destroy |
287 | | * \param h IO handle |
288 | | */ |
289 | | static void destroy_devpoll(io_wait_h* h) |
290 | | { |
291 | | if (h->dpoll_fd!=-1){ |
292 | | close(h->dpoll_fd); |
293 | | h->dpoll_fd=-1; |
294 | | } |
295 | | } |
296 | | #endif |
297 | | |
298 | | |
299 | | |
300 | | #ifdef HAVE_SELECT |
301 | | /*! |
302 | | * \brief select specific init |
303 | | * \param h IO handle |
304 | | * \return zero |
305 | | * \todo make this method void, and remove the check in io_wait.c |
306 | | */ |
307 | | static int init_select(io_wait_h* h) |
308 | 0 | { |
309 | 0 | FD_ZERO(&h->master_set); |
310 | 0 | return 0; |
311 | 0 | } |
312 | | #endif |
313 | | |
314 | | |
315 | | |
316 | | /*! |
317 | | * \brief return system version |
318 | | * Return system version (major.minor.minor2) as (major<<16)|(minor)<<8|(minor2) |
319 | | * (if some of them are missing, they are set to 0) |
320 | | * if the parameters are not null they are set to the coresp. part |
321 | | * \param major major version |
322 | | * \param minor minor version |
323 | | * \param minor2 minor2 version |
324 | | * \return (major<<16)|(minor)<<8|(minor2) |
325 | | */ |
326 | | static unsigned int get_sys_version(int* major, int* minor, int* minor2) |
327 | 0 | { |
328 | 0 | struct utsname un; |
329 | 0 | int m1; |
330 | 0 | int m2; |
331 | 0 | int m3; |
332 | 0 | char* p; |
333 | |
|
334 | 0 | memset (&un, 0, sizeof(un)); |
335 | 0 | m1=m2=m3=0; |
336 | | /* get sys version */ |
337 | 0 | uname(&un); |
338 | 0 | m1=strtol(un.release, &p, 10); |
339 | 0 | if (*p=='.'){ |
340 | 0 | p++; |
341 | 0 | m2=strtol(p, &p, 10); |
342 | 0 | if (*p=='.'){ |
343 | 0 | p++; |
344 | 0 | m3=strtol(p, &p, 10); |
345 | 0 | } |
346 | 0 | } |
347 | 0 | if (major) *major=m1; |
348 | 0 | if (minor) *minor=m2; |
349 | 0 | if (minor2) *minor2=m3; |
350 | 0 | return ((m1<<16)|(m2<<8)|(m3)); |
351 | 0 | } |
352 | | |
353 | | |
354 | | |
355 | | /*! |
356 | | * \brief Check preferred OS poll method |
357 | | * \param poll_method supported IO poll methods |
358 | | * \return 0 on success, and an error message on error |
359 | | */ |
360 | | char* check_poll_method(enum poll_types poll_method) |
361 | 0 | { |
362 | 0 | char* ret; |
363 | 0 | unsigned int os_ver; |
364 | |
|
365 | 0 | ret=0; |
366 | 0 | os_ver=get_sys_version(0,0,0); |
367 | 0 | (void)os_ver; |
368 | 0 | switch(poll_method){ |
369 | 0 | case POLL_NONE: |
370 | 0 | break; |
371 | 0 | case POLL_POLL: |
372 | | /* always supported */ |
373 | 0 | break; |
374 | 0 | case POLL_SELECT: |
375 | | /* should be always supported */ |
376 | | #ifndef HAVE_SELECT |
377 | | ret="select not supported, try re-compiling with -DHAVE_SELECT"; |
378 | | #endif |
379 | 0 | break; |
380 | 0 | case POLL_EPOLL: |
381 | | #ifndef HAVE_EPOLL |
382 | | ret="epoll not supported, try re-compiling with -DHAVE_EPOLL"; |
383 | | #else |
384 | | /* only on 2.6 + */ |
385 | 0 | if (os_ver<0x020542) /* if ver < 2.5.66 */ |
386 | 0 | ret="epoll not supported on kernels < 2.6"; |
387 | 0 | #endif |
388 | 0 | break; |
389 | 0 | case POLL_SIGIO_RT: |
390 | | #ifndef HAVE_SIGIO_RT |
391 | | ret="sigio_rt not supported, try re-compiling with" |
392 | | " -DHAVE_SIGIO_RT"; |
393 | | #else |
394 | | /* only on 2.2 + ?? */ |
395 | 0 | if (os_ver<0x020200) /* if ver < 2.2.0 */ |
396 | 0 | ret="epoll not supported on kernels < 2.2 (?)"; |
397 | 0 | #endif |
398 | 0 | break; |
399 | 0 | case POLL_KQUEUE: |
400 | 0 | #ifndef HAVE_KQUEUE |
401 | 0 | ret="kqueue not supported, try re-compiling with -DHAVE_KQUEUE"; |
402 | | #else |
403 | | /* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD 2.9, Darwin */ |
404 | | #ifdef __OS_freebsd |
405 | | if (os_ver<0x0401) /* if ver < 4.1 */ |
406 | | ret="kqueue not supported on FreeBSD < 4.1"; |
407 | | #elif defined (__OS_netbsd) |
408 | | if (os_ver<0x020000) /* if ver < 2.0 */ |
409 | | ret="kqueue not supported on NetBSD < 2.0"; |
410 | | #elif defined (__OS_openbsd) |
411 | | if (os_ver<0x0209) /* if ver < 2.9 ? */ |
412 | | ret="kqueue not supported on OpenBSD < 2.9 (?)"; |
413 | | #endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */ |
414 | | #endif |
415 | 0 | break; |
416 | 0 | case POLL_DEVPOLL: |
417 | 0 | #ifndef HAVE_DEVPOLL |
418 | 0 | ret="/dev/poll not supported, try re-compiling with" |
419 | 0 | " -DHAVE_DEVPOLL"; |
420 | | #else |
421 | | /* only in Solaris >= 7.0 (?) */ |
422 | | #ifdef __OS_solaris |
423 | | if (os_ver<0x0507) /* ver < 5.7 */ |
424 | | ret="/dev/poll not supported on Solaris < 7.0 (SunOS 5.7)"; |
425 | | #endif |
426 | | #endif |
427 | 0 | break; |
428 | | |
429 | 0 | default: |
430 | 0 | ret="unknown not supported method"; |
431 | 0 | } |
432 | 0 | return ret; |
433 | 0 | } |
434 | | |
435 | | |
436 | | /*! |
437 | | * \brief Choose a IO poll method |
438 | | * \return the choosen poll method |
439 | | */ |
440 | | enum poll_types choose_poll_method(void) |
441 | 0 | { |
442 | 0 | enum poll_types poll_method; |
443 | 0 | unsigned int os_ver; |
444 | |
|
445 | 0 | os_ver=get_sys_version(0,0,0); |
446 | 0 | (void)os_ver; |
447 | 0 | poll_method=0; |
448 | 0 | #ifdef HAVE_EPOLL |
449 | 0 | if (os_ver>=0x020542) /* if ver >= 2.5.66 */ |
450 | 0 | poll_method=POLL_EPOLL; |
451 | |
|
452 | 0 | #endif |
453 | | #ifdef HAVE_KQUEUE |
454 | | if (poll_method==0) |
455 | | /* only in FreeBSD 4.1, NETBSD 2.0, OpenBSD 2.9, Darwin */ |
456 | | #ifdef __OS_freebsd |
457 | | if (os_ver>=0x0401) /* if ver >= 4.1 */ |
458 | | #elif defined (__OS_netbsd) |
459 | | if (os_ver>=0x020000) /* if ver >= 2.0 */ |
460 | | #elif defined (__OS_openbsd) |
461 | | if (os_ver>=0x0209) /* if ver >= 2.9 (?) */ |
462 | | #endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */ |
463 | | poll_method=POLL_KQUEUE; |
464 | | #endif |
465 | | #ifdef HAVE_DEVPOLL |
466 | | #ifdef __OS_solaris |
467 | | if (poll_method==0) |
468 | | /* only in Solaris >= 7.0 (?) */ |
469 | | if (os_ver>=0x0507) /* if ver >=SunOS 5.7 */ |
470 | | poll_method=POLL_DEVPOLL; |
471 | | #endif |
472 | | #endif |
473 | 0 | #ifdef HAVE_SIGIO_RT |
474 | 0 | if (poll_method==0) |
475 | 0 | if (os_ver>=0x020200) /* if ver >= 2.2.0 */ |
476 | 0 | poll_method=POLL_SIGIO_RT; |
477 | 0 | #endif |
478 | 0 | if (poll_method==0) poll_method=POLL_POLL; |
479 | 0 | return poll_method; |
480 | 0 | } |
481 | | |
482 | | |
483 | | /*! |
484 | | * \brief output the IO poll method name |
485 | | * \param poll_method used poll method |
486 | | */ |
487 | | char* poll_method_name(enum poll_types poll_method) |
488 | 0 | { |
489 | 0 | if ( poll_method<POLL_END ) |
490 | 0 | return poll_method_str[poll_method]; |
491 | 0 | else |
492 | 0 | return "invalid poll method"; |
493 | 0 | } |
494 | | |
495 | | |
496 | | |
497 | | |
498 | | /*! |
499 | | * \brief converts a string into a poll_method |
500 | | * \param s converted string |
501 | | * \return POLL_NONE (0) on error, else the corresponding poll type |
502 | | */ |
503 | | enum poll_types get_poll_type(char* s) |
504 | 0 | { |
505 | 0 | int r; |
506 | 0 | unsigned int l; |
507 | |
|
508 | 0 | l=strlen(s); |
509 | 0 | for (r=POLL_END-1; r>POLL_NONE; r--) |
510 | 0 | if ((strlen(poll_method_str[r])==l) && |
511 | 0 | (strncasecmp(poll_method_str[r], s, l)==0)) |
512 | 0 | break; |
513 | 0 | return r; |
514 | 0 | } |
515 | | |
516 | | |
517 | | |
518 | | /*! |
519 | | * \brief initializes the static vars/arrays |
520 | | * \param h - pointer to the io_wait_h that will be initialized |
521 | | * \param max_fd - maximum allowed fd number |
522 | | * \param poll_method - poll method (0 for automatic best fit) |
523 | | */ |
524 | | int init_io_wait(io_wait_h* h, char *name, int max_fd, |
525 | | enum poll_types poll_method, int max_prio) |
526 | 0 | { |
527 | 0 | char * poll_err; |
528 | |
|
529 | 0 | memset(h, 0, sizeof(*h)); |
530 | 0 | h->name = name; |
531 | 0 | h->max_prio = max_prio; |
532 | 0 | h->max_fd_no=max_fd; |
533 | 0 | #ifdef HAVE_EPOLL |
534 | 0 | h->epfd=-1; |
535 | 0 | #endif |
536 | | #ifdef HAVE_KQUEUE |
537 | | h->kq_fd=-1; |
538 | | #endif |
539 | | #ifdef HAVE_DEVPOLL |
540 | | h->dpoll_fd=-1; |
541 | | #endif |
542 | 0 | poll_err=check_poll_method(poll_method); |
543 | | |
544 | | /* set an appropiate poll method */ |
545 | 0 | if (poll_err || (poll_method==0)){ |
546 | 0 | poll_method=choose_poll_method(); |
547 | 0 | if (poll_err){ |
548 | 0 | LM_ERR("%s, using %s instead\n", |
549 | 0 | poll_err, poll_method_str[poll_method]); |
550 | 0 | }else{ |
551 | 0 | LM_INFO("using %s as the io watch method" |
552 | 0 | " (auto detected)\n", poll_method_str[poll_method]); |
553 | 0 | } |
554 | 0 | } |
555 | |
|
556 | 0 | h->poll_method=poll_method; |
557 | | |
558 | | /* common stuff, everybody has fd_hash */ |
559 | 0 | h->fd_hash=local_malloc(sizeof(*(h->fd_hash))*h->max_fd_no); |
560 | 0 | if (h->fd_hash==0){ |
561 | 0 | LM_CRIT("could not alloc fd hashtable (%ld bytes)\n", |
562 | 0 | (long)sizeof(*(h->fd_hash))*h->max_fd_no ); |
563 | 0 | goto error; |
564 | 0 | } |
565 | 0 | memset((void*)h->fd_hash, 0, sizeof(*(h->fd_hash))*h->max_fd_no); |
566 | | |
567 | | /* init the fd array as needed for priority ordering */ |
568 | 0 | h->fd_array=local_malloc(sizeof(*(h->fd_array))*h->max_fd_no); |
569 | 0 | if (h->fd_array==0){ |
570 | 0 | LM_CRIT("could not alloc fd array (%ld bytes)\n", |
571 | 0 | (long)sizeof(*(h->fd_hash))*h->max_fd_no); |
572 | 0 | goto error; |
573 | 0 | } |
574 | 0 | memset((void*)h->fd_array, 0, sizeof(*(h->fd_array))*h->max_fd_no); |
575 | | /* array with indexes in fd_array where the priority changes */ |
576 | 0 | h->prio_idx=local_malloc(sizeof(*(h->prio_idx))*h->max_prio); |
577 | 0 | if (h->prio_idx==0){ |
578 | 0 | LM_CRIT("could not alloc fd array (%ld bytes)\n", |
579 | 0 | (long)sizeof(*(h->prio_idx))*h->max_prio); |
580 | 0 | goto error; |
581 | 0 | } |
582 | 0 | memset((void*)h->prio_idx, 0, sizeof(*(h->prio_idx))*h->max_prio); |
583 | |
|
584 | 0 | switch(poll_method){ |
585 | 0 | case POLL_POLL: |
586 | 0 | break; |
587 | 0 | #ifdef HAVE_SELECT |
588 | 0 | case POLL_SELECT: |
589 | 0 | if ((poll_method==POLL_SELECT) && (init_select(h)<0)){ |
590 | 0 | LM_CRIT("select init failed\n"); |
591 | 0 | goto error; |
592 | 0 | } |
593 | 0 | break; |
594 | 0 | #endif |
595 | | #ifdef HAVE_DEVPOLL |
596 | | case POLL_DEVPOLL: |
597 | | if ((poll_method==POLL_DEVPOLL) && (init_devpoll(h)<0)){ |
598 | | LM_CRIT("/dev/poll init failed\n"); |
599 | | goto error; |
600 | | } |
601 | | h->dp_changes=local_malloc(sizeof(*(h->dp_changes))*h->max_fd_no); |
602 | | if (h->dp_changes==0){ |
603 | | LM_CRIT("could not alloc db changes array (%ld bytes)\n", |
604 | | (long)sizeof(*(h->dp_changes))*h->max_fd_no); |
605 | | goto error; |
606 | | } |
607 | | memset((void*)h->dp_changes, 0, |
608 | | sizeof(*(h->dp_changes))*h->max_fd_no); |
609 | | break; |
610 | | #endif |
611 | 0 | #ifdef HAVE_SIGIO_RT |
612 | 0 | case POLL_SIGIO_RT: |
613 | 0 | if ((poll_method==POLL_SIGIO_RT) && (init_sigio(h, 0)<0)){ |
614 | 0 | LM_CRIT("sigio init failed\n"); |
615 | 0 | goto error; |
616 | 0 | } |
617 | 0 | break; |
618 | 0 | #endif |
619 | 0 | #ifdef HAVE_EPOLL |
620 | 0 | case POLL_EPOLL: |
621 | 0 | h->ep_array=local_malloc(sizeof(*(h->ep_array))*h->max_fd_no); |
622 | 0 | if (h->ep_array==0){ |
623 | 0 | LM_CRIT("could not alloc epoll array\n"); |
624 | 0 | goto error; |
625 | 0 | } |
626 | 0 | memset((void*)h->ep_array, 0, sizeof(*(h->ep_array))*h->max_fd_no); |
627 | 0 | if (init_epoll(h)<0){ |
628 | 0 | LM_CRIT("epoll init failed\n"); |
629 | 0 | goto error; |
630 | 0 | } |
631 | 0 | break; |
632 | 0 | #endif |
633 | | #ifdef HAVE_KQUEUE |
634 | | case POLL_KQUEUE: |
635 | | h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->max_fd_no); |
636 | | if (h->kq_array==0){ |
637 | | LM_CRIT("could not alloc kqueue event array\n"); |
638 | | goto error; |
639 | | } |
640 | | h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE; |
641 | | h->kq_changes=local_malloc(sizeof(*(h->kq_changes))* |
642 | | h->kq_changes_size); |
643 | | if (h->kq_changes==0){ |
644 | | LM_CRIT("could not alloc kqueue changes array\n"); |
645 | | goto error; |
646 | | } |
647 | | h->kq_nchanges=0; |
648 | | memset((void*)h->kq_array, 0, sizeof(*(h->kq_array))*h->max_fd_no); |
649 | | memset((void*)h->kq_changes, 0, |
650 | | sizeof(*(h->kq_changes))* h->kq_changes_size); |
651 | | if (init_kqueue(h)<0){ |
652 | | LM_CRIT("kqueue init failed\n"); |
653 | | goto error; |
654 | | } |
655 | | break; |
656 | | #endif |
657 | 0 | default: |
658 | 0 | LM_CRIT("unknown/unsupported poll method %s (%d)\n", |
659 | 0 | poll_method_str[poll_method], poll_method); |
660 | 0 | goto error; |
661 | 0 | } |
662 | 0 | return 0; |
663 | 0 | error: |
664 | 0 | return -1; |
665 | 0 | } |
666 | | |
667 | | |
668 | | |
669 | | /*! |
670 | | * \brief destroys everything init_io_wait allocated |
671 | | * \param h IO handle |
672 | | */ |
673 | | void destroy_io_wait(io_wait_h* h) |
674 | 0 | { |
675 | 0 | switch(h->poll_method){ |
676 | 0 | #ifdef HAVE_EPOLL |
677 | 0 | case POLL_EPOLL: |
678 | 0 | destroy_epoll(h); |
679 | 0 | if (h->ep_array){ |
680 | 0 | local_free(h->ep_array); |
681 | 0 | h->ep_array=0; |
682 | 0 | } |
683 | 0 | break; |
684 | 0 | #endif |
685 | | #ifdef HAVE_KQUEUE |
686 | | case POLL_KQUEUE: |
687 | | destroy_kqueue(h); |
688 | | if (h->kq_array){ |
689 | | local_free(h->kq_array); |
690 | | h->kq_array=0; |
691 | | } |
692 | | if (h->kq_changes){ |
693 | | local_free(h->kq_changes); |
694 | | h->kq_changes=0; |
695 | | } |
696 | | break; |
697 | | #endif |
698 | 0 | #ifdef HAVE_SIGIO_RT |
699 | 0 | case POLL_SIGIO_RT: |
700 | 0 | destroy_sigio(h); |
701 | 0 | break; |
702 | 0 | #endif |
703 | | #ifdef HAVE_DEVPOLL |
704 | | case POLL_DEVPOLL: |
705 | | destroy_devpoll(h); |
706 | | if (h->dp_changes){ |
707 | | local_free(h->dp_changes); |
708 | | h->dp_changes=0; |
709 | | } |
710 | | break; |
711 | | #endif |
712 | 0 | default: /*do nothing*/ |
713 | 0 | ; |
714 | 0 | } |
715 | 0 | if (h->fd_array){ |
716 | 0 | local_free(h->fd_array); |
717 | 0 | h->fd_array=0; |
718 | 0 | } |
719 | 0 | if (h->fd_hash){ |
720 | 0 | local_free(h->fd_hash); |
721 | 0 | h->fd_hash=0; |
722 | 0 | } |
723 | 0 | if (h->prio_idx){ |
724 | 0 | local_free(h->prio_idx); |
725 | 0 | h->prio_idx=0; |
726 | 0 | } |
727 | |
|
728 | 0 | } |
729 | | |
730 | | |
731 | | void fix_poll_method( enum poll_types *poll_method ) |
732 | 0 | { |
733 | 0 | char* poll_err; |
734 | | |
735 | | /* fix config variables */ |
736 | | /* they can have only positive values due the config parser so we can |
737 | | * ignore most of them */ |
738 | 0 | poll_err=check_poll_method(*poll_method); |
739 | | |
740 | | /* set an appropiate poll method */ |
741 | 0 | if (poll_err || (*poll_method==0)){ |
742 | 0 | *poll_method=choose_poll_method(); |
743 | 0 | if (poll_err){ |
744 | 0 | LM_ERR("%s, using %s instead\n", |
745 | 0 | poll_err, poll_method_name(*poll_method)); |
746 | 0 | }else{ |
747 | 0 | LM_INFO("using %s as the IO watch method" |
748 | 0 | " (auto detected)\n", poll_method_name(*poll_method)); |
749 | 0 | } |
750 | 0 | }else{ |
751 | 0 | LM_INFO("using %s as the IO watch method (config)\n", |
752 | 0 | poll_method_name(*poll_method)); |
753 | 0 | } |
754 | |
|
755 | 0 | return; |
756 | 0 | } |
757 | | |
758 | | |
759 | | int io_set_app_flag( io_wait_h *h , int type, int app_flag) |
760 | 0 | { |
761 | 0 | int i; |
762 | 0 | int res=0; |
763 | |
|
764 | 0 | for( i=0 ; i<h->fd_no ; i++) { |
765 | 0 | if (h->fd_hash[i].fd<=0 && h->fd_hash[i].type==type) { |
766 | 0 | h->fd_hash[i].app_flags |= app_flag; |
767 | 0 | res = 1; |
768 | 0 | } |
769 | 0 | } |
770 | 0 | return res; |
771 | 0 | } |
772 | | |
773 | | |
774 | | int io_check_app_flag( io_wait_h *h , int app_flag) |
775 | 0 | { |
776 | 0 | int i; |
777 | |
|
778 | 0 | for( i=0 ; i<h->fd_no ; i++) { |
779 | 0 | if ( h->fd_hash[i].fd<=0 && |
780 | 0 | (h->fd_hash[i].app_flags & app_flag) ) |
781 | 0 | return 1; |
782 | 0 | } |
783 | | /* nothing found, return false*/ |
784 | 0 | return 0; |
785 | |
|
786 | 0 | } |
787 | | |