فهرست منبع

- solaris /dev/poll support added

Andrei Pelinescu-Onciul 20 سال پیش
والد
کامیت
9eda59565b
4فایلهای تغییر یافته به همراه179 افزوده شده و 5 حذف شده
  1. 8 1
      Makefile.defs
  2. 79 2
      io_wait.c
  3. 83 1
      io_wait.h
  4. 9 1
      tcp_main.c

+ 8 - 1
Makefile.defs

@@ -39,7 +39,8 @@
 #  2004-12-19  amd64 transformed in x86_64 (andrei)
 #  2004-12-19  amd64 transformed in x86_64 (andrei)
 #  2005-04-27  alpha support added (andrei)
 #  2005-04-27  alpha support added (andrei)
 #  2005-06-01  use $(LOCALBASE) instead of /usr/{local,pkg} (andrei)
 #  2005-06-01  use $(LOCALBASE) instead of /usr/{local,pkg} (andrei)
-#  2006-06-26  numeric OSREL & HAVE_KQUEUE added to the *BSD (andrei)
+#  2005-06-26  numeric OSREL & HAVE_KQUEUE added to the *BSD (andrei)
+#  2005-07-04  HAVE_DEVPOLL added to solaris (andrei)
 
 
 
 
 # check if already included/exported
 # check if already included/exported
@@ -945,6 +946,12 @@ ifeq  ($(OS), solaris)
 		DEFS+= -DUSE_PTHREAD_MUTEX  # try pthread sems
 		DEFS+= -DUSE_PTHREAD_MUTEX  # try pthread sems
 		found_lock_method=yes
 		found_lock_method=yes
 	endif
 	endif
+	# check for ver >= 5.7
+	ifeq ($(shell [ $(OSREL_N) -gt 5007 ] && echo has_devpoll), has_devpoll)
+		ifeq ($(NO_DEVPOLL),)
+			DEFS+=-DHAVE_DEVPOLL
+		endif
+	endif
 	ifeq ($(NO_SELECT),)
 	ifeq ($(NO_SELECT),)
 		DEFS+=-DHAVE_SELECT
 		DEFS+=-DHAVE_SELECT
 	endif
 	endif

+ 79 - 2
io_wait.c

@@ -33,6 +33,7 @@
  * --------
  * --------
  *  2005-06-15  created by andrei
  *  2005-06-15  created by andrei
  *  2005-06-26  added kqueue (andrei)
  *  2005-06-26  added kqueue (andrei)
+ *  2005-07-04  added /dev/poll (andrei)
  */
  */
 
 
 
 
@@ -42,6 +43,12 @@
 #ifdef HAVE_EPOLL
 #ifdef HAVE_EPOLL
 #include <unistd.h> /* close() */
 #include <unistd.h> /* close() */
 #endif
 #endif
+#ifdef HAVE_DEVPOLL
+#include <sys/types.h> /* open */
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h> /* close, ioctl */
+#endif
 
 
 #include <sys/utsname.h> /* uname() */
 #include <sys/utsname.h> /* uname() */
 #include <stdlib.h> /* strtol() */
 #include <stdlib.h> /* strtol() */
@@ -195,8 +202,10 @@ static void destroy_sigio(io_wait_h* h)
  * returns -1 on error, 0 on success */
  * returns -1 on error, 0 on success */
 static int init_epoll(io_wait_h* h)
 static int init_epoll(io_wait_h* h)
 {
 {
+again:
 	h->epfd=epoll_create(h->max_fd_no);
 	h->epfd=epoll_create(h->max_fd_no);
 	if (h->epfd==-1){
 	if (h->epfd==-1){
+		if (errno==EINTR) goto again;
 		LOG(L_ERR, "ERROR: init_epoll: epoll_create: %s [%d]\n",
 		LOG(L_ERR, "ERROR: init_epoll: epoll_create: %s [%d]\n",
 				strerror(errno), errno);
 				strerror(errno), errno);
 		return -1;
 		return -1;
@@ -222,8 +231,10 @@ static void destroy_epoll(io_wait_h* h)
  * returns -1 on error, 0 on success */
  * returns -1 on error, 0 on success */
 static int init_kqueue(io_wait_h* h)
 static int init_kqueue(io_wait_h* h)
 {
 {
+again:
 	h->kq_fd=kqueue();
 	h->kq_fd=kqueue();
 	if (h->kq_fd==-1){
 	if (h->kq_fd==-1){
+		if (errno==EINTR) goto again;
 		LOG(L_ERR, "ERROR: init_kqueue: kqueue: %s [%d]\n",
 		LOG(L_ERR, "ERROR: init_kqueue: kqueue: %s [%d]\n",
 				strerror(errno), errno);
 				strerror(errno), errno);
 		return -1;
 		return -1;
@@ -244,6 +255,35 @@ static void destroy_kqueue(io_wait_h* h)
 
 
 
 
 
 
+#ifdef HAVE_DEVPOLL
+/* /dev/poll specific init
+ * returns -1 on error, 0 on success */
+static int init_devpoll(io_wait_h* h)
+{
+again:
+	h->dpoll_fd=open("/dev/poll", O_RDWR);
+	if (h->dpoll_fd==-1){
+		if (errno==EINTR) goto again;
+		LOG(L_ERR, "ERROR: init_/dev/poll: open: %s [%d]\n",
+				strerror(errno), errno);
+		return -1;
+	}
+	return 0;
+}
+
+
+
+static void destroy_devpoll(io_wait_h* h)
+{
+	if (h->dpoll_fd!=-1){
+		close(h->dpoll_fd);
+		h->dpoll_fd=-1;
+	}
+}
+#endif
+
+
+
 #ifdef HAVE_SELECT
 #ifdef HAVE_SELECT
 static int init_select(io_wait_h* h)
 static int init_select(io_wait_h* h)
 {
 {
@@ -346,7 +386,19 @@ char* check_poll_method(enum poll_types poll_method)
 				ret="kqueue not supported on OpenBSD < 2.9 (?)";
 				ret="kqueue not supported on OpenBSD < 2.9 (?)";
 	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
 	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
 #endif
 #endif
-			break;	
+			break;
+		case POLL_DEVPOLL:
+#ifndef HAVE_DEVPOLL
+			ret="/dev/poll not supported, try re-compiling with"
+					" -DHAVE_DEVPOLL";
+#else
+	/* only in Solaris >= 7.0 (?) */
+	#ifdef __OS_solaris
+		if (os_ver<0x0507) /* ver < 5.7 */
+			ret="/dev/poll not supported on Solaris < 7.0 (SunOS 5.7)";
+	#endif
+#endif
+			break;
 
 
 		default:
 		default:
 			ret="unknown not supported method";
 			ret="unknown not supported method";
@@ -380,6 +432,14 @@ enum poll_types choose_poll_method()
 	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
 	#endif /* assume that the rest support kqueue ifdef HAVE_KQUEUE */
 			poll_method=POLL_KQUEUE;
 			poll_method=POLL_KQUEUE;
 #endif
 #endif
+#ifdef HAVE_DEVPOLL
+	#ifdef __OS_solaris
+	if (poll_method==0)
+		/* only in Solaris >= 7.0 (?) */
+		if (os_ver>=0x0507) /* if ver >=SunOS 5.7 */
+			poll_method=POLL_DEVPOLL;
+	#endif
+#endif
 #ifdef  HAVE_SIGIO_RT
 #ifdef  HAVE_SIGIO_RT
 		if (poll_method==0) 
 		if (poll_method==0) 
 			if (os_ver>=0x020200) /* if ver >= 2.2.0 */
 			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)
 #endif
 #endif
 #ifdef HAVE_KQUEUE
 #ifdef HAVE_KQUEUE
 	h->kq_fd=-1;
 	h->kq_fd=-1;
+#endif
+#ifdef HAVE_DEVPOLL
+	h->dpoll_fd=-1;
 #endif
 #endif
 	poll_err=check_poll_method(poll_method);
 	poll_err=check_poll_method(poll_method);
 	
 	
@@ -456,7 +519,7 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
 	
 	
 	h->poll_method=poll_method;
 	h->poll_method=poll_method;
 	
 	
-	/* common stuff, evrybody has fd_hash */
+	/* common stuff, everybody has fd_hash */
 	h->fd_hash=local_malloc(sizeof(*(h->fd_hash))*h->max_fd_no);
 	h->fd_hash=local_malloc(sizeof(*(h->fd_hash))*h->max_fd_no);
 	if (h->fd_hash==0){
 	if (h->fd_hash==0){
 		LOG(L_CRIT, "ERROR: init_io_wait: could not alloc"
 		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)
 #endif
 #endif
 #ifdef HAVE_SIGIO_RT
 #ifdef HAVE_SIGIO_RT
 		case POLL_SIGIO_RT:
 		case POLL_SIGIO_RT:
+#endif
+#ifdef HAVE_DEVPOLL
+		case POLL_DEVPOLL:
 #endif
 #endif
 			h->fd_array=local_malloc(sizeof(*(h->fd_array))*h->max_fd_no);
 			h->fd_array=local_malloc(sizeof(*(h->fd_array))*h->max_fd_no);
 			if (h->fd_array==0){
 			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)
 				goto error;
 				goto error;
 			}
 			}
 #endif
 #endif
+#ifdef HAVE_DEVPOLL
+			if ((poll_method==POLL_DEVPOLL) && (init_devpoll(h)<0)){
+				LOG(L_CRIT, "ERROR: init_io_wait: /dev/poll init failed\n");
+				goto error;
+			}
+#endif
 #ifdef HAVE_SELECT
 #ifdef HAVE_SELECT
 			if ((poll_method==POLL_SELECT) && (init_select(h)<0)){
 			if ((poll_method==POLL_SELECT) && (init_select(h)<0)){
 				LOG(L_CRIT, "ERROR: init_io_wait: select init failed\n");
 				LOG(L_CRIT, "ERROR: init_io_wait: select init failed\n");
@@ -582,6 +654,11 @@ void destroy_io_wait(io_wait_h* h)
 		case POLL_SIGIO_RT:
 		case POLL_SIGIO_RT:
 			destroy_sigio(h);
 			destroy_sigio(h);
 			break;
 			break;
+#endif
+#ifdef HAVE_DEVPOLL
+		case POLL_DEVPOLL:
+			destroy_devpoll(h);
+			break;
 #endif
 #endif
 		default: /*do  nothing*/
 		default: /*do  nothing*/
 			;
 			;

+ 83 - 1
io_wait.h

@@ -47,6 +47,7 @@
  * --------
  * --------
  *  2005-06-13  created by andrei
  *  2005-06-13  created by andrei
  *  2005-06-26  added kqueue (andrei)
  *  2005-06-26  added kqueue (andrei)
+ *  2005-07-01  added /dev/poll (andrei)
  */
  */
 
 
 
 
@@ -70,6 +71,9 @@
 #include <sys/event.h>
 #include <sys/event.h>
 #include <sys/time.h>
 #include <sys/time.h>
 #endif
 #endif
+#ifdef HAVE_DEVPOLL
+#include <sys/devpoll.h>
+#endif
 #ifdef HAVE_SELECT
 #ifdef HAVE_SELECT
 /* needed on openbsd for select*/
 /* needed on openbsd for select*/
 #include <sys/time.h> 
 #include <sys/time.h> 
@@ -140,6 +144,9 @@ struct io_wait_handler{
 	size_t kq_changes_size; /* size of the changes array */
 	size_t kq_changes_size; /* size of the changes array */
 	int kq_fd;
 	int kq_fd;
 #endif
 #endif
+#ifdef HAVE_DEVPOLL
+	int dpoll_fd;
+#endif
 #ifdef HAVE_SELECT
 #ifdef HAVE_SELECT
 	fd_set master_set;
 	fd_set master_set;
 	int max_fd_select; /* maximum select used fd */
 	int max_fd_select; /* maximum select used fd */
@@ -293,6 +300,9 @@ inline static int io_watch_add(	io_wait_h* h,
 #ifdef HAVE_SIGIO_RT
 #ifdef HAVE_SIGIO_RT
 	static char buf[65536];
 	static char buf[65536];
 #endif
 #endif
+#ifdef HAVE_DEVPOLL
+	struct pollfd pfd;
+#endif
 	
 	
 	if (fd==-1){
 	if (fd==-1){
 		LOG(L_CRIT, "BUG: io_watch_add: fd is -1!\n");
 		LOG(L_CRIT, "BUG: io_watch_add: fd is -1!\n");
@@ -390,6 +400,21 @@ again2:
 				goto error;
 				goto error;
 			break;
 			break;
 #endif
 #endif
+#ifdef HAVE_DEVPOLL
+		case POLL_DEVPOLL:
+			pfd.fd=fd;
+			pfd.events=POLLIN;
+			pfd.revents=0;
+again_devpoll:
+			if (write(h->dpoll_fd, &pfd, sizeof(pfd))==-1){
+				if (errno==EAGAIN) goto again_devpoll;
+				LOG(L_ERR, "ERROR: io_watch_add: /dev/poll write failed:"
+							"%s [%d]\n", strerror(errno), errno);
+				goto error;
+			}
+			break;
+#endif
+			
 		default:
 		default:
 			LOG(L_CRIT, "BUG: io_watch_add: no support for poll method "
 			LOG(L_CRIT, "BUG: io_watch_add: no support for poll method "
 					" %s (%d)\n", poll_method_str[h->poll_method],
 					" %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)
 	int n;
 	int n;
 	struct epoll_event ep_event;
 	struct epoll_event ep_event;
 #endif
 #endif
+#ifdef HAVE_DEVPOLL
+	struct pollfd pfd;
+#endif
 	
 	
 	if ((fd<0) || (fd>=h->max_fd_no)){
 	if ((fd<0) || (fd>=h->max_fd_no)){
 		LOG(L_CRIT, "BUG: io_watch_del: invalid fd %d, not in [0, %d) \n",
 		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)
 					goto error;
 					goto error;
 			}
 			}
 			break;
 			break;
+#endif
+#ifdef HAVE_DEVPOLL
+		case POLL_DEVPOLL:
+				/* for /dev/poll the closed fds _must_ be removed
+				   (they are not removed automatically on close()) */
+				pfd.fd=fd;
+				pfd.events=POLLREMOVE;
+				pfd.revents=0;
+again_devpoll:
+				if (write(h->dpoll_fd, &pfd, sizeof(pfd))==-1){
+					if (errno==EINTR) goto again_devpoll;
+					LOG(L_ERR, "ERROR: io_watch_del: removing fd from "
+								"/dev/poll failed: %s [%d]\n", 
+								strerror(errno), errno);
+					goto error;
+				}
+				break;
 #endif
 #endif
 		default:
 		default:
 			LOG(L_CRIT, "BUG: io_watch_del: no support for poll method "
 			LOG(L_CRIT, "BUG: io_watch_del: no support for poll method "
@@ -530,7 +575,7 @@ error:
  * params: h      - io_wait handle
  * params: h      - io_wait handle
  *         t      - timeout in s
  *         t      - timeout in s
  *         repeat - if !=0 handle_io will be called until it returns <=0
  *         repeat - if !=0 handle_io will be called until it returns <=0
- * returns: 0 on success, -1 on err
+ * returns: number of IO events handled on success (can be 0), -1 on error
  */
  */
 inline static int io_wait_loop_poll(io_wait_h* h, int t, int repeat)
 inline static int io_wait_loop_poll(io_wait_h* h, int t, int repeat)
 {
 {
@@ -778,6 +823,43 @@ error:
 
 
 
 
 
 
+#ifdef HAVE_DEVPOLL
+inline static int io_wait_loop_devpoll(io_wait_h* h, int t, int repeat)
+{
+	int n, r;
+	int ret;
+	struct dvpoll dpoll;
+
+		dpoll.dp_timeout=t*1000;
+		dpoll.dp_nfds=h->fd_no;
+		dpoll.dp_fds=h->fd_array;
+again:
+		ret=n=ioctl(h->dpoll_fd, DP_POLL, &dpoll);
+		if (n==-1){
+			if (errno==EINTR) goto again; /* signal, ignore it */
+			else{
+				LOG(L_ERR, "ERROR:io_wait_loop_devpoll: ioctl: %s [%d]\n",
+						strerror(errno), errno);
+				goto error;
+			}
+		}
+		for (r=0; r< n; r++){
+			if (h->fd_array[r].revents & (POLLNVAL|POLLERR)){
+				LOG(L_ERR, "ERROR: io_wait_loop_devpoll: pollinval returned"
+							" for fd %d, revents=%x\n",
+							h->fd_array[r].fd, h->fd_array[r].revents);
+			}
+			/* POLLIN|POLLHUP just go through */
+			while((handle_io(get_fd_map(h, h->fd_array[r].fd), r) > 0) &&
+						repeat);
+		}
+error:
+	return ret;
+}
+#endif
+
+
+
 /* init */
 /* init */
 
 
 
 

+ 9 - 1
tcp_main.c

@@ -55,6 +55,7 @@
  *  2005-06-07  new tcp optimized code, supports epoll (LT), sigio + real time
  *  2005-06-07  new tcp optimized code, supports epoll (LT), sigio + real time
  *               signals, poll & select (andrei)
  *               signals, poll & select (andrei)
  *  2005-06-26  *bsd kqueue support (andrei)
  *  2005-06-26  *bsd kqueue support (andrei)
+ *  2005-07-04  solaris /dev/poll support (andrei)
  */
  */
 
 
 
 
@@ -1515,6 +1516,14 @@ void tcp_main_loop()
 				tcpconn_timeout();
 				tcpconn_timeout();
 			}
 			}
 			break;
 			break;
+#endif
+#ifdef HAVE_DEVPOLL
+		case POLL_DEVPOLL:
+			while(1){
+				io_wait_loop_devpoll(&io_h, TCP_MAIN_SELECT_TIMEOUT, 0);
+				tcpconn_timeout();
+			}
+			break;
 #endif
 #endif
 		default:
 		default:
 			LOG(L_CRIT, "BUG: tcp_main_loop: no support for poll method "
 			LOG(L_CRIT, "BUG: tcp_main_loop: no support for poll method "
@@ -1530,7 +1539,6 @@ error:
 
 
 
 
 
 
-
 /* cleanup before exit */
 /* cleanup before exit */
 void destroy_tcp()
 void destroy_tcp()
 {
 {