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 945
 		DEFS+= -DUSE_PTHREAD_MUTEX  # try pthread sems
946 946
 		found_lock_method=yes
947 947
 	endif
948
+	# check for ver >= 5.7
949
+	ifeq ($(shell [ $(OSREL_N) -gt 5007 ] && echo has_devpoll), has_devpoll)
950
+		ifeq ($(NO_DEVPOLL),)
951
+			DEFS+=-DHAVE_DEVPOLL
952
+		endif
953
+	endif
948 954
 	ifeq ($(NO_SELECT),)
949 955
 		DEFS+=-DHAVE_SELECT
950 956
 	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 42
 #ifdef HAVE_EPOLL
43 43
 #include <unistd.h> /* close() */
44 44
 #endif
45
+#ifdef HAVE_DEVPOLL
46
+#include <sys/types.h> /* open */
47
+#include <sys/stat.h>
48
+#include <fcntl.h>
49
+#include <unistd.h> /* close, ioctl */
50
+#endif
45 51
 
46 52
 #include <sys/utsname.h> /* uname() */
47 53
 #include <stdlib.h> /* strtol() */
... ...
@@ -195,8 +202,10 @@ static void destroy_sigio(io_wait_h* h)
195 195
  * returns -1 on error, 0 on success */
196 196
 static int init_epoll(io_wait_h* h)
197 197
 {
198
+again:
198 199
 	h->epfd=epoll_create(h->max_fd_no);
199 200
 	if (h->epfd==-1){
201
+		if (errno==EINTR) goto again;
200 202
 		LOG(L_ERR, "ERROR: init_epoll: epoll_create: %s [%d]\n",
201 203
 				strerror(errno), errno);
202 204
 		return -1;
... ...
@@ -222,8 +231,10 @@ static void destroy_epoll(io_wait_h* h)
222 222
  * returns -1 on error, 0 on success */
223 223
 static int init_kqueue(io_wait_h* h)
224 224
 {
225
+again:
225 226
 	h->kq_fd=kqueue();
226 227
 	if (h->kq_fd==-1){
228
+		if (errno==EINTR) goto again;
227 229
 		LOG(L_ERR, "ERROR: init_kqueue: kqueue: %s [%d]\n",
228 230
 				strerror(errno), errno);
229 231
 		return -1;
... ...
@@ -244,6 +255,35 @@ static void destroy_kqueue(io_wait_h* h)
244 244
 
245 245
 
246 246
 
247
+#ifdef HAVE_DEVPOLL
248
+/* /dev/poll specific init
249
+ * returns -1 on error, 0 on success */
250
+static int init_devpoll(io_wait_h* h)
251
+{
252
+again:
253
+	h->dpoll_fd=open("/dev/poll", O_RDWR);
254
+	if (h->dpoll_fd==-1){
255
+		if (errno==EINTR) goto again;
256
+		LOG(L_ERR, "ERROR: init_/dev/poll: open: %s [%d]\n",
257
+				strerror(errno), errno);
258
+		return -1;
259
+	}
260
+	return 0;
261
+}
262
+
263
+
264
+
265
+static void destroy_devpoll(io_wait_h* h)
266
+{
267
+	if (h->dpoll_fd!=-1){
268
+		close(h->dpoll_fd);
269
+		h->dpoll_fd=-1;
270
+	}
271
+}
272
+#endif
273
+
274
+
275
+
247 276
 #ifdef HAVE_SELECT
248 277
 static int init_select(io_wait_h* h)
249 278
 {
... ...
@@ -346,7 +386,19 @@ char* check_poll_method(enum poll_types poll_method)
346 346
 				ret="kqueue not supported on OpenBSD < 2.9 (?)";
347 347
 	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
348 348
 #endif
349
-			break;	
349
+			break;
350
+		case POLL_DEVPOLL:
351
+#ifndef HAVE_DEVPOLL
352
+			ret="/dev/poll not supported, try re-compiling with"
353
+					" -DHAVE_DEVPOLL";
354
+#else
355
+	/* only in Solaris >= 7.0 (?) */
356
+	#ifdef __OS_solaris
357
+		if (os_ver<0x0507) /* ver < 5.7 */
358
+			ret="/dev/poll not supported on Solaris < 7.0 (SunOS 5.7)";
359
+	#endif
360
+#endif
361
+			break;
350 362
 
351 363
 		default:
352 364
 			ret="unknown not supported method";
... ...
@@ -380,6 +432,14 @@ enum poll_types choose_poll_method()
380 380
 	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
381 381
 			poll_method=POLL_KQUEUE;
382 382
 #endif
383
+#ifdef HAVE_DEVPOLL
384
+	#ifdef __OS_solaris
385
+	if (poll_method==0)
386
+		/* only in Solaris >= 7.0 (?) */
387
+		if (os_ver>=0x0507) /* if ver >=SunOS 5.7 */
388
+			poll_method=POLL_DEVPOLL;
389
+	#endif
390
+#endif
383 391
 #ifdef  HAVE_SIGIO_RT
384 392
 		if (poll_method==0) 
385 393
 			if (os_ver>=0x020200) /* if ver >= 2.2.0 */
... ...
@@ -436,6 +496,9 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
436 436
 #ifdef HAVE_KQUEUE
437 437
 	h->kq_fd=-1;
438 438
 #endif
439
+#ifdef HAVE_DEVPOLL
440
+	h->dpoll_fd=-1;
441
+#endif
439 442
 	poll_err=check_poll_method(poll_method);
440 443
 	
441 444
 	/* set an appropiate poll method */
... ...
@@ -456,7 +519,7 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
456 456
 	
457 457
 	h->poll_method=poll_method;
458 458
 	
459
-	/* common stuff, evrybody has fd_hash */
459
+	/* common stuff, everybody has fd_hash */
460 460
 	h->fd_hash=local_malloc(sizeof(*(h->fd_hash))*h->max_fd_no);
461 461
 	if (h->fd_hash==0){
462 462
 		LOG(L_CRIT, "ERROR: init_io_wait: could not alloc"
... ...
@@ -474,6 +537,9 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
474 474
 #ifdef HAVE_SIGIO_RT
475 475
 		case POLL_SIGIO_RT:
476 476
 #endif
477
+#ifdef HAVE_DEVPOLL
478
+		case POLL_DEVPOLL:
479
+#endif
477 480
 			h->fd_array=local_malloc(sizeof(*(h->fd_array))*h->max_fd_no);
478 481
 			if (h->fd_array==0){
479 482
 				LOG(L_CRIT, "ERROR: init_io_wait: could not"
... ...
@@ -488,6 +554,12 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
488 488
 				goto error;
489 489
 			}
490 490
 #endif
491
+#ifdef HAVE_DEVPOLL
492
+			if ((poll_method==POLL_DEVPOLL) && (init_devpoll(h)<0)){
493
+				LOG(L_CRIT, "ERROR: init_io_wait: /dev/poll init failed\n");
494
+				goto error;
495
+			}
496
+#endif
491 497
 #ifdef HAVE_SELECT
492 498
 			if ((poll_method==POLL_SELECT) && (init_select(h)<0)){
493 499
 				LOG(L_CRIT, "ERROR: init_io_wait: select init failed\n");
... ...
@@ -583,6 +655,11 @@ void destroy_io_wait(io_wait_h* h)
583 583
 			destroy_sigio(h);
584 584
 			break;
585 585
 #endif
586
+#ifdef HAVE_DEVPOLL
587
+		case POLL_DEVPOLL:
588
+			destroy_devpoll(h);
589
+			break;
590
+#endif
586 591
 		default: /*do  nothing*/
587 592
 			;
588 593
 	}
... ...
@@ -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 70
 #include <sys/event.h>
71 71
 #include <sys/time.h>
72 72
 #endif
73
+#ifdef HAVE_DEVPOLL
74
+#include <sys/devpoll.h>
75
+#endif
73 76
 #ifdef HAVE_SELECT
74 77
 /* needed on openbsd for select*/
75 78
 #include <sys/time.h> 
... ...
@@ -140,6 +144,9 @@ struct io_wait_handler{
140 140
 	size_t kq_changes_size; /* size of the changes array */
141 141
 	int kq_fd;
142 142
 #endif
143
+#ifdef HAVE_DEVPOLL
144
+	int dpoll_fd;
145
+#endif
143 146
 #ifdef HAVE_SELECT
144 147
 	fd_set master_set;
145 148
 	int max_fd_select; /* maximum select used fd */
... ...
@@ -293,6 +300,9 @@ inline static int io_watch_add(	io_wait_h* h,
293 293
 #ifdef HAVE_SIGIO_RT
294 294
 	static char buf[65536];
295 295
 #endif
296
+#ifdef HAVE_DEVPOLL
297
+	struct pollfd pfd;
298
+#endif
296 299
 	
297 300
 	if (fd==-1){
298 301
 		LOG(L_CRIT, "BUG: io_watch_add: fd is -1!\n");
... ...
@@ -390,6 +400,21 @@ again2:
390 390
 				goto error;
391 391
 			break;
392 392
 #endif
393
+#ifdef HAVE_DEVPOLL
394
+		case POLL_DEVPOLL:
395
+			pfd.fd=fd;
396
+			pfd.events=POLLIN;
397
+			pfd.revents=0;
398
+again_devpoll:
399
+			if (write(h->dpoll_fd, &pfd, sizeof(pfd))==-1){
400
+				if (errno==EAGAIN) goto again_devpoll;
401
+				LOG(L_ERR, "ERROR: io_watch_add: /dev/poll write failed:"
402
+							"%s [%d]\n", strerror(errno), errno);
403
+				goto error;
404
+			}
405
+			break;
406
+#endif
407
+			
393 408
 		default:
394 409
 			LOG(L_CRIT, "BUG: io_watch_add: no support for poll method "
395 410
 					" %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 441
 	int n;
442 442
 	struct epoll_event ep_event;
443 443
 #endif
444
+#ifdef HAVE_DEVPOLL
445
+	struct pollfd pfd;
446
+#endif
444 447
 	
445 448
 	if ((fd<0) || (fd>=h->max_fd_no)){
446 449
 		LOG(L_CRIT, "BUG: io_watch_del: invalid fd %d, not in [0, %d) \n",
... ...
@@ -510,6 +538,23 @@ inline static int io_watch_del(io_wait_h* h, int fd, int idx, int flags)
510 510
 			}
511 511
 			break;
512 512
 #endif
513
+#ifdef HAVE_DEVPOLL
514
+		case POLL_DEVPOLL:
515
+				/* for /dev/poll the closed fds _must_ be removed
516
+				   (they are not removed automatically on close()) */
517
+				pfd.fd=fd;
518
+				pfd.events=POLLREMOVE;
519
+				pfd.revents=0;
520
+again_devpoll:
521
+				if (write(h->dpoll_fd, &pfd, sizeof(pfd))==-1){
522
+					if (errno==EINTR) goto again_devpoll;
523
+					LOG(L_ERR, "ERROR: io_watch_del: removing fd from "
524
+								"/dev/poll failed: %s [%d]\n", 
525
+								strerror(errno), errno);
526
+					goto error;
527
+				}
528
+				break;
529
+#endif
513 530
 		default:
514 531
 			LOG(L_CRIT, "BUG: io_watch_del: no support for poll method "
515 532
 					" %s (%d)\n", poll_method_str[h->poll_method], 
... ...
@@ -530,7 +575,7 @@ error:
530 530
  * params: h      - io_wait handle
531 531
  *         t      - timeout in s
532 532
  *         repeat - if !=0 handle_io will be called until it returns <=0
533
- * returns: 0 on success, -1 on err
533
+ * returns: number of IO events handled on success (can be 0), -1 on error
534 534
  */
535 535
 inline static int io_wait_loop_poll(io_wait_h* h, int t, int repeat)
536 536
 {
... ...
@@ -778,6 +823,43 @@ error:
778 778
 
779 779
 
780 780
 
781
+#ifdef HAVE_DEVPOLL
782
+inline static int io_wait_loop_devpoll(io_wait_h* h, int t, int repeat)
783
+{
784
+	int n, r;
785
+	int ret;
786
+	struct dvpoll dpoll;
787
+
788
+		dpoll.dp_timeout=t*1000;
789
+		dpoll.dp_nfds=h->fd_no;
790
+		dpoll.dp_fds=h->fd_array;
791
+again:
792
+		ret=n=ioctl(h->dpoll_fd, DP_POLL, &dpoll);
793
+		if (n==-1){
794
+			if (errno==EINTR) goto again; /* signal, ignore it */
795
+			else{
796
+				LOG(L_ERR, "ERROR:io_wait_loop_devpoll: ioctl: %s [%d]\n",
797
+						strerror(errno), errno);
798
+				goto error;
799
+			}
800
+		}
801
+		for (r=0; r< n; r++){
802
+			if (h->fd_array[r].revents & (POLLNVAL|POLLERR)){
803
+				LOG(L_ERR, "ERROR: io_wait_loop_devpoll: pollinval returned"
804
+							" for fd %d, revents=%x\n",
805
+							h->fd_array[r].fd, h->fd_array[r].revents);
806
+			}
807
+			/* POLLIN|POLLHUP just go through */
808
+			while((handle_io(get_fd_map(h, h->fd_array[r].fd), r) > 0) &&
809
+						repeat);
810
+		}
811
+error:
812
+	return ret;
813
+}
814
+#endif
815
+
816
+
817
+
781 818
 /* init */
782 819
 
783 820
 
... ...
@@ -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
 
... ...
@@ -1516,6 +1517,14 @@ void tcp_main_loop()
1516 1516
 			}
1517 1517
 			break;
1518 1518
 #endif
1519
+#ifdef HAVE_DEVPOLL
1520
+		case POLL_DEVPOLL:
1521
+			while(1){
1522
+				io_wait_loop_devpoll(&io_h, TCP_MAIN_SELECT_TIMEOUT, 0);
1523
+				tcpconn_timeout();
1524
+			}
1525
+			break;
1526
+#endif
1519 1527
 		default:
1520 1528
 			LOG(L_CRIT, "BUG: tcp_main_loop: no support for poll method "
1521 1529
 					" %s (%d)\n", 
... ...
@@ -1530,7 +1539,6 @@ error:
1530 1530
 
1531 1531
 
1532 1532
 
1533
-
1534 1533
 /* cleanup before exit */
1535 1534
 void destroy_tcp()
1536 1535
 {