Browse code

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 authored on 18/06/2010 22:16:38
Showing 2 changed files
... ...
@@ -549,13 +549,21 @@ int init_io_wait(io_wait_h* h, int max_fd, enum poll_types poll_method)
549 549
 #endif
550 550
 #ifdef HAVE_KQUEUE
551 551
 		case POLL_KQUEUE:
552
-			h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->max_fd_no);
552
+			h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE;
553
+			/* kevent returns different events for read & write
554
+			   => to get all the possible events in one call we
555
+			   need twice the number of added fds + space
556
+			   for possible changelist errors.
557
+			   OTOH if memory is to be saved at all costs, one can
558
+			   decrease the array size.
559
+			 */
560
+			h->kq_array_size=2 * h->max_fd_no + h->kq_changes_size;
561
+			h->kq_array=local_malloc(sizeof(*(h->kq_array))*h->kq_array_size);
553 562
 			if (h->kq_array==0){
554 563
 				LOG(L_CRIT, "ERROR: init_io_wait: could not alloc"
555 564
 							" kqueue event array\n");
556 565
 				goto error;
557 566
 			}
558
-			h->kq_changes_size=KQ_CHANGES_ARRAY_SIZE;
559 567
 			h->kq_changes=local_malloc(sizeof(*(h->kq_changes))*
560 568
 										h->kq_changes_size);
561 569
 			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)
564 564
 				goto error;
565 565
 			}
566 566
 			h->kq_nchanges=0;
567
-			memset((void*)h->kq_array, 0, sizeof(*(h->kq_array))*h->max_fd_no);
567
+			memset((void*)h->kq_array, 0,
568
+						sizeof(*(h->kq_array))*h->kq_array_size);
568 569
 			memset((void*)h->kq_changes, 0,
569 570
 						sizeof(*(h->kq_changes))* h->kq_changes_size);
570 571
 			if (init_kqueue(h)<0){
... ...
@@ -148,7 +148,9 @@ struct io_wait_handler{
148 148
 	int flags;
149 149
 	struct fd_map* fd_hash;
150 150
 	int fd_no; /*  current index used in fd_array and the passed size for 
151
-				   ep_array & kq_array*/
151
+				   ep_array (for kq_array at least
152
+				    max(twice the size, kq_changes_size) should be
153
+				   be passed). */
152 154
 	int max_fd_no; /* maximum fd no, is also the size of fd_array,
153 155
 						       fd_hash  and ep_array*/
154 156
 	/* common stuff for POLL, SIGIO_RT and SELECT
... ...
@@ -170,6 +172,7 @@ struct io_wait_handler{
170 170
 	struct kevent* kq_array;   /* used for the eventlist*/
171 171
 	struct kevent* kq_changes; /* used for the changelist */
172 172
 	size_t kq_nchanges;
173
+	size_t kq_array_size;   /* array size */
173 174
 	size_t kq_changes_size; /* size of the changes array */
174 175
 #endif
175 176
 #ifdef HAVE_DEVPOLL
... ...
@@ -1115,7 +1118,7 @@ inline static int io_wait_loop_kqueue(io_wait_h* h, int t, int repeat)
1115 1115
 	do {
1116 1116
 again:
1117 1117
 		n=kevent(h->kq_fd, h->kq_changes, apply_changes,  h->kq_array,
1118
-					h->fd_no, &tspec);
1118
+					h->kq_array_size, &tspec);
1119 1119
 		if (unlikely(n==-1)){
1120 1120
 			if (unlikely(errno==EINTR)) goto again; /* signal, ignore it */
1121 1121
 			else {
... ...
@@ -1127,7 +1130,7 @@ again:
1127 1127
 				/* some of the FDs in kq_changes are bad (already closed)
1128 1128
 				   and there is not enough space in kq_array to return all
1129 1129
 				   of them back */
1130
-				apply_changes = h->fd_no;
1130
+				apply_changes = h->kq_array_size;
1131 1131
 				goto again;
1132 1132
 			}
1133 1133
 		}