Browse code

- solaris /dev/poll support added

Andrei Pelinescu-Onciul authored on 04/07/2005 15:10:52
Showing 4 changed files
... ...
@@ -39,7 +39,8 @@
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
+#  2005-06-26  numeric OSREL & HAVE_KQUEUE added to the *BSD (andrei)
43
+#  2005-07-04  HAVE_DEVPOLL added to solaris (andrei)
43 44
 
44 45
 
45 46
 # check if already included/exported
... ...
@@ -945,6 +946,12 @@ ifeq  ($(OS), solaris)
945 946
 		DEFS+= -DUSE_PTHREAD_MUTEX  # try pthread sems
946 947
 		found_lock_method=yes
947 948
 	endif
949
+	# check for ver >= 5.7
950
+	ifeq ($(shell [ $(OSREL_N) -gt 5007 ] && echo has_devpoll), has_devpoll)
951
+		ifeq ($(NO_DEVPOLL),)
952
+			DEFS+=-DHAVE_DEVPOLL
953
+		endif
954
+	endif
948 955
 	ifeq ($(NO_SELECT),)
949 956
 		DEFS+=-DHAVE_SELECT
950 957
 	endif
... ...
@@ -33,6 +33,7 @@
33 33
  * --------
34 34
  *  2005-06-15  created by andrei
35 35
  *  2005-06-26  added kqueue (andrei)
36
+ *  2005-07-04  added /dev/poll (andrei)
36 37
  */
37 38
 
38 39
 
... ...
@@ -42,6 +43,12 @@
42 43
 #ifdef HAVE_EPOLL
43 44
 #include <unistd.h> /* close() */
44 45
 #endif
46
+#ifdef HAVE_DEVPOLL
47
+#include <sys/types.h> /* open */
48
+#include <sys/stat.h>
49
+#include <fcntl.h>
50
+#include <unistd.h> /* close, ioctl */
51
+#endif
45 52
 
46 53
 #include <sys/utsname.h> /* uname() */
47 54
 #include <stdlib.h> /* strtol() */
... ...
@@ -195,8 +202,10 @@ static void destroy_sigio(io_wait_h* h)
195 202
  * returns -1 on error, 0 on success */
196 203
 static int init_epoll(io_wait_h* h)
197 204
 {
205
+again:
198 206
 	h->epfd=epoll_create(h->max_fd_no);
199 207
 	if (h->epfd==-1){
208
+		if (errno==EINTR) goto again;
200 209
 		LOG(L_ERR, "ERROR: init_epoll: epoll_create: %s [%d]\n",
201 210
 				strerror(errno), errno);
202 211
 		return -1;
... ...
@@ -222,8 +231,10 @@ static void destroy_epoll(io_wait_h* h)
222 231
  * returns -1 on error, 0 on success */
223 232
 static int init_kqueue(io_wait_h* h)
224 233
 {
234
+again:
225 235
 	h->kq_fd=kqueue();
226 236
 	if (h->kq_fd==-1){
237
+		if (errno==EINTR) goto again;
227 238
 		LOG(L_ERR, "ERROR: init_kqueue: kqueue: %s [%d]\n",
228 239
 				strerror(errno), errno);
229 240
 		return -1;
... ...
@@ -244,6 +255,35 @@ static void destroy_kqueue(io_wait_h* h)
244 255
 
245 256
 
246 257
 
258
+#ifdef HAVE_DEVPOLL
259
+/* /dev/poll specific init
260
+ * returns -1 on error, 0 on success */
261
+static int init_devpoll(io_wait_h* h)
262
+{
263
+again:
264
+	h->dpoll_fd=open("/dev/poll", O_RDWR);
265
+	if (h->dpoll_fd==-1){
266
+		if (errno==EINTR) goto again;
267
+		LOG(L_ERR, "ERROR: init_/dev/poll: open: %s [%d]\n",
268
+				strerror(errno), errno);
269
+		return -1;
270
+	}
271
+	return 0;
272
+}
273
+
274
+
275
+
276
+static void destroy_devpoll(io_wait_h* h)
277
+{
278
+	if (h->dpoll_fd!=-1){
279
+		close(h->dpoll_fd);
280
+		h->dpoll_fd=-1;
281
+	}
282
+}
283
+#endif
284
+
285
+
286
+
247 287
 #ifdef HAVE_SELECT
248 288
 static int init_select(io_wait_h* h)
249 289
 {
... ...
@@ -346,7 +386,19 @@ char* check_poll_method(enum poll_types poll_method)
346 386
 				ret="kqueue not supported on OpenBSD < 2.9 (?)";
347 387
 	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
348 388
 #endif
349
-			break;	
389
+			break;
390
+		case POLL_DEVPOLL:
391
+#ifndef HAVE_DEVPOLL
392
+			ret="/dev/poll not supported, try re-compiling with"
393
+					" -DHAVE_DEVPOLL";
394
+#else
395
+	/* only in Solaris >= 7.0 (?) */
396
+	#ifdef __OS_solaris
397
+		if (os_ver<0x0507) /* ver < 5.7 */
398
+			ret="/dev/poll not supported on Solaris < 7.0 (SunOS 5.7)";
399
+	#endif
400
+#endif
401
+			break;
350 402
 
351 403
 		default:
352 404
 			ret="unknown not supported method";
... ...
@@ -380,6 +432,14 @@ enum poll_types choose_poll_method()
380 432
 	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
381 433
 			poll_method=POLL_KQUEUE;
382 434
 #endif
435
+#ifdef HAVE_DEVPOLL
436
+	#ifdef __OS_solaris
437
+	if (poll_method==0)
438
+		/* only in Solaris >= 7.0 (?) */
439
+		if (os_ver>=0x0507) /* if ver >=SunOS 5.7 */
440
+			poll_method=POLL_DEVPOLL;
441
+	#endif
442
+#endif
383 443
 #ifdef  HAVE_SIGIO_RT
384 444
 		if (poll_method==0) 
385 445
 			if (os_ver>=0x020200) /* if ver >= 2.2.0 */
... ...
@@ -435,6 +495,9 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
435 495
 #endif
436 496
 #ifdef HAVE_KQUEUE
437 497
 	h->kq_fd=-1;
498
+#endif
499
+#ifdef HAVE_DEVPOLL
500
+	h->dpoll_fd=-1;
438 501
 #endif
439 502
 	poll_err=check_poll_method(poll_method);
440 503
 	
... ...
@@ -456,7 +519,7 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
456 519
 	
457 520
 	h->poll_method=poll_method;
458 521
 	
459
-	/* common stuff, evrybody has fd_hash */
522
+	/* common stuff, everybody has fd_hash */
460 523
 	h->fd_hash=local_malloc(sizeof(*(h->fd_hash))*h->max_fd_no);
461 524
 	if (h->fd_hash==0){
462 525
 		LOG(L_CRIT, "ERROR: init_io_wait: could not alloc"
... ...
@@ -473,6 +536,9 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
473 536
 #endif
474 537
 #ifdef HAVE_SIGIO_RT
475 538
 		case POLL_SIGIO_RT:
539
+#endif
540
+#ifdef HAVE_DEVPOLL
541
+		case POLL_DEVPOLL:
476 542
 #endif
477 543
 			h->fd_array=local_malloc(sizeof(*(h->fd_array))*h->max_fd_no);
478 544
 			if (h->fd_array==0){
... ...
@@ -488,6 +554,12 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
488 554
 				goto error;
489 555
 			}
490 556
 #endif
557
+#ifdef HAVE_DEVPOLL
558
+			if ((poll_method==POLL_DEVPOLL) && (init_devpoll(h)<0)){
559
+				LOG(L_CRIT, "ERROR: init_io_wait: /dev/poll init failed\n");
560
+				goto error;
561
+			}
562
+#endif
491 563
 #ifdef HAVE_SELECT
492 564
 			if ((poll_method==POLL_SELECT) && (init_select(h)<0)){
493 565
 				LOG(L_CRIT, "ERROR: init_io_wait: select init failed\n");
... ...
@@ -582,6 +654,11 @@ void destroy_io_wait(io_wait_h* h)
582 654
 		case POLL_SIGIO_RT:
583 655
 			destroy_sigio(h);
584 656
 			break;
657
+#endif
658
+#ifdef HAVE_DEVPOLL
659
+		case POLL_DEVPOLL:
660
+			destroy_devpoll(h);
661
+			break;
585 662
 #endif
586 663
 		default: /*do  nothing*/
587 664
 			;
... ...
@@ -47,6 +47,7 @@
47 47
  * --------
48 48
  *  2005-06-13  created by andrei
49 49
  *  2005-06-26  added kqueue (andrei)
50
+ *  2005-07-01  added /dev/poll (andrei)
50 51
  */
51 52
 
52 53
 
... ...
@@ -70,6 +71,9 @@
70 71
 #include <sys/event.h>
71 72
 #include <sys/time.h>
72 73
 #endif
74
+#ifdef HAVE_DEVPOLL
75
+#include <sys/devpoll.h>
76
+#endif
73 77
 #ifdef HAVE_SELECT
74 78
 /* needed on openbsd for select*/
75 79
 #include <sys/time.h> 
... ...
@@ -140,6 +144,9 @@ struct io_wait_handler{
140 144
 	size_t kq_changes_size; /* size of the changes array */
141 145
 	int kq_fd;
142 146
 #endif
147
+#ifdef HAVE_DEVPOLL
148
+	int dpoll_fd;
149
+#endif
143 150
 #ifdef HAVE_SELECT
144 151
 	fd_set master_set;
145 152
 	int max_fd_select; /* maximum select used fd */
... ...
@@ -293,6 +300,9 @@ inline static int io_watch_add(	io_wait_h* h,
293 300
 #ifdef HAVE_SIGIO_RT
294 301
 	static char buf[65536];
295 302
 #endif
303
+#ifdef HAVE_DEVPOLL
304
+	struct pollfd pfd;
305
+#endif
296 306
 	
297 307
 	if (fd==-1){
298 308
 		LOG(L_CRIT, "BUG: io_watch_add: fd is -1!\n");
... ...
@@ -390,6 +400,21 @@ again2:
390 400
 				goto error;
391 401
 			break;
392 402
 #endif
403
+#ifdef HAVE_DEVPOLL
404
+		case POLL_DEVPOLL:
405
+			pfd.fd=fd;
406
+			pfd.events=POLLIN;
407
+			pfd.revents=0;
408
+again_devpoll:
409
+			if (write(h->dpoll_fd, &pfd, sizeof(pfd))==-1){
410
+				if (errno==EAGAIN) goto again_devpoll;
411
+				LOG(L_ERR, "ERROR: io_watch_add: /dev/poll write failed:"
412
+							"%s [%d]\n", strerror(errno), errno);
413
+				goto error;
414
+			}
415
+			break;
416
+#endif
417
+			
393 418
 		default:
394 419
 			LOG(L_CRIT, "BUG: io_watch_add: no support for poll method "
395 420
 					" %s (%d)\n", poll_method_str[h->poll_method],
... ...
@@ -441,6 +466,9 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
441 466
 	int n;
442 467
 	struct epoll_event ep_event;
443 468
 #endif
469
+#ifdef HAVE_DEVPOLL
470
+	struct pollfd pfd;
471
+#endif
444 472
 	
445 473
 	if ((fd<0) || (fd>=h->max_fd_no)){
446 474
 		LOG(L_CRIT, "BUG: io_watch_del: invalid fd %d, not in [0, %d) \n",
... ...
@@ -509,6 +537,23 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
509 537
 					goto error;
510 538
 			}
511 539
 			break;
540
+#endif
541
+#ifdef HAVE_DEVPOLL
542
+		case POLL_DEVPOLL:
543
+				/* for /dev/poll the closed fds _must_ be removed
544
+				   (they are not removed automatically on close()) */
545
+				pfd.fd=fd;
546
+				pfd.events=POLLREMOVE;
547
+				pfd.revents=0;
548
+again_devpoll:
549
+				if (write(h->dpoll_fd, &pfd, sizeof(pfd))==-1){
550
+					if (errno==EINTR) goto again_devpoll;
551
+					LOG(L_ERR, "ERROR: io_watch_del: removing fd from "
552
+								"/dev/poll failed: %s [%d]\n", 
553
+								strerror(errno), errno);
554
+					goto error;
555
+				}
556
+				break;
512 557
 #endif
513 558
 		default:
514 559
 			LOG(L_CRIT, "BUG: io_watch_del: no support for poll method "
... ...
@@ -530,7 +575,7 @@ error:
530 575
  * params: h      - io_wait handle
531 576
  *         t      - timeout in s
532 577
  *         repeat - if !=0 handle_io will be called until it returns <=0
533
- * returns: 0 on success, -1 on err
578
+ * returns: number of IO events handled on success (can be 0), -1 on error
534 579
  */
535 580
 inline static int io_wait_loop_poll(io_wait_h* h, int t, int repeat)
536 581
 {
... ...
@@ -778,6 +823,43 @@ error:
778 823
 
779 824
 
780 825
 
826
+#ifdef HAVE_DEVPOLL
827
+inline static int io_wait_loop_devpoll(io_wait_h* h, int t, int repeat)
828
+{
829
+	int n, r;
830
+	int ret;
831
+	struct dvpoll dpoll;
832
+
833
+		dpoll.dp_timeout=t*1000;
834
+		dpoll.dp_nfds=h->fd_no;
835
+		dpoll.dp_fds=h->fd_array;
836
+again:
837
+		ret=n=ioctl(h->dpoll_fd, DP_POLL, &dpoll);
838
+		if (n==-1){
839
+			if (errno==EINTR) goto again; /* signal, ignore it */
840
+			else{
841
+				LOG(L_ERR, "ERROR:io_wait_loop_devpoll: ioctl: %s [%d]\n",
842
+						strerror(errno), errno);
843
+				goto error;
844
+			}
845
+		}
846
+		for (r=0; r< n; r++){
847
+			if (h->fd_array[r].revents & (POLLNVAL|POLLERR)){
848
+				LOG(L_ERR, "ERROR: io_wait_loop_devpoll: pollinval returned"
849
+							" for fd %d, revents=%x\n",
850
+							h->fd_array[r].fd, h->fd_array[r].revents);
851
+			}
852
+			/* POLLIN|POLLHUP just go through */
853
+			while((handle_io(get_fd_map(h, h->fd_array[r].fd), r) > 0) &&
854
+						repeat);
855
+		}
856
+error:
857
+	return ret;
858
+}
859
+#endif
860
+
861
+
862
+
781 863
 /* init */
782 864
 
783 865
 
... ...
@@ -55,6 +55,7 @@
55 55
  *  2005-06-07  new tcp optimized code, supports epoll (LT), sigio + real time
56 56
  *               signals, poll & select (andrei)
57 57
  *  2005-06-26  *bsd kqueue support (andrei)
58
+ *  2005-07-04  solaris /dev/poll support (andrei)
58 59
  */
59 60
 
60 61
 
... ...
@@ -1515,6 +1516,14 @@ void tcp_main_loop()
1515 1516
 				tcpconn_timeout();
1516 1517
 			}
1517 1518
 			break;
1519
+#endif
1520
+#ifdef HAVE_DEVPOLL
1521
+		case POLL_DEVPOLL:
1522
+			while(1){
1523
+				io_wait_loop_devpoll(&io_h, TCP_MAIN_SELECT_TIMEOUT, 0);
1524
+				tcpconn_timeout();
1525
+			}
1526
+			break;
1518 1527
 #endif
1519 1528
 		default:
1520 1529
 			LOG(L_CRIT, "BUG: tcp_main_loop: no support for poll method "
... ...
@@ -1530,7 +1539,6 @@ error:
1530 1539
 
1531 1540
 
1532 1541
 
1533
-
1534 1542
 /* cleanup before exit */
1535 1543
 void destroy_tcp()
1536 1544
 {