Prechádzať zdrojové kódy

io_wait: kqueue: use a bigger array

Use a bigger array for kevent(). Instead of the fd number, use
2* max_fd_no (2 because read and write events are not merged) and
with extra space for possible changelist errors.
(minor optimization)
Andrei Pelinescu-Onciul 15 rokov pred
rodič
commit
99682621f3
2 zmenil súbory, kde vykonal 18 pridanie a 6 odobranie
  1. 12 3
      io_wait.c
  2. 6 3
      io_wait.h

+ 12 - 3
io_wait.c

@@ -549,13 +549,21 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
 #endif
 #ifdef HAVE_KQUEUE
 		case POLL_KQUEUE:
-			h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->max_fd_no);
+			h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE;
+			/* kevent returns different events for read & write
+			   => to get all the possible events in one call we
+			   need twice the number of added fds + space
+			   for possible changelist errors.
+			   OTOH if memory is to be saved at all costs, one can
+			   decrease the array size.
+			 */
+			h->kq_array_size=2 * h->max_fd_no + h->kq_changes_size;
+			h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->kq_array_size);
 			if (h->kq_array==0){
 				LOG(L_CRIT, "ERROR: init_io_wait: could not alloc"
 							" kqueue event array\n");
 				goto error;
 			}
-			h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE;
 			h->kq_changes=local_malloc(sizeof(*(h->kq_changes))*
 										h->kq_changes_size);
 			if (h->kq_changes==0){
@@ -564,7 +572,8 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
 				goto error;
 			}
 			h->kq_nchanges=0;
-			memset((void*)h->kq_array, 0, sizeof(*(h->kq_array))*h->max_fd_no);
+			memset((void*)h->kq_array, 0,
+						sizeof(*(h->kq_array))*h->kq_array_size);
 			memset((void*)h->kq_changes, 0,
 						sizeof(*(h->kq_changes))* h->kq_changes_size);
 			if (init_kqueue(h)<0){

+ 6 - 3
io_wait.h

@@ -148,7 +148,9 @@ struct io_wait_handler{
 	int flags;
 	struct fd_map* fd_hash;
 	int fd_no; /*  current index used in fd_array and the passed size for 
-				   ep_array & kq_array*/
+				   ep_array (for kq_array at least
+				    max(twice the size, kq_changes_size) should be
+				   be passed). */
 	int max_fd_no; /* maximum fd no, is also the size of fd_array,
 						       fd_hash  and ep_array*/
 	/* common stuff for POLL, SIGIO_RT and SELECT
@@ -170,6 +172,7 @@ struct io_wait_handler{
 	struct kevent* kq_array;   /* used for the eventlist*/
 	struct kevent* kq_changes; /* used for the changelist */
 	size_t kq_nchanges;
+	size_t kq_array_size;   /* array size */
 	size_t kq_changes_size; /* size of the changes array */
 #endif
 #ifdef HAVE_DEVPOLL
@@ -1115,7 +1118,7 @@ inline static int io_wait_loop_kqueue(io_wait_h* h, int t, int repeat)
 	do {
 again:
 		n=kevent(h->kq_fd, h->kq_changes, apply_changes,  h->kq_array,
-					h->fd_no, &tspec);
+					h->kq_array_size, &tspec);
 		if (unlikely(n==-1)){
 			if (unlikely(errno==EINTR)) goto again; /* signal, ignore it */
 			else {
@@ -1127,7 +1130,7 @@ again:
 				/* some of the FDs in kq_changes are bad (already closed)
 				   and there is not enough space in kq_array to return all
 				   of them back */
-				apply_changes = h->fd_no;
+				apply_changes = h->kq_array_size;
 				goto again;
 			}
 		}