diff options
Diffstat (limited to 'src/lib/eventloop.c')
-rw-r--r-- | src/lib/eventloop.c | 133 |
1 files changed, 72 insertions, 61 deletions
diff --git a/src/lib/eventloop.c b/src/lib/eventloop.c index 24e8cba3..19e0647c 100644 --- a/src/lib/eventloop.c +++ b/src/lib/eventloop.c | |||
@@ -26,6 +26,14 @@ | |||
26 | #include "gnunet_gtk.h" | 26 | #include "gnunet_gtk.h" |
27 | 27 | ||
28 | 28 | ||
29 | /** | ||
30 | * Initial size of our poll array cache. | ||
31 | * | ||
32 | * TODO: get some statistics, find the maximum number of fds ever | ||
33 | * polled during normal gnunet-gtk operation, and set this to that number. | ||
34 | */ | ||
35 | #define INITIAL_POLL_ARRAY_SIZE 30 | ||
36 | |||
29 | /** | 37 | /** |
30 | * Main context for our event loop. | 38 | * Main context for our event loop. |
31 | */ | 39 | */ |
@@ -92,7 +100,6 @@ struct GNUNET_GTK_MainLoop | |||
92 | */ | 100 | */ |
93 | gint max_priority; | 101 | gint max_priority; |
94 | 102 | ||
95 | |||
96 | #if WINDOWS | 103 | #if WINDOWS |
97 | /** | 104 | /** |
98 | * Array to hold pipe handles during a select() call | 105 | * Array to hold pipe handles during a select() call |
@@ -206,6 +213,21 @@ gnunet_gtk_dispatch_task (void *cls, | |||
206 | } | 213 | } |
207 | 214 | ||
208 | 215 | ||
216 | /** | ||
217 | * Change the size of the cached poll array to the given value. | ||
218 | * | ||
219 | * @param ml main loop context with the cached poll array | ||
220 | * @param new_size desired size of the cached poll array | ||
221 | */ | ||
222 | static void | ||
223 | resize_cached_poll_array (struct GNUNET_GTK_MainLoop *ml, | ||
224 | guint new_size) | ||
225 | { | ||
226 | ml->cached_poll_array = g_new (GPollFD, new_size); | ||
227 | ml->cached_poll_array_size = new_size; | ||
228 | } | ||
229 | |||
230 | |||
209 | #ifndef FD_COPY | 231 | #ifndef FD_COPY |
210 | #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set))) | 232 | #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set))) |
211 | #endif | 233 | #endif |
@@ -234,11 +256,9 @@ gnunet_gtk_select (void *cls, | |||
234 | struct GNUNET_GTK_MainLoop *ml = cls; | 256 | struct GNUNET_GTK_MainLoop *ml = cls; |
235 | int max_nfds; | 257 | int max_nfds; |
236 | gint poll_result; | 258 | gint poll_result; |
237 | GPollFD *gfds; | ||
238 | gint delay; | 259 | gint delay; |
239 | guint i; | 260 | guint i; |
240 | guint fd_counter = 0; | 261 | guint fd_counter = 0; |
241 | guint allocated_nfds; | ||
242 | guint need_gfds; | 262 | guint need_gfds; |
243 | fd_set aread; | 263 | fd_set aread; |
244 | fd_set awrite; | 264 | fd_set awrite; |
@@ -292,24 +312,17 @@ gnunet_gtk_select (void *cls, | |||
292 | if (efds != NULL) | 312 | if (efds != NULL) |
293 | max_nfds = GNUNET_MAX (max_nfds, efds->nsds); | 313 | max_nfds = GNUNET_MAX (max_nfds, efds->nsds); |
294 | 314 | ||
295 | allocated_nfds = ml->cached_poll_array_size; | 315 | ml->cached_poll_array_size = ml->cached_poll_array_size; |
296 | gfds = ml->cached_poll_array; | 316 | if (ml->cached_poll_array_size == 0) |
297 | if (allocated_nfds == 0) | 317 | resize_cached_poll_array (ml, INITIAL_POLL_ARRAY_SIZE); |
298 | { | ||
299 | /* TODO: get some statistics, find the maximum number of fds ever | ||
300 | * polled during normal gnunet-gtk operation, and set this to that number. | ||
301 | */ | ||
302 | ml->cached_poll_array = gfds = g_new (GPollFD, 30); | ||
303 | ml->cached_poll_array_size = allocated_nfds = 30; | ||
304 | } | ||
305 | 318 | ||
306 | while (1) | 319 | while (1) |
307 | { | ||
308 | fd_counter = 0; | ||
309 | #if !WINDOWS | ||
310 | gboolean need_realloc = FALSE; | ||
311 | for (i = 0; !need_realloc && i < max_nfds; i += 1) | ||
312 | { | 320 | { |
321 | fd_counter = 0; | ||
322 | #if !WINDOWS | ||
323 | gboolean need_realloc = FALSE; | ||
324 | for (i = 0; !need_realloc && i < max_nfds; i += 1) | ||
325 | { | ||
313 | int isset[3]; | 326 | int isset[3]; |
314 | 327 | ||
315 | isset[0] = (rfds == NULL) ? 0 : FD_ISSET (i, &rfds->sds); | 328 | isset[0] = (rfds == NULL) ? 0 : FD_ISSET (i, &rfds->sds); |
@@ -317,23 +330,22 @@ gnunet_gtk_select (void *cls, | |||
317 | isset[2] = (efds == NULL) ? 0 : FD_ISSET (i, &efds->sds); | 330 | isset[2] = (efds == NULL) ? 0 : FD_ISSET (i, &efds->sds); |
318 | if (!isset[0] && !isset[1] && !isset[2]) | 331 | if (!isset[0] && !isset[1] && !isset[2]) |
319 | continue; | 332 | continue; |
320 | if (fd_counter >= allocated_nfds) | 333 | if (fd_counter >= ml->cached_poll_array_size) |
321 | { | 334 | { |
322 | need_realloc = TRUE; | 335 | need_realloc = TRUE; |
323 | break; | 336 | break; |
324 | } | 337 | } |
325 | gfds[fd_counter].fd = i; | 338 | ml->cached_poll_array[fd_counter].fd = i; |
326 | gfds[fd_counter].events = (isset[0] ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0) | 339 | ml->cached_poll_array[fd_counter].events = (isset[0] ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0) |
327 | | (isset[1] ? G_IO_OUT | G_IO_ERR : 0) | (isset[2] ? G_IO_ERR : 0); | 340 | | (isset[1] ? G_IO_OUT | G_IO_ERR : 0) | (isset[2] ? G_IO_ERR : 0); |
328 | fd_counter += 1; | 341 | fd_counter += 1; |
329 | } | 342 | } |
330 | if (need_realloc) | 343 | if (need_realloc) |
331 | { | 344 | { |
332 | ml->cached_poll_array = gfds = g_renew (GPollFD, gfds, ml->cached_poll_array_size * 2); | 345 | resize_cached_poll_array (ml, ml->cached_poll_array_size * 2); |
333 | ml->cached_poll_array_size = allocated_nfds = ml->cached_poll_array_size * 2; | 346 | fd_counter = 0; |
334 | fd_counter = 0; | 347 | need_realloc = FALSE; |
335 | need_realloc = FALSE; | 348 | } |
336 | } | ||
337 | else | 349 | else |
338 | break; | 350 | break; |
339 | #else | 351 | #else |
@@ -343,13 +355,13 @@ gnunet_gtk_select (void *cls, | |||
343 | + (rfds == NULL ? 0 : GNUNET_CONTAINER_slist_count (rfds->handles)) | 355 | + (rfds == NULL ? 0 : GNUNET_CONTAINER_slist_count (rfds->handles)) |
344 | + (wfds == NULL ? 0 : 1) | 356 | + (wfds == NULL ? 0 : 1) |
345 | + 1; | 357 | + 1; |
346 | if (need_nfds >= allocated_nfds) | 358 | if (need_nfds >= ml->cached_poll_array_size) |
347 | { | 359 | { |
348 | /* Since there are also gmainloop's own fds, just need_nfds won't be | 360 | /* Since there are also gmainloop's own fds, just need_nfds won't be |
349 | * enough, so make it twice as long. | 361 | * enough, so make it twice as long. |
350 | */ | 362 | */ |
351 | ml->cached_poll_array = gfds = g_renew (GPollFD, gfds, need_nfds * 2); | 363 | ml->cached_poll_array = ml->cached_poll_array = g_renew (GPollFD, ml->cached_poll_array, need_nfds * 2); |
352 | ml->cached_poll_array_size = allocated_nfds = need_nfds * 2; | 364 | ml->cached_poll_array_size = ml->cached_poll_array_size = need_nfds * 2; |
353 | } | 365 | } |
354 | if (ml->read_array_length < GNUNET_CONTAINER_slist_count (rfds->handles)) | 366 | if (ml->read_array_length < GNUNET_CONTAINER_slist_count (rfds->handles)) |
355 | { | 367 | { |
@@ -374,20 +386,20 @@ gnunet_gtk_select (void *cls, | |||
374 | #if DEBUG_NETWORK | 386 | #if DEBUG_NETWORK |
375 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the pipe's 0x%x overlapped event to the array as %d\n", fh->h, nhandles); | 387 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the pipe's 0x%x overlapped event to the array as %d\n", fh->h, nhandles); |
376 | #endif | 388 | #endif |
377 | gfds[fd_counter].fd = (intptr_t) fh->oOverlapRead->hEvent; | 389 | ml->cached_poll_array[fd_counter].fd = (intptr_t) fh->oOverlapRead->hEvent; |
378 | /* On W32 .events makes no sense - g_poll will just OR its | 390 | /* On W32 .events makes no sense - g_poll will just OR its |
379 | * contents into .revents when the .fd event fires. | 391 | * contents into .revents when the .fd event fires. |
380 | * So we'll use it in the way that suits us the best. | 392 | * So we'll use it in the way that suits us the best. |
381 | */ | 393 | */ |
382 | gfds[fd_counter].events = G_IO_IN; | 394 | ml->cached_poll_array[fd_counter].events = G_IO_IN; |
383 | fd_counter += 1; | 395 | fd_counter += 1; |
384 | ml->read_array[read_handles] = fh; | 396 | ml->read_array[read_handles] = fh; |
385 | read_handles += 1; | 397 | read_handles += 1; |
386 | } | 398 | } |
387 | else | 399 | else |
388 | { | 400 | { |
389 | gfds[fd_counter].fd = (intptr_t) ml->hEventReadReady; | 401 | ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventReadReady; |
390 | gfds[fd_counter].events = G_IO_HUP; | 402 | ml->cached_poll_array[fd_counter].events = G_IO_HUP; |
391 | fd_counter += 1; | 403 | fd_counter += 1; |
392 | ml->read_array[read_handles] = fh; | 404 | ml->read_array[read_handles] = fh; |
393 | read_handles += 1; | 405 | read_handles += 1; |
@@ -398,8 +410,8 @@ gnunet_gtk_select (void *cls, | |||
398 | #if DEBUG_NETWORK | 410 | #if DEBUG_NETWORK |
399 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the read ready event to the array as %d\n", nhandles); | 411 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the read ready event to the array as %d\n", nhandles); |
400 | #endif | 412 | #endif |
401 | gfds[fd_counter].fd = (intptr_t) ml->hEventReadReady; | 413 | ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventReadReady; |
402 | gfds[fd_counter].events = G_IO_IN; | 414 | ml->cached_poll_array[fd_counter].events = G_IO_IN; |
403 | fd_counter += 1; | 415 | fd_counter += 1; |
404 | ml->read_array[read_handles] = fh; | 416 | ml->read_array[read_handles] = fh; |
405 | read_handles += 1; | 417 | read_handles += 1; |
@@ -416,8 +428,8 @@ gnunet_gtk_select (void *cls, | |||
416 | } | 428 | } |
417 | if (wfds != NULL && GNUNET_CONTAINER_slist_count (wfds->handles) > 0) | 429 | if (wfds != NULL && GNUNET_CONTAINER_slist_count (wfds->handles) > 0) |
418 | { | 430 | { |
419 | gfds[fd_counter].fd = (intptr_t) ml->hEventPipeWrite; | 431 | ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventPipeWrite; |
420 | gfds[fd_counter].events = G_IO_OUT; | 432 | ml->cached_poll_array[fd_counter].events = G_IO_OUT; |
421 | always_ready_write_fd = fd_counter; | 433 | always_ready_write_fd = fd_counter; |
422 | fd_counter += 1; | 434 | fd_counter += 1; |
423 | } | 435 | } |
@@ -449,8 +461,8 @@ gnunet_gtk_select (void *cls, | |||
449 | #if DEBUG_NETWORK | 461 | #if DEBUG_NETWORK |
450 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket read event to the array as %d\n", fd_counter); | 462 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket read event to the array as %d\n", fd_counter); |
451 | #endif | 463 | #endif |
452 | gfds[fd_counter].fd = (intptr_t) ml->hEventRead; | 464 | ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventRead; |
453 | gfds[fd_counter].events = G_IO_IN; | 465 | ml->cached_poll_array[fd_counter].events = G_IO_IN; |
454 | for (i = 0; i < rfds->sds.fd_count; i++) | 466 | for (i = 0; i < rfds->sds.fd_count; i++) |
455 | WSAEventSelect (rfds->sds.fd_array[i], ml->hEventRead, FD_ACCEPT | FD_READ | FD_CLOSE); | 467 | WSAEventSelect (rfds->sds.fd_array[i], ml->hEventRead, FD_ACCEPT | FD_READ | FD_CLOSE); |
456 | fd_counter += 1; | 468 | fd_counter += 1; |
@@ -462,8 +474,8 @@ gnunet_gtk_select (void *cls, | |||
462 | #if DEBUG_NETWORK | 474 | #if DEBUG_NETWORK |
463 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket write event to the array as %d\n", fd_counter); | 475 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket write event to the array as %d\n", fd_counter); |
464 | #endif | 476 | #endif |
465 | gfds[fd_counter].fd = (intptr_t) ml->hEventWrite; | 477 | ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventWrite; |
466 | gfds[fd_counter].events = G_IO_OUT; | 478 | ml->cached_poll_array[fd_counter].events = G_IO_OUT; |
467 | for (i = 0; i < wfds->sds.fd_count; i++) | 479 | for (i = 0; i < wfds->sds.fd_count; i++) |
468 | { | 480 | { |
469 | DWORD error; | 481 | DWORD error; |
@@ -487,8 +499,8 @@ gnunet_gtk_select (void *cls, | |||
487 | #if DEBUG_NETWORK | 499 | #if DEBUG_NETWORK |
488 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket error event to the array as %d\n", fd_counter); | 500 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket error event to the array as %d\n", fd_counter); |
489 | #endif | 501 | #endif |
490 | gfds[fd_counter].fd = (intptr_t) ml->hEventException; | 502 | ml->cached_poll_array[fd_counter].fd = (intptr_t) ml->hEventException; |
491 | gfds[fd_counter].events = G_IO_ERR; | 503 | ml->cached_poll_array[fd_counter].events = G_IO_ERR; |
492 | for (i = 0; i < efds->sds.fd_count; i++) | 504 | for (i = 0; i < efds->sds.fd_count; i++) |
493 | WSAEventSelect (efds->sds.fd_array[i], ml->hEventException, FD_OOB | FD_CLOSE); | 505 | WSAEventSelect (efds->sds.fd_array[i], ml->hEventException, FD_OOB | FD_CLOSE); |
494 | fd_counter += 1; | 506 | fd_counter += 1; |
@@ -500,12 +512,11 @@ gnunet_gtk_select (void *cls, | |||
500 | socks = sock_read + sock_write + sock_err; | 512 | socks = sock_read + sock_write + sock_err; |
501 | 513 | ||
502 | g_main_context_prepare (ml->gmc, &ml->max_priority); | 514 | g_main_context_prepare (ml->gmc, &ml->max_priority); |
503 | while (allocated_nfds < (need_gfds = g_main_context_query (ml->gmc, | 515 | while (ml->cached_poll_array_size < (need_gfds = g_main_context_query (ml->gmc, |
504 | ml->max_priority, &delay, &gfds[fd_counter], allocated_nfds - fd_counter))) | 516 | ml->max_priority, &delay, &ml->cached_poll_array[fd_counter], ml->cached_poll_array_size - fd_counter))) |
505 | { | 517 | resize_cached_poll_array (ml, |
506 | ml->cached_poll_array = gfds = g_renew (GPollFD, gfds, allocated_nfds - fd_counter + need_gfds); | 518 | ml->cached_poll_array_size - fd_counter + need_gfds); |
507 | ml->cached_poll_array_size = allocated_nfds = allocated_nfds - fd_counter + need_gfds; | 519 | |
508 | } | ||
509 | ml->poll_array_active = fd_counter + need_gfds; | 520 | ml->poll_array_active = fd_counter + need_gfds; |
510 | 521 | ||
511 | if (timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value) | 522 | if (timeout.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value) |
@@ -528,7 +539,7 @@ gnunet_gtk_select (void *cls, | |||
528 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We have %d of our FDs and %d of GMC ones, going to wait %6dms\n", fd_counter, need_gfds, delay); | 539 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We have %d of our FDs and %d of GMC ones, going to wait %6dms\n", fd_counter, need_gfds, delay); |
529 | #endif | 540 | #endif |
530 | 541 | ||
531 | poll_result = g_poll (gfds, fd_counter + need_gfds, delay); | 542 | poll_result = g_poll (ml->cached_poll_array, fd_counter + need_gfds, delay); |
532 | 543 | ||
533 | #if DEBUG_NETWORK | 544 | #if DEBUG_NETWORK |
534 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "g_poll returned : %d\n", poll_result); | 545 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "g_poll returned : %d\n", poll_result); |
@@ -539,7 +550,7 @@ gnunet_gtk_select (void *cls, | |||
539 | * from within a task (currently we're not in a task, but in a select() call, remember) | 550 | * from within a task (currently we're not in a task, but in a select() call, remember) |
540 | * Startup reason is used to pass the scheduler sanity check. | 551 | * Startup reason is used to pass the scheduler sanity check. |
541 | */ | 552 | */ |
542 | if (TRUE == g_main_context_check (ml->gmc, ml->max_priority, &gfds[fd_counter], need_gfds)) | 553 | if (TRUE == g_main_context_check (ml->gmc, ml->max_priority, &ml->cached_poll_array[fd_counter], need_gfds)) |
543 | GNUNET_SCHEDULER_add_continuation (gnunet_gtk_dispatch_task, ml, | 554 | GNUNET_SCHEDULER_add_continuation (gnunet_gtk_dispatch_task, ml, |
544 | GNUNET_SCHEDULER_REASON_STARTUP); | 555 | GNUNET_SCHEDULER_REASON_STARTUP); |
545 | 556 | ||
@@ -553,12 +564,12 @@ gnunet_gtk_select (void *cls, | |||
553 | for (i = 0; i < fd_counter; i++) | 564 | for (i = 0; i < fd_counter; i++) |
554 | { | 565 | { |
555 | int set[3]; | 566 | int set[3]; |
556 | if ((set[0] = FD_ISSET (gfds[i].fd, &aread))) | 567 | if ((set[0] = FD_ISSET (ml->cached_poll_array[i].fd, &aread))) |
557 | FD_SET (gfds[i].fd, &rfds->sds); | 568 | FD_SET (ml->cached_poll_array[i].fd, &rfds->sds); |
558 | if ((set[1] = FD_ISSET (gfds[i].fd, &awrite))) | 569 | if ((set[1] = FD_ISSET (ml->cached_poll_array[i].fd, &awrite))) |
559 | FD_SET (gfds[i].fd, &wfds->sds); | 570 | FD_SET (ml->cached_poll_array[i].fd, &wfds->sds); |
560 | if ((set[2] = FD_ISSET (gfds[i].fd, &aexcept))) | 571 | if ((set[2] = FD_ISSET (ml->cached_poll_array[i].fd, &aexcept))) |
561 | FD_SET (gfds[i].fd, &efds->sds); | 572 | FD_SET (ml->cached_poll_array[i].fd, &efds->sds); |
562 | if (set[0] || set[1] || set[2]) | 573 | if (set[0] || set[1] || set[2]) |
563 | result += 1; | 574 | result += 1; |
564 | } | 575 | } |
@@ -575,7 +586,7 @@ gnunet_gtk_select (void *cls, | |||
575 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "select() returned %d\n", select_ret); | 586 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "select() returned %d\n", select_ret); |
576 | #endif | 587 | #endif |
577 | } | 588 | } |
578 | if (always_ready_write_fd >= 0 && gfds[always_ready_write_fd].revents & G_IO_OUT) | 589 | if (always_ready_write_fd >= 0 && ml->cached_poll_array[always_ready_write_fd].revents & G_IO_OUT) |
579 | { | 590 | { |
580 | GNUNET_CONTAINER_slist_append (ml->handles_write, wfds->handles); | 591 | GNUNET_CONTAINER_slist_append (ml->handles_write, wfds->handles); |
581 | result += GNUNET_CONTAINER_slist_count (ml->handles_write); | 592 | result += GNUNET_CONTAINER_slist_count (ml->handles_write); |
@@ -587,7 +598,7 @@ gnunet_gtk_select (void *cls, | |||
587 | { | 598 | { |
588 | DWORD error; | 599 | DWORD error; |
589 | BOOL bret; | 600 | BOOL bret; |
590 | if (!(gfds[i].revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) | 601 | if (!(ml->cached_poll_array[i].revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) |
591 | continue; | 602 | continue; |
592 | SetLastError (0); | 603 | SetLastError (0); |
593 | waitstatus = 0; | 604 | waitstatus = 0; |
@@ -596,7 +607,7 @@ gnunet_gtk_select (void *cls, | |||
596 | #if DEBUG_NETWORK | 607 | #if DEBUG_NETWORK |
597 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n", i, ml->read_array[i]->h, bret, waitstatus, error); | 608 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n", i, ml->read_array[i]->h, bret, waitstatus, error); |
598 | #endif | 609 | #endif |
599 | if (bret == 0 || (gfds[i].revents & G_IO_ERR)) | 610 | if (bret == 0 || (ml->cached_poll_array[i].revents & G_IO_ERR)) |
600 | { | 611 | { |
601 | if (efds != NULL) | 612 | if (efds != NULL) |
602 | { | 613 | { |