From a9d92c556d88da778dcde68114cd21b36d6db539 Mon Sep 17 00:00:00 2001 From: t3sserakt Date: Thu, 20 Jul 2017 15:23:36 +0200 Subject: started further refactoring of scheduler. ATTENTION, actual Status does not compile! --- src/util/scheduler.c | 417 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 264 insertions(+), 153 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index a7b1d8e2a..e27eb0fe0 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -73,7 +73,7 @@ * Argument to be passed from the driver to * #GNUNET_SCHEDULER_run_from_driver(). Contains the * scheduler's internal state. - */ + */ struct GNUNET_SCHEDULER_Handle { /** @@ -94,7 +94,7 @@ struct GNUNET_SCHEDULER_Handle * Driver we used for the event loop. */ const struct GNUNET_SCHEDULER_Driver *driver; - + }; @@ -127,7 +127,7 @@ struct GNUNET_SCHEDULER_Task * Handle to the scheduler's state. */ const struct GNUNET_SCHEDULER_Handle *sh; - + /** * Set of file descriptors this task is waiting * for for reading. Once ready, this is updated @@ -172,7 +172,7 @@ struct GNUNET_SCHEDULER_Task * Size of the @e fds array. */ unsigned int fds_len; - + /** * Why is the task ready? Set after task is added to ready queue. * Initially set to zero. All reasons that have already been @@ -227,6 +227,14 @@ struct GNUNET_SCHEDULER_Task }; +/** + * The driver used for the event loop. Will be handed over to + * the scheduler in #GNUNET_SCHEDULER_run_from_driver(), peristed + * there in this variable for later use in functions like + * #GNUNET_SCHEDULER_add_select(), #add_without_sets() and + * #GNUNET_SCHEDULER_cancel(). + */ +GNUNET_SCHEDULER_Driver *scheduler_driver; /** * Head of list of tasks waiting for an event. @@ -370,11 +378,9 @@ check_priority (enum GNUNET_SCHEDULER_Priority p) * @param ws write-set, set to all FDs we would like to write (updated) * @param timeout next timeout (updated) */ -static void -update_sets (struct GNUNET_NETWORK_FDSet *rs, - struct GNUNET_NETWORK_FDSet *ws, - struct GNUNET_TIME_Relative *timeout) +void getNextPendingTimeout(struct GNUNET_TIME_Relative *timeout) { + struct GNUNET_SCHEDULER_Task *pos; struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Relative to; @@ -389,6 +395,20 @@ update_sets (struct GNUNET_NETWORK_FDSet *rs, if (0 != pos->reason) *timeout = GNUNET_TIME_UNIT_ZERO; } +} + +static void +update_sets (struct GNUNET_NETWORK_FDSet *rs, + struct GNUNET_NETWORK_FDSet *ws, + struct GNUNET_TIME_Relative *timeout) +{ + struct GNUNET_SCHEDULER_Task *pos; + struct GNUNET_TIME_Absolute now; + struct GNUNET_TIME_Relative to; + + now = GNUNET_TIME_absolute_get (); + + getNextPendingTimeout(timeout); for (pos = pending_head; NULL != pos; pos = pos->next) { if (pos->timeout.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) @@ -593,10 +613,10 @@ dump_backtrace (struct GNUNET_SCHEDULER_Task *t) for (i = 0; i < t->num_backtrace_strings; i++) LOG (GNUNET_ERROR_TYPE_DEBUG, - "Task %p trace %u: %s\n", - t, - i, - t->backtrace_strings[i]); + "Task %p trace %u: %s\n", + t, + i, + t->backtrace_strings[i]); #endif } @@ -645,7 +665,7 @@ run_ready (struct GNUNET_NETWORK_FDSet *rs, DELAY_THRESHOLD.rel_value_us) { LOG (GNUNET_ERROR_TYPE_DEBUG, - "Task %p took %s to be scheduled\n", + "Task %p took %s to be scheduled\n", pos, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), GNUNET_YES)); @@ -665,7 +685,7 @@ run_ready (struct GNUNET_NETWORK_FDSet *rs, (!GNUNET_NETWORK_fdset_test_native (ws, pos->write_fd))) GNUNET_assert (0); // added to ready in previous select loop! LOG (GNUNET_ERROR_TYPE_DEBUG, - "Running task: %p\n", + "Running task: %p\n", pos); pos->callback (pos->callback_cls); dump_backtrace (pos); @@ -769,88 +789,22 @@ check_lifeness () } -/** - * Initialize and run scheduler. This function will return when all - * tasks have completed. On systems with signals, receiving a SIGTERM - * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown() - * to be run after the active task is complete. As a result, SIGTERM - * causes all active tasks to be scheduled with reason - * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added - * afterwards will execute normally!). Note that any particular signal - * will only shut down one scheduler; applications should always only - * create a single scheduler. - * - * @param task task to run immediately - * @param task_cls closure of @a task - */ -void -GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, - void *task_cls) + +void while_live(struct GNUNET_NETWORK_FDSet *rs, struct GNUNET_NETWORK_FDSet *ws) { - struct GNUNET_NETWORK_FDSet *rs; - struct GNUNET_NETWORK_FDSet *ws; - struct GNUNET_TIME_Relative timeout; int ret; - struct GNUNET_SIGNAL_Context *shc_int; - struct GNUNET_SIGNAL_Context *shc_term; -#if (SIGTERM != GNUNET_TERM_SIG) - struct GNUNET_SIGNAL_Context *shc_gterm; -#endif - -#ifndef MINGW - struct GNUNET_SIGNAL_Context *shc_quit; - struct GNUNET_SIGNAL_Context *shc_hup; - struct GNUNET_SIGNAL_Context *shc_pipe; -#endif - unsigned long long last_tr; unsigned int busy_wait_warning; + unsigned long long last_tr; const struct GNUNET_DISK_FileHandle *pr; char c; + struct GNUNET_TIME_Relative timeout; - GNUNET_assert (NULL == active_task); - rs = GNUNET_NETWORK_fdset_create (); - ws = GNUNET_NETWORK_fdset_create (); - GNUNET_assert (NULL == shutdown_pipe_handle); - shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO, - GNUNET_NO, - GNUNET_NO, - GNUNET_NO); - GNUNET_assert (NULL != shutdown_pipe_handle); + busy_wait_warning = 0; pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_READ); GNUNET_assert (NULL != pr); - my_pid = getpid (); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Registering signal handlers\n"); - shc_int = GNUNET_SIGNAL_handler_install (SIGINT, - &sighandler_shutdown); - shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, - &sighandler_shutdown); -#if (SIGTERM != GNUNET_TERM_SIG) - shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG, - &sighandler_shutdown); -#endif -#ifndef MINGW - shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, - &sighandler_pipe); - shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, - &sighandler_shutdown); - shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, - &sighandler_shutdown); -#endif - current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; - current_lifeness = GNUNET_YES; - GNUNET_SCHEDULER_add_with_reason_and_priority (task, - task_cls, - GNUNET_SCHEDULER_REASON_STARTUP, - GNUNET_SCHEDULER_PRIORITY_DEFAULT); - active_task = (void *) (long) -1; /* force passing of sanity check */ - GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO, - &GNUNET_OS_install_parent_control_handler, - NULL); - active_task = NULL; last_tr = 0; - busy_wait_warning = 0; + while (GNUNET_OK == check_lifeness ()) { GNUNET_NETWORK_fdset_zero (rs); @@ -905,7 +859,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, LOG (GNUNET_ERROR_TYPE_ERROR, "Got invalid file descriptor %d!\n", t->read_fd); - dump_backtrace (t); + dump_backtrace (t); } } if (-1 != t->write_fd) @@ -916,7 +870,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, LOG (GNUNET_ERROR_TYPE_ERROR, "Got invalid file descriptor %d!\n", t->write_fd); - dump_backtrace (t); + dump_backtrace (t); } } } @@ -953,6 +907,89 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, busy_wait_warning = 0; } } +} + +/** + * Initialize and run scheduler. This function will return when all + * tasks have completed. On systems with signals, receiving a SIGTERM + * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown() + * to be run after the active task is complete. As a result, SIGTERM + * causes all active tasks to be scheduled with reason + * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added + * afterwards will execute normally!). Note that any particular signal + * will only shut down one scheduler; applications should always only + * create a single scheduler. + * + * @param task task to run immediately + * @param task_cls closure of @a task + */ +void +GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, + void *task_cls) +{ + struct GNUNET_NETWORK_FDSet *rs; + struct GNUNET_NETWORK_FDSet *ws; + + + struct GNUNET_SIGNAL_Context *shc_int; + struct GNUNET_SIGNAL_Context *shc_term; +#if (SIGTERM != GNUNET_TERM_SIG) + struct GNUNET_SIGNAL_Context *shc_gterm; +#endif + +#ifndef MINGW + struct GNUNET_SIGNAL_Context *shc_quit; + struct GNUNET_SIGNAL_Context *shc_hup; + struct GNUNET_SIGNAL_Context *shc_pipe; +#endif + + unsigned int busy_wait_warning; + + + + GNUNET_assert (NULL == active_task); + rs = GNUNET_NETWORK_fdset_create (); + ws = GNUNET_NETWORK_fdset_create (); + GNUNET_assert (NULL == shutdown_pipe_handle); + shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO, + GNUNET_NO, + GNUNET_NO, + GNUNET_NO); + GNUNET_assert (NULL != shutdown_pipe_handle); + + my_pid = getpid (); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Registering signal handlers\n"); + shc_int = GNUNET_SIGNAL_handler_install (SIGINT, + &sighandler_shutdown); + shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, + &sighandler_shutdown); +#if (SIGTERM != GNUNET_TERM_SIG) + shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG, + &sighandler_shutdown); +#endif +#ifndef MINGW + shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, + &sighandler_pipe); + shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, + &sighandler_shutdown); + shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, + &sighandler_shutdown); +#endif + current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; + current_lifeness = GNUNET_YES; + GNUNET_SCHEDULER_add_with_reason_and_priority (task, + task_cls, + GNUNET_SCHEDULER_REASON_STARTUP, + GNUNET_SCHEDULER_PRIORITY_DEFAULT); + active_task = (void *) (long) -1; /* force passing of sanity check */ + GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO, + &GNUNET_OS_install_parent_control_handler, + NULL); + active_task = NULL; + + + while_live(rs, ws); GNUNET_SIGNAL_handler_uninstall (shc_int); GNUNET_SIGNAL_handler_uninstall (shc_term); #if (SIGTERM != GNUNET_TERM_SIG) @@ -1018,14 +1055,29 @@ GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) * @param task id of the task to cancel * @return original closure of the task */ +void initFdINfo(GNUNET_SCHEDULER_FdInfo *fdi, struct GNUNET_SCHEDULER_Task *task) +{ + if (-1 != task->read_fd) + { + fdi->sock=task->read_fd; + }else if (-1 != task->write_fd){ + fdi->sock=task->write_fd; + } else if (NULL != task->read_set){ + fdi->fd=task->read_set; + }else if (NULL != task->write_set){ + fdi->fd=task->write_set; + } +} + void * GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) { enum GNUNET_SCHEDULER_Priority p; void *ret; + GNUNET_SCHEDULER_FdInfo *fdi; GNUNET_assert ( (NULL != active_task) || - (GNUNET_NO == task->lifeness) ); + (GNUNET_NO == task->lifeness) ); if (! task->in_ready_list) { if ( (-1 == task->read_fd) && @@ -1034,21 +1086,24 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) (NULL == task->write_set) ) { if (GNUNET_YES == task->on_shutdown) - GNUNET_CONTAINER_DLL_remove (shutdown_head, - shutdown_tail, - task); + GNUNET_CONTAINER_DLL_remove (shutdown_head, + shutdown_tail, + task); else - GNUNET_CONTAINER_DLL_remove (pending_timeout_head, - pending_timeout_tail, - task); + GNUNET_CONTAINER_DLL_remove (pending_timeout_head, + pending_timeout_tail, + task); if (task == pending_timeout_last) pending_timeout_last = NULL; } else { - GNUNET_CONTAINER_DLL_remove (pending_head, + /*GNUNET_CONTAINER_DLL_remove (pending_head, pending_tail, - task); + task);*/ + fdi = GNUNET_new (struct GNUNET_SCHEDULER_FdInfo); + initFdINfo(fdi, task); + scheduler_driver->del(scheduler_driver->cls, task, fdi); } } else @@ -1083,7 +1138,7 @@ init_backtrace (struct GNUNET_SCHEDULER_Task *t) = backtrace (backtrace_array, MAX_TRACE_DEPTH); t->backtrace_strings = backtrace_symbols (backtrace_array, - t->num_backtrace_strings); + t->num_backtrace_strings); dump_backtrace (t); #endif } @@ -1220,8 +1275,8 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, */ struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, - enum GNUNET_SCHEDULER_Priority priority, - GNUNET_SCHEDULER_TaskCallback task, + enum GNUNET_SCHEDULER_Priority priority, + GNUNET_SCHEDULER_TaskCallback task, void *task_cls) { return GNUNET_SCHEDULER_add_at_with_priority (GNUNET_TIME_relative_to_absolute (delay), @@ -1289,11 +1344,11 @@ GNUNET_SCHEDULER_add_at (struct GNUNET_TIME_Absolute at, struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, - void *task_cls) + void *task_cls) { return GNUNET_SCHEDULER_add_delayed_with_priority (delay, - GNUNET_SCHEDULER_PRIORITY_DEFAULT, - task, + GNUNET_SCHEDULER_PRIORITY_DEFAULT, + task, task_cls); } @@ -1315,11 +1370,11 @@ GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, */ struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task, - void *task_cls) + void *task_cls) { return GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_ZERO, - task, - task_cls); + task, + task_cls); } @@ -1335,7 +1390,7 @@ GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task, */ struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task, - void *task_cls) + void *task_cls) { struct GNUNET_SCHEDULER_Task *t; @@ -1354,8 +1409,8 @@ GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task, t->on_shutdown = GNUNET_YES; t->lifeness = GNUNET_YES; GNUNET_CONTAINER_DLL_insert (shutdown_head, - shutdown_tail, - t); + shutdown_tail, + t); LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding task: %p\n", t); @@ -1419,8 +1474,8 @@ GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, #ifndef MINGW static struct GNUNET_SCHEDULER_Task * add_without_sets (struct GNUNET_TIME_Relative delay, - enum GNUNET_SCHEDULER_Priority priority, - int rfd, + enum GNUNET_SCHEDULER_Priority priority, + int rfd, int wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls) @@ -1469,9 +1524,12 @@ add_without_sets (struct GNUNET_TIME_Relative delay, t->timeout = GNUNET_TIME_relative_to_absolute (delay); t->priority = check_priority ((priority == GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : priority); t->lifeness = current_lifeness; - GNUNET_CONTAINER_DLL_insert (pending_head, + /*GNUNET_CONTAINER_DLL_insert (pending_head, pending_tail, - t); + t);*/ + fdi = GNUNET_new (struct GNUNET_SCHEDULER_FdInfo); + initFdINfo(fdi, task); + scheduler_driver->add(scheduler_driver, t , fdi); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1504,8 +1562,8 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay, void *task_cls) { return GNUNET_SCHEDULER_add_read_net_with_priority (delay, - GNUNET_SCHEDULER_PRIORITY_DEFAULT, - rfd, task, task_cls); + GNUNET_SCHEDULER_PRIORITY_DEFAULT, + rfd, task, task_cls); } @@ -1527,9 +1585,9 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay, */ struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, - enum GNUNET_SCHEDULER_Priority priority, - struct GNUNET_NETWORK_Handle *rfd, - GNUNET_SCHEDULER_TaskCallback task, + enum GNUNET_SCHEDULER_Priority priority, + struct GNUNET_NETWORK_Handle *rfd, + GNUNET_SCHEDULER_TaskCallback task, void *task_cls) { return GNUNET_SCHEDULER_add_net_with_priority (delay, priority, @@ -1789,11 +1847,14 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : prio); t->lifeness = current_lifeness; - GNUNET_CONTAINER_DLL_insert (pending_head, + /*GNUNET_CONTAINER_DLL_insert (pending_head, pending_tail, - t); + t);*/ + fdi = GNUNET_new (struct GNUNET_SCHEDULER_FdInfo); + initFdINfo(fdi, task); + scheduler_driver->add(scheduler_driver, t , fdi); max_priority_added = GNUNET_MAX (max_priority_added, - t->priority); + t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding task %p\n", t); @@ -1814,7 +1875,7 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, */ void GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, - enum GNUNET_SCHEDULER_EventType et) + enum GNUNET_SCHEDULER_EventType et) { enum GNUNET_SCHEDULER_Reason reason; struct GNUNET_TIME_Absolute now; @@ -1849,7 +1910,7 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, * * @param sh scheduler handle that was given to the `loop` * @return #GNUNET_OK if there are more tasks that are ready, - * and thus we would like to run more (yield to avoid + * and thus we would like to run more (yield to avoid * blocking other activities for too long) * #GNUNET_NO if we are done running tasks (yield to block) * #GNUNET_SYSERR on error @@ -1876,11 +1937,11 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) pending_timeout_last = NULL; queue_ready_task (pos); } - + if (0 == ready_count) return GNUNET_NO; - /* find out which task priority level we are going to + /* find out which task priority level we are going to process this time */ max_priority_added = GNUNET_SCHEDULER_PRIORITY_KEEP; GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]); @@ -1898,21 +1959,21 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) while (NULL != (pos = ready_head[p])) { GNUNET_CONTAINER_DLL_remove (ready_head[p], - ready_tail[p], - pos); + ready_tail[p], + pos); ready_count--; current_priority = pos->priority; current_lifeness = pos->lifeness; active_task = pos; #if PROFILE_DELAYS if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us > - DELAY_THRESHOLD.rel_value_us) + DELAY_THRESHOLD.rel_value_us) { LOG (GNUNET_ERROR_TYPE_DEBUG, - "Task %p took %s to be scheduled\n", - pos, - GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), - GNUNET_YES)); + "Task %p took %s to be scheduled\n", + pos, + GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), + GNUNET_YES)); } #endif tc.reason = pos->reason; @@ -1922,17 +1983,17 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) tc.fds = pos->fds; tc.read_ready = (NULL == pos->read_set) ? sh->rs : pos->read_set; if ( (-1 != pos->read_fd) && - (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ) + (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ) GNUNET_NETWORK_fdset_set_native (sh->rs, - pos->read_fd); + pos->read_fd); tc.write_ready = (NULL == pos->write_set) ? sh->ws : pos->write_set; if ((-1 != pos->write_fd) && - (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))) + (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))) GNUNET_NETWORK_fdset_set_native (sh->ws, - pos->write_fd); + pos->write_fd); LOG (GNUNET_ERROR_TYPE_DEBUG, - "Running task: %p\n", - pos); + "Running task: %p\n", + pos); pos->callback (pos->callback_cls); active_task = NULL; dump_backtrace (pos); @@ -1963,8 +2024,8 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) */ int GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, - GNUNET_SCHEDULER_TaskCallback task, - void *task_cls) + GNUNET_SCHEDULER_TaskCallback task, + void *task_cls) { int ret; struct GNUNET_SIGNAL_Context *shc_int; @@ -1979,7 +2040,7 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, #endif struct GNUNET_SCHEDULER_Task tsk; const struct GNUNET_DISK_FileHandle *pr; - struct GNUNET_SCHEDULER_Handle sh; + scheduler_driver = driver; /* general set-up */ GNUNET_assert (NULL == active_task); @@ -1998,28 +2059,28 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering signal handlers\n"); shc_int = GNUNET_SIGNAL_handler_install (SIGINT, - &sighandler_shutdown); + &sighandler_shutdown); shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, - &sighandler_shutdown); + &sighandler_shutdown); #if (SIGTERM != GNUNET_TERM_SIG) shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG, - &sighandler_shutdown); + &sighandler_shutdown); #endif #ifndef MINGW shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, - &sighandler_pipe); + &sighandler_pipe); shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, - &sighandler_shutdown); + &sighandler_shutdown); shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, - &sighandler_shutdown); + &sighandler_shutdown); #endif /* Setup initial tasks */ current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; current_lifeness = GNUNET_YES; memset (&tsk, - 0, - sizeof (tsk)); + 0, + sizeof (tsk)); active_task = &tsk; tsk.sh = &sh; GNUNET_SCHEDULER_add_with_reason_and_priority (task, @@ -2031,14 +2092,15 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, NULL); active_task = NULL; driver->set_wakeup (driver->cls, - GNUNET_TIME_absolute_get ()); + GNUNET_TIME_absolute_get ()); /* begin main event loop */ sh.rs = GNUNET_NETWORK_fdset_create (); sh.ws = GNUNET_NETWORK_fdset_create (); + GNUNET_NETWORK_fdset_handle_set (rs, pr); sh.driver = driver; ret = driver->loop (driver->cls, - &sh); + &sh); GNUNET_NETWORK_fdset_destroy (sh.rs); GNUNET_NETWORK_fdset_destroy (sh.ws); @@ -2058,6 +2120,45 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, return ret; } +int +select_add(void *cls, + struct GNUNET_SCHEDULER_Task *task, + struct GNUNET_SCHEDULER_FdInfo *fdi){ + + GNUNET_CONTAINER_DLL_insert (pending_head, + pending_tail, + task); + +} + +int +select_del(void *cls, + struct GNUNET_SCHEDULER_Task *task, + struct GNUNET_SCHEDULER_FdInfo *fdi){ + + GNUNET_CONTAINER_DLL_remove (pending_head, + pending_tail, + task); + +} + + +int +select_loop(void *cls, + struct GNUNET_SCHEDULER_Handle *sh){ + + while_live(sh-rs, sh->ws); + +} + +void +select_set_wakeup(void *cls, + struct GNUNET_TIME_Absolute dt){ + + + +} + /** * Obtain the driver for using select() as the event loop. @@ -2067,8 +2168,18 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, const struct GNUNET_SCHEDULER_Driver * GNUNET_SCHEDULER_driver_select () { - GNUNET_break (0); // not implemented - return NULL; + + GNUNET_SCHEDULER_Driver *select_driver; + + select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver); + + select_driver->loop = &select_loop; + select_driver->add = &select_add; + select_driver->del = &select_del; + select_driver->set_wakeup = &select_set_wakeup; + + + return select_driver; } -- cgit v1.2.3 From 7f843df63bd3d1a85d687f3e0de23594b43af6d3 Mon Sep 17 00:00:00 2001 From: lurchi Date: Thu, 20 Jul 2017 18:04:02 +0200 Subject: small fixes --- src/util/scheduler.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index e27eb0fe0..1275a684b 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -234,7 +234,7 @@ struct GNUNET_SCHEDULER_Task * #GNUNET_SCHEDULER_add_select(), #add_without_sets() and * #GNUNET_SCHEDULER_cancel(). */ -GNUNET_SCHEDULER_Driver *scheduler_driver; +static struct GNUNET_SCHEDULER_Driver *scheduler_driver; /** * Head of list of tasks waiting for an event. @@ -1055,16 +1055,22 @@ GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) * @param task id of the task to cancel * @return original closure of the task */ -void initFdINfo(GNUNET_SCHEDULER_FdInfo *fdi, struct GNUNET_SCHEDULER_Task *task) +void initFdInfo(struct GNUNET_SCHEDULER_FdInfo *fdi, struct GNUNET_SCHEDULER_Task *task) { if (-1 != task->read_fd) { fdi->sock=task->read_fd; - }else if (-1 != task->write_fd){ + } + else if (-1 != task->write_fd) + { fdi->sock=task->write_fd; - } else if (NULL != task->read_set){ + } + else if (NULL != task->read_set) + { fdi->fd=task->read_set; - }else if (NULL != task->write_set){ + } + else if (NULL != task->write_set) + { fdi->fd=task->write_set; } } @@ -1102,7 +1108,7 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) pending_tail, task);*/ fdi = GNUNET_new (struct GNUNET_SCHEDULER_FdInfo); - initFdINfo(fdi, task); + initFdInfo(fdi, task); scheduler_driver->del(scheduler_driver->cls, task, fdi); } } @@ -1528,8 +1534,8 @@ add_without_sets (struct GNUNET_TIME_Relative delay, pending_tail, t);*/ fdi = GNUNET_new (struct GNUNET_SCHEDULER_FdInfo); - initFdINfo(fdi, task); - scheduler_driver->add(scheduler_driver, t , fdi); + initFdInfo(fdi, t); + scheduler_driver->add(scheduler_driver->cls, t , fdi); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1851,8 +1857,8 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, pending_tail, t);*/ fdi = GNUNET_new (struct GNUNET_SCHEDULER_FdInfo); - initFdINfo(fdi, task); - scheduler_driver->add(scheduler_driver, t , fdi); + initFdInfo(fdi, t); + scheduler_driver->add(scheduler_driver->cls, t , fdi); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, -- cgit v1.2.3 From 516babaed25b7b23ba27fc837bdc19643ec54d78 Mon Sep 17 00:00:00 2001 From: lurchi Date: Fri, 21 Jul 2017 01:27:22 +0200 Subject: adapt add_without_sets to scheduler driver API; reimplement initFdInfo --- src/util/scheduler.c | 113 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 84 insertions(+), 29 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 1275a684b..070c0daa8 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -1055,23 +1055,67 @@ GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) * @param task id of the task to cancel * @return original closure of the task */ -void initFdInfo(struct GNUNET_SCHEDULER_FdInfo *fdi, struct GNUNET_SCHEDULER_Task *task) +void +initFdInfo(struct GNUNET_SCHEDULER_Task *task, + struct GNUNET_NETWORK_Handle *read_nh, + struct GNUNET_NETWORK_Handle *write_nh, + struct GNUNET_DISK_FileHandle *read_fh, + struct GNUNET_DISK_FileHandle *write_fh) { - if (-1 != task->read_fd) + // either only network handles or only file handles are allowed + GNUNET_assert (!((NULL != read_nh || NULL != write_nh) && (NULL != read_fh || NULL != write_fh))); + + if (NULL != read_nh && NULL != write_nh) + { + t->fds_len = 2; + t->fds = + GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); + struct GNUNET_SCHEDULER_FdInfo *read_fdi = t->fds; + struct GNUENT_SCHEDULER_FdInfo *write_fdi = t->fds + 1; + read_fdi->fd = read_nh; + read_fdi->et = GNUNET_SCHEDULER_ET_IN; + read_fdi->sock = GNUNET_NETWORK_get_fd (read_nh); + write_fdi->fd = write_nh; + write_fdi->et = GNUNET_SCHEDULER_ET_OUT; + write_fdi->sock = GNUNET_NETWORK_get_fd (write_nh); + } + else if (NULL != read_fh && NULL != write_fh) { - fdi->sock=task->read_fd; + t->fds_len = 2; + t->fds = + GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); + struct GNUNET_SCHEDULER_FdInfo *read_fdi = t->fds; + struct GNUENT_SCHEDULER_FdInfo *write_fdi = t->fds + 1; + read_fdi->fh = read_fh; + read_fdi->et = GNUNET_SCHEDULER_ET_IN; + write_fdi->fh = write_fh; + write_fdi->et = GNUNET_SCHEDULER_ET_OUT; } - else if (-1 != task->write_fd) + else if (NULL != read_nh) { - fdi->sock=task->write_fd; + struct GNUNET_SCHEDULER_FdInfo *read_fdi = &t->fdx; + read_fdi->fd = read_nh; + read_fdi->et = GNUNET_SCHEDULER_ET_IN; + read_fdi->sock = GNUNET_NETWORK_get_fd (read_nh); } - else if (NULL != task->read_set) + else if (NULL != write_nh) { - fdi->fd=task->read_set; + struct GNUNET_SCHEDULER_FdInfo *write_fdi = &t->fdx; + write_fdi->fd = write_nh; + write_fdi->et = GNUNET_SCHEDULER_ET_OUT; + write_fdi->sock = GNUNET_NETWORK_get_fd (write_nh); } - else if (NULL != task->write_set) + else if (NULL != read_fh) { - fdi->fd=task->write_set; + struct GNUNET_SCHEDULER_FdInfo *read_fdi = &t->fdx; + read_fdi->fh = read_fh; + read_fdi->et = GNUNET_SCHEDULER_ET_IN; + } + else if (NULL != write_fh) + { + struct GNUNET_SCHEDULER_FdInfo *write_fdi = &t->fdx; + write_fdi->fh = write_fh; + write_fdi->et = GNUNET_SCHEDULER_ET_OUT; } } @@ -1080,7 +1124,7 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) { enum GNUNET_SCHEDULER_Priority p; void *ret; - GNUNET_SCHEDULER_FdInfo *fdi; + struct GNUNET_SCHEDULER_FdInfo *fdi; GNUNET_assert ( (NULL != active_task) || (GNUNET_NO == task->lifeness) ); @@ -1480,9 +1524,13 @@ GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, #ifndef MINGW static struct GNUNET_SCHEDULER_Task * add_without_sets (struct GNUNET_TIME_Relative delay, - enum GNUNET_SCHEDULER_Priority priority, - int rfd, - int wfd, + enum GNUNET_SCHEDULER_Priority priority, + struct GNUNET_NETWORK_Handle *read_nh, + struct GNUNET_NETWORK_Handle *write_nh, + struct GNUNET_DISK_FileHandle *read_fh, + struct GNUNET_DISK_FileHandle *write_fh, + //int rfd, + //int wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls) { @@ -1530,12 +1578,17 @@ add_without_sets (struct GNUNET_TIME_Relative delay, t->timeout = GNUNET_TIME_relative_to_absolute (delay); t->priority = check_priority ((priority == GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : priority); t->lifeness = current_lifeness; - /*GNUNET_CONTAINER_DLL_insert (pending_head, - pending_tail, - t);*/ - fdi = GNUNET_new (struct GNUNET_SCHEDULER_FdInfo); - initFdInfo(fdi, t); + //GNUNET_CONTAINER_DLL_insert (pending_head, + // pending_tail, + // t); + //fdi = GNUNET_new (struct GNUNET_SCHEDULER_FdInfo); + //initFdInfo(fdi, t); + //scheduler_driver->add(scheduler_driver->cls, t , fdi); + //initFdInfo (&t->fdx, read_nh, write_nh, read_fh, write_fh) + initFdInfo (t, read_nh, write_nh, read_fh, write_fh); + // FIXME: call add for each fdi if t->fds is a list scheduler_driver->add(scheduler_driver->cls, t , fdi); + max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1673,10 +1726,13 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, GNUNET_NETWORK_fdset_destroy (s); return ret; #else + GNUNET_assert (on_read || on_write); GNUNET_assert (GNUNET_NETWORK_get_fd (fd) >= 0); return add_without_sets (delay, priority, - on_read ? GNUNET_NETWORK_get_fd (fd) : -1, - on_write ? GNUNET_NETWORK_get_fd (fd) : -1, + on_read ? fd : NULL, + on_write ? fd : NULL, + NULL, + NULL, task, task_cls); #endif } @@ -1773,15 +1829,14 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, GNUNET_NETWORK_fdset_destroy (s); return ret; #else - int real_fd; - - GNUNET_DISK_internal_file_handle_ (fd, &real_fd, sizeof (int)); - GNUNET_assert (real_fd >= 0); - return add_without_sets ( - delay, priority, - on_read ? real_fd : -1, - on_write ? real_fd : -1, - task, task_cls); + GNUNET_assert (on_read || on_write); + GNUNET_assert(fd->fd >= 0); + return add_without_sets (delay, priority, + NULL, + NULL, + on_read ? fd : NULL, + on_write ? fd : NULL, + task, task_cls); #endif } -- cgit v1.2.3 From d3cd9042bf5ba56e4577507842d6f66c8ba4b3c4 Mon Sep 17 00:00:00 2001 From: t3sserakt Date: Wed, 2 Aug 2017 22:55:04 +0200 Subject: Nearly finished. Call to set_wakeup missing in case of tasks added to pending_timeout --- src/include/gnunet_scheduler_lib.h | 6 +- src/util/scheduler.c | 158 +++++++++++++++++-------------------- 2 files changed, 76 insertions(+), 88 deletions(-) (limited to 'src/util') diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h index 875f5043a..5baf4806d 100644 --- a/src/include/gnunet_scheduler_lib.h +++ b/src/include/gnunet_scheduler_lib.h @@ -152,14 +152,14 @@ struct GNUNET_SCHEDULER_FdInfo * NULL if this is about a file handle or if no network * handle was given to the scheduler originally. */ - struct GNUNET_NETWORK_Handle *fd; + const struct GNUNET_NETWORK_Handle *fd; /** * GNUnet file handle the event is about, matches @a sock, * NULL if this is about a network socket or if no network * handle was given to the scheduler originally. */ - struct GNUNET_DISK_FileHandle *fh; + const struct GNUNET_DISK_FileHandle *fh; /** * Type of the event that was generated related to @e sock. @@ -280,7 +280,7 @@ struct GNUNET_SCHEDULER_Driver int (*add)(void *cls, struct GNUNET_SCHEDULER_Task *task, - struct GNUNET_SCHEDULER_FdInfo *fdi); + const struct GNUNET_SCHEDULER_FdInfo *fdi); /** * Delete a @a task from the set of tasks to be run. diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 070c0daa8..9061200bd 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -234,7 +234,7 @@ struct GNUNET_SCHEDULER_Task * #GNUNET_SCHEDULER_add_select(), #add_without_sets() and * #GNUNET_SCHEDULER_cancel(). */ -static struct GNUNET_SCHEDULER_Driver *scheduler_driver; +static const struct GNUNET_SCHEDULER_Driver *scheduler_driver; /** * Head of list of tasks waiting for an event. @@ -943,8 +943,6 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, struct GNUNET_SIGNAL_Context *shc_pipe; #endif - unsigned int busy_wait_warning; - GNUNET_assert (NULL == active_task); @@ -1047,84 +1045,74 @@ GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) return ret; } - -/** - * Cancel the task with the specified identifier. - * The task must not yet have run. - * - * @param task id of the task to cancel - * @return original closure of the task - */ -void -initFdInfo(struct GNUNET_SCHEDULER_Task *task, - struct GNUNET_NETWORK_Handle *read_nh, - struct GNUNET_NETWORK_Handle *write_nh, - struct GNUNET_DISK_FileHandle *read_fh, - struct GNUNET_DISK_FileHandle *write_fh) +static struct GNUNET_SCHEDULER_Task* +initFdInfo(const struct GNUNET_NETWORK_Handle *read_nh, + const struct GNUNET_NETWORK_Handle *write_nh, + const struct GNUNET_DISK_FileHandle *read_fh, + const struct GNUNET_DISK_FileHandle *write_fh) { + + + struct GNUNET_SCHEDULER_Task *t; + + t = GNUNET_new (struct GNUNET_SCHEDULER_Task); + // either only network handles or only file handles are allowed GNUNET_assert (!((NULL != read_nh || NULL != write_nh) && (NULL != read_fh || NULL != write_fh))); if (NULL != read_nh && NULL != write_nh) { t->fds_len = 2; - t->fds = - GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); - struct GNUNET_SCHEDULER_FdInfo *read_fdi = t->fds; - struct GNUENT_SCHEDULER_FdInfo *write_fdi = t->fds + 1; - read_fdi->fd = read_nh; - read_fdi->et = GNUNET_SCHEDULER_ET_IN; - read_fdi->sock = GNUNET_NETWORK_get_fd (read_nh); - write_fdi->fd = write_nh; - write_fdi->et = GNUNET_SCHEDULER_ET_OUT; - write_fdi->sock = GNUNET_NETWORK_get_fd (write_nh); + t->fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); + const struct GNUNET_SCHEDULER_FdInfo read_fdi = { .fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = GNUNET_NETWORK_get_fd (read_nh)}; + const struct GNUNET_SCHEDULER_FdInfo write_fdi = { .fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; + + const struct GNUNET_SCHEDULER_FdInfo array[2] = {read_fdi, write_fdi}; + t->fds = array; } else if (NULL != read_fh && NULL != write_fh) { t->fds_len = 2; - t->fds = - GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); - struct GNUNET_SCHEDULER_FdInfo *read_fdi = t->fds; - struct GNUENT_SCHEDULER_FdInfo *write_fdi = t->fds + 1; - read_fdi->fh = read_fh; - read_fdi->et = GNUNET_SCHEDULER_ET_IN; - write_fdi->fh = write_fh; - write_fdi->et = GNUNET_SCHEDULER_ET_OUT; + t->fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); + const struct GNUNET_SCHEDULER_FdInfo read_fdi = { .fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN}; + const struct GNUNET_SCHEDULER_FdInfo write_fdi = { .fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; + const struct GNUNET_SCHEDULER_FdInfo array[2] = {read_fdi, write_fdi}; + t->fds = array; } else if (NULL != read_nh) { - struct GNUNET_SCHEDULER_FdInfo *read_fdi = &t->fdx; - read_fdi->fd = read_nh; - read_fdi->et = GNUNET_SCHEDULER_ET_IN; - read_fdi->sock = GNUNET_NETWORK_get_fd (read_nh); + struct GNUNET_SCHEDULER_FdInfo read_fdi = { .fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = GNUNET_NETWORK_get_fd (read_nh)}; + t->fdx = read_fdi; } else if (NULL != write_nh) { - struct GNUNET_SCHEDULER_FdInfo *write_fdi = &t->fdx; - write_fdi->fd = write_nh; - write_fdi->et = GNUNET_SCHEDULER_ET_OUT; - write_fdi->sock = GNUNET_NETWORK_get_fd (write_nh); + struct GNUNET_SCHEDULER_FdInfo write_fdi = { .fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; + t->fdx = write_fdi; } else if (NULL != read_fh) { - struct GNUNET_SCHEDULER_FdInfo *read_fdi = &t->fdx; - read_fdi->fh = read_fh; - read_fdi->et = GNUNET_SCHEDULER_ET_IN; + struct GNUNET_SCHEDULER_FdInfo read_fdi = { .fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN}; + t->fdx = read_fdi; } else if (NULL != write_fh) { - struct GNUNET_SCHEDULER_FdInfo *write_fdi = &t->fdx; - write_fdi->fh = write_fh; - write_fdi->et = GNUNET_SCHEDULER_ET_OUT; + struct GNUNET_SCHEDULER_FdInfo write_fdi = { .fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; + t->fdx = write_fdi; } } +/** + * Cancel the task with the specified identifier. + * The task must not yet have run. + * + * @param task id of the task to cancel + * @return original closure of the task + */ void * GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) { enum GNUNET_SCHEDULER_Priority p; void *ret; - struct GNUNET_SCHEDULER_FdInfo *fdi; GNUNET_assert ( (NULL != active_task) || (GNUNET_NO == task->lifeness) ); @@ -1148,12 +1136,7 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) } else { - /*GNUNET_CONTAINER_DLL_remove (pending_head, - pending_tail, - task);*/ - fdi = GNUNET_new (struct GNUNET_SCHEDULER_FdInfo); - initFdInfo(fdi, task); - scheduler_driver->del(scheduler_driver->cls, task, fdi); + scheduler_multi_function_call(task, scheduler_driver->del); } } else @@ -1496,6 +1479,20 @@ GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, } + +int scheduler_multi_function_call(struct GNUNET_SCHEDULER_Task *t, int (*driver_func)()) +{ + if (t->fds_len > 1){ + int success = GNUNET_YES; + for (int i = 0; i < t->fds_len;i++){ + success = driver_func(scheduler_driver->cls, t , t->fds+i) && success; + } + return success; + }else{ + return driver_func(scheduler_driver->cls, t , t->fds); + } +} + /** * Schedule a new task to be run with a specified delay or when any of * the specified file descriptor sets is ready. The delay can be used @@ -1525,10 +1522,10 @@ GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, static struct GNUNET_SCHEDULER_Task * add_without_sets (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, - struct GNUNET_NETWORK_Handle *read_nh, - struct GNUNET_NETWORK_Handle *write_nh, - struct GNUNET_DISK_FileHandle *read_fh, - struct GNUNET_DISK_FileHandle *write_fh, + const struct GNUNET_NETWORK_Handle *read_nh, + const struct GNUNET_NETWORK_Handle *write_nh, + const struct GNUNET_DISK_FileHandle *read_fh, + const struct GNUNET_DISK_FileHandle *write_fh, //int rfd, //int wfd, GNUNET_SCHEDULER_TaskCallback task, @@ -1538,7 +1535,8 @@ add_without_sets (struct GNUNET_TIME_Relative delay, GNUNET_assert (NULL != active_task); GNUNET_assert (NULL != task); - t = GNUNET_new (struct GNUNET_SCHEDULER_Task); + t= initFdInfo (read_nh, write_nh, read_fh, write_fh); + t->callback = task; t->callback_cls = task_cls; #if DEBUG_FDS @@ -1569,26 +1567,18 @@ add_without_sets (struct GNUNET_TIME_Relative delay, } } #endif - t->read_fd = rfd; - GNUNET_assert (wfd >= -1); - t->write_fd = wfd; + #if PROFILE_DELAYS t->start_time = GNUNET_TIME_absolute_get (); #endif t->timeout = GNUNET_TIME_relative_to_absolute (delay); t->priority = check_priority ((priority == GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : priority); t->lifeness = current_lifeness; - //GNUNET_CONTAINER_DLL_insert (pending_head, - // pending_tail, - // t); - //fdi = GNUNET_new (struct GNUNET_SCHEDULER_FdInfo); - //initFdInfo(fdi, t); - //scheduler_driver->add(scheduler_driver->cls, t , fdi); - //initFdInfo (&t->fdx, read_nh, write_nh, read_fh, write_fh) - initFdInfo (t, read_nh, write_nh, read_fh, write_fh); - // FIXME: call add for each fdi if t->fds is a list - scheduler_driver->add(scheduler_driver->cls, t , fdi); - + + + + scheduler_multi_function_call(t, scheduler_driver->add); + max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1908,12 +1898,9 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : prio); t->lifeness = current_lifeness; - /*GNUNET_CONTAINER_DLL_insert (pending_head, - pending_tail, - t);*/ - fdi = GNUNET_new (struct GNUNET_SCHEDULER_FdInfo); - initFdInfo(fdi, t); - scheduler_driver->add(scheduler_driver->cls, t , fdi); + + scheduler_multi_function_call(t, scheduler_driver->add); + max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -2089,6 +2076,7 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, void *task_cls) { int ret; + struct GNUNET_SCHEDULER_Handle sh; struct GNUNET_SIGNAL_Context *shc_int; struct GNUNET_SIGNAL_Context *shc_term; #if (SIGTERM != GNUNET_TERM_SIG) @@ -2158,7 +2146,7 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, /* begin main event loop */ sh.rs = GNUNET_NETWORK_fdset_create (); sh.ws = GNUNET_NETWORK_fdset_create (); - GNUNET_NETWORK_fdset_handle_set (rs, pr); + GNUNET_NETWORK_fdset_handle_set (sh.rs, pr); sh.driver = driver; ret = driver->loop (driver->cls, &sh); @@ -2208,11 +2196,11 @@ int select_loop(void *cls, struct GNUNET_SCHEDULER_Handle *sh){ - while_live(sh-rs, sh->ws); + while_live(sh->rs, sh->ws); } -void +static void select_set_wakeup(void *cls, struct GNUNET_TIME_Absolute dt){ @@ -2230,7 +2218,7 @@ const struct GNUNET_SCHEDULER_Driver * GNUNET_SCHEDULER_driver_select () { - GNUNET_SCHEDULER_Driver *select_driver; + struct GNUNET_SCHEDULER_Driver *select_driver; select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver); -- cgit v1.2.3 From 06a875a49e9e020a504ff38e5e61691cb116fe14 Mon Sep 17 00:00:00 2001 From: t3sserakt Date: Thu, 3 Aug 2017 06:04:45 +0200 Subject: Call to set_wakeup added after tasks added/removed to/from pending_timeout --- src/util/scheduler.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 9061200bd..7fe18bbe6 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -539,6 +539,7 @@ check_ready (const struct GNUNET_NETWORK_FDSet *rs, GNUNET_CONTAINER_DLL_remove (pending_timeout_head, pending_timeout_tail, pos); + scheduler_driver->set_wakeup(scheduler_driver->cls,pending_timeout_head->timeout); if (pending_timeout_last == pos) pending_timeout_last = NULL; queue_ready_task (pos); @@ -1131,6 +1132,7 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) GNUNET_CONTAINER_DLL_remove (pending_timeout_head, pending_timeout_tail, task); + scheduler_driver->set_wakeup(scheduler_driver->cls,pending_timeout_head->timeout); if (task == pending_timeout_last) pending_timeout_last = NULL; } @@ -1259,6 +1261,7 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, GNUNET_CONTAINER_DLL_insert (pending_timeout_head, pending_timeout_tail, t); + scheduler_driver->set_wakeup(scheduler_driver->cls,pending_timeout_head->timeout); } else { @@ -1981,6 +1984,7 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) GNUNET_CONTAINER_DLL_remove (pending_timeout_head, pending_timeout_tail, pos); + scheduler_driver->set_wakeup(scheduler_driver->cls,pending_timeout_head->timeout); if (pending_timeout_last == pos) pending_timeout_last = NULL; queue_ready_task (pos); -- cgit v1.2.3 From 646bbf4ddba3a37c4af0bb62e90be48a465d2004 Mon Sep 17 00:00:00 2001 From: t3sserakt Date: Fri, 4 Aug 2017 08:45:30 +0200 Subject: GNUNET_SCHEDULER_run is calling GNUNET_SCHEDULER_run_with_driver with the default select polling backend. --- src/util/scheduler.c | 74 +--------------------------------------------------- 1 file changed, 1 insertion(+), 73 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 7fe18bbe6..e442989d0 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -928,81 +928,9 @@ void GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, void *task_cls) { - struct GNUNET_NETWORK_FDSet *rs; - struct GNUNET_NETWORK_FDSet *ws; - - - struct GNUNET_SIGNAL_Context *shc_int; - struct GNUNET_SIGNAL_Context *shc_term; -#if (SIGTERM != GNUNET_TERM_SIG) - struct GNUNET_SIGNAL_Context *shc_gterm; -#endif - -#ifndef MINGW - struct GNUNET_SIGNAL_Context *shc_quit; - struct GNUNET_SIGNAL_Context *shc_hup; - struct GNUNET_SIGNAL_Context *shc_pipe; -#endif - - - GNUNET_assert (NULL == active_task); - rs = GNUNET_NETWORK_fdset_create (); - ws = GNUNET_NETWORK_fdset_create (); - GNUNET_assert (NULL == shutdown_pipe_handle); - shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO, - GNUNET_NO, - GNUNET_NO, - GNUNET_NO); - GNUNET_assert (NULL != shutdown_pipe_handle); + GNUNET_SCHEDULER_run_with_driver(GNUNET_SCHEDULER_driver_select, task, task_cls); - my_pid = getpid (); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Registering signal handlers\n"); - shc_int = GNUNET_SIGNAL_handler_install (SIGINT, - &sighandler_shutdown); - shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, - &sighandler_shutdown); -#if (SIGTERM != GNUNET_TERM_SIG) - shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG, - &sighandler_shutdown); -#endif -#ifndef MINGW - shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, - &sighandler_pipe); - shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, - &sighandler_shutdown); - shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, - &sighandler_shutdown); -#endif - current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; - current_lifeness = GNUNET_YES; - GNUNET_SCHEDULER_add_with_reason_and_priority (task, - task_cls, - GNUNET_SCHEDULER_REASON_STARTUP, - GNUNET_SCHEDULER_PRIORITY_DEFAULT); - active_task = (void *) (long) -1; /* force passing of sanity check */ - GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO, - &GNUNET_OS_install_parent_control_handler, - NULL); - active_task = NULL; - - - while_live(rs, ws); - GNUNET_SIGNAL_handler_uninstall (shc_int); - GNUNET_SIGNAL_handler_uninstall (shc_term); -#if (SIGTERM != GNUNET_TERM_SIG) - GNUNET_SIGNAL_handler_uninstall (shc_gterm); -#endif -#ifndef MINGW - GNUNET_SIGNAL_handler_uninstall (shc_pipe); - GNUNET_SIGNAL_handler_uninstall (shc_quit); - GNUNET_SIGNAL_handler_uninstall (shc_hup); -#endif - GNUNET_DISK_pipe_close (shutdown_pipe_handle); - shutdown_pipe_handle = NULL; - GNUNET_NETWORK_fdset_destroy (rs); - GNUNET_NETWORK_fdset_destroy (ws); } -- cgit v1.2.3 From e8e8d889a4c92a36ec1491f8b255457cd42922d3 Mon Sep 17 00:00:00 2001 From: lurchi Date: Sat, 5 Aug 2017 13:33:55 +0200 Subject: make input of getters const (needed for new scheduler API) --- src/include/gnunet_network_lib.h | 6 +++--- src/util/network.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/util') diff --git a/src/include/gnunet_network_lib.h b/src/include/gnunet_network_lib.h index d9d3d90e7..9e692bbbf 100644 --- a/src/include/gnunet_network_lib.h +++ b/src/include/gnunet_network_lib.h @@ -464,7 +464,7 @@ GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to, * @return POSIX file descriptor */ int -GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc); +GNUNET_NETWORK_get_fd (const struct GNUNET_NETWORK_Handle *desc); /** @@ -474,7 +474,7 @@ GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc); * @return POSIX file descriptor */ struct sockaddr* -GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc); +GNUNET_NETWORK_get_addr (const struct GNUNET_NETWORK_Handle *desc); /** @@ -484,7 +484,7 @@ GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc); * @return socklen_t for sockaddr */ socklen_t -GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc); +GNUNET_NETWORK_get_addrlen (const struct GNUNET_NETWORK_Handle *desc); /** diff --git a/src/util/network.c b/src/util/network.c index 66a468e45..a3c1876c5 100644 --- a/src/util/network.c +++ b/src/util/network.c @@ -1223,7 +1223,7 @@ GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to, * @return POSIX file descriptor */ int -GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc) +GNUNET_NETWORK_get_fd (const struct GNUNET_NETWORK_Handle *desc) { return desc->fd; } @@ -1236,7 +1236,7 @@ GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc) * @return sockaddr */ struct sockaddr* -GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc) +GNUNET_NETWORK_get_addr (const struct GNUNET_NETWORK_Handle *desc) { return desc->addr; } @@ -1249,7 +1249,7 @@ GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc) * @return socklen_t for sockaddr */ socklen_t -GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc) +GNUNET_NETWORK_get_addrlen (const struct GNUNET_NETWORK_Handle *desc) { return desc->addrlen; } -- cgit v1.2.3 From df4dae1db83ca19b0ba0ddef64699b89558675ed Mon Sep 17 00:00:00 2001 From: lurchi Date: Sat, 5 Aug 2017 13:35:10 +0200 Subject: fix warnings --- src/include/gnunet_scheduler_lib.h | 4 +- src/util/scheduler.c | 100 +++++++++++++++++-------------------- 2 files changed, 49 insertions(+), 55 deletions(-) (limited to 'src/util') diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h index 5baf4806d..837a23ba5 100644 --- a/src/include/gnunet_scheduler_lib.h +++ b/src/include/gnunet_scheduler_lib.h @@ -280,7 +280,7 @@ struct GNUNET_SCHEDULER_Driver int (*add)(void *cls, struct GNUNET_SCHEDULER_Task *task, - const struct GNUNET_SCHEDULER_FdInfo *fdi); + struct GNUNET_SCHEDULER_FdInfo *fdi); /** * Delete a @a task from the set of tasks to be run. @@ -294,7 +294,7 @@ struct GNUNET_SCHEDULER_Driver int (*del)(void *cls, struct GNUNET_SCHEDULER_Task *task, - const struct GNUNET_SCHEDULER_FdInfo *fdi); + struct GNUNET_SCHEDULER_FdInfo *fdi); /** * Set time at which we definitively want to get a wakeup call. diff --git a/src/util/scheduler.c b/src/util/scheduler.c index e442989d0..7a65069a2 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -791,7 +791,7 @@ check_lifeness () -void while_live(struct GNUNET_NETWORK_FDSet *rs, struct GNUNET_NETWORK_FDSet *ws) +int while_live(struct GNUNET_NETWORK_FDSet *rs, struct GNUNET_NETWORK_FDSet *ws) { int ret; unsigned int busy_wait_warning; @@ -908,6 +908,7 @@ void while_live(struct GNUNET_NETWORK_FDSet *rs, struct GNUNET_NETWORK_FDSet *ws busy_wait_warning = 0; } } + return ret; } /** @@ -929,7 +930,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, void *task_cls) { - GNUNET_SCHEDULER_run_with_driver(GNUNET_SCHEDULER_driver_select, task, task_cls); + GNUNET_SCHEDULER_run_with_driver(GNUNET_SCHEDULER_driver_select (), task, task_cls); } @@ -974,18 +975,14 @@ GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) return ret; } -static struct GNUNET_SCHEDULER_Task* -initFdInfo(const struct GNUNET_NETWORK_Handle *read_nh, + +void +initFdInfo(struct GNUNET_SCHEDULER_Task *t, + const struct GNUNET_NETWORK_Handle *read_nh, const struct GNUNET_NETWORK_Handle *write_nh, const struct GNUNET_DISK_FileHandle *read_fh, const struct GNUNET_DISK_FileHandle *write_fh) { - - - struct GNUNET_SCHEDULER_Task *t; - - t = GNUNET_new (struct GNUNET_SCHEDULER_Task); - // either only network handles or only file handles are allowed GNUNET_assert (!((NULL != read_nh || NULL != write_nh) && (NULL != read_fh || NULL != write_fh))); @@ -1020,16 +1017,31 @@ initFdInfo(const struct GNUNET_NETWORK_Handle *read_nh, } else if (NULL != read_fh) { - struct GNUNET_SCHEDULER_FdInfo read_fdi = { .fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN}; + struct GNUNET_SCHEDULER_FdInfo read_fdi = { .fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fh->fd}; t->fdx = read_fdi; } else if (NULL != write_fh) { - struct GNUNET_SCHEDULER_FdInfo write_fdi = { .fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; + struct GNUNET_SCHEDULER_FdInfo write_fdi = { .fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fh->fd}; t->fdx = write_fdi; } } + +int scheduler_multi_function_call(struct GNUNET_SCHEDULER_Task *t, int (*driver_func)()) +{ + if (t->fds_len > 1){ + int success = GNUNET_YES; + for (int i = 0; i < t->fds_len;i++){ + success = driver_func(scheduler_driver->cls, t , t->fds+i) && success; + } + return success; + }else{ + return driver_func(scheduler_driver->cls, t , t->fds); + } +} + + /** * Cancel the task with the specified identifier. * The task must not yet have run. @@ -1066,6 +1078,9 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) } else { + GNUNET_CONTAINER_DLL_remove (pending_head, + pending_tail, + task); scheduler_multi_function_call(task, scheduler_driver->del); } } @@ -1410,20 +1425,6 @@ GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, } - -int scheduler_multi_function_call(struct GNUNET_SCHEDULER_Task *t, int (*driver_func)()) -{ - if (t->fds_len > 1){ - int success = GNUNET_YES; - for (int i = 0; i < t->fds_len;i++){ - success = driver_func(scheduler_driver->cls, t , t->fds+i) && success; - } - return success; - }else{ - return driver_func(scheduler_driver->cls, t , t->fds); - } -} - /** * Schedule a new task to be run with a specified delay or when any of * the specified file descriptor sets is ready. The delay can be used @@ -1466,8 +1467,8 @@ add_without_sets (struct GNUNET_TIME_Relative delay, GNUNET_assert (NULL != active_task); GNUNET_assert (NULL != task); - t= initFdInfo (read_nh, write_nh, read_fh, write_fh); - + t = GNUNET_new (struct GNUNET_SCHEDULER_Task); + initFdInfo (t, read_nh, write_nh, read_fh, write_fh); t->callback = task; t->callback_cls = task_cls; #if DEBUG_FDS @@ -1505,11 +1506,10 @@ add_without_sets (struct GNUNET_TIME_Relative delay, t->timeout = GNUNET_TIME_relative_to_absolute (delay); t->priority = check_priority ((priority == GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : priority); t->lifeness = current_lifeness; - - - + GNUNET_CONTAINER_DLL_insert (pending_head, + pending_tail, + t); scheduler_multi_function_call(t, scheduler_driver->add); - max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -2103,40 +2103,34 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, int select_add(void *cls, - struct GNUNET_SCHEDULER_Task *task, - struct GNUNET_SCHEDULER_FdInfo *fdi){ - - GNUNET_CONTAINER_DLL_insert (pending_head, - pending_tail, - task); - + struct GNUNET_SCHEDULER_Task *task, + struct GNUNET_SCHEDULER_FdInfo *fdi) +{ + return GNUNET_OK; } + int select_del(void *cls, - struct GNUNET_SCHEDULER_Task *task, - struct GNUNET_SCHEDULER_FdInfo *fdi){ - - GNUNET_CONTAINER_DLL_remove (pending_head, - pending_tail, - task); - + struct GNUNET_SCHEDULER_Task *task, + struct GNUNET_SCHEDULER_FdInfo *fdi) +{ + return GNUNET_OK; } int select_loop(void *cls, - struct GNUNET_SCHEDULER_Handle *sh){ - - while_live(sh->rs, sh->ws); - + struct GNUNET_SCHEDULER_Handle *sh) +{ + return while_live(sh->rs, sh->ws); } + static void select_set_wakeup(void *cls, - struct GNUNET_TIME_Absolute dt){ - - + struct GNUNET_TIME_Absolute dt) +{ } -- cgit v1.2.3 From 290af4d573924059c0492eacb8a5e67a849d94d6 Mon Sep 17 00:00:00 2001 From: lurchi Date: Sat, 5 Aug 2017 13:38:45 +0200 Subject: add missing DLL insert --- src/util/scheduler.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 7a65069a2..3da4eaddb 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -1829,9 +1829,10 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : prio); t->lifeness = current_lifeness; - + GNUNET_CONTAINER_DLL_insert (pending_head, + pending_tail, + t); scheduler_multi_function_call(t, scheduler_driver->add); - max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, -- cgit v1.2.3 From b60af34ef8ec413af4eea572ce211ab03a79ca17 Mon Sep 17 00:00:00 2001 From: lurchi Date: Sat, 5 Aug 2017 16:31:09 +0200 Subject: fix segfault and pending_timeout logic --- src/util/scheduler.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 3da4eaddb..42309c199 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -536,10 +536,11 @@ check_ready (const struct GNUNET_NETWORK_FDSet *rs, pos->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; if (0 == pos->reason) break; + scheduler_driver->set_wakeup (scheduler_driver->cls, + pending_timeout_head->timeout); GNUNET_CONTAINER_DLL_remove (pending_timeout_head, pending_timeout_tail, pos); - scheduler_driver->set_wakeup(scheduler_driver->cls,pending_timeout_head->timeout); if (pending_timeout_last == pos) pending_timeout_last = NULL; queue_ready_task (pos); @@ -1065,14 +1066,20 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) (NULL == task->write_set) ) { if (GNUNET_YES == task->on_shutdown) - GNUNET_CONTAINER_DLL_remove (shutdown_head, - shutdown_tail, - task); + GNUNET_CONTAINER_DLL_remove (shutdown_head, + shutdown_tail, + task); else - GNUNET_CONTAINER_DLL_remove (pending_timeout_head, - pending_timeout_tail, - task); - scheduler_driver->set_wakeup(scheduler_driver->cls,pending_timeout_head->timeout); + { + GNUNET_CONTAINER_DLL_remove (pending_timeout_head, + pending_timeout_tail, + task); + if (pending_timeout_last == task) + pending_timeout_last = NULL; + else + scheduler_driver->set_wakeup (scheduler_driver->cls, + pending_timeout_head->timeout); + } if (task == pending_timeout_last) pending_timeout_last = NULL; } @@ -2082,7 +2089,7 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, GNUNET_NETWORK_fdset_handle_set (sh.rs, pr); sh.driver = driver; ret = driver->loop (driver->cls, - &sh); + &sh); GNUNET_NETWORK_fdset_destroy (sh.rs); GNUNET_NETWORK_fdset_destroy (sh.ws); @@ -2128,7 +2135,7 @@ select_loop(void *cls, } -static void +void select_set_wakeup(void *cls, struct GNUNET_TIME_Absolute dt) { -- cgit v1.2.3 From b1e413857618caed22d882da06d38bde79592d02 Mon Sep 17 00:00:00 2001 From: t3sserakt Date: Tue, 8 Aug 2017 18:30:33 +0200 Subject: Smaller changes. Changed order when set_wakeup is called after some task is removed from pending_timeout --- src/util/scheduler.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 42309c199..e90763fb4 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -536,13 +536,15 @@ check_ready (const struct GNUNET_NETWORK_FDSet *rs, pos->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; if (0 == pos->reason) break; - scheduler_driver->set_wakeup (scheduler_driver->cls, - pending_timeout_head->timeout); + GNUNET_CONTAINER_DLL_remove (pending_timeout_head, pending_timeout_tail, pos); if (pending_timeout_last == pos) pending_timeout_last = NULL; + else + scheduler_driver->set_wakeup (scheduler_driver->cls, + pending_timeout_head->timeout); queue_ready_task (pos); } pos = pending_head; @@ -1080,6 +1082,7 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) scheduler_driver->set_wakeup (scheduler_driver->cls, pending_timeout_head->timeout); } + //TODO check if this is redundant if (task == pending_timeout_last) pending_timeout_last = NULL; } @@ -1920,9 +1923,12 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) GNUNET_CONTAINER_DLL_remove (pending_timeout_head, pending_timeout_tail, pos); - scheduler_driver->set_wakeup(scheduler_driver->cls,pending_timeout_head->timeout); + if (pending_timeout_last == pos) pending_timeout_last = NULL; + else + scheduler_driver->set_wakeup(scheduler_driver->cls,pending_timeout_head->timeout); + queue_ready_task (pos); } -- cgit v1.2.3 From 6a1cd49f753ee946599266d0265afdd9ba20e68e Mon Sep 17 00:00:00 2001 From: lurchi Date: Tue, 8 Aug 2017 18:35:53 +0200 Subject: separate the select driver's fd sets from the driver-internal fdsets --- src/include/gnunet_scheduler_lib.h | 2 +- src/util/scheduler.c | 849 ++++++++++++++++++------------------- 2 files changed, 407 insertions(+), 444 deletions(-) (limited to 'src/util') diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h index 837a23ba5..68a5ac534 100644 --- a/src/include/gnunet_scheduler_lib.h +++ b/src/include/gnunet_scheduler_lib.h @@ -359,7 +359,7 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, * * @return NULL on error */ -const struct GNUNET_SCHEDULER_Driver * +struct GNUNET_SCHEDULER_Driver * GNUNET_SCHEDULER_driver_select (void); diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 42309c199..7cd42dcea 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -89,12 +89,6 @@ struct GNUNET_SCHEDULER_Handle * @deprecated */ struct GNUNET_NETWORK_FDSet *ws; - - /** - * Driver we used for the event loop. - */ - const struct GNUNET_SCHEDULER_Driver *driver; - }; @@ -123,11 +117,6 @@ struct GNUNET_SCHEDULER_Task */ void *callback_cls; - /** - * Handle to the scheduler's state. - */ - const struct GNUNET_SCHEDULER_Handle *sh; - /** * Set of file descriptors this task is waiting * for for reading. Once ready, this is updated @@ -224,9 +213,38 @@ struct GNUNET_SCHEDULER_Task int num_backtrace_strings; #endif +}; + + +struct Scheduled +{ + struct Scheduled *prev; + + struct Scheduled *next; + + struct GNUNET_SCHEDULER_Task *task; + struct GNUNET_SCHEDULER_FdInfo *fdi; }; + +/** + * Driver context used by GNUNET_SCHEDULER_run + */ +struct DriverContext +{ + struct Scheduled *scheduled_in_head; + + struct Scheduled *scheduled_in_tail; + + struct Scheduled *scheduled_out_head; + + struct Scheduled *scheduled_out_tail; + + struct GNUNET_TIME_Relative timeout; +}; + + /** * The driver used for the event loop. Will be handed over to * the scheduler in #GNUNET_SCHEDULER_run_from_driver(), peristed @@ -338,6 +356,11 @@ static struct GNUNET_SCHEDULER_TaskContext tc; */ static void *scheduler_select_cls; +/** + * Scheduler handle used for the driver functions + */ +static struct GNUNET_SCHEDULER_Handle sh; + /** * Sets the select function to use in the scheduler (scheduler_select). @@ -372,127 +395,44 @@ check_priority (enum GNUNET_SCHEDULER_Priority p) /** - * Update all sets and timeout for select. - * - * @param rs read-set, set to all FDs we would like to read (updated) - * @param ws write-set, set to all FDs we would like to write (updated) - * @param timeout next timeout (updated) + * chooses the nearest timeout from all pending tasks, to be used + * to tell the driver the next wakeup time (using its set_wakeup + * callback) */ -void getNextPendingTimeout(struct GNUNET_TIME_Relative *timeout) +struct GNUNET_TIME_Absolute +get_timeout () { - struct GNUNET_SCHEDULER_Task *pos; struct GNUNET_TIME_Absolute now; - struct GNUNET_TIME_Relative to; + struct GNUNET_TIME_Absolute timeout; - now = GNUNET_TIME_absolute_get (); pos = pending_timeout_head; + now = GNUNET_TIME_absolute_get (); + timeout = GNUNET_TIME_UNIT_FOREVER_ABS; if (NULL != pos) { - to = GNUNET_TIME_absolute_get_difference (now, pos->timeout); - if (timeout->rel_value_us > to.rel_value_us) - *timeout = to; if (0 != pos->reason) - *timeout = GNUNET_TIME_UNIT_ZERO; + { + timeout = now; + } + else + { + timeout = pos->timeout; + } } -} - -static void -update_sets (struct GNUNET_NETWORK_FDSet *rs, - struct GNUNET_NETWORK_FDSet *ws, - struct GNUNET_TIME_Relative *timeout) -{ - struct GNUNET_SCHEDULER_Task *pos; - struct GNUNET_TIME_Absolute now; - struct GNUNET_TIME_Relative to; - - now = GNUNET_TIME_absolute_get (); - - getNextPendingTimeout(timeout); for (pos = pending_head; NULL != pos; pos = pos->next) { - if (pos->timeout.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) + if (0 != pos->reason) { - to = GNUNET_TIME_absolute_get_difference (now, pos->timeout); - if (timeout->rel_value_us > to.rel_value_us) - *timeout = to; + timeout = now; + } + else if ((pos->timeout.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) && + (timeout.abs_value_us > pos->timeout.abs_value_us)) + { + timeout = pos->timeout; } - if (-1 != pos->read_fd) - GNUNET_NETWORK_fdset_set_native (rs, pos->read_fd); - if (-1 != pos->write_fd) - GNUNET_NETWORK_fdset_set_native (ws, pos->write_fd); - if (NULL != pos->read_set) - GNUNET_NETWORK_fdset_add (rs, pos->read_set); - if (NULL != pos->write_set) - GNUNET_NETWORK_fdset_add (ws, pos->write_set); - if (0 != pos->reason) - *timeout = GNUNET_TIME_UNIT_ZERO; - } -} - - -/** - * Check if the ready set overlaps with the set we want to have ready. - * If so, update the want set (set all FDs that are ready). If not, - * return #GNUNET_NO. - * - * @param ready set that is ready - * @param want set that we want to be ready - * @return #GNUNET_YES if there was some overlap - */ -static int -set_overlaps (const struct GNUNET_NETWORK_FDSet *ready, - struct GNUNET_NETWORK_FDSet *want) -{ - if ((NULL == want) || (NULL == ready)) - return GNUNET_NO; - if (GNUNET_NETWORK_fdset_overlap (ready, want)) - { - /* copy all over (yes, there maybe unrelated bits, - * but this should not hurt well-written clients) */ - GNUNET_NETWORK_fdset_copy (want, ready); - return GNUNET_YES; } - return GNUNET_NO; -} - - -/** - * Check if the given task is eligible to run now. - * Also set the reason why it is eligible. - * - * @param task task to check if it is ready - * @param now the current time - * @param rs set of FDs ready for reading - * @param ws set of FDs ready for writing - * @return #GNUNET_YES if we can run it, #GNUNET_NO if not. - */ -static int -is_ready (struct GNUNET_SCHEDULER_Task *task, - struct GNUNET_TIME_Absolute now, - const struct GNUNET_NETWORK_FDSet *rs, - const struct GNUNET_NETWORK_FDSet *ws) -{ - enum GNUNET_SCHEDULER_Reason reason; - - reason = task->reason; - if (now.abs_value_us >= task->timeout.abs_value_us) - reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; - if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) && - (((task->read_fd != -1) && - (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (rs, task->read_fd))) || - (set_overlaps (rs, task->read_set)))) - reason |= GNUNET_SCHEDULER_REASON_READ_READY; - if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) && - (((task->write_fd != -1) && - (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (ws, task->write_fd))) - || (set_overlaps (ws, task->write_set)))) - reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; - if (0 == reason) - return GNUNET_NO; /* not ready */ - reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; - task->reason = reason; - return GNUNET_YES; + return timeout; } @@ -514,53 +454,6 @@ queue_ready_task (struct GNUNET_SCHEDULER_Task *task) } -/** - * Check which tasks are ready and move them - * to the respective ready queue. - * - * @param rs FDs ready for reading - * @param ws FDs ready for writing - */ -static void -check_ready (const struct GNUNET_NETWORK_FDSet *rs, - const struct GNUNET_NETWORK_FDSet *ws) -{ - struct GNUNET_SCHEDULER_Task *pos; - struct GNUNET_SCHEDULER_Task *next; - struct GNUNET_TIME_Absolute now; - - now = GNUNET_TIME_absolute_get (); - while (NULL != (pos = pending_timeout_head)) - { - if (now.abs_value_us >= pos->timeout.abs_value_us) - pos->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; - if (0 == pos->reason) - break; - scheduler_driver->set_wakeup (scheduler_driver->cls, - pending_timeout_head->timeout); - GNUNET_CONTAINER_DLL_remove (pending_timeout_head, - pending_timeout_tail, - pos); - if (pending_timeout_last == pos) - pending_timeout_last = NULL; - queue_ready_task (pos); - } - pos = pending_head; - while (NULL != pos) - { - next = pos->next; - if (GNUNET_YES == is_ready (pos, now, rs, ws)) - { - GNUNET_CONTAINER_DLL_remove (pending_head, - pending_tail, - pos); - queue_ready_task (pos); - } - pos = next; - } -} - - /** * Request the shutdown of a scheduler. Marks all tasks * awaiting shutdown as ready. Note that tasks @@ -614,7 +507,7 @@ dump_backtrace (struct GNUNET_SCHEDULER_Task *t) unsigned int i; for (i = 0; i < t->num_backtrace_strings; i++) - LOG (GNUNET_ERROR_TYPE_DEBUG, + LOG (GNUNET_ERROR_TYPE_WARNING, "Task %p trace %u: %s\n", t, i, @@ -623,82 +516,6 @@ dump_backtrace (struct GNUNET_SCHEDULER_Task *t) } -/** - * Run at least one task in the highest-priority queue that is not - * empty. Keep running tasks until we are either no longer running - * "URGENT" tasks or until we have at least one "pending" task (which - * may become ready, hence we should select on it). Naturally, if - * there are no more ready tasks, we also return. - * - * @param rs FDs ready for reading - * @param ws FDs ready for writing - */ -static void -run_ready (struct GNUNET_NETWORK_FDSet *rs, - struct GNUNET_NETWORK_FDSet *ws) -{ - enum GNUNET_SCHEDULER_Priority p; - struct GNUNET_SCHEDULER_Task *pos; - - max_priority_added = GNUNET_SCHEDULER_PRIORITY_KEEP; - do - { - if (0 == ready_count) - return; - GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]); - /* yes, p>0 is correct, 0 is "KEEP" which should - * always be an empty queue (see assertion)! */ - for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--) - { - pos = ready_head[p]; - if (NULL != pos) - break; - } - GNUNET_assert (NULL != pos); /* ready_count wrong? */ - GNUNET_CONTAINER_DLL_remove (ready_head[p], - ready_tail[p], - pos); - ready_count--; - current_priority = pos->priority; - current_lifeness = pos->lifeness; - active_task = pos; -#if PROFILE_DELAYS - if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us > - DELAY_THRESHOLD.rel_value_us) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Task %p took %s to be scheduled\n", - pos, - GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), - GNUNET_YES)); - } -#endif - tc.reason = pos->reason; - tc.read_ready = (NULL == pos->read_set) ? rs : pos->read_set; - if ((-1 != pos->read_fd) && - (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY))) - GNUNET_NETWORK_fdset_set_native (rs, pos->read_fd); - tc.write_ready = (NULL == pos->write_set) ? ws : pos->write_set; - if ((-1 != pos->write_fd) && - (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))) - GNUNET_NETWORK_fdset_set_native (ws, pos->write_fd); - if ((0 != (tc.reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) && - (-1 != pos->write_fd) && - (!GNUNET_NETWORK_fdset_test_native (ws, pos->write_fd))) - GNUNET_assert (0); // added to ready in previous select loop! - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Running task: %p\n", - pos); - pos->callback (pos->callback_cls); - dump_backtrace (pos); - active_task = NULL; - destroy_task (pos); - tasks_run++; - } - while ((NULL == pending_head) || (p >= max_priority_added)); -} - - /** * Pipe used to communicate shutdown via signal. */ @@ -766,152 +583,31 @@ sighandler_shutdown () * @return #GNUNET_OK to continue the main loop, * #GNUNET_NO to exit */ -static int -check_lifeness () -{ - struct GNUNET_SCHEDULER_Task *t; - - if (ready_count > 0) - return GNUNET_OK; - for (t = pending_head; NULL != t; t = t->next) - if (t->lifeness == GNUNET_YES) - return GNUNET_OK; - for (t = shutdown_head; NULL != t; t = t->next) - if (t->lifeness == GNUNET_YES) - return GNUNET_OK; - for (t = pending_timeout_head; NULL != t; t = t->next) - if (t->lifeness == GNUNET_YES) - return GNUNET_OK; - if (NULL != shutdown_head) - { - GNUNET_SCHEDULER_shutdown (); - return GNUNET_OK; - } - return GNUNET_NO; -} - +//static int +//check_lifeness () +//{ +// struct GNUNET_SCHEDULER_Task *t; +// +// if (ready_count > 0) +// return GNUNET_OK; +// for (t = pending_head; NULL != t; t = t->next) +// if (t->lifeness == GNUNET_YES) +// return GNUNET_OK; +// for (t = shutdown_head; NULL != t; t = t->next) +// if (t->lifeness == GNUNET_YES) +// return GNUNET_OK; +// for (t = pending_timeout_head; NULL != t; t = t->next) +// if (t->lifeness == GNUNET_YES) +// return GNUNET_OK; +// if (NULL != shutdown_head) +// { +// GNUNET_SCHEDULER_shutdown (); +// return GNUNET_OK; +// } +// return GNUNET_NO; +//} -int while_live(struct GNUNET_NETWORK_FDSet *rs, struct GNUNET_NETWORK_FDSet *ws) -{ - int ret; - unsigned int busy_wait_warning; - unsigned long long last_tr; - const struct GNUNET_DISK_FileHandle *pr; - char c; - struct GNUNET_TIME_Relative timeout; - - busy_wait_warning = 0; - pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle, - GNUNET_DISK_PIPE_END_READ); - GNUNET_assert (NULL != pr); - last_tr = 0; - - while (GNUNET_OK == check_lifeness ()) - { - GNUNET_NETWORK_fdset_zero (rs); - GNUNET_NETWORK_fdset_zero (ws); - timeout = GNUNET_TIME_UNIT_FOREVER_REL; - update_sets (rs, ws, &timeout); - GNUNET_NETWORK_fdset_handle_set (rs, pr); - if (ready_count > 0) - { - /* no blocking, more work already ready! */ - timeout = GNUNET_TIME_UNIT_ZERO; - } - if (NULL == scheduler_select) - ret = GNUNET_NETWORK_socket_select (rs, - ws, - NULL, - timeout); - else - ret = scheduler_select (scheduler_select_cls, - rs, - ws, - NULL, - timeout); - if (ret == GNUNET_SYSERR) - { - if (errno == EINTR) - continue; - - LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "select"); -#ifndef MINGW -#if USE_LSOF - char lsof[512]; - - snprintf (lsof, sizeof (lsof), "lsof -p %d", getpid ()); - (void) close (1); - (void) dup2 (2, 1); - if (0 != system (lsof)) - LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, - "system"); -#endif -#endif -#if DEBUG_FDS - struct GNUNET_SCHEDULER_Task *t; - - for (t = pending_head; NULL != t; t = t->next) - { - if (-1 != t->read_fd) - { - int flags = fcntl (t->read_fd, F_GETFD); - if ((flags == -1) && (errno == EBADF)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Got invalid file descriptor %d!\n", - t->read_fd); - dump_backtrace (t); - } - } - if (-1 != t->write_fd) - { - int flags = fcntl (t->write_fd, F_GETFD); - if ((flags == -1) && (errno == EBADF)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Got invalid file descriptor %d!\n", - t->write_fd); - dump_backtrace (t); - } - } - } -#endif - GNUNET_assert (0); - break; - } - - if ( (0 == ret) && - (0 == timeout.rel_value_us) && - (busy_wait_warning > 16) ) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "Looks like we're busy waiting...\n"); - short_wait (100); /* mitigate */ - } - check_ready (rs, ws); - run_ready (rs, ws); - if (GNUNET_NETWORK_fdset_handle_isset (rs, pr)) - { - /* consume the signal */ - GNUNET_DISK_file_read (pr, &c, sizeof (c)); - /* mark all active tasks as ready due to shutdown */ - GNUNET_SCHEDULER_shutdown (); - } - if (last_tr == tasks_run) - { - short_wait (1); - busy_wait_warning++; - } - else - { - last_tr = tasks_run; - busy_wait_warning = 0; - } - } - return ret; -} - /** * Initialize and run scheduler. This function will return when all * tasks have completed. On systems with signals, receiving a SIGTERM @@ -930,9 +626,19 @@ void GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, void *task_cls) { - - GNUNET_SCHEDULER_run_with_driver(GNUNET_SCHEDULER_driver_select (), task, task_cls); - + struct GNUNET_SCHEDULER_Driver *driver; + struct DriverContext context = {.scheduled_in_head = NULL, + .scheduled_in_tail = NULL, + .scheduled_out_head = NULL, + .scheduled_out_tail = NULL, + .timeout = GNUNET_TIME_UNIT_FOREVER_REL}; + + driver = GNUNET_SCHEDULER_driver_select (); + driver->cls = &context; + + GNUNET_SCHEDULER_run_with_driver (driver, task, task_cls); + + GNUNET_free (driver); } @@ -1010,39 +716,63 @@ initFdInfo(struct GNUNET_SCHEDULER_Task *t, { struct GNUNET_SCHEDULER_FdInfo read_fdi = { .fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = GNUNET_NETWORK_get_fd (read_nh)}; t->fdx = read_fdi; + t->fds = &t->fdx; } else if (NULL != write_nh) { struct GNUNET_SCHEDULER_FdInfo write_fdi = { .fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; t->fdx = write_fdi; + t->fds = &t->fdx; } else if (NULL != read_fh) { struct GNUNET_SCHEDULER_FdInfo read_fdi = { .fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fh->fd}; t->fdx = read_fdi; + t->fds = &t->fdx; } else if (NULL != write_fh) { struct GNUNET_SCHEDULER_FdInfo write_fdi = { .fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fh->fd}; t->fdx = write_fdi; + t->fds = &t->fdx; } } int scheduler_multi_function_call(struct GNUNET_SCHEDULER_Task *t, int (*driver_func)()) { - if (t->fds_len > 1){ + if (t->fds_len > 1) + { int success = GNUNET_YES; - for (int i = 0; i < t->fds_len;i++){ - success = driver_func(scheduler_driver->cls, t , t->fds+i) && success; + for (int i = 0; i < t->fds_len;i++) + { + success = driver_func (scheduler_driver->cls, t , t->fds+i) && success; } return success; - }else{ - return driver_func(scheduler_driver->cls, t , t->fds); + } + else + { + return driver_func (scheduler_driver->cls, t , t->fds); } } +void +shutdown_task (void *cls) +{ + char c; + const struct GNUNET_DISK_FileHandle *pr; + + pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle, + GNUNET_DISK_PIPE_END_READ); + GNUNET_assert (! GNUNET_DISK_handle_invalid (pr)); + /* consume the signal */ + GNUNET_DISK_file_read (pr, &c, sizeof (c)); + /* mark all active tasks as ready due to shutdown */ + GNUNET_SCHEDULER_shutdown (); +} + + /** * Cancel the task with the specified identifier. * The task must not yet have run. @@ -1078,7 +808,7 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) pending_timeout_last = NULL; else scheduler_driver->set_wakeup (scheduler_driver->cls, - pending_timeout_head->timeout); + get_timeout ()); } if (task == pending_timeout_last) pending_timeout_last = NULL; @@ -1099,10 +829,10 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) task); ready_count--; } - ret = task->callback_cls; - LOG (GNUNET_ERROR_TYPE_DEBUG, + LOG (GNUNET_ERROR_TYPE_WARNING, "Canceling task %p\n", task); + ret = task->callback_cls; destroy_task (task); return ret; } @@ -1161,7 +891,7 @@ GNUNET_SCHEDULER_add_with_reason_and_priority (GNUNET_SCHEDULER_TaskCallback tas t->reason = reason; t->priority = priority; t->lifeness = current_lifeness; - LOG (GNUNET_ERROR_TYPE_DEBUG, + LOG (GNUNET_ERROR_TYPE_WARNING, "Adding continuation task %p\n", t); init_backtrace (t); @@ -1211,7 +941,8 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, GNUNET_CONTAINER_DLL_insert (pending_timeout_head, pending_timeout_tail, t); - scheduler_driver->set_wakeup(scheduler_driver->cls,pending_timeout_head->timeout); + scheduler_driver->set_wakeup (scheduler_driver->cls, + at); } else { @@ -1236,11 +967,13 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, pending_timeout_tail, prev, t); + scheduler_driver->set_wakeup (scheduler_driver->cls, + get_timeout()); } /* finally, update heuristic insertion point to last insertion... */ pending_timeout_last = t; - LOG (GNUNET_ERROR_TYPE_DEBUG, + LOG (GNUNET_ERROR_TYPE_WARNING, "Adding task: %p\n", t); init_backtrace (t); @@ -1356,11 +1089,11 @@ GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, */ struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task, - void *task_cls) + void *task_cls) { return GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_ZERO, - task, - task_cls); + task, + task_cls); } @@ -1376,7 +1109,7 @@ GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task, */ struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task, - void *task_cls) + void *task_cls) { struct GNUNET_SCHEDULER_Task *t; @@ -1395,10 +1128,10 @@ GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task, t->on_shutdown = GNUNET_YES; t->lifeness = GNUNET_YES; GNUNET_CONTAINER_DLL_insert (shutdown_head, - shutdown_tail, - t); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Adding task: %p\n", + shutdown_tail, + t); + LOG (GNUNET_ERROR_TYPE_WARNING, + "Adding shutdown task: %p\n", t); init_backtrace (t); return t; @@ -1465,8 +1198,6 @@ add_without_sets (struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_Handle *write_nh, const struct GNUNET_DISK_FileHandle *read_fh, const struct GNUNET_DISK_FileHandle *write_fh, - //int rfd, - //int wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls) { @@ -1517,6 +1248,8 @@ add_without_sets (struct GNUNET_TIME_Relative delay, pending_tail, t); scheduler_multi_function_call(t, scheduler_driver->add); + scheduler_driver->set_wakeup (scheduler_driver->cls, + get_timeout ()); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1758,7 +1491,7 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, return ret; #else GNUNET_assert (on_read || on_write); - GNUNET_assert(fd->fd >= 0); + GNUNET_assert (fd->fd >= 0); return add_without_sets (delay, priority, NULL, NULL, @@ -1840,9 +1573,11 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, pending_tail, t); scheduler_multi_function_call(t, scheduler_driver->add); + scheduler_driver->set_wakeup (scheduler_driver->cls, + get_timeout ()); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); - LOG (GNUNET_ERROR_TYPE_DEBUG, + LOG (GNUNET_ERROR_TYPE_WARNING, "Adding task %p\n", t); init_backtrace (t); @@ -1862,11 +1597,15 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, */ void GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, - enum GNUNET_SCHEDULER_EventType et) + enum GNUNET_SCHEDULER_EventType et) { enum GNUNET_SCHEDULER_Reason reason; struct GNUNET_TIME_Absolute now; + LOG (GNUNET_ERROR_TYPE_WARNING, + "task ready: %p\n", + task); + now = GNUNET_TIME_absolute_get (); reason = task->reason; if (now.abs_value_us >= task->timeout.abs_value_us) @@ -1882,6 +1621,9 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, task->fds = &task->fdx; task->fdx.et = et; task->fds_len = 1; + GNUNET_CONTAINER_DLL_remove (pending_head, + pending_tail, + task); queue_ready_task (task); } @@ -1905,6 +1647,7 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, int GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) { + // FIXME: we have to check lifeness here! enum GNUNET_SCHEDULER_Priority p; struct GNUNET_SCHEDULER_Task *pos; struct GNUNET_TIME_Absolute now; @@ -1920,7 +1663,6 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) GNUNET_CONTAINER_DLL_remove (pending_timeout_head, pending_timeout_tail, pos); - scheduler_driver->set_wakeup(scheduler_driver->cls,pending_timeout_head->timeout); if (pending_timeout_last == pos) pending_timeout_last = NULL; queue_ready_task (pos); @@ -1957,7 +1699,7 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us > DELAY_THRESHOLD.rel_value_us) { - LOG (GNUNET_ERROR_TYPE_DEBUG, + LOG (GNUNET_ERROR_TYPE_WARNING, "Task %p took %s to be scheduled\n", pos, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), @@ -1979,8 +1721,8 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))) GNUNET_NETWORK_fdset_set_native (sh->ws, pos->write_fd); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Running task: %p\n", + LOG (GNUNET_ERROR_TYPE_WARNING, + "Running task from driver: %p\n", pos); pos->callback (pos->callback_cls); active_task = NULL; @@ -1988,6 +1730,8 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) destroy_task (pos); tasks_run++; } + scheduler_driver->set_wakeup (scheduler_driver->cls, + get_timeout ()); if (0 == ready_count) return GNUNET_NO; return GNUNET_OK; @@ -2012,11 +1756,10 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) */ int GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, - GNUNET_SCHEDULER_TaskCallback task, - void *task_cls) + GNUNET_SCHEDULER_TaskCallback task, + void *task_cls) { int ret; - struct GNUNET_SCHEDULER_Handle sh; struct GNUNET_SIGNAL_Context *shc_int; struct GNUNET_SIGNAL_Context *shc_term; #if (SIGTERM != GNUNET_TERM_SIG) @@ -2029,7 +1772,6 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, #endif struct GNUNET_SCHEDULER_Task tsk; const struct GNUNET_DISK_FileHandle *pr; - scheduler_driver = driver; /* general set-up */ GNUNET_assert (NULL == active_task); @@ -2041,11 +1783,11 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, GNUNET_assert (NULL != shutdown_pipe_handle); pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_READ); - GNUNET_assert (NULL != pr); my_pid = getpid (); + scheduler_driver = driver; /* install signal handlers */ - LOG (GNUNET_ERROR_TYPE_DEBUG, + LOG (GNUNET_ERROR_TYPE_WARNING, "Registering signal handlers\n"); shc_int = GNUNET_SIGNAL_handler_install (SIGINT, &sighandler_shutdown); @@ -2071,7 +1813,6 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, 0, sizeof (tsk)); active_task = &tsk; - tsk.sh = &sh; GNUNET_SCHEDULER_add_with_reason_and_priority (task, task_cls, GNUNET_SCHEDULER_REASON_STARTUP, @@ -2079,17 +1820,19 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO, &GNUNET_OS_install_parent_control_handler, NULL); + GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + pr, + &shutdown_task, + NULL); active_task = NULL; - driver->set_wakeup (driver->cls, - GNUNET_TIME_absolute_get ()); - /* begin main event loop */ sh.rs = GNUNET_NETWORK_fdset_create (); sh.ws = GNUNET_NETWORK_fdset_create (); - GNUNET_NETWORK_fdset_handle_set (sh.rs, pr); - sh.driver = driver; + //GNUNET_NETWORK_fdset_handle_set (sh.rs, pr); ret = driver->loop (driver->cls, &sh); + LOG (GNUNET_ERROR_TYPE_WARNING, + "loop finished!"); GNUNET_NETWORK_fdset_destroy (sh.rs); GNUNET_NETWORK_fdset_destroy (sh.ws); @@ -2109,29 +1852,249 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, return ret; } + int -select_add(void *cls, - struct GNUNET_SCHEDULER_Task *task, - struct GNUNET_SCHEDULER_FdInfo *fdi) +select_add (void *cls, + struct GNUNET_SCHEDULER_Task *task, + struct GNUNET_SCHEDULER_FdInfo *fdi) { + struct DriverContext *context = cls; + GNUNET_assert (NULL != context); + + if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (0 >= fdi->sock)) + { + /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */ + return GNUNET_SYSERR; + } + + struct Scheduled *scheduled = GNUNET_new (struct Scheduled); + scheduled->task = task; + scheduled->fdi = fdi; + + switch (fdi->et) + { + case GNUNET_SCHEDULER_ET_IN: + { + GNUNET_CONTAINER_DLL_insert (context->scheduled_in_head, + context->scheduled_in_tail, + scheduled); + break; + } + case GNUNET_SCHEDULER_ET_OUT: + { + GNUNET_CONTAINER_DLL_insert (context->scheduled_out_head, + context->scheduled_out_tail, + scheduled); + break; + } + default: + { + // FIXME: other event types not implemented yet + GNUNET_assert (0); + } + } return GNUNET_OK; } int -select_del(void *cls, - struct GNUNET_SCHEDULER_Task *task, - struct GNUNET_SCHEDULER_FdInfo *fdi) +select_del (void *cls, + struct GNUNET_SCHEDULER_Task *task, + struct GNUNET_SCHEDULER_FdInfo *fdi) { - return GNUNET_OK; + struct DriverContext *context = cls; + GNUNET_assert (NULL != context); + + int ret = GNUNET_SYSERR; + struct Scheduled *pos; + switch (fdi->et) + { + case GNUNET_SCHEDULER_ET_IN: + { + for (pos = context->scheduled_in_head; NULL != pos; pos = pos->next) + { + if (pos->task == task) + { + GNUNET_CONTAINER_DLL_remove (context->scheduled_in_head, + context->scheduled_in_tail, + pos); + ret = GNUNET_OK; + } + } + break; + } + case GNUNET_SCHEDULER_ET_OUT: + { + for (pos = context->scheduled_out_head; NULL != pos; pos = pos->next) + { + if (pos->task == task) + { + GNUNET_CONTAINER_DLL_remove (context->scheduled_out_head, + context->scheduled_out_tail, + pos); + ret = GNUNET_OK; + } + } + break; + } + default: + { + // FIXME: other event types not implemented yet + GNUNET_assert (0); + } + } + return ret; } +//int +//select_loop_condition (const struct DriverContext *context) +//{ +// struct GNUNET_TIME_absolute_ +//} + + int -select_loop(void *cls, - struct GNUNET_SCHEDULER_Handle *sh) +select_loop (void *cls, + struct GNUNET_SCHEDULER_Handle *sh) { - return while_live(sh->rs, sh->ws); + struct GNUNET_NETWORK_FDSet *rs; + struct GNUNET_NETWORK_FDSet *ws; + struct DriverContext *context; + int select_result; + unsigned long long last_tr; + unsigned int busy_wait_warning; + + context = cls; + GNUNET_assert (NULL != context); + rs = GNUNET_NETWORK_fdset_create (); + ws = GNUNET_NETWORK_fdset_create (); + last_tr = 0; + busy_wait_warning = 0; + while ((NULL != context->scheduled_in_head) || + (NULL != context->scheduled_out_head)) + { + GNUNET_NETWORK_fdset_zero (rs); + GNUNET_NETWORK_fdset_zero (ws); + struct Scheduled *pos; + for (pos = context->scheduled_in_head; NULL != pos; pos = pos->next) + { + GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock); + } + for (pos = context->scheduled_out_head; NULL != pos; pos = pos->next) + { + GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock); + } + if (ready_count > 0) + { + /* no blocking, more work already ready! */ + context->timeout = GNUNET_TIME_UNIT_ZERO; + } + if (NULL == scheduler_select) + { + select_result = GNUNET_NETWORK_socket_select (rs, + ws, + NULL, + context->timeout); + } + else + { + select_result = scheduler_select (scheduler_select_cls, + rs, + ws, + NULL, + context->timeout); + } + if (select_result == GNUNET_SYSERR) + { + if (errno == EINTR) + continue; + + LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "select"); +#ifndef MINGW +#if USE_LSOF + char lsof[512]; + + snprintf (lsof, sizeof (lsof), "lsof -p %d", getpid ()); + (void) close (1); + (void) dup2 (2, 1); + if (0 != system (lsof)) + LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, + "system"); +#endif +#endif +#if DEBUG_FDS + struct GNUNET_SCHEDULER_Task *t; + for (t = pending_head; NULL != t; t = t->next) + { + if (-1 != t->read_fd) + { + int flags = fcntl (t->read_fd, F_GETFD); + if ((flags == -1) && (errno == EBADF)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Got invalid file descriptor %d!\n", + t->read_fd); + dump_backtrace (t); + } + } + if (-1 != t->write_fd) + { + int flags = fcntl (t->write_fd, F_GETFD); + if ((flags == -1) && (errno == EBADF)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Got invalid file descriptor %d!\n", + t->write_fd); + dump_backtrace (t); + } + } + } +#endif + GNUNET_assert (0); + return GNUNET_SYSERR; + } + if ( (0 == select_result) && + (0 == context->timeout.rel_value_us) && + (busy_wait_warning > 16) ) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Looks like we're busy waiting...\n"); + short_wait (100); /* mitigate */ + } + for (pos = context->scheduled_in_head; NULL != pos; pos = pos->next) + { + if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (rs, pos->fdi->sock)) + { + GNUNET_SCHEDULER_task_ready (pos->task, GNUNET_SCHEDULER_ET_IN); + GNUNET_CONTAINER_DLL_remove (context->scheduled_in_head, + context->scheduled_in_tail, + pos); + } + } + for (pos = context->scheduled_out_head; NULL != pos; pos = pos->next) + { + if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (ws, pos->fdi->sock)) + { + GNUNET_SCHEDULER_task_ready (pos->task, GNUNET_SCHEDULER_ET_OUT); + GNUNET_CONTAINER_DLL_remove (context->scheduled_out_head, + context->scheduled_out_tail, + pos); + } + } + GNUNET_SCHEDULER_run_from_driver (sh); + if (last_tr == tasks_run) + { + short_wait (1); + busy_wait_warning++; + } + else + { + last_tr = tasks_run; + busy_wait_warning = 0; + } + } + return GNUNET_OK; } @@ -2139,7 +2102,10 @@ void select_set_wakeup(void *cls, struct GNUNET_TIME_Absolute dt) { - + struct DriverContext *context = cls; + GNUNET_assert (NULL != context); + + context->timeout = GNUNET_TIME_absolute_get_remaining (dt); } @@ -2148,12 +2114,10 @@ select_set_wakeup(void *cls, * * @return NULL on error */ -const struct GNUNET_SCHEDULER_Driver * +struct GNUNET_SCHEDULER_Driver * GNUNET_SCHEDULER_driver_select () { - struct GNUNET_SCHEDULER_Driver *select_driver; - select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver); select_driver->loop = &select_loop; @@ -2161,7 +2125,6 @@ GNUNET_SCHEDULER_driver_select () select_driver->del = &select_del; select_driver->set_wakeup = &select_set_wakeup; - return select_driver; } -- cgit v1.2.3 From 8bff0082dd564946d184b5eb8f7e2b253e65aeee Mon Sep 17 00:00:00 2001 From: lurchi Date: Wed, 9 Aug 2017 13:28:45 +0200 Subject: fix indentation; remove unneeded set_wakeup call --- src/util/scheduler.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 68143d051..8a7155d07 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -1238,7 +1238,6 @@ add_without_sets (struct GNUNET_TIME_Relative delay, } } #endif - #if PROFILE_DELAYS t->start_time = GNUNET_TIME_absolute_get (); #endif @@ -1619,7 +1618,7 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; task->reason = reason; - task->fds = &task->fdx; + task->fds = &task->fdx; // FIXME: if task contains a list of fds, this is wrong! task->fdx.et = et; task->fds_len = 1; GNUNET_CONTAINER_DLL_remove (pending_head, @@ -1666,9 +1665,6 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) pos); if (pending_timeout_last == pos) pending_timeout_last = NULL; - else - scheduler_driver->set_wakeup(scheduler_driver->cls,pending_timeout_head->timeout); - queue_ready_task (pos); } @@ -1701,13 +1697,13 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) active_task = pos; #if PROFILE_DELAYS if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us > - DELAY_THRESHOLD.rel_value_us) + DELAY_THRESHOLD.rel_value_us) { LOG (GNUNET_ERROR_TYPE_WARNING, - "Task %p took %s to be scheduled\n", - pos, - GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), - GNUNET_YES)); + "Task %p took %s to be scheduled\n", + pos, + GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), + GNUNET_YES)); } #endif tc.reason = pos->reason; @@ -1717,17 +1713,17 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) tc.fds = pos->fds; tc.read_ready = (NULL == pos->read_set) ? sh->rs : pos->read_set; if ( (-1 != pos->read_fd) && - (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ) + (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ) GNUNET_NETWORK_fdset_set_native (sh->rs, - pos->read_fd); + pos->read_fd); tc.write_ready = (NULL == pos->write_set) ? sh->ws : pos->write_set; - if ((-1 != pos->write_fd) && - (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))) + if ( (-1 != pos->write_fd) && + (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ) GNUNET_NETWORK_fdset_set_native (sh->ws, - pos->write_fd); + pos->write_fd); LOG (GNUNET_ERROR_TYPE_WARNING, - "Running task from driver: %p\n", - pos); + "Running task from driver: %p\n", + pos); pos->callback (pos->callback_cls); active_task = NULL; dump_backtrace (pos); @@ -1832,7 +1828,7 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, /* begin main event loop */ sh.rs = GNUNET_NETWORK_fdset_create (); sh.ws = GNUNET_NETWORK_fdset_create (); - //GNUNET_NETWORK_fdset_handle_set (sh.rs, pr); + GNUNET_NETWORK_fdset_handle_set (sh.rs, pr); ret = driver->loop (driver->cls, &sh); LOG (GNUNET_ERROR_TYPE_WARNING, -- cgit v1.2.3 From 564ca7f14fce740e848b68bf78c358eca53d2c9e Mon Sep 17 00:00:00 2001 From: lurchi Date: Wed, 9 Aug 2017 13:50:09 +0200 Subject: fix initFdInfo; rename to init_fd_info --- src/util/scheduler.c | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 8a7155d07..c7471ee0b 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -684,57 +684,62 @@ GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) void -initFdInfo(struct GNUNET_SCHEDULER_Task *t, - const struct GNUNET_NETWORK_Handle *read_nh, - const struct GNUNET_NETWORK_Handle *write_nh, - const struct GNUNET_DISK_FileHandle *read_fh, - const struct GNUNET_DISK_FileHandle *write_fh) +init_fd_info (struct GNUNET_SCHEDULER_Task *t, + const struct GNUNET_NETWORK_Handle *read_nh, + const struct GNUNET_NETWORK_Handle *write_nh, + const struct GNUNET_DISK_FileHandle *read_fh, + const struct GNUNET_DISK_FileHandle *write_fh) { // either only network handles or only file handles are allowed GNUNET_assert (!((NULL != read_nh || NULL != write_nh) && (NULL != read_fh || NULL != write_fh))); if (NULL != read_nh && NULL != write_nh) { + struct GNUNET_SCHEDULER_FdInfo *fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); + struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = GNUNET_NETWORK_get_fd (read_nh)}; + struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; + fds[0] = read_fdi; + fds[1] = write_fdi; + t->fds = fds; t->fds_len = 2; - t->fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); - const struct GNUNET_SCHEDULER_FdInfo read_fdi = { .fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = GNUNET_NETWORK_get_fd (read_nh)}; - const struct GNUNET_SCHEDULER_FdInfo write_fdi = { .fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; - - const struct GNUNET_SCHEDULER_FdInfo array[2] = {read_fdi, write_fdi}; - t->fds = array; } else if (NULL != read_fh && NULL != write_fh) { + struct GNUNET_SCHEDULER_FdInfo *fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); + struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fh->fd}; + struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fh->fd}; + fds[0] = read_fdi; + fds[1] = write_fdi; + t->fds = fds; t->fds_len = 2; - t->fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); - const struct GNUNET_SCHEDULER_FdInfo read_fdi = { .fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN}; - const struct GNUNET_SCHEDULER_FdInfo write_fdi = { .fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; - const struct GNUNET_SCHEDULER_FdInfo array[2] = {read_fdi, write_fdi}; - t->fds = array; } else if (NULL != read_nh) { - struct GNUNET_SCHEDULER_FdInfo read_fdi = { .fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = GNUNET_NETWORK_get_fd (read_nh)}; + struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = GNUNET_NETWORK_get_fd (read_nh)}; t->fdx = read_fdi; t->fds = &t->fdx; + t->read_fd = t->fdx.sock; } else if (NULL != write_nh) { - struct GNUNET_SCHEDULER_FdInfo write_fdi = { .fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; + struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; t->fdx = write_fdi; t->fds = &t->fdx; + t->write_fd = t->fdx.sock; } else if (NULL != read_fh) { - struct GNUNET_SCHEDULER_FdInfo read_fdi = { .fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fh->fd}; + struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fh->fd}; t->fdx = read_fdi; t->fds = &t->fdx; + t->read_fd = t->fdx.sock; } else if (NULL != write_fh) { - struct GNUNET_SCHEDULER_FdInfo write_fdi = { .fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fh->fd}; + struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fh->fd}; t->fdx = write_fdi; t->fds = &t->fdx; + t->write_fd = t->fdx.sock; } } @@ -1207,7 +1212,7 @@ add_without_sets (struct GNUNET_TIME_Relative delay, GNUNET_assert (NULL != active_task); GNUNET_assert (NULL != task); t = GNUNET_new (struct GNUNET_SCHEDULER_Task); - initFdInfo (t, read_nh, write_nh, read_fh, write_fh); + init_fd_info (t, read_nh, write_nh, read_fh, write_fh); t->callback = task; t->callback_cls = task_cls; #if DEBUG_FDS -- cgit v1.2.3 From b44cf84da67b78b4022009321a01376d74530685 Mon Sep 17 00:00:00 2001 From: lurchi Date: Wed, 9 Aug 2017 19:21:30 +0200 Subject: lifeness checks; shutdown now working; checkSignal not passing yet --- src/util/scheduler.c | 129 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 51 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index c7471ee0b..e1b6b4b51 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -583,29 +583,29 @@ sighandler_shutdown () * @return #GNUNET_OK to continue the main loop, * #GNUNET_NO to exit */ -//static int -//check_lifeness () -//{ -// struct GNUNET_SCHEDULER_Task *t; -// -// if (ready_count > 0) -// return GNUNET_OK; -// for (t = pending_head; NULL != t; t = t->next) -// if (t->lifeness == GNUNET_YES) -// return GNUNET_OK; -// for (t = shutdown_head; NULL != t; t = t->next) -// if (t->lifeness == GNUNET_YES) -// return GNUNET_OK; -// for (t = pending_timeout_head; NULL != t; t = t->next) -// if (t->lifeness == GNUNET_YES) -// return GNUNET_OK; -// if (NULL != shutdown_head) -// { -// GNUNET_SCHEDULER_shutdown (); -// return GNUNET_OK; -// } -// return GNUNET_NO; -//} +static int +check_lifeness () +{ + struct GNUNET_SCHEDULER_Task *t; + + if (ready_count > 0) + return GNUNET_OK; + for (t = pending_head; NULL != t; t = t->next) + if (t->lifeness == GNUNET_YES) + return GNUNET_OK; + for (t = shutdown_head; NULL != t; t = t->next) + if (t->lifeness == GNUNET_YES) + return GNUNET_OK; + for (t = pending_timeout_head; NULL != t; t = t->next) + if (t->lifeness == GNUNET_YES) + return GNUNET_OK; + if (NULL != shutdown_head) + { + GNUNET_SCHEDULER_shutdown (); + return GNUNET_OK; + } + return GNUNET_NO; +} /** @@ -1652,7 +1652,6 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, int GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) { - // FIXME: we have to check lifeness here! enum GNUNET_SCHEDULER_Priority p; struct GNUNET_SCHEDULER_Task *pos; struct GNUNET_TIME_Absolute now; @@ -1735,10 +1734,29 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) destroy_task (pos); tasks_run++; } - scheduler_driver->set_wakeup (scheduler_driver->cls, - get_timeout ()); + if (GNUNET_NO == check_lifeness ()) + { + /* cancel fd tasks without lifeness */ + pos = pending_head; + while (NULL != pos) + { + struct GNUNET_SCHEDULER_Task *tsk = pos; + pos = pos->next; + if (GNUNET_NO == tsk->lifeness) + { + GNUNET_SCHEDULER_cancel (tsk); + } + } + //sighandler_shutdown(); + } if (0 == ready_count) + { + scheduler_driver->set_wakeup (scheduler_driver->cls, + get_timeout ()); return GNUNET_NO; + } + scheduler_driver->set_wakeup (scheduler_driver->cls, + GNUNET_TIME_absolute_get ()); return GNUNET_OK; } @@ -1812,23 +1830,40 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, #endif /* Setup initial tasks */ + //current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; + //current_lifeness = GNUNET_YES; + //memset (&tsk, + // 0, + // sizeof (tsk)); + //active_task = &tsk; + //GNUNET_SCHEDULER_add_with_reason_and_priority (task, + // task_cls, + // GNUNET_SCHEDULER_REASON_STARTUP, + // GNUNET_SCHEDULER_PRIORITY_DEFAULT); + //GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO, + // &GNUNET_OS_install_parent_control_handler, + // NULL); + //GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + // pr, + // &shutdown_task, + // NULL); current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; - current_lifeness = GNUNET_YES; + current_lifeness = GNUNET_NO; memset (&tsk, 0, sizeof (tsk)); active_task = &tsk; - GNUNET_SCHEDULER_add_with_reason_and_priority (task, - task_cls, - GNUNET_SCHEDULER_REASON_STARTUP, - GNUNET_SCHEDULER_PRIORITY_DEFAULT); - GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO, - &GNUNET_OS_install_parent_control_handler, - NULL); + GNUNET_SCHEDULER_add_now (&GNUNET_OS_install_parent_control_handler, + NULL); GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, pr, &shutdown_task, NULL); + current_lifeness = GNUNET_YES; + GNUNET_SCHEDULER_add_with_reason_and_priority (task, + task_cls, + GNUNET_SCHEDULER_REASON_STARTUP, + GNUNET_SCHEDULER_PRIORITY_DEFAULT); active_task = NULL; /* begin main event loop */ sh.rs = GNUNET_NETWORK_fdset_create (); @@ -1837,7 +1872,7 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, ret = driver->loop (driver->cls, &sh); LOG (GNUNET_ERROR_TYPE_WARNING, - "loop finished!"); + "loop finished!\n"); GNUNET_NETWORK_fdset_destroy (sh.rs); GNUNET_NETWORK_fdset_destroy (sh.ws); @@ -1912,6 +1947,7 @@ select_del (void *cls, int ret = GNUNET_SYSERR; struct Scheduled *pos; + // FIXME: are multiple ORed event types allowed? switch (fdi->et) { case GNUNET_SCHEDULER_ET_IN: @@ -1952,13 +1988,6 @@ select_del (void *cls, } -//int -//select_loop_condition (const struct DriverContext *context) -//{ -// struct GNUNET_TIME_absolute_ -//} - - int select_loop (void *cls, struct GNUNET_SCHEDULER_Handle *sh) @@ -1976,8 +2005,7 @@ select_loop (void *cls, ws = GNUNET_NETWORK_fdset_create (); last_tr = 0; busy_wait_warning = 0; - while ((NULL != context->scheduled_in_head) || - (NULL != context->scheduled_out_head)) + while ((NULL != context->scheduled_in_head) || (NULL != context->scheduled_out_head)) { GNUNET_NETWORK_fdset_zero (rs); GNUNET_NETWORK_fdset_zero (ws); @@ -1990,11 +2018,6 @@ select_loop (void *cls, { GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock); } - if (ready_count > 0) - { - /* no blocking, more work already ready! */ - context->timeout = GNUNET_TIME_UNIT_ZERO; - } if (NULL == scheduler_select) { select_result = GNUNET_NETWORK_socket_select (rs, @@ -2071,20 +2094,20 @@ select_loop (void *cls, { if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (rs, pos->fdi->sock)) { - GNUNET_SCHEDULER_task_ready (pos->task, GNUNET_SCHEDULER_ET_IN); GNUNET_CONTAINER_DLL_remove (context->scheduled_in_head, context->scheduled_in_tail, pos); + GNUNET_SCHEDULER_task_ready (pos->task, GNUNET_SCHEDULER_ET_IN); } } for (pos = context->scheduled_out_head; NULL != pos; pos = pos->next) { if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (ws, pos->fdi->sock)) { - GNUNET_SCHEDULER_task_ready (pos->task, GNUNET_SCHEDULER_ET_OUT); GNUNET_CONTAINER_DLL_remove (context->scheduled_out_head, context->scheduled_out_tail, pos); + GNUNET_SCHEDULER_task_ready (pos->task, GNUNET_SCHEDULER_ET_OUT); } } GNUNET_SCHEDULER_run_from_driver (sh); @@ -2098,6 +2121,10 @@ select_loop (void *cls, last_tr = tasks_run; busy_wait_warning = 0; } + LOG (GNUNET_ERROR_TYPE_WARNING, + "scheduled_in_head = %p, scheduled_out_head = %p\n", + context->scheduled_in_head, + context->scheduled_out_head); } return GNUNET_OK; } -- cgit v1.2.3 From 850ba0f677939b740ccff2d4dcaabe028ff5faf2 Mon Sep 17 00:00:00 2001 From: lurchi Date: Wed, 9 Aug 2017 22:24:25 +0200 Subject: test_scheduler passing; new API function GNUNET_SCHEDULER_check_lifeness --- src/include/gnunet_scheduler_lib.h | 15 ++++++++ src/util/scheduler.c | 72 ++++++++------------------------------ 2 files changed, 30 insertions(+), 57 deletions(-) (limited to 'src/util') diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h index 68a5ac534..dea0a006a 100644 --- a/src/include/gnunet_scheduler_lib.h +++ b/src/include/gnunet_scheduler_lib.h @@ -382,6 +382,21 @@ typedef int struct GNUNET_TIME_Relative timeout); +/** + * Check if the system has initiated shutdown. This means no tasks + * that prevent shutdown were present and all tasks added with + * #GNUNET_SCHEDULER_add_shutdown were run already. + * + * Can be used by external event loop implementations to decide + * whether to keep running or not. + * + * @return #GNUNET_YES if tasks which prevent shutdown exist + * #GNUNET_NO if the system has initiated shutdown + */ +int +GNUNET_SCHEDULER_check_lifeness (); + + /** * Initialize and run scheduler. This function will return when all * tasks have completed. On systems with signals, receiving a SIGTERM diff --git a/src/util/scheduler.c b/src/util/scheduler.c index e1b6b4b51..f2fdbef2b 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -583,8 +583,8 @@ sighandler_shutdown () * @return #GNUNET_OK to continue the main loop, * #GNUNET_NO to exit */ -static int -check_lifeness () +int +GNUNET_SCHEDULER_check_lifeness () { struct GNUNET_SCHEDULER_Task *t; @@ -767,7 +767,7 @@ shutdown_task (void *cls) { char c; const struct GNUNET_DISK_FileHandle *pr; - + pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_READ); GNUNET_assert (! GNUNET_DISK_handle_invalid (pr)); @@ -835,7 +835,7 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) task); ready_count--; } - LOG (GNUNET_ERROR_TYPE_WARNING, + LOG (GNUNET_ERROR_TYPE_DEBUG, "Canceling task %p\n", task); ret = task->callback_cls; @@ -897,7 +897,7 @@ GNUNET_SCHEDULER_add_with_reason_and_priority (GNUNET_SCHEDULER_TaskCallback tas t->reason = reason; t->priority = priority; t->lifeness = current_lifeness; - LOG (GNUNET_ERROR_TYPE_WARNING, + LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding continuation task %p\n", t); init_backtrace (t); @@ -979,8 +979,8 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, /* finally, update heuristic insertion point to last insertion... */ pending_timeout_last = t; - LOG (GNUNET_ERROR_TYPE_WARNING, - "Adding task: %p\n", + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Adding task %p\n", t); init_backtrace (t); return t; @@ -1136,8 +1136,8 @@ GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task, GNUNET_CONTAINER_DLL_insert (shutdown_head, shutdown_tail, t); - LOG (GNUNET_ERROR_TYPE_WARNING, - "Adding shutdown task: %p\n", + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Adding shutdown task %p\n", t); init_backtrace (t); return t; @@ -1582,7 +1582,7 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, get_timeout ()); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); - LOG (GNUNET_ERROR_TYPE_WARNING, + LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding task %p\n", t); init_backtrace (t); @@ -1607,10 +1607,6 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, enum GNUNET_SCHEDULER_Reason reason; struct GNUNET_TIME_Absolute now; - LOG (GNUNET_ERROR_TYPE_WARNING, - "task ready: %p\n", - task); - now = GNUNET_TIME_absolute_get (); reason = task->reason; if (now.abs_value_us >= task->timeout.abs_value_us) @@ -1703,7 +1699,7 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us > DELAY_THRESHOLD.rel_value_us) { - LOG (GNUNET_ERROR_TYPE_WARNING, + LOG (GNUNET_ERROR_TYPE_DEBUG, "Task %p took %s to be scheduled\n", pos, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), @@ -1725,8 +1721,8 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ) GNUNET_NETWORK_fdset_set_native (sh->ws, pos->write_fd); - LOG (GNUNET_ERROR_TYPE_WARNING, - "Running task from driver: %p\n", + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Running task %p\n", pos); pos->callback (pos->callback_cls); active_task = NULL; @@ -1734,21 +1730,6 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) destroy_task (pos); tasks_run++; } - if (GNUNET_NO == check_lifeness ()) - { - /* cancel fd tasks without lifeness */ - pos = pending_head; - while (NULL != pos) - { - struct GNUNET_SCHEDULER_Task *tsk = pos; - pos = pos->next; - if (GNUNET_NO == tsk->lifeness) - { - GNUNET_SCHEDULER_cancel (tsk); - } - } - //sighandler_shutdown(); - } if (0 == ready_count) { scheduler_driver->set_wakeup (scheduler_driver->cls, @@ -1810,7 +1791,7 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, scheduler_driver = driver; /* install signal handlers */ - LOG (GNUNET_ERROR_TYPE_WARNING, + LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering signal handlers\n"); shc_int = GNUNET_SIGNAL_handler_install (SIGINT, &sighandler_shutdown); @@ -1830,23 +1811,6 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, #endif /* Setup initial tasks */ - //current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; - //current_lifeness = GNUNET_YES; - //memset (&tsk, - // 0, - // sizeof (tsk)); - //active_task = &tsk; - //GNUNET_SCHEDULER_add_with_reason_and_priority (task, - // task_cls, - // GNUNET_SCHEDULER_REASON_STARTUP, - // GNUNET_SCHEDULER_PRIORITY_DEFAULT); - //GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO, - // &GNUNET_OS_install_parent_control_handler, - // NULL); - //GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, - // pr, - // &shutdown_task, - // NULL); current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; current_lifeness = GNUNET_NO; memset (&tsk, @@ -1871,8 +1835,6 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, GNUNET_NETWORK_fdset_handle_set (sh.rs, pr); ret = driver->loop (driver->cls, &sh); - LOG (GNUNET_ERROR_TYPE_WARNING, - "loop finished!\n"); GNUNET_NETWORK_fdset_destroy (sh.rs); GNUNET_NETWORK_fdset_destroy (sh.ws); @@ -2005,7 +1967,7 @@ select_loop (void *cls, ws = GNUNET_NETWORK_fdset_create (); last_tr = 0; busy_wait_warning = 0; - while ((NULL != context->scheduled_in_head) || (NULL != context->scheduled_out_head)) + while (GNUNET_YES == GNUNET_SCHEDULER_check_lifeness ()) { GNUNET_NETWORK_fdset_zero (rs); GNUNET_NETWORK_fdset_zero (ws); @@ -2121,10 +2083,6 @@ select_loop (void *cls, last_tr = tasks_run; busy_wait_warning = 0; } - LOG (GNUNET_ERROR_TYPE_WARNING, - "scheduled_in_head = %p, scheduled_out_head = %p\n", - context->scheduled_in_head, - context->scheduled_out_head); } return GNUNET_OK; } -- cgit v1.2.3 From 6fcafa3adc10394ad79db171a3a22c3260512f43 Mon Sep 17 00:00:00 2001 From: lurchi Date: Wed, 9 Aug 2017 22:37:43 +0200 Subject: cosmetic fixes --- src/util/scheduler.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index f2fdbef2b..5a727c663 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -577,11 +577,15 @@ sighandler_shutdown () /** - * Check if the system is still alive. Trigger shutdown if we - * have tasks, but none of them give us lifeness. + * Check if the system has initiated shutdown. This means no tasks + * that prevent shutdown were present and all tasks added with + * #GNUNET_SCHEDULER_add_shutdown were run already. * - * @return #GNUNET_OK to continue the main loop, - * #GNUNET_NO to exit + * Can be used by external event loop implementations to decide + * whether to keep running or not. + * + * @return #GNUNET_YES if tasks which prevent shutdown exist + * #GNUNET_NO if the system has initiated shutdown */ int GNUNET_SCHEDULER_check_lifeness () @@ -589,20 +593,20 @@ GNUNET_SCHEDULER_check_lifeness () struct GNUNET_SCHEDULER_Task *t; if (ready_count > 0) - return GNUNET_OK; + return GNUNET_YES; for (t = pending_head; NULL != t; t = t->next) if (t->lifeness == GNUNET_YES) - return GNUNET_OK; + return GNUNET_YES; for (t = shutdown_head; NULL != t; t = t->next) if (t->lifeness == GNUNET_YES) - return GNUNET_OK; + return GNUNET_YES; for (t = pending_timeout_head; NULL != t; t = t->next) if (t->lifeness == GNUNET_YES) - return GNUNET_OK; + return GNUNET_YES; if (NULL != shutdown_head) { GNUNET_SCHEDULER_shutdown (); - return GNUNET_OK; + return GNUNET_YES; } return GNUNET_NO; } -- cgit v1.2.3 From 4e82b4961abb33ccacf95fa7b3101450230bf10d Mon Sep 17 00:00:00 2001 From: lurchi Date: Thu, 10 Aug 2017 20:05:37 +0200 Subject: fix compilation of debug code enabled by DEBUG_FDS; fix indentation --- src/util/scheduler.c | 63 +++++++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 28 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 5a727c663..918460ca7 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -1073,12 +1073,12 @@ GNUNET_SCHEDULER_add_at (struct GNUNET_TIME_Absolute at, struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, - void *task_cls) + void *task_cls) { return GNUNET_SCHEDULER_add_delayed_with_priority (delay, GNUNET_SCHEDULER_PRIORITY_DEFAULT, task, - task_cls); + task_cls); } @@ -1175,6 +1175,33 @@ GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, } +#if DEBUG_FDS +/** + * check a raw file descriptor and abort if it is bad (for debugging purposes) + * + * @param t the task related to the file descriptor + * @param raw_fd the raw file descriptor to check + */ +void +check_fd (struct GNUNET_SCHEDULER_Task *t, int raw_fd) +{ + if (-1 != raw_fd) + { + int flags = fcntl (raw_fd, F_GETFD); + + if ((flags == -1) && (errno == EBADF)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "Got invalid file descriptor %d!\n", + raw_fd); + init_backtrace (t); + GNUNET_assert (0); + } + } +} +#endif + + /** * Schedule a new task to be run with a specified delay or when any of * the specified file descriptor sets is ready. The delay can be used @@ -1220,32 +1247,10 @@ add_without_sets (struct GNUNET_TIME_Relative delay, t->callback = task; t->callback_cls = task_cls; #if DEBUG_FDS - if (-1 != rfd) - { - int flags = fcntl (rfd, F_GETFD); - - if ((flags == -1) && (errno == EBADF)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Got invalid file descriptor %d!\n", - rfd); - init_backtrace (t); - GNUNET_assert (0); - } - } - if (-1 != wfd) - { - int flags = fcntl (wfd, F_GETFD); - - if (flags == -1 && errno == EBADF) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Got invalid file descriptor %d!\n", - wfd); - init_backtrace (t); - GNUNET_assert (0); - } - } + check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1); + check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1); + check_fd (t, NULL != read_fh ? read_fh->fd : -1); + check_fd (t, NULL != write_fh ? write_fh->fd : -1); #endif #if PROFILE_DELAYS t->start_time = GNUNET_TIME_absolute_get (); @@ -1971,6 +1976,8 @@ select_loop (void *cls, ws = GNUNET_NETWORK_fdset_create (); last_tr = 0; busy_wait_warning = 0; + // FIXME: remove check_lifeness, instead the condition should be: + // pending_in_head != NULL || pending_out_head != NULL || context->timeout > 0 while (GNUNET_YES == GNUNET_SCHEDULER_check_lifeness ()) { GNUNET_NETWORK_fdset_zero (rs); -- cgit v1.2.3 From 2e026896f04e3d4ea2e5f2d52932191e01cc9cc8 Mon Sep 17 00:00:00 2001 From: lurchi Date: Thu, 10 Aug 2017 21:09:18 +0200 Subject: remove unnecessary set_wakup call --- src/util/scheduler.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 918460ca7..ba4176a0a 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -977,8 +977,6 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, pending_timeout_tail, prev, t); - scheduler_driver->set_wakeup (scheduler_driver->cls, - get_timeout()); } /* finally, update heuristic insertion point to last insertion... */ pending_timeout_last = t; -- cgit v1.2.3 From 7d42c453fbb032ac8fb43c8e56bb84354ecedf2d Mon Sep 17 00:00:00 2001 From: lurchi Date: Fri, 11 Aug 2017 18:49:55 +0200 Subject: set fds_len in all cases; call set_wakeup only in two places --- src/testbed/gnunet-helper-testbed.c | 6 ++++++ src/util/scheduler.c | 17 ++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'src/util') diff --git a/src/testbed/gnunet-helper-testbed.c b/src/testbed/gnunet-helper-testbed.c index 392f257dd..5a5cfa0d2 100644 --- a/src/testbed/gnunet-helper-testbed.c +++ b/src/testbed/gnunet-helper-testbed.c @@ -556,6 +556,10 @@ run (void *cls, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { + FILE *f = FOPEN ("helper_output", "w"); + FPRINTF (f, "run\n"); + FCLOSE (f); + LOG_DEBUG ("Starting testbed helper...\n"); tokenizer = GNUNET_MST_create (&tokenizer_cb, NULL); stdin_fd = GNUNET_DISK_get_handle_from_native (stdin); @@ -604,6 +608,8 @@ main (int argc, }; int ret; + //sleep (10); + status = GNUNET_OK; if (NULL == (sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO))) diff --git a/src/util/scheduler.c b/src/util/scheduler.c index ba4176a0a..89b6e41f3 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -722,6 +722,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = GNUNET_NETWORK_get_fd (read_nh)}; t->fdx = read_fdi; t->fds = &t->fdx; + t->fds_len = 1; t->read_fd = t->fdx.sock; } else if (NULL != write_nh) @@ -729,6 +730,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; t->fdx = write_fdi; t->fds = &t->fdx; + t->fds_len = 1; t->write_fd = t->fdx.sock; } else if (NULL != read_fh) @@ -736,6 +738,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fh->fd}; t->fdx = read_fdi; t->fds = &t->fdx; + t->fds_len = 1; t->read_fd = t->fdx.sock; } else if (NULL != write_fh) @@ -743,6 +746,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fh->fd}; t->fdx = write_fdi; t->fds = &t->fdx; + t->fds_len = 1; t->write_fd = t->fdx.sock; } } @@ -815,9 +819,6 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) task); if (pending_timeout_last == task) pending_timeout_last = NULL; - else - scheduler_driver->set_wakeup (scheduler_driver->cls, - get_timeout ()); } //TODO check if this is redundant if (task == pending_timeout_last) @@ -951,8 +952,6 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, GNUNET_CONTAINER_DLL_insert (pending_timeout_head, pending_timeout_tail, t); - scheduler_driver->set_wakeup (scheduler_driver->cls, - at); } else { @@ -1260,8 +1259,6 @@ add_without_sets (struct GNUNET_TIME_Relative delay, pending_tail, t); scheduler_multi_function_call(t, scheduler_driver->add); - scheduler_driver->set_wakeup (scheduler_driver->cls, - get_timeout ()); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1585,8 +1582,6 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, pending_tail, t); scheduler_multi_function_call(t, scheduler_driver->add); - scheduler_driver->set_wakeup (scheduler_driver->cls, - get_timeout ()); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1625,6 +1620,7 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, (0 != (GNUNET_SCHEDULER_ET_OUT & et)) ) reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; + GNUNET_assert (1 == task->fds_len); task->reason = reason; task->fds = &task->fdx; // FIXME: if task contains a list of fds, this is wrong! task->fdx.et = et; @@ -1836,6 +1832,8 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, GNUNET_SCHEDULER_REASON_STARTUP, GNUNET_SCHEDULER_PRIORITY_DEFAULT); active_task = NULL; + scheduler_driver->set_wakeup (scheduler_driver->cls, + get_timeout ()); /* begin main event loop */ sh.rs = GNUNET_NETWORK_fdset_create (); sh.ws = GNUNET_NETWORK_fdset_create (); @@ -1858,6 +1856,7 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, #endif GNUNET_DISK_pipe_close (shutdown_pipe_handle); shutdown_pipe_handle = NULL; + scheduler_driver = NULL; return ret; } -- cgit v1.2.3 From 848358d875f9c246de451818b456219eb0bf6408 Mon Sep 17 00:00:00 2001 From: lurchi Date: Fri, 11 Aug 2017 19:02:16 +0200 Subject: Revert "set fds_len in all cases; call set_wakeup only in two places" This reverts commit 7d42c453fbb032ac8fb43c8e56bb84354ecedf2d. --- src/testbed/gnunet-helper-testbed.c | 6 ------ src/util/scheduler.c | 17 +++++++++-------- 2 files changed, 9 insertions(+), 14 deletions(-) (limited to 'src/util') diff --git a/src/testbed/gnunet-helper-testbed.c b/src/testbed/gnunet-helper-testbed.c index 5a5cfa0d2..392f257dd 100644 --- a/src/testbed/gnunet-helper-testbed.c +++ b/src/testbed/gnunet-helper-testbed.c @@ -556,10 +556,6 @@ run (void *cls, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { - FILE *f = FOPEN ("helper_output", "w"); - FPRINTF (f, "run\n"); - FCLOSE (f); - LOG_DEBUG ("Starting testbed helper...\n"); tokenizer = GNUNET_MST_create (&tokenizer_cb, NULL); stdin_fd = GNUNET_DISK_get_handle_from_native (stdin); @@ -608,8 +604,6 @@ main (int argc, }; int ret; - //sleep (10); - status = GNUNET_OK; if (NULL == (sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO))) diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 89b6e41f3..ba4176a0a 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -722,7 +722,6 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = GNUNET_NETWORK_get_fd (read_nh)}; t->fdx = read_fdi; t->fds = &t->fdx; - t->fds_len = 1; t->read_fd = t->fdx.sock; } else if (NULL != write_nh) @@ -730,7 +729,6 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; t->fdx = write_fdi; t->fds = &t->fdx; - t->fds_len = 1; t->write_fd = t->fdx.sock; } else if (NULL != read_fh) @@ -738,7 +736,6 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fh->fd}; t->fdx = read_fdi; t->fds = &t->fdx; - t->fds_len = 1; t->read_fd = t->fdx.sock; } else if (NULL != write_fh) @@ -746,7 +743,6 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fh->fd}; t->fdx = write_fdi; t->fds = &t->fdx; - t->fds_len = 1; t->write_fd = t->fdx.sock; } } @@ -819,6 +815,9 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) task); if (pending_timeout_last == task) pending_timeout_last = NULL; + else + scheduler_driver->set_wakeup (scheduler_driver->cls, + get_timeout ()); } //TODO check if this is redundant if (task == pending_timeout_last) @@ -952,6 +951,8 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, GNUNET_CONTAINER_DLL_insert (pending_timeout_head, pending_timeout_tail, t); + scheduler_driver->set_wakeup (scheduler_driver->cls, + at); } else { @@ -1259,6 +1260,8 @@ add_without_sets (struct GNUNET_TIME_Relative delay, pending_tail, t); scheduler_multi_function_call(t, scheduler_driver->add); + scheduler_driver->set_wakeup (scheduler_driver->cls, + get_timeout ()); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1582,6 +1585,8 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, pending_tail, t); scheduler_multi_function_call(t, scheduler_driver->add); + scheduler_driver->set_wakeup (scheduler_driver->cls, + get_timeout ()); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1620,7 +1625,6 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, (0 != (GNUNET_SCHEDULER_ET_OUT & et)) ) reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; - GNUNET_assert (1 == task->fds_len); task->reason = reason; task->fds = &task->fdx; // FIXME: if task contains a list of fds, this is wrong! task->fdx.et = et; @@ -1832,8 +1836,6 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, GNUNET_SCHEDULER_REASON_STARTUP, GNUNET_SCHEDULER_PRIORITY_DEFAULT); active_task = NULL; - scheduler_driver->set_wakeup (scheduler_driver->cls, - get_timeout ()); /* begin main event loop */ sh.rs = GNUNET_NETWORK_fdset_create (); sh.ws = GNUNET_NETWORK_fdset_create (); @@ -1856,7 +1858,6 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, #endif GNUNET_DISK_pipe_close (shutdown_pipe_handle); shutdown_pipe_handle = NULL; - scheduler_driver = NULL; return ret; } -- cgit v1.2.3 From 7289071d2aa0e5795e78d3dd0433f82dde7d90ac Mon Sep 17 00:00:00 2001 From: lurchi Date: Fri, 11 Aug 2017 18:57:20 +0200 Subject: set fds_len in all cases; call set_wakeup only in two places --- src/util/scheduler.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index ba4176a0a..89b6e41f3 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -722,6 +722,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = GNUNET_NETWORK_get_fd (read_nh)}; t->fdx = read_fdi; t->fds = &t->fdx; + t->fds_len = 1; t->read_fd = t->fdx.sock; } else if (NULL != write_nh) @@ -729,6 +730,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; t->fdx = write_fdi; t->fds = &t->fdx; + t->fds_len = 1; t->write_fd = t->fdx.sock; } else if (NULL != read_fh) @@ -736,6 +738,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fh->fd}; t->fdx = read_fdi; t->fds = &t->fdx; + t->fds_len = 1; t->read_fd = t->fdx.sock; } else if (NULL != write_fh) @@ -743,6 +746,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fh->fd}; t->fdx = write_fdi; t->fds = &t->fdx; + t->fds_len = 1; t->write_fd = t->fdx.sock; } } @@ -815,9 +819,6 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) task); if (pending_timeout_last == task) pending_timeout_last = NULL; - else - scheduler_driver->set_wakeup (scheduler_driver->cls, - get_timeout ()); } //TODO check if this is redundant if (task == pending_timeout_last) @@ -951,8 +952,6 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, GNUNET_CONTAINER_DLL_insert (pending_timeout_head, pending_timeout_tail, t); - scheduler_driver->set_wakeup (scheduler_driver->cls, - at); } else { @@ -1260,8 +1259,6 @@ add_without_sets (struct GNUNET_TIME_Relative delay, pending_tail, t); scheduler_multi_function_call(t, scheduler_driver->add); - scheduler_driver->set_wakeup (scheduler_driver->cls, - get_timeout ()); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1585,8 +1582,6 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, pending_tail, t); scheduler_multi_function_call(t, scheduler_driver->add); - scheduler_driver->set_wakeup (scheduler_driver->cls, - get_timeout ()); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1625,6 +1620,7 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, (0 != (GNUNET_SCHEDULER_ET_OUT & et)) ) reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; + GNUNET_assert (1 == task->fds_len); task->reason = reason; task->fds = &task->fdx; // FIXME: if task contains a list of fds, this is wrong! task->fdx.et = et; @@ -1836,6 +1832,8 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, GNUNET_SCHEDULER_REASON_STARTUP, GNUNET_SCHEDULER_PRIORITY_DEFAULT); active_task = NULL; + scheduler_driver->set_wakeup (scheduler_driver->cls, + get_timeout ()); /* begin main event loop */ sh.rs = GNUNET_NETWORK_fdset_create (); sh.ws = GNUNET_NETWORK_fdset_create (); @@ -1858,6 +1856,7 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, #endif GNUNET_DISK_pipe_close (shutdown_pipe_handle); shutdown_pipe_handle = NULL; + scheduler_driver = NULL; return ret; } -- cgit v1.2.3 From 6ee6dbd04d1e3d0e8c0cb5701e381eb4c22287c1 Mon Sep 17 00:00:00 2001 From: lurchi Date: Sat, 12 Aug 2017 17:39:21 +0200 Subject: init_fd_info now completely initializes fd information; Allow calling add/cancel functions only when the scheduler is running --- src/util/program.c | 12 ++++++- src/util/scheduler.c | 100 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 91 insertions(+), 21 deletions(-) (limited to 'src/util') diff --git a/src/util/program.c b/src/util/program.c index 92a9750f3..233792387 100644 --- a/src/util/program.c +++ b/src/util/program.c @@ -68,6 +68,16 @@ struct CommandContext }; +/** + * task run when the scheduler shuts down + */ +static void +shutdown_task (void *cls) +{ + GNUNET_SPEEDUP_stop_ (); +} + + /** * Initial task called by the scheduler for each * program. Runs the program-specific main task. @@ -78,6 +88,7 @@ program_main (void *cls) struct CommandContext *cc = cls; GNUNET_SPEEDUP_start_(cc->cfg); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); GNUNET_RESOLVER_connect (cc->cfg); cc->task (cc->task_cls, cc->args, cc->cfgfile, cc->cfg); } @@ -306,7 +317,6 @@ GNUNET_PROGRAM_run2 (int argc, char *const *argv, const char *binaryName, } ret = GNUNET_OK; cleanup: - GNUNET_SPEEDUP_stop_ (); GNUNET_CONFIGURATION_destroy (cfg); GNUNET_free_non_null (cc.cfgfile); GNUNET_free (cfg_fn); diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 89b6e41f3..1f5fe3f61 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -606,6 +606,8 @@ GNUNET_SCHEDULER_check_lifeness () if (NULL != shutdown_head) { GNUNET_SCHEDULER_shutdown (); + scheduler_driver->set_wakeup (scheduler_driver->cls, + GNUNET_TIME_absolute_get ()); return GNUNET_YES; } return GNUNET_NO; @@ -699,9 +701,13 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, if (NULL != read_nh && NULL != write_nh) { + int read_fd = GNUNET_NETWORK_get_fd (read_nh); + int write_fd = GNUNET_NETWORK_get_fd (write_nh); + t->read_fd = read_fd; + t->write_fd = write_fd; struct GNUNET_SCHEDULER_FdInfo *fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); - struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = GNUNET_NETWORK_get_fd (read_nh)}; - struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; + struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; + struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; fds[0] = read_fdi; fds[1] = write_fdi; t->fds = fds; @@ -709,9 +715,13 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, } else if (NULL != read_fh && NULL != write_fh) { + int read_fd = read_fh->fd; + int write_fd = write_fh->fd; struct GNUNET_SCHEDULER_FdInfo *fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); - struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fh->fd}; - struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fh->fd}; + struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; + struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; + t->read_fd = read_fd; + t->write_fd = write_fd; fds[0] = read_fdi; fds[1] = write_fdi; t->fds = fds; @@ -719,53 +729,65 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, } else if (NULL != read_nh) { - struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = GNUNET_NETWORK_get_fd (read_nh)}; + int read_fd = GNUNET_NETWORK_get_fd (read_nh); + struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; + t->read_fd = read_fd; + t->write_fd = -1; t->fdx = read_fdi; t->fds = &t->fdx; t->fds_len = 1; - t->read_fd = t->fdx.sock; } else if (NULL != write_nh) { - struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = GNUNET_NETWORK_get_fd (write_nh)}; + int write_fd = GNUNET_NETWORK_get_fd (write_nh); + struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; + t->read_fd = -1; + t->write_fd = write_fd; t->fdx = write_fdi; t->fds = &t->fdx; t->fds_len = 1; - t->write_fd = t->fdx.sock; } else if (NULL != read_fh) { - struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fh->fd}; + int read_fd = read_fh->fd; + struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; + t->read_fd = read_fd; + t->write_fd = -1; t->fdx = read_fdi; t->fds = &t->fdx; t->fds_len = 1; - t->read_fd = t->fdx.sock; } else if (NULL != write_fh) { - struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fh->fd}; + int write_fd = write_fh->fd; + struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; + t->read_fd = -1; + t->write_fd = write_fd; t->fdx = write_fdi; t->fds = &t->fdx; t->fds_len = 1; - t->write_fd = t->fdx.sock; } } -int scheduler_multi_function_call(struct GNUNET_SCHEDULER_Task *t, int (*driver_func)()) +void scheduler_multi_function_call(struct GNUNET_SCHEDULER_Task *t, int (*driver_func)()) { + int success = GNUNET_YES; if (t->fds_len > 1) { - int success = GNUNET_YES; for (int i = 0; i < t->fds_len;i++) { success = driver_func (scheduler_driver->cls, t , t->fds+i) && success; } - return success; } else { - return driver_func (scheduler_driver->cls, t , t->fds); + success = driver_func (scheduler_driver->cls, t , t->fds); + } + if (GNUNET_YES != success) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "driver call not successful"); } } @@ -788,7 +810,9 @@ shutdown_task (void *cls) /** * Cancel the task with the specified identifier. - * The task must not yet have run. + * The task must not yet have run. Only allowed to be called as long as the + * scheduler is running (#GNUNET_SCHEDULER_run or + * #GNUNET_SCHEDULER_run_with_driver has been called and has not returned yet). * * @param task id of the task to cancel * @return original closure of the task @@ -799,6 +823,8 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) enum GNUNET_SCHEDULER_Priority p; void *ret; + /* scheduler must be running */ + GNUNET_assert (NULL != scheduler_driver); GNUNET_assert ( (NULL != active_task) || (GNUNET_NO == task->lifeness) ); if (! task->in_ready_list) @@ -1133,7 +1159,7 @@ GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task, t->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; t->priority = GNUNET_SCHEDULER_PRIORITY_SHUTDOWN; t->on_shutdown = GNUNET_YES; - t->lifeness = GNUNET_YES; + t->lifeness = GNUNET_NO; GNUNET_CONTAINER_DLL_insert (shutdown_head, shutdown_tail, t); @@ -1258,7 +1284,7 @@ add_without_sets (struct GNUNET_TIME_Relative delay, GNUNET_CONTAINER_DLL_insert (pending_head, pending_tail, t); - scheduler_multi_function_call(t, scheduler_driver->add); + scheduler_multi_function_call (t, scheduler_driver->add); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1276,6 +1302,9 @@ add_without_sets (struct GNUNET_TIME_Relative delay, * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. It will be run with the DEFAULT priority. + * Only allowed to be called as long as the scheduler is running + * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been + * called and has not returned yet). * * @param delay when should this operation time out? * @param rfd read file-descriptor @@ -1303,6 +1332,9 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay, * socket being ready. The task will be scheduled for execution once * either the delay has expired or the socket operation is ready. It * will be run with the DEFAULT priority. + * Only allowed to be called as long as the scheduler is running + * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been + * called and has not returned yet). * * @param delay when should this operation time out? * @param priority priority to use for the task @@ -1334,6 +1366,9 @@ GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, * scheduled for execution once either the delay has expired or the * socket operation is ready. It will be run with the priority of * the calling task. + * Only allowed to be called as long as the scheduler is running + * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been + * called and has not returned yet). * * @param delay when should this operation time out? * @param wfd write file-descriptor @@ -1361,6 +1396,9 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay, * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. + * Only allowed to be called as long as the scheduler is running + * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been + * called and has not returned yet). * * @param delay when should this operation time out? * @param priority priority of the task @@ -1381,6 +1419,9 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls) { + /* scheduler must be running */ + GNUNET_assert (NULL != scheduler_driver); + #if MINGW struct GNUNET_NETWORK_FDSet *s; struct GNUNET_SCHEDULER_Task * ret; @@ -1414,6 +1455,9 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. It will be run with the DEFAULT priority. + * Only allowed to be called as long as the scheduler is running + * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been + * called and has not returned yet). * * @param delay when should this operation time out? * @param rfd read file-descriptor @@ -1440,6 +1484,9 @@ GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. It will be run with the DEFAULT priority. + * Only allowed to be called as long as the scheduler is running + * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been + * called and has not returned yet). * * @param delay when should this operation time out? * @param wfd write file-descriptor @@ -1466,6 +1513,9 @@ GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay, * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. + * Only allowed to be called as long as the scheduler is running + * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been + * called and has not returned yet). * * @param delay when should this operation time out? * @param priority priority of the task @@ -1484,6 +1534,9 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, int on_read, int on_write, GNUNET_SCHEDULER_TaskCallback task, void *task_cls) { + /* scheduler must be running */ + GNUNET_assert (NULL != scheduler_driver); + #if MINGW struct GNUNET_NETWORK_FDSet *s; struct GNUNET_SCHEDULER_Task * ret; @@ -1526,6 +1579,9 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, * || any-rs-ready * || any-ws-ready) ) * + * Only allowed to be called as long as the scheduler is running + * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been + * called and has not returned yet). * * @param prio how important is this task? * @param delay how long should we wait? @@ -1552,6 +1608,8 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, prio, task, task_cls); + /* scheduler must be running */ + GNUNET_assert (NULL != scheduler_driver); GNUNET_assert (NULL != active_task); GNUNET_assert (NULL != task); t = GNUNET_new (struct GNUNET_SCHEDULER_Task); @@ -1581,7 +1639,7 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, GNUNET_CONTAINER_DLL_insert (pending_head, pending_tail, t); - scheduler_multi_function_call(t, scheduler_driver->add); + scheduler_multi_function_call (t, scheduler_driver->add); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1868,6 +1926,8 @@ select_add (void *cls, { struct DriverContext *context = cls; GNUNET_assert (NULL != context); + GNUNET_assert (NULL != task); + GNUNET_assert (NULL != fdi); if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (0 >= fdi->sock)) { -- cgit v1.2.3 From 70fedfb249696028103dd77f5641f8f7b46f5c61 Mon Sep 17 00:00:00 2001 From: lurchi Date: Sat, 12 Aug 2017 17:39:54 +0200 Subject: fix off-by-one error that prevented reading from stdin --- src/util/scheduler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 1f5fe3f61..2ea2378eb 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -1929,7 +1929,7 @@ select_add (void *cls, GNUNET_assert (NULL != task); GNUNET_assert (NULL != fdi); - if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (0 >= fdi->sock)) + if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (0 > fdi->sock)) { /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */ return GNUNET_SYSERR; -- cgit v1.2.3 From a4cf7b69030ba9ded923828a781a65f62e5dc616 Mon Sep 17 00:00:00 2001 From: lurchi Date: Sun, 13 Aug 2017 21:04:34 +0200 Subject: reimplement init_fd_info as preparation for refactoring GNUNET_SCHEDULER_add_select --- src/util/scheduler.c | 282 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 206 insertions(+), 76 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 2ea2378eb..c4017f23b 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -484,6 +484,7 @@ GNUNET_SCHEDULER_shutdown () static void destroy_task (struct GNUNET_SCHEDULER_Task *t) { + // FIXME: destroy fds! if (NULL != t->read_set) GNUNET_NETWORK_fdset_destroy (t->read_set); if (NULL != t->write_set) @@ -587,6 +588,7 @@ sighandler_shutdown () * @return #GNUNET_YES if tasks which prevent shutdown exist * #GNUNET_NO if the system has initiated shutdown */ +// FIXME: make it an internal function again int GNUNET_SCHEDULER_check_lifeness () { @@ -606,6 +608,8 @@ GNUNET_SCHEDULER_check_lifeness () if (NULL != shutdown_head) { GNUNET_SCHEDULER_shutdown (); + LOG (GNUNET_ERROR_TYPE_WARNING, + "shutting down\n"); scheduler_driver->set_wakeup (scheduler_driver->cls, GNUNET_TIME_absolute_get ()); return GNUNET_YES; @@ -691,84 +695,173 @@ GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) void init_fd_info (struct GNUNET_SCHEDULER_Task *t, - const struct GNUNET_NETWORK_Handle *read_nh, - const struct GNUNET_NETWORK_Handle *write_nh, - const struct GNUNET_DISK_FileHandle *read_fh, - const struct GNUNET_DISK_FileHandle *write_fh) + const struct GNUNET_NETWORK_Handle **read_nh, + size_t read_nh_len, + const struct GNUNET_NETWORK_Handle **write_nh, + size_t write_nh_len, + const struct GNUNET_DISK_FileHandle **read_fh, + size_t read_fh_len, + const struct GNUNET_DISK_FileHandle **write_fh, + size_t write_fh_len) { - // either only network handles or only file handles are allowed - GNUNET_assert (!((NULL != read_nh || NULL != write_nh) && (NULL != read_fh || NULL != write_fh))); + struct GNUNET_SCHEDULER_FdInfo *fdi; - if (NULL != read_nh && NULL != write_nh) - { - int read_fd = GNUNET_NETWORK_get_fd (read_nh); - int write_fd = GNUNET_NETWORK_get_fd (write_nh); - t->read_fd = read_fd; - t->write_fd = write_fd; - struct GNUNET_SCHEDULER_FdInfo *fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); - struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; - struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; - fds[0] = read_fdi; - fds[1] = write_fdi; - t->fds = fds; - t->fds_len = 2; - } - else if (NULL != read_fh && NULL != write_fh) - { - int read_fd = read_fh->fd; - int write_fd = write_fh->fd; - struct GNUNET_SCHEDULER_FdInfo *fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); - struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; - struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; - t->read_fd = read_fd; - t->write_fd = write_fd; - fds[0] = read_fdi; - fds[1] = write_fdi; - t->fds = fds; - t->fds_len = 2; - } - else if (NULL != read_nh) + t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len; + if (1 == t->fds_len) { - int read_fd = GNUNET_NETWORK_get_fd (read_nh); - struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; - t->read_fd = read_fd; - t->write_fd = -1; - t->fdx = read_fdi; - t->fds = &t->fdx; - t->fds_len = 1; + fdi = &t->fdx; + t->fds = fdi; + if (1 == read_nh_len) + { + fdi->fd = *read_nh; + fdi->et = GNUNET_SCHEDULER_ET_IN; + fdi->sock = GNUNET_NETWORK_get_fd (*read_nh); + t->read_fd = fdi->sock; + t->write_fd = -1; + } + else if (1 == write_nh_len) + { + fdi->fd = *write_nh; + fdi->et = GNUNET_SCHEDULER_ET_OUT; + fdi->sock = GNUNET_NETWORK_get_fd (*write_nh); + t->read_fd = -1; + t->write_fd = fdi->sock; + } + else if (1 == read_fh_len) + { + fdi->fh = *read_fh; + fdi->et = GNUNET_SCHEDULER_ET_IN; + fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32 + t->read_fd = fdi->sock; + t->write_fd = -1; + } + else + { + fdi->fh = *write_fh; + fdi->et = GNUNET_SCHEDULER_ET_OUT; + fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32 + t->read_fd = -1; + t->write_fd = fdi->sock; + } } - else if (NULL != write_nh) + else { - int write_fd = GNUNET_NETWORK_get_fd (write_nh); - struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; + fdi = GNUNET_new_array (t->fds_len, struct GNUNET_SCHEDULER_FdInfo); + t->fds = fdi; t->read_fd = -1; - t->write_fd = write_fd; - t->fdx = write_fdi; - t->fds = &t->fdx; - t->fds_len = 1; - } - else if (NULL != read_fh) - { - int read_fd = read_fh->fd; - struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; - t->read_fd = read_fd; t->write_fd = -1; - t->fdx = read_fdi; - t->fds = &t->fdx; - t->fds_len = 1; - } - else if (NULL != write_fh) - { - int write_fd = write_fh->fd; - struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; - t->read_fd = -1; - t->write_fd = write_fd; - t->fdx = write_fdi; - t->fds = &t->fdx; - t->fds_len = 1; + size_t i; + for (i = 0; i != read_nh_len; ++i) + { + fdi->fd = read_nh[i]; + fdi->et = GNUNET_SCHEDULER_ET_IN; + fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]); + ++fdi; + } + for (i = 0; i != write_nh_len; ++i) + { + fdi->fd = write_nh[i]; + fdi->et = GNUNET_SCHEDULER_ET_OUT; + fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]); + ++fdi; + } + for (i = 0; i != read_fh_len; ++i) + { + fdi->fh = read_fh[i]; + fdi->et = GNUNET_SCHEDULER_ET_IN; + fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32 + ++fdi; + } + for (i = 0; i != write_fh_len; ++i) + { + fdi->fh = write_fh[i]; + fdi->et = GNUNET_SCHEDULER_ET_OUT; + fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32 + ++fdi; + } } } +//void +//init_fd_info (struct GNUNET_SCHEDULER_Task *t, +// const struct GNUNET_NETWORK_Handle *read_nh, +// const struct GNUNET_NETWORK_Handle *write_nh, +// const struct GNUNET_DISK_FileHandle *read_fh, +// const struct GNUNET_DISK_FileHandle *write_fh) +//{ +// // either only network handles or only file handles are allowed +// GNUNET_assert (!((NULL != read_nh || NULL != write_nh) && (NULL != read_fh || NULL != write_fh))); +// +// if (NULL != read_nh && NULL != write_nh) +// { +// int read_fd = GNUNET_NETWORK_get_fd (read_nh); +// int write_fd = GNUNET_NETWORK_get_fd (write_nh); +// t->read_fd = read_fd; +// t->write_fd = write_fd; +// struct GNUNET_SCHEDULER_FdInfo *fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); +// struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; +// struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; +// fds[0] = read_fdi; +// fds[1] = write_fdi; +// t->fds = fds; +// t->fds_len = 2; +// } +// else if (NULL != read_fh && NULL != write_fh) +// { +// int read_fd = read_fh->fd; +// int write_fd = write_fh->fd; +// struct GNUNET_SCHEDULER_FdInfo *fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); +// struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; +// struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; +// t->read_fd = read_fd; +// t->write_fd = write_fd; +// fds[0] = read_fdi; +// fds[1] = write_fdi; +// t->fds = fds; +// t->fds_len = 2; +// } +// else if (NULL != read_nh) +// { +// int read_fd = GNUNET_NETWORK_get_fd (read_nh); +// struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; +// t->read_fd = read_fd; +// t->write_fd = -1; +// t->fdx = read_fdi; +// t->fds = &t->fdx; +// t->fds_len = 1; +// } +// else if (NULL != write_nh) +// { +// int write_fd = GNUNET_NETWORK_get_fd (write_nh); +// struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; +// t->read_fd = -1; +// t->write_fd = write_fd; +// t->fdx = write_fdi; +// t->fds = &t->fdx; +// t->fds_len = 1; +// } +// else if (NULL != read_fh) +// { +// int read_fd = read_fh->fd; +// struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; +// t->read_fd = read_fd; +// t->write_fd = -1; +// t->fdx = read_fdi; +// t->fds = &t->fdx; +// t->fds_len = 1; +// } +// else if (NULL != write_fh) +// { +// int write_fd = write_fh->fd; +// struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; +// t->read_fd = -1; +// t->write_fd = write_fd; +// t->fdx = write_fdi; +// t->fds = &t->fdx; +// t->fds_len = 1; +// } +//} + void scheduler_multi_function_call(struct GNUNET_SCHEDULER_Task *t, int (*driver_func)()) { @@ -1262,11 +1355,25 @@ add_without_sets (struct GNUNET_TIME_Relative delay, void *task_cls) { struct GNUNET_SCHEDULER_Task *t; - + GNUNET_assert (NULL != active_task); GNUNET_assert (NULL != task); t = GNUNET_new (struct GNUNET_SCHEDULER_Task); - init_fd_info (t, read_nh, write_nh, read_fh, write_fh); + + init_fd_info (t, + &read_nh, + read_nh ? 1 : 0, + &write_nh, + write_nh ? 1 : 0, + &read_fh, + read_fh ? 1 : 0, + &write_fh, + write_fh ? 1 : 0); + + //int read_fds[2] = {GNUNET_NETWORK_get_fd (read_nh), read_fh->fd}; + //int write_fds[2] = {GNUNET_NETWORK_get_fd (write_nh), write_fh->fd}; + //init_fd_info (t, read_fds, 2, write_fds, 2); + //init_fd_info (t, read_nh, write_nh, read_fh, write_fh); t->callback = task; t->callback_cls = task_cls; #if DEBUG_FDS @@ -1678,7 +1785,10 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, (0 != (GNUNET_SCHEDULER_ET_OUT & et)) ) reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; - GNUNET_assert (1 == task->fds_len); + + + + task->reason = reason; task->fds = &task->fdx; // FIXME: if task contains a list of fds, this is wrong! task->fdx.et = et; @@ -1709,6 +1819,7 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, int GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) { + // FIXME: call check_lifeness here! enum GNUNET_SCHEDULER_Priority p; struct GNUNET_SCHEDULER_Task *pos; struct GNUNET_TIME_Absolute now; @@ -1772,12 +1883,14 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) GNUNET_NETWORK_fdset_zero (sh->ws); tc.fds_len = pos->fds_len; tc.fds = pos->fds; - tc.read_ready = (NULL == pos->read_set) ? sh->rs : pos->read_set; + //tc.read_ready = (NULL == pos->read_set) ? sh->rs : pos->read_set; + tc.read_ready = sh->rs; if ( (-1 != pos->read_fd) && (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ) GNUNET_NETWORK_fdset_set_native (sh->rs, pos->read_fd); - tc.write_ready = (NULL == pos->write_set) ? sh->ws : pos->write_set; + //tc.write_ready = (NULL == pos->write_set) ? sh->ws : pos->write_set; + tc.write_ready = sh->ws; if ( (-1 != pos->write_fd) && (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ) GNUNET_NETWORK_fdset_set_native (sh->ws, @@ -2034,9 +2147,14 @@ select_loop (void *cls, last_tr = 0; busy_wait_warning = 0; // FIXME: remove check_lifeness, instead the condition should be: - // pending_in_head != NULL || pending_out_head != NULL || context->timeout > 0 + // pending_in_head != NULL || pending_out_head != NULL || tasks_ready while (GNUNET_YES == GNUNET_SCHEDULER_check_lifeness ()) { + LOG (GNUNET_ERROR_TYPE_WARNING, + "[%p] timeout = %s\n", + sh, + GNUNET_STRINGS_relative_time_to_string (context->timeout, GNUNET_NO)); + GNUNET_NETWORK_fdset_zero (rs); GNUNET_NETWORK_fdset_zero (ws); struct Scheduled *pos; @@ -2083,6 +2201,7 @@ select_loop (void *cls, #endif #if DEBUG_FDS struct GNUNET_SCHEDULER_Task *t; + // FIXME: pending_head is a scheduler-internal variable! for (t = pending_head; NULL != t; t = t->next) { if (-1 != t->read_fd) @@ -2117,7 +2236,9 @@ select_loop (void *cls, (busy_wait_warning > 16) ) { LOG (GNUNET_ERROR_TYPE_WARNING, - "Looks like we're busy waiting...\n"); + "[%p] Looks like we're busy waiting...\n", + sh); + GNUNET_assert (0); short_wait (100); /* mitigate */ } for (pos = context->scheduled_in_head; NULL != pos; pos = pos->next) @@ -2140,9 +2261,18 @@ select_loop (void *cls, GNUNET_SCHEDULER_task_ready (pos->task, GNUNET_SCHEDULER_ET_OUT); } } - GNUNET_SCHEDULER_run_from_driver (sh); + int tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); + LOG (GNUNET_ERROR_TYPE_WARNING, + "[%p] tasks_ready: %d\n", + sh, + tasks_ready); + // FIXME: tasks_run is a driver-internal variable! Instead we should increment + // a local variable tasks_ready_count everytime we're calling GNUNET_SCHEDULER_task_ready. if (last_tr == tasks_run) { + LOG (GNUNET_ERROR_TYPE_WARNING, + "[%p] no tasks run\n", + sh); short_wait (1); busy_wait_warning++; } -- cgit v1.2.3 From 16824d5bb7c3699bc6628c1bfabd53e2f3fe5a95 Mon Sep 17 00:00:00 2001 From: lurchi Date: Wed, 16 Aug 2017 13:57:37 +0200 Subject: add buggy state of refactored GNUNET_SCHEDULER_add_select --- src/util/scheduler.c | 305 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 186 insertions(+), 119 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index c4017f23b..353b4a669 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -117,20 +117,20 @@ struct GNUNET_SCHEDULER_Task */ void *callback_cls; - /** - * Set of file descriptors this task is waiting - * for for reading. Once ready, this is updated - * to reflect the set of file descriptors ready - * for operation. - */ - struct GNUNET_NETWORK_FDSet *read_set; - - /** - * Set of file descriptors this task is waiting for for writing. - * Once ready, this is updated to reflect the set of file - * descriptors ready for operation. - */ - struct GNUNET_NETWORK_FDSet *write_set; + ///** + // * Set of file descriptors this task is waiting + // * for for reading. Once ready, this is updated + // * to reflect the set of file descriptors ready + // * for operation. + // */ + //struct GNUNET_NETWORK_FDSet *read_set; + + ///** + // * Set of file descriptors this task is waiting for for writing. + // * Once ready, this is updated to reflect the set of file + // * descriptors ready for operation. + // */ + //struct GNUNET_NETWORK_FDSet *write_set; /** * Information about which FDs are ready for this task (and why). @@ -485,10 +485,30 @@ static void destroy_task (struct GNUNET_SCHEDULER_Task *t) { // FIXME: destroy fds! - if (NULL != t->read_set) - GNUNET_NETWORK_fdset_destroy (t->read_set); - if (NULL != t->write_set) - GNUNET_NETWORK_fdset_destroy (t->write_set); + if (t->fds_len > 1) + { + size_t i; + for (i = 0; i != t->fds_len; ++i) + { + const struct GNUNET_SCHEDULER_FdInfo *fdi = t->fds + i; + if (fdi->fd) + { + GNUNET_NETWORK_socket_free_memory_only_ ((struct GNUNET_NETWORK_Handle *) fdi->fd); + } + if (fdi->fh) + { + // FIXME: on WIN32 this is not enough! A function + // GNUNET_DISK_file_free_memory_only would be nice + GNUNET_free ((void *) fdi->fh); + } + } + /* free the array */ + GNUNET_array_grow (t->fds, t->fds_len, 0); + } + //if (NULL != t->read_set) + // GNUNET_NETWORK_fdset_destroy (t->read_set); + //if (NULL != t->write_set) + // GNUNET_NETWORK_fdset_destroy (t->write_set); #if EXECINFO GNUNET_free (t->backtrace_strings); #endif @@ -695,13 +715,13 @@ GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) void init_fd_info (struct GNUNET_SCHEDULER_Task *t, - const struct GNUNET_NETWORK_Handle **read_nh, + const struct GNUNET_NETWORK_Handle *const *read_nh, size_t read_nh_len, - const struct GNUNET_NETWORK_Handle **write_nh, + const struct GNUNET_NETWORK_Handle *const *write_nh, size_t write_nh_len, - const struct GNUNET_DISK_FileHandle **read_fh, + const struct GNUNET_DISK_FileHandle *const *read_fh, size_t read_fh_len, - const struct GNUNET_DISK_FileHandle **write_fh, + const struct GNUNET_DISK_FileHandle *const *write_fh, size_t write_fh_len) { struct GNUNET_SCHEDULER_FdInfo *fdi; @@ -713,7 +733,8 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, t->fds = fdi; if (1 == read_nh_len) { - fdi->fd = *read_nh; + fdi->fd = GNUNET_NETWORK_socket_box_native (GNUNET_NETWORK_get_fd (*read_nh)); + GNUNET_assert (NULL != fdi->fd); fdi->et = GNUNET_SCHEDULER_ET_IN; fdi->sock = GNUNET_NETWORK_get_fd (*read_nh); t->read_fd = fdi->sock; @@ -721,7 +742,8 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, } else if (1 == write_nh_len) { - fdi->fd = *write_nh; + fdi->fd = GNUNET_NETWORK_socket_box_native (GNUNET_NETWORK_get_fd (*write_nh)); + GNUNET_assert (NULL != fdi->fd); fdi->et = GNUNET_SCHEDULER_ET_OUT; fdi->sock = GNUNET_NETWORK_get_fd (*write_nh); t->read_fd = -1; @@ -729,7 +751,8 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, } else if (1 == read_fh_len) { - fdi->fh = *read_fh; + fdi->fh = GNUNET_DISK_get_handle_from_int_fd ((*read_fh)->fd); + GNUNET_assert (NULL != fdi->fh); fdi->et = GNUNET_SCHEDULER_ET_IN; fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32 t->read_fd = fdi->sock; @@ -737,7 +760,8 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, } else { - fdi->fh = *write_fh; + fdi->fh = GNUNET_DISK_get_handle_from_int_fd ((*write_fh)->fd); + GNUNET_assert (NULL != fdi->fh); fdi->et = GNUNET_SCHEDULER_ET_OUT; fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32 t->read_fd = -1; @@ -753,28 +777,32 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, size_t i; for (i = 0; i != read_nh_len; ++i) { - fdi->fd = read_nh[i]; + fdi->fd = GNUNET_NETWORK_socket_box_native (GNUNET_NETWORK_get_fd (read_nh[i])); + GNUNET_assert (NULL != fdi->fd); fdi->et = GNUNET_SCHEDULER_ET_IN; fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]); ++fdi; } for (i = 0; i != write_nh_len; ++i) { - fdi->fd = write_nh[i]; + fdi->fd = GNUNET_NETWORK_socket_box_native (GNUNET_NETWORK_get_fd (write_nh[i])); + GNUNET_assert (NULL != fdi->fd); fdi->et = GNUNET_SCHEDULER_ET_OUT; fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]); ++fdi; } for (i = 0; i != read_fh_len; ++i) { - fdi->fh = read_fh[i]; + fdi->fh = GNUNET_DISK_get_handle_from_int_fd (read_fh[i]->fd); + GNUNET_assert (NULL != fdi->fh); fdi->et = GNUNET_SCHEDULER_ET_IN; fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32 ++fdi; } for (i = 0; i != write_fh_len; ++i) { - fdi->fh = write_fh[i]; + fdi->fh = GNUNET_DISK_get_handle_from_int_fd (write_fh[i]->fd); + GNUNET_assert (NULL != fdi->fh); fdi->et = GNUNET_SCHEDULER_ET_OUT; fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32 ++fdi; @@ -782,86 +810,6 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, } } -//void -//init_fd_info (struct GNUNET_SCHEDULER_Task *t, -// const struct GNUNET_NETWORK_Handle *read_nh, -// const struct GNUNET_NETWORK_Handle *write_nh, -// const struct GNUNET_DISK_FileHandle *read_fh, -// const struct GNUNET_DISK_FileHandle *write_fh) -//{ -// // either only network handles or only file handles are allowed -// GNUNET_assert (!((NULL != read_nh || NULL != write_nh) && (NULL != read_fh || NULL != write_fh))); -// -// if (NULL != read_nh && NULL != write_nh) -// { -// int read_fd = GNUNET_NETWORK_get_fd (read_nh); -// int write_fd = GNUNET_NETWORK_get_fd (write_nh); -// t->read_fd = read_fd; -// t->write_fd = write_fd; -// struct GNUNET_SCHEDULER_FdInfo *fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); -// struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; -// struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; -// fds[0] = read_fdi; -// fds[1] = write_fdi; -// t->fds = fds; -// t->fds_len = 2; -// } -// else if (NULL != read_fh && NULL != write_fh) -// { -// int read_fd = read_fh->fd; -// int write_fd = write_fh->fd; -// struct GNUNET_SCHEDULER_FdInfo *fds = GNUNET_new_array (2, struct GNUNET_SCHEDULER_FdInfo); -// struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; -// struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; -// t->read_fd = read_fd; -// t->write_fd = write_fd; -// fds[0] = read_fdi; -// fds[1] = write_fdi; -// t->fds = fds; -// t->fds_len = 2; -// } -// else if (NULL != read_nh) -// { -// int read_fd = GNUNET_NETWORK_get_fd (read_nh); -// struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fd = read_nh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; -// t->read_fd = read_fd; -// t->write_fd = -1; -// t->fdx = read_fdi; -// t->fds = &t->fdx; -// t->fds_len = 1; -// } -// else if (NULL != write_nh) -// { -// int write_fd = GNUNET_NETWORK_get_fd (write_nh); -// struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fd = write_nh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; -// t->read_fd = -1; -// t->write_fd = write_fd; -// t->fdx = write_fdi; -// t->fds = &t->fdx; -// t->fds_len = 1; -// } -// else if (NULL != read_fh) -// { -// int read_fd = read_fh->fd; -// struct GNUNET_SCHEDULER_FdInfo read_fdi = {.fh = read_fh, .et = GNUNET_SCHEDULER_ET_IN, .sock = read_fd}; -// t->read_fd = read_fd; -// t->write_fd = -1; -// t->fdx = read_fdi; -// t->fds = &t->fdx; -// t->fds_len = 1; -// } -// else if (NULL != write_fh) -// { -// int write_fd = write_fh->fd; -// struct GNUNET_SCHEDULER_FdInfo write_fdi = {.fh = write_fh, .et = GNUNET_SCHEDULER_ET_OUT, .sock = write_fd}; -// t->read_fd = -1; -// t->write_fd = write_fd; -// t->fdx = write_fdi; -// t->fds = &t->fdx; -// t->fds_len = 1; -// } -//} - void scheduler_multi_function_call(struct GNUNET_SCHEDULER_Task *t, int (*driver_func)()) { @@ -922,10 +870,11 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) (GNUNET_NO == task->lifeness) ); if (! task->in_ready_list) { - if ( (-1 == task->read_fd) && - (-1 == task->write_fd) && - (NULL == task->read_set) && - (NULL == task->write_set) ) + //if ( (-1 == task->read_fd) && + // (-1 == task->write_fd) && + // (NULL == task->read_set) && + // (NULL == task->write_set) ) + if (NULL == task->fds) { if (GNUNET_YES == task->on_shutdown) GNUNET_CONTAINER_DLL_remove (shutdown_head, @@ -1671,6 +1620,92 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, } +int +extract_handles (const struct GNUNET_NETWORK_FDSet *fdset, + const struct GNUNET_NETWORK_Handle ***ntarget, + unsigned int *extracted_nhandles, + const struct GNUNET_DISK_FileHandle ***ftarget, + unsigned int *extracted_fhandles) +{ + // FIXME: this implementation only works for unix, for WIN32 the file handles + // in fdset must be handled separately + const struct GNUNET_NETWORK_Handle **nhandles; + const struct GNUNET_DISK_FileHandle **fhandles; + unsigned int nhandle_count, fhandle_count; + int sock; + int ret; + + nhandles = NULL; + fhandles = NULL; + nhandle_count = 0; + fhandle_count = 0; + ret = GNUNET_OK; + for (sock = 0; sock != fdset->nsds; ++sock) + { + if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock)) + { + const struct GNUNET_NETWORK_Handle *nhandle; + const struct GNUNET_DISK_FileHandle *fhandle; + + nhandle = GNUNET_NETWORK_socket_box_native (sock); + if (NULL != nhandle) + { + GNUNET_array_append (nhandles, nhandle_count, nhandle); + ++nhandle_count; + } + else + { + fhandle = GNUNET_DISK_get_handle_from_int_fd (sock); + if (NULL == fhandle) + { + ret = GNUNET_SYSERR; + // DEBUG + GNUNET_assert (0); + } + else + { + GNUNET_array_append (fhandles, fhandle_count, fhandle); + ++fhandle_count; + } + } + } + } + *ntarget = nhandles; + *ftarget = fhandles; + *extracted_nhandles = nhandle_count; + *extracted_fhandles = fhandle_count; + return ret; +} + + +void +destroy_network_handles (const struct GNUNET_NETWORK_Handle **handles, + unsigned int handles_len) +{ + size_t i; + + for (i = 0; i != handles_len; ++i) + { + GNUNET_free ((void *) handles[i]); + } + GNUNET_array_grow (handles, handles_len, 0); +} + + +void +destroy_file_handles (const struct GNUNET_DISK_FileHandle **handles, + unsigned int handles_len) +{ + size_t i; + + for (i = 0; i != handles_len; ++i) + { + GNUNET_free ((void *) handles[i]); + } + GNUNET_array_grow (handles, handles_len, 0); +} + + /** * Schedule a new task to be run with a specified delay or when any of * the specified file descriptor sets is ready. The delay can be used @@ -1708,6 +1743,14 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, void *task_cls) { struct GNUNET_SCHEDULER_Task *t; + const struct GNUNET_NETWORK_Handle **read_nhandles, **write_nhandles; + const struct GNUNET_DISK_FileHandle **read_fhandles, **write_fhandles; + unsigned int read_nhandles_len, write_nhandles_len, + read_fhandles_len, write_fhandles_len; + + LOG (GNUNET_ERROR_TYPE_WARNING, + "[%p] GNUNET_SCHDULER_add_select\n", + sh); if ( (NULL == rs) && (NULL == ws) ) @@ -1724,16 +1767,40 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, t->callback_cls = task_cls; t->read_fd = -1; t->write_fd = -1; + read_nhandles_len = 0; + write_nhandles_len = 0; + read_fhandles_len = 0; + write_fhandles_len = 0; if (NULL != rs) { - t->read_set = GNUNET_NETWORK_fdset_create (); - GNUNET_NETWORK_fdset_copy (t->read_set, rs); + extract_handles (rs, + &read_nhandles, + &read_nhandles_len, + &read_fhandles, + &read_fhandles_len); } if (NULL != ws) { - t->write_set = GNUNET_NETWORK_fdset_create (); - GNUNET_NETWORK_fdset_copy (t->write_set, ws); + extract_handles (ws, + &write_nhandles, + &write_nhandles_len, + &write_fhandles, + &write_fhandles_len); } + GNUNET_assert (read_nhandles_len + write_nhandles_len > 0); + init_fd_info (t, + read_nhandles, + read_nhandles_len, + write_nhandles, + write_nhandles_len, + read_fhandles, + read_fhandles_len, + write_fhandles, + write_fhandles_len); + destroy_network_handles (read_nhandles, read_nhandles_len); + destroy_network_handles (write_nhandles, write_nhandles_len); + destroy_file_handles (read_fhandles, read_fhandles_len); + destroy_file_handles (write_fhandles, write_fhandles_len); #if PROFILE_DELAYS t->start_time = GNUNET_TIME_absolute_get (); #endif @@ -2238,7 +2305,7 @@ select_loop (void *cls, LOG (GNUNET_ERROR_TYPE_WARNING, "[%p] Looks like we're busy waiting...\n", sh); - GNUNET_assert (0); + //GNUNET_assert (0); short_wait (100); /* mitigate */ } for (pos = context->scheduled_in_head; NULL != pos; pos = pos->next) -- cgit v1.2.3 From 59837ecc5f54c39322cc5afba2dfc9fed154a8fe Mon Sep 17 00:00:00 2001 From: lurchi Date: Thu, 17 Aug 2017 20:32:17 +0200 Subject: increasing length variable is already done by GNUNET_xgrow_ (called by the GNUNET_array_append macro) --- src/util/scheduler.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 353b4a669..19ec4efeb 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -1651,7 +1651,6 @@ extract_handles (const struct GNUNET_NETWORK_FDSet *fdset, if (NULL != nhandle) { GNUNET_array_append (nhandles, nhandle_count, nhandle); - ++nhandle_count; } else { @@ -1665,7 +1664,6 @@ extract_handles (const struct GNUNET_NETWORK_FDSet *fdset, else { GNUNET_array_append (fhandles, fhandle_count, fhandle); - ++fhandle_count; } } } @@ -1748,10 +1746,6 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, unsigned int read_nhandles_len, write_nhandles_len, read_fhandles_len, write_fhandles_len; - LOG (GNUNET_ERROR_TYPE_WARNING, - "[%p] GNUNET_SCHDULER_add_select\n", - sh); - if ( (NULL == rs) && (NULL == ws) ) return GNUNET_SCHEDULER_add_delayed_with_priority (delay, -- cgit v1.2.3 From e29921e503d8da33f0b9b15302288c5572ec9bf4 Mon Sep 17 00:00:00 2001 From: lurchi Date: Fri, 18 Aug 2017 16:17:28 +0200 Subject: implement bookkeeping about which FDs related to a tasks have been marked ready (required API change in GNUNET_SCHEDULER_task_ready) --- src/include/gnunet_scheduler_lib.h | 4 +- src/util/scheduler.c | 139 ++++++++++++++++++++++--------------- 2 files changed, 86 insertions(+), 57 deletions(-) (limited to 'src/util') diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h index dea0a006a..5f9389726 100644 --- a/src/include/gnunet_scheduler_lib.h +++ b/src/include/gnunet_scheduler_lib.h @@ -222,11 +222,11 @@ struct GNUNET_SCHEDULER_TaskContext * that the task is ready (with the respective priority). * * @param task the task that is ready - * @param et information about why the task is ready + * @param fdi information about the related FD */ void GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, - enum GNUNET_SCHEDULER_EventType et); + struct GNUNET_SCHEDULER_FdInfo *fdi); /** diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 19ec4efeb..33aba9ad6 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -148,6 +148,24 @@ struct GNUNET_SCHEDULER_Task * Absolute timeout value for the task, or * #GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout". */ + + /** + * Size of the @e fds array. + */ + unsigned int fds_len; + + /** + * if this task is related to multiple FDs this array contains + * all FdInfo structs that were marked as ready by calling + * #GNUNET_SCHEDULER_task_ready + */ + struct GNUNET_SCHEDULER_FdInfo *ready_fds; + + /** + * Size of the @e ready_fds array + */ + unsigned int ready_fds_len; + struct GNUNET_TIME_Absolute timeout; #if PROFILE_DELAYS @@ -157,11 +175,6 @@ struct GNUNET_SCHEDULER_Task struct GNUNET_TIME_Absolute start_time; #endif - /** - * Size of the @e fds array. - */ - unsigned int fds_len; - /** * Why is the task ready? Set after task is added to ready queue. * Initially set to zero. All reasons that have already been @@ -476,6 +489,29 @@ GNUNET_SCHEDULER_shutdown () } +static void +destroy_fd_info_list (struct GNUNET_SCHEDULER_FdInfo *fds, unsigned int fds_len) +{ + unsigned int i; + for (i = 0; i != fds_len; ++i) + { + const struct GNUNET_SCHEDULER_FdInfo *fdi = fds + i; + if (fdi->fd) + { + GNUNET_NETWORK_socket_free_memory_only_ ((struct GNUNET_NETWORK_Handle *) fdi->fd); + } + if (fdi->fh) + { + // FIXME: on WIN32 this is not enough! A function + // GNUNET_DISK_file_free_memory_only would be nice + GNUNET_free ((void *) fdi->fh); + } + } + /* free the array */ + GNUNET_array_grow (fds, fds_len, 0); +} + + /** * Destroy a task (release associated resources) * @@ -484,31 +520,16 @@ GNUNET_SCHEDULER_shutdown () static void destroy_task (struct GNUNET_SCHEDULER_Task *t) { - // FIXME: destroy fds! if (t->fds_len > 1) { - size_t i; - for (i = 0; i != t->fds_len; ++i) - { - const struct GNUNET_SCHEDULER_FdInfo *fdi = t->fds + i; - if (fdi->fd) - { - GNUNET_NETWORK_socket_free_memory_only_ ((struct GNUNET_NETWORK_Handle *) fdi->fd); - } - if (fdi->fh) - { - // FIXME: on WIN32 this is not enough! A function - // GNUNET_DISK_file_free_memory_only would be nice - GNUNET_free ((void *) fdi->fh); - } - } - /* free the array */ - GNUNET_array_grow (t->fds, t->fds_len, 0); + destroy_fd_info_list ((struct GNUNET_SCHEDULER_FdInfo *) t->fds, + t->fds_len); + } + if (t->ready_fds_len > 0) + { + destroy_fd_info_list ((struct GNUNET_SCHEDULER_FdInfo *) t->ready_fds, + t->ready_fds_len); } - //if (NULL != t->read_set) - // GNUNET_NETWORK_fdset_destroy (t->read_set); - //if (NULL != t->write_set) - // GNUNET_NETWORK_fdset_destroy (t->write_set); #if EXECINFO GNUNET_free (t->backtrace_strings); #endif @@ -1318,11 +1339,6 @@ add_without_sets (struct GNUNET_TIME_Relative delay, read_fh ? 1 : 0, &write_fh, write_fh ? 1 : 0); - - //int read_fds[2] = {GNUNET_NETWORK_get_fd (read_nh), read_fh->fd}; - //int write_fds[2] = {GNUNET_NETWORK_get_fd (write_nh), write_fh->fd}; - //init_fd_info (t, read_fds, 2, write_fds, 2); - //init_fd_info (t, read_nh, write_nh, read_fh, write_fh); t->callback = task; t->callback_cls = task_cls; #if DEBUG_FDS @@ -1826,11 +1842,11 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, * that the task is ready (with the respective priority). * * @param task the task that is ready, NULL for wake up calls - * @param et information about why the task is ready + * @param fdi information about the related FD */ void GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, - enum GNUNET_SCHEDULER_EventType et) + struct GNUNET_SCHEDULER_FdInfo *fdi) { enum GNUNET_SCHEDULER_Reason reason; struct GNUNET_TIME_Absolute now; @@ -1840,24 +1856,24 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, if (now.abs_value_us >= task->timeout.abs_value_us) reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; if ( (0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) && - (0 != (GNUNET_SCHEDULER_ET_IN & et)) ) + (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)) ) reason |= GNUNET_SCHEDULER_REASON_READ_READY; if ( (0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) && - (0 != (GNUNET_SCHEDULER_ET_OUT & et)) ) + (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)) ) reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; - - - - task->reason = reason; - task->fds = &task->fdx; // FIXME: if task contains a list of fds, this is wrong! - task->fdx.et = et; - task->fds_len = 1; - GNUNET_CONTAINER_DLL_remove (pending_head, - pending_tail, - task); - queue_ready_task (task); + if (task->fds_len > 1) + { + GNUNET_array_append (task->ready_fds, task->ready_fds_len, *fdi); + } + if (GNUNET_NO == task->in_ready_list) + { + GNUNET_CONTAINER_DLL_remove (pending_head, + pending_tail, + task); + queue_ready_task (task); + } } @@ -1884,6 +1900,7 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) enum GNUNET_SCHEDULER_Priority p; struct GNUNET_SCHEDULER_Task *pos; struct GNUNET_TIME_Absolute now; + int i; /* check for tasks that reached the timeout! */ now = GNUNET_TIME_absolute_get (); @@ -1942,20 +1959,32 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) tc.reason = pos->reason; GNUNET_NETWORK_fdset_zero (sh->rs); GNUNET_NETWORK_fdset_zero (sh->ws); - tc.fds_len = pos->fds_len; - tc.fds = pos->fds; - //tc.read_ready = (NULL == pos->read_set) ? sh->rs : pos->read_set; - tc.read_ready = sh->rs; + tc.fds_len = pos->ready_fds_len; + tc.fds = pos->ready_fds; + for (i = 0; i != pos->ready_fds_len; ++i) + { + struct GNUNET_SCHEDULER_FdInfo *fdi = pos->ready_fds + i; + if (GNUNET_SCHEDULER_ET_IN == fdi->et) + { + GNUNET_NETWORK_fdset_set_native (sh->rs, + fdi->sock); + } + else if (GNUNET_SCHEDULER_ET_OUT == fdi->et) + { + GNUNET_NETWORK_fdset_set_native (sh->ws, + fdi->sock); + } + } if ( (-1 != pos->read_fd) && (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ) GNUNET_NETWORK_fdset_set_native (sh->rs, pos->read_fd); - //tc.write_ready = (NULL == pos->write_set) ? sh->ws : pos->write_set; - tc.write_ready = sh->ws; if ( (-1 != pos->write_fd) && (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ) GNUNET_NETWORK_fdset_set_native (sh->ws, pos->write_fd); + tc.read_ready = sh->rs; + tc.write_ready = sh->ws; LOG (GNUNET_ERROR_TYPE_DEBUG, "Running task %p\n", pos); @@ -2309,7 +2338,7 @@ select_loop (void *cls, GNUNET_CONTAINER_DLL_remove (context->scheduled_in_head, context->scheduled_in_tail, pos); - GNUNET_SCHEDULER_task_ready (pos->task, GNUNET_SCHEDULER_ET_IN); + GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi); } } for (pos = context->scheduled_out_head; NULL != pos; pos = pos->next) @@ -2319,7 +2348,7 @@ select_loop (void *cls, GNUNET_CONTAINER_DLL_remove (context->scheduled_out_head, context->scheduled_out_tail, pos); - GNUNET_SCHEDULER_task_ready (pos->task, GNUNET_SCHEDULER_ET_OUT); + GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi); } } int tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); -- cgit v1.2.3 From 024beb50aadb8e5a58dbb85cd3e819748dd4de3e Mon Sep 17 00:00:00 2001 From: lurchi Date: Mon, 21 Aug 2017 01:07:27 +0200 Subject: only allocate network / file handles and store them in the task when GNUNET_SCHEDULER_add_select is used --- src/util/scheduler.c | 194 +++++++++++++++++++++------------------------------ 1 file changed, 78 insertions(+), 116 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 33aba9ad6..71a3bd956 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -117,21 +117,6 @@ struct GNUNET_SCHEDULER_Task */ void *callback_cls; - ///** - // * Set of file descriptors this task is waiting - // * for for reading. Once ready, this is updated - // * to reflect the set of file descriptors ready - // * for operation. - // */ - //struct GNUNET_NETWORK_FDSet *read_set; - - ///** - // * Set of file descriptors this task is waiting for for writing. - // * Once ready, this is updated to reflect the set of file - // * descriptors ready for operation. - // */ - //struct GNUNET_NETWORK_FDSet *write_set; - /** * Information about which FDs are ready for this task (and why). */ @@ -144,11 +129,6 @@ struct GNUNET_SCHEDULER_Task */ struct GNUNET_SCHEDULER_FdInfo fdx; - /** - * Absolute timeout value for the task, or - * #GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout". - */ - /** * Size of the @e fds array. */ @@ -166,6 +146,17 @@ struct GNUNET_SCHEDULER_Task */ unsigned int ready_fds_len; + /** + * Do we own the network and file handlers referenced by the FdInfo + * structs in the fds array. This will only be GNUNET_YES if the + * task was created by the #GNUNET_SCHEDULER_add_select function. + */ + int own_handlers; + + /** + * Absolute timeout value for the task, or + * #GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout". + */ struct GNUNET_TIME_Absolute timeout; #if PROFILE_DELAYS @@ -489,29 +480,6 @@ GNUNET_SCHEDULER_shutdown () } -static void -destroy_fd_info_list (struct GNUNET_SCHEDULER_FdInfo *fds, unsigned int fds_len) -{ - unsigned int i; - for (i = 0; i != fds_len; ++i) - { - const struct GNUNET_SCHEDULER_FdInfo *fdi = fds + i; - if (fdi->fd) - { - GNUNET_NETWORK_socket_free_memory_only_ ((struct GNUNET_NETWORK_Handle *) fdi->fd); - } - if (fdi->fh) - { - // FIXME: on WIN32 this is not enough! A function - // GNUNET_DISK_file_free_memory_only would be nice - GNUNET_free ((void *) fdi->fh); - } - } - /* free the array */ - GNUNET_array_grow (fds, fds_len, 0); -} - - /** * Destroy a task (release associated resources) * @@ -520,15 +488,33 @@ destroy_fd_info_list (struct GNUNET_SCHEDULER_FdInfo *fds, unsigned int fds_len) static void destroy_task (struct GNUNET_SCHEDULER_Task *t) { + unsigned int i; + + if (GNUNET_YES == t->own_handlers) + { + for (i = 0; i != t->fds_len; ++i) + { + const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd; + const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh; + if (fd) + { + GNUNET_NETWORK_socket_free_memory_only_ ((struct GNUNET_NETWORK_Handle *) fd); + } + if (fh) + { + // FIXME: on WIN32 this is not enough! A function + // GNUNET_DISK_file_free_memory_only would be nice + GNUNET_free ((void *) fh); + } + } + } if (t->fds_len > 1) { - destroy_fd_info_list ((struct GNUNET_SCHEDULER_FdInfo *) t->fds, - t->fds_len); + GNUNET_array_grow (t->fds, t->fds_len, 0); } if (t->ready_fds_len > 0) { - destroy_fd_info_list ((struct GNUNET_SCHEDULER_FdInfo *) t->ready_fds, - t->ready_fds_len); + GNUNET_array_grow (t->ready_fds, t->ready_fds_len, 0); } #if EXECINFO GNUNET_free (t->backtrace_strings); @@ -737,13 +723,13 @@ GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) void init_fd_info (struct GNUNET_SCHEDULER_Task *t, const struct GNUNET_NETWORK_Handle *const *read_nh, - size_t read_nh_len, + unsigned int read_nh_len, const struct GNUNET_NETWORK_Handle *const *write_nh, - size_t write_nh_len, + unsigned int write_nh_len, const struct GNUNET_DISK_FileHandle *const *read_fh, - size_t read_fh_len, + unsigned int read_fh_len, const struct GNUNET_DISK_FileHandle *const *write_fh, - size_t write_fh_len) + unsigned int write_fh_len) { struct GNUNET_SCHEDULER_FdInfo *fdi; @@ -754,7 +740,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, t->fds = fdi; if (1 == read_nh_len) { - fdi->fd = GNUNET_NETWORK_socket_box_native (GNUNET_NETWORK_get_fd (*read_nh)); + fdi->fd = *read_nh; GNUNET_assert (NULL != fdi->fd); fdi->et = GNUNET_SCHEDULER_ET_IN; fdi->sock = GNUNET_NETWORK_get_fd (*read_nh); @@ -763,7 +749,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, } else if (1 == write_nh_len) { - fdi->fd = GNUNET_NETWORK_socket_box_native (GNUNET_NETWORK_get_fd (*write_nh)); + fdi->fd = *write_nh; GNUNET_assert (NULL != fdi->fd); fdi->et = GNUNET_SCHEDULER_ET_OUT; fdi->sock = GNUNET_NETWORK_get_fd (*write_nh); @@ -772,7 +758,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, } else if (1 == read_fh_len) { - fdi->fh = GNUNET_DISK_get_handle_from_int_fd ((*read_fh)->fd); + fdi->fh = *read_fh; GNUNET_assert (NULL != fdi->fh); fdi->et = GNUNET_SCHEDULER_ET_IN; fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32 @@ -781,7 +767,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, } else { - fdi->fh = GNUNET_DISK_get_handle_from_int_fd ((*write_fh)->fd); + fdi->fh = *write_fh; GNUNET_assert (NULL != fdi->fh); fdi->et = GNUNET_SCHEDULER_ET_OUT; fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32 @@ -795,10 +781,10 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, t->fds = fdi; t->read_fd = -1; t->write_fd = -1; - size_t i; + unsigned int i; for (i = 0; i != read_nh_len; ++i) { - fdi->fd = GNUNET_NETWORK_socket_box_native (GNUNET_NETWORK_get_fd (read_nh[i])); + fdi->fd = read_nh[i]; GNUNET_assert (NULL != fdi->fd); fdi->et = GNUNET_SCHEDULER_ET_IN; fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]); @@ -806,7 +792,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, } for (i = 0; i != write_nh_len; ++i) { - fdi->fd = GNUNET_NETWORK_socket_box_native (GNUNET_NETWORK_get_fd (write_nh[i])); + fdi->fd = write_nh[i]; GNUNET_assert (NULL != fdi->fd); fdi->et = GNUNET_SCHEDULER_ET_OUT; fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]); @@ -814,7 +800,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, } for (i = 0; i != read_fh_len; ++i) { - fdi->fh = GNUNET_DISK_get_handle_from_int_fd (read_fh[i]->fd); + fdi->fh = read_fh[i]; GNUNET_assert (NULL != fdi->fh); fdi->et = GNUNET_SCHEDULER_ET_IN; fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32 @@ -822,7 +808,7 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, } for (i = 0; i != write_fh_len; ++i) { - fdi->fh = GNUNET_DISK_get_handle_from_int_fd (write_fh[i]->fd); + fdi->fh = write_fh[i]; GNUNET_assert (NULL != fdi->fh); fdi->et = GNUNET_SCHEDULER_ET_OUT; fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32 @@ -891,10 +877,6 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) (GNUNET_NO == task->lifeness) ); if (! task->in_ready_list) { - //if ( (-1 == task->read_fd) && - // (-1 == task->write_fd) && - // (NULL == task->read_set) && - // (NULL == task->write_set) ) if (NULL == task->fds) { if (GNUNET_YES == task->on_shutdown) @@ -1637,7 +1619,8 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, int -extract_handles (const struct GNUNET_NETWORK_FDSet *fdset, +extract_handles (struct GNUNET_SCHEDULER_Task *t, + const struct GNUNET_NETWORK_FDSet *fdset, const struct GNUNET_NETWORK_Handle ***ntarget, unsigned int *extracted_nhandles, const struct GNUNET_DISK_FileHandle ***ftarget, @@ -1647,79 +1630,51 @@ extract_handles (const struct GNUNET_NETWORK_FDSet *fdset, // in fdset must be handled separately const struct GNUNET_NETWORK_Handle **nhandles; const struct GNUNET_DISK_FileHandle **fhandles; - unsigned int nhandle_count, fhandle_count; + unsigned int nhandles_len, fhandles_len; int sock; int ret; nhandles = NULL; fhandles = NULL; - nhandle_count = 0; - fhandle_count = 0; + nhandles_len = 0; + fhandles_len = 0; ret = GNUNET_OK; for (sock = 0; sock != fdset->nsds; ++sock) { if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock)) { - const struct GNUNET_NETWORK_Handle *nhandle; - const struct GNUNET_DISK_FileHandle *fhandle; + struct GNUNET_NETWORK_Handle *nhandle; + struct GNUNET_DISK_FileHandle *fhandle; nhandle = GNUNET_NETWORK_socket_box_native (sock); if (NULL != nhandle) { - GNUNET_array_append (nhandles, nhandle_count, nhandle); + GNUNET_array_append (nhandles, nhandles_len, nhandle); } else { fhandle = GNUNET_DISK_get_handle_from_int_fd (sock); - if (NULL == fhandle) + if (NULL != fhandle) { - ret = GNUNET_SYSERR; - // DEBUG - GNUNET_assert (0); + GNUNET_array_append (fhandles, fhandles_len, fhandle); } else { - GNUNET_array_append (fhandles, fhandle_count, fhandle); + ret = GNUNET_SYSERR; + // DEBUG + GNUNET_assert (0); } } } } - *ntarget = nhandles; - *ftarget = fhandles; - *extracted_nhandles = nhandle_count; - *extracted_fhandles = fhandle_count; + *ntarget = nhandles_len > 0 ? nhandles : NULL; + *ftarget = fhandles_len > 0 ? fhandles : NULL; + *extracted_nhandles = nhandles_len; + *extracted_fhandles = fhandles_len; return ret; } -void -destroy_network_handles (const struct GNUNET_NETWORK_Handle **handles, - unsigned int handles_len) -{ - size_t i; - - for (i = 0; i != handles_len; ++i) - { - GNUNET_free ((void *) handles[i]); - } - GNUNET_array_grow (handles, handles_len, 0); -} - - -void -destroy_file_handles (const struct GNUNET_DISK_FileHandle **handles, - unsigned int handles_len) -{ - size_t i; - - for (i = 0; i != handles_len; ++i) - { - GNUNET_free ((void *) handles[i]); - } - GNUNET_array_grow (handles, handles_len, 0); -} - - /** * Schedule a new task to be run with a specified delay or when any of * the specified file descriptor sets is ready. The delay can be used @@ -1757,8 +1712,10 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, void *task_cls) { struct GNUNET_SCHEDULER_Task *t; - const struct GNUNET_NETWORK_Handle **read_nhandles, **write_nhandles; - const struct GNUNET_DISK_FileHandle **read_fhandles, **write_fhandles; + const struct GNUNET_NETWORK_Handle **read_nhandles; + const struct GNUNET_NETWORK_Handle **write_nhandles; + const struct GNUNET_DISK_FileHandle **read_fhandles; + const struct GNUNET_DISK_FileHandle **write_fhandles; unsigned int read_nhandles_len, write_nhandles_len, read_fhandles_len, write_fhandles_len; @@ -1777,13 +1734,15 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, t->callback_cls = task_cls; t->read_fd = -1; t->write_fd = -1; + t->own_handlers = GNUNET_YES; read_nhandles_len = 0; write_nhandles_len = 0; read_fhandles_len = 0; write_fhandles_len = 0; if (NULL != rs) { - extract_handles (rs, + extract_handles (t, + rs, &read_nhandles, &read_nhandles_len, &read_fhandles, @@ -1791,7 +1750,8 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, } if (NULL != ws) { - extract_handles (ws, + extract_handles (t, + ws, &write_nhandles, &write_nhandles_len, &write_fhandles, @@ -1807,10 +1767,12 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, read_fhandles_len, write_fhandles, write_fhandles_len); - destroy_network_handles (read_nhandles, read_nhandles_len); - destroy_network_handles (write_nhandles, write_nhandles_len); - destroy_file_handles (read_fhandles, read_fhandles_len); - destroy_file_handles (write_fhandles, write_fhandles_len); + /* free the arrays of pointers to network / file handles, the actual + * handles will be freed in destroy_task */ + GNUNET_array_grow (read_nhandles, read_nhandles_len, 0); + GNUNET_array_grow (write_nhandles, write_nhandles_len, 0); + GNUNET_array_grow (read_fhandles, read_fhandles_len, 0); + GNUNET_array_grow (write_fhandles, write_fhandles_len, 0); #if PROFILE_DELAYS t->start_time = GNUNET_TIME_absolute_get (); #endif -- cgit v1.2.3 From 357181530f9089ee30ba88c55ed429ec58505357 Mon Sep 17 00:00:00 2001 From: lurchi Date: Wed, 23 Aug 2017 15:44:52 +0200 Subject: tasks in the pending queue must be be checked for reached timeouts, too; allow multiple event types per FdInfo --- src/util/scheduler.c | 346 ++++++++++++++++++++++++++++----------------------- 1 file changed, 193 insertions(+), 153 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 71a3bd956..084ca43df 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -120,7 +120,7 @@ struct GNUNET_SCHEDULER_Task /** * Information about which FDs are ready for this task (and why). */ - const struct GNUNET_SCHEDULER_FdInfo *fds; + struct GNUNET_SCHEDULER_FdInfo *fds; /** * Storage location used for @e fds if we want to avoid @@ -229,6 +229,10 @@ struct Scheduled struct GNUNET_SCHEDULER_Task *task; struct GNUNET_SCHEDULER_FdInfo *fdi; + + enum GNUNET_SCHEDULER_EventType et; + + int is_ready; }; @@ -237,13 +241,9 @@ struct Scheduled */ struct DriverContext { - struct Scheduled *scheduled_in_head; - - struct Scheduled *scheduled_in_tail; + struct Scheduled *scheduled_head; - struct Scheduled *scheduled_out_head; - - struct Scheduled *scheduled_out_tail; + struct Scheduled *scheduled_tail; struct GNUNET_TIME_Relative timeout; }; @@ -480,6 +480,27 @@ GNUNET_SCHEDULER_shutdown () } +/** + * Output stack trace of task @a t. + * + * @param t task to dump stack trace of + */ +static void +dump_backtrace (struct GNUNET_SCHEDULER_Task *t) +{ +#if EXECINFO + unsigned int i; + + for (i = 0; i < t->num_backtrace_strings; i++) + LOG (GNUNET_ERROR_TYPE_WARNING, + "Task %p trace %u: %s\n", + t, + i, + t->backtrace_strings[i]); +#endif +} + + /** * Destroy a task (release associated resources) * @@ -523,27 +544,6 @@ destroy_task (struct GNUNET_SCHEDULER_Task *t) } -/** - * Output stack trace of task @a t. - * - * @param t task to dump stack trace of - */ -static void -dump_backtrace (struct GNUNET_SCHEDULER_Task *t) -{ -#if EXECINFO - unsigned int i; - - for (i = 0; i < t->num_backtrace_strings; i++) - LOG (GNUNET_ERROR_TYPE_WARNING, - "Task %p trace %u: %s\n", - t, - i, - t->backtrace_strings[i]); -#endif -} - - /** * Pipe used to communicate shutdown via signal. */ @@ -645,6 +645,34 @@ GNUNET_SCHEDULER_check_lifeness () } +void +shutdown_if_no_lifeness () +{ + struct GNUNET_SCHEDULER_Task *t; + + if (ready_count > 0) + return; + for (t = pending_head; NULL != t; t = t->next) + if (GNUNET_YES == t->lifeness) + return; + for (t = shutdown_head; NULL != t; t = t->next) + if (GNUNET_YES == t->lifeness) + return; + for (t = pending_timeout_head; NULL != t; t = t->next) + if (GNUNET_YES == t->lifeness) + return; + /* No lifeness! Cancel all pending tasks the driver knows about and shutdown */ + t = pending_head; + while (NULL != t) + { + struct GNUNET_SCHEDULER_Task *next = t->next; + GNUNET_SCHEDULER_cancel (t); + t = next; + } + GNUNET_SCHEDULER_shutdown (); +} + + /** * Initialize and run scheduler. This function will return when all * tasks have completed. On systems with signals, receiving a SIGTERM @@ -664,10 +692,8 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, void *task_cls) { struct GNUNET_SCHEDULER_Driver *driver; - struct DriverContext context = {.scheduled_in_head = NULL, - .scheduled_in_tail = NULL, - .scheduled_out_head = NULL, - .scheduled_out_tail = NULL, + struct DriverContext context = {.scheduled_head = NULL, + .scheduled_tail = NULL, .timeout = GNUNET_TIME_UNIT_FOREVER_REL}; driver = GNUNET_SCHEDULER_driver_select (); @@ -731,6 +757,9 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, const struct GNUNET_DISK_FileHandle *const *write_fh, unsigned int write_fh_len) { + // FIXME: if we have exactly two network handles / exactly two file handles + // and they are equal, we can make one FdInfo with both + // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set. struct GNUNET_SCHEDULER_FdInfo *fdi; t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len; @@ -818,20 +847,39 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, } -void scheduler_multi_function_call(struct GNUNET_SCHEDULER_Task *t, int (*driver_func)()) +/** + * calls the given function @a func on each FdInfo related to @a t. + * Optionally updates the event type field in each FdInfo after calling + * @a func. + * + * @param t the task + * @param driver_func the function to call with each FdInfo contained in + * in @a t + * @param if_not_ready only call @a driver_func on FdInfos that are not + * ready + * @param et the event type to be set in each FdInfo after calling + * @a driver_func on it, or -1 if no updating not desired. + */ +void scheduler_multi_function_call (struct GNUNET_SCHEDULER_Task *t, + int (*driver_func)(), + int if_not_ready, + enum GNUNET_SCHEDULER_EventType et) { + struct GNUNET_SCHEDULER_FdInfo *fdi; int success = GNUNET_YES; - if (t->fds_len > 1) + + for (int i = 0; i != t->fds_len; ++i) { - for (int i = 0; i < t->fds_len;i++) + fdi = &t->fds[i]; + if ((GNUNET_NO == if_not_ready) || (GNUNET_SCHEDULER_ET_NONE == fdi->et)) { - success = driver_func (scheduler_driver->cls, t , t->fds+i) && success; + success = driver_func (scheduler_driver->cls, t, fdi) && success; + if (et != -1) + { + fdi->et = et; + } } } - else - { - success = driver_func (scheduler_driver->cls, t , t->fds); - } if (GNUNET_YES != success) { LOG (GNUNET_ERROR_TYPE_ERROR, @@ -841,7 +889,7 @@ void scheduler_multi_function_call(struct GNUNET_SCHEDULER_Task *t, int (*driver void -shutdown_task (void *cls) +shutdown_cb (void *cls) { char c; const struct GNUNET_DISK_FileHandle *pr; @@ -900,7 +948,7 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) GNUNET_CONTAINER_DLL_remove (pending_head, pending_tail, task); - scheduler_multi_function_call(task, scheduler_driver->del); + scheduler_multi_function_call(task, scheduler_driver->del, GNUNET_NO, -1); } } else @@ -911,9 +959,6 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) task); ready_count--; } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Canceling task %p\n", - task); ret = task->callback_cls; destroy_task (task); return ret; @@ -1307,11 +1352,10 @@ add_without_sets (struct GNUNET_TIME_Relative delay, void *task_cls) { struct GNUNET_SCHEDULER_Task *t; - + GNUNET_assert (NULL != active_task); GNUNET_assert (NULL != task); t = GNUNET_new (struct GNUNET_SCHEDULER_Task); - init_fd_info (t, &read_nh, read_nh ? 1 : 0, @@ -1338,7 +1382,7 @@ add_without_sets (struct GNUNET_TIME_Relative delay, GNUNET_CONTAINER_DLL_insert (pending_head, pending_tail, t); - scheduler_multi_function_call (t, scheduler_driver->add); + scheduler_multi_function_call (t, scheduler_driver->add, GNUNET_NO, GNUNET_SCHEDULER_ET_NONE); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1785,7 +1829,7 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, GNUNET_CONTAINER_DLL_insert (pending_head, pending_tail, t); - scheduler_multi_function_call (t, scheduler_driver->add); + scheduler_multi_function_call (t, scheduler_driver->add, GNUNET_NO, GNUNET_SCHEDULER_ET_NONE); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1825,10 +1869,6 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; task->reason = reason; - if (task->fds_len > 1) - { - GNUNET_array_append (task->ready_fds, task->ready_fds_len, *fdi); - } if (GNUNET_NO == task->in_ready_list) { GNUNET_CONTAINER_DLL_remove (pending_head, @@ -1858,11 +1898,9 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, int GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) { - // FIXME: call check_lifeness here! enum GNUNET_SCHEDULER_Priority p; struct GNUNET_SCHEDULER_Task *pos; struct GNUNET_TIME_Absolute now; - int i; /* check for tasks that reached the timeout! */ now = GNUNET_TIME_absolute_get (); @@ -1879,9 +1917,27 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) pending_timeout_last = NULL; queue_ready_task (pos); } + pos = pending_head; + while (NULL != pos) + { + struct GNUNET_SCHEDULER_Task *next = pos->next; + if (now.abs_value_us >= pos->timeout.abs_value_us) + { + pos->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; + GNUNET_CONTAINER_DLL_remove (pending_head, + pending_tail, + pos); + queue_ready_task (pos); + } + pos = next; + } if (0 == ready_count) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "no tasks run!\n"); return GNUNET_NO; + } /* find out which task priority level we are going to process this time */ @@ -1921,41 +1977,36 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) tc.reason = pos->reason; GNUNET_NETWORK_fdset_zero (sh->rs); GNUNET_NETWORK_fdset_zero (sh->ws); - tc.fds_len = pos->ready_fds_len; - tc.fds = pos->ready_fds; - for (i = 0; i != pos->ready_fds_len; ++i) + // FIXME: do we have to remove FdInfos from fds if they are not ready? + tc.fds_len = pos->fds_len; + tc.fds = pos->fds; + for (int i = 0; i != pos->fds_len; ++i) { - struct GNUNET_SCHEDULER_FdInfo *fdi = pos->ready_fds + i; - if (GNUNET_SCHEDULER_ET_IN == fdi->et) + struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i]; + if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)) { GNUNET_NETWORK_fdset_set_native (sh->rs, fdi->sock); } - else if (GNUNET_SCHEDULER_ET_OUT == fdi->et) + if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)) { GNUNET_NETWORK_fdset_set_native (sh->ws, fdi->sock); } } - if ( (-1 != pos->read_fd) && - (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ) - GNUNET_NETWORK_fdset_set_native (sh->rs, - pos->read_fd); - if ( (-1 != pos->write_fd) && - (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ) - GNUNET_NETWORK_fdset_set_native (sh->ws, - pos->write_fd); tc.read_ready = sh->rs; tc.write_ready = sh->ws; LOG (GNUNET_ERROR_TYPE_DEBUG, "Running task %p\n", pos); pos->callback (pos->callback_cls); + scheduler_multi_function_call (pos, scheduler_driver->del, GNUNET_YES, -1); active_task = NULL; dump_backtrace (pos); destroy_task (pos); tasks_run++; } + shutdown_if_no_lifeness (); if (0 == ready_count) { scheduler_driver->set_wakeup (scheduler_driver->cls, @@ -2047,7 +2098,7 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, NULL); GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, pr, - &shutdown_task, + &shutdown_cb, NULL); current_lifeness = GNUNET_YES; GNUNET_SCHEDULER_add_with_reason_and_priority (task, @@ -2093,8 +2144,10 @@ select_add (void *cls, GNUNET_assert (NULL != context); GNUNET_assert (NULL != task); GNUNET_assert (NULL != fdi); + GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) || + 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)); - if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (0 > fdi->sock)) + if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0)) { /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */ return GNUNET_SYSERR; @@ -2103,29 +2156,31 @@ select_add (void *cls, struct Scheduled *scheduled = GNUNET_new (struct Scheduled); scheduled->task = task; scheduled->fdi = fdi; - - switch (fdi->et) - { - case GNUNET_SCHEDULER_ET_IN: - { - GNUNET_CONTAINER_DLL_insert (context->scheduled_in_head, - context->scheduled_in_tail, - scheduled); - break; - } - case GNUNET_SCHEDULER_ET_OUT: - { - GNUNET_CONTAINER_DLL_insert (context->scheduled_out_head, - context->scheduled_out_tail, - scheduled); - break; - } - default: - { - // FIXME: other event types not implemented yet - GNUNET_assert (0); - } - } + scheduled->et = fdi->et; + + GNUNET_CONTAINER_DLL_insert (context->scheduled_head, + context->scheduled_tail, + scheduled); + //if (0 != (GNUNET_SCHEDULER_ET_IN & scheduled->et)) + //{ + // GNUNET_CONTAINER_DLL_insert (context->scheduled_in_head, + // context->scheduled_in_tail, + // scheduled); + //} + //if (0 != (GNUNET_SCHEDULER_ET_OUT & scheduled->et)) + //{ + // GNUNET_CONTAINER_DLL_insert (context->scheduled_out_head, + // context->scheduled_out_tail, + // scheduled); + //} + //if (0 != (GNUNET_SCHEDULER_ET_HUP & scheduled->et) || + // 0 != (GNUNET_SCHEDULER_ET_ERR & scheduled->et) || + // 0 != (GNUNET_SCHEDULER_ET_PRI & scheduled->et) || + // 0 != (GNUNET_SCHEDULER_ET_NVAL & scheduled->et)) + //{ + // // FIXME: other event types not implemented yet + // GNUNET_assert (0); + //} return GNUNET_OK; } @@ -2135,47 +2190,24 @@ select_del (void *cls, struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi) { - struct DriverContext *context = cls; - GNUNET_assert (NULL != context); - - int ret = GNUNET_SYSERR; + struct DriverContext *context; struct Scheduled *pos; - // FIXME: are multiple ORed event types allowed? - switch (fdi->et) - { - case GNUNET_SCHEDULER_ET_IN: - { - for (pos = context->scheduled_in_head; NULL != pos; pos = pos->next) - { - if (pos->task == task) - { - GNUNET_CONTAINER_DLL_remove (context->scheduled_in_head, - context->scheduled_in_tail, - pos); - ret = GNUNET_OK; - } - } - break; - } - case GNUNET_SCHEDULER_ET_OUT: + int ret; + + GNUNET_assert (NULL != cls); + + context = cls; + ret = GNUNET_SYSERR; + for (pos = context->scheduled_head; NULL != pos; pos = pos->next) { - for (pos = context->scheduled_out_head; NULL != pos; pos = pos->next) + if (pos->task == task && pos->fdi == fdi) { - if (pos->task == task) - { - GNUNET_CONTAINER_DLL_remove (context->scheduled_out_head, - context->scheduled_out_tail, - pos); - ret = GNUNET_OK; - } + GNUNET_CONTAINER_DLL_remove (context->scheduled_head, + context->scheduled_tail, + pos); + ret = GNUNET_OK; + break; } - break; - } - default: - { - // FIXME: other event types not implemented yet - GNUNET_assert (0); - } } return ret; } @@ -2189,6 +2221,7 @@ select_loop (void *cls, struct GNUNET_NETWORK_FDSet *ws; struct DriverContext *context; int select_result; + int tasks_ready; unsigned long long last_tr; unsigned int busy_wait_warning; @@ -2196,11 +2229,10 @@ select_loop (void *cls, GNUNET_assert (NULL != context); rs = GNUNET_NETWORK_fdset_create (); ws = GNUNET_NETWORK_fdset_create (); + tasks_ready = GNUNET_NO; last_tr = 0; busy_wait_warning = 0; - // FIXME: remove check_lifeness, instead the condition should be: - // pending_in_head != NULL || pending_out_head != NULL || tasks_ready - while (GNUNET_YES == GNUNET_SCHEDULER_check_lifeness ()) + while (NULL != context->scheduled_head || GNUNET_YES == tasks_ready) { LOG (GNUNET_ERROR_TYPE_WARNING, "[%p] timeout = %s\n", @@ -2210,13 +2242,16 @@ select_loop (void *cls, GNUNET_NETWORK_fdset_zero (rs); GNUNET_NETWORK_fdset_zero (ws); struct Scheduled *pos; - for (pos = context->scheduled_in_head; NULL != pos; pos = pos->next) - { - GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock); - } - for (pos = context->scheduled_out_head; NULL != pos; pos = pos->next) + for (pos = context->scheduled_head; NULL != pos; pos = pos->next) { - GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock); + if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et)) + { + GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock); + } + if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et)) + { + GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock); + } } if (NULL == scheduler_select) { @@ -2235,6 +2270,8 @@ select_loop (void *cls, } if (select_result == GNUNET_SYSERR) { + LOG (GNUNET_ERROR_TYPE_WARNING, + "select_result = GNUNET_SYSERR\n"); if (errno == EINTR) continue; @@ -2293,27 +2330,30 @@ select_loop (void *cls, //GNUNET_assert (0); short_wait (100); /* mitigate */ } - for (pos = context->scheduled_in_head; NULL != pos; pos = pos->next) + for (pos = context->scheduled_head; NULL != pos; pos = pos->next) { - if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (rs, pos->fdi->sock)) + int is_ready = GNUNET_NO; + if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et) && + GNUNET_YES == GNUNET_NETWORK_fdset_test_native (rs, pos->fdi->sock)) { - GNUNET_CONTAINER_DLL_remove (context->scheduled_in_head, - context->scheduled_in_tail, - pos); - GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi); + pos->fdi->et |= GNUNET_SCHEDULER_ET_IN; + is_ready = GNUNET_YES; } - } - for (pos = context->scheduled_out_head; NULL != pos; pos = pos->next) - { - if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (ws, pos->fdi->sock)) + if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et) && + GNUNET_YES == GNUNET_NETWORK_fdset_test_native (ws, pos->fdi->sock)) + { + pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT; + is_ready = GNUNET_YES; + } + if (GNUNET_YES == is_ready) { - GNUNET_CONTAINER_DLL_remove (context->scheduled_out_head, - context->scheduled_out_tail, + GNUNET_CONTAINER_DLL_remove (context->scheduled_head, + context->scheduled_tail, pos); GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi); } } - int tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); + tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); LOG (GNUNET_ERROR_TYPE_WARNING, "[%p] tasks_ready: %d\n", sh, -- cgit v1.2.3 From b5080c190338cc9031a9d81916828b0ddd855eb3 Mon Sep 17 00:00:00 2001 From: lurchi Date: Wed, 23 Aug 2017 15:45:52 +0200 Subject: GNUNET_SCHEDULER_check_lifeness not needed anymore --- src/include/gnunet_scheduler_lib.h | 15 -------------- src/util/scheduler.c | 41 -------------------------------------- 2 files changed, 56 deletions(-) (limited to 'src/util') diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h index 5f9389726..119f3c8ed 100644 --- a/src/include/gnunet_scheduler_lib.h +++ b/src/include/gnunet_scheduler_lib.h @@ -382,21 +382,6 @@ typedef int struct GNUNET_TIME_Relative timeout); -/** - * Check if the system has initiated shutdown. This means no tasks - * that prevent shutdown were present and all tasks added with - * #GNUNET_SCHEDULER_add_shutdown were run already. - * - * Can be used by external event loop implementations to decide - * whether to keep running or not. - * - * @return #GNUNET_YES if tasks which prevent shutdown exist - * #GNUNET_NO if the system has initiated shutdown - */ -int -GNUNET_SCHEDULER_check_lifeness (); - - /** * Initialize and run scheduler. This function will return when all * tasks have completed. On systems with signals, receiving a SIGTERM diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 084ca43df..b59919818 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -604,47 +604,6 @@ sighandler_shutdown () } -/** - * Check if the system has initiated shutdown. This means no tasks - * that prevent shutdown were present and all tasks added with - * #GNUNET_SCHEDULER_add_shutdown were run already. - * - * Can be used by external event loop implementations to decide - * whether to keep running or not. - * - * @return #GNUNET_YES if tasks which prevent shutdown exist - * #GNUNET_NO if the system has initiated shutdown - */ -// FIXME: make it an internal function again -int -GNUNET_SCHEDULER_check_lifeness () -{ - struct GNUNET_SCHEDULER_Task *t; - - if (ready_count > 0) - return GNUNET_YES; - for (t = pending_head; NULL != t; t = t->next) - if (t->lifeness == GNUNET_YES) - return GNUNET_YES; - for (t = shutdown_head; NULL != t; t = t->next) - if (t->lifeness == GNUNET_YES) - return GNUNET_YES; - for (t = pending_timeout_head; NULL != t; t = t->next) - if (t->lifeness == GNUNET_YES) - return GNUNET_YES; - if (NULL != shutdown_head) - { - GNUNET_SCHEDULER_shutdown (); - LOG (GNUNET_ERROR_TYPE_WARNING, - "shutting down\n"); - scheduler_driver->set_wakeup (scheduler_driver->cls, - GNUNET_TIME_absolute_get ()); - return GNUNET_YES; - } - return GNUNET_NO; -} - - void shutdown_if_no_lifeness () { -- cgit v1.2.3 From 9bb58990f8935958d1ae963305eb69cd55dcea6d Mon Sep 17 00:00:00 2001 From: lurchi Date: Wed, 23 Aug 2017 15:57:58 +0200 Subject: cleanup --- src/util/scheduler.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index b59919818..5e8d0844c 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -1621,7 +1621,7 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, } -int +void extract_handles (struct GNUNET_SCHEDULER_Task *t, const struct GNUNET_NETWORK_FDSet *fdset, const struct GNUNET_NETWORK_Handle ***ntarget, @@ -1635,13 +1635,11 @@ extract_handles (struct GNUNET_SCHEDULER_Task *t, const struct GNUNET_DISK_FileHandle **fhandles; unsigned int nhandles_len, fhandles_len; int sock; - int ret; nhandles = NULL; fhandles = NULL; nhandles_len = 0; fhandles_len = 0; - ret = GNUNET_OK; for (sock = 0; sock != fdset->nsds; ++sock) { if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock)) @@ -1663,8 +1661,6 @@ extract_handles (struct GNUNET_SCHEDULER_Task *t, } else { - ret = GNUNET_SYSERR; - // DEBUG GNUNET_assert (0); } } @@ -1674,7 +1670,6 @@ extract_handles (struct GNUNET_SCHEDULER_Task *t, *ftarget = fhandles_len > 0 ? fhandles : NULL; *extracted_nhandles = nhandles_len; *extracted_fhandles = fhandles_len; - return ret; } @@ -2120,26 +2115,6 @@ select_add (void *cls, GNUNET_CONTAINER_DLL_insert (context->scheduled_head, context->scheduled_tail, scheduled); - //if (0 != (GNUNET_SCHEDULER_ET_IN & scheduled->et)) - //{ - // GNUNET_CONTAINER_DLL_insert (context->scheduled_in_head, - // context->scheduled_in_tail, - // scheduled); - //} - //if (0 != (GNUNET_SCHEDULER_ET_OUT & scheduled->et)) - //{ - // GNUNET_CONTAINER_DLL_insert (context->scheduled_out_head, - // context->scheduled_out_tail, - // scheduled); - //} - //if (0 != (GNUNET_SCHEDULER_ET_HUP & scheduled->et) || - // 0 != (GNUNET_SCHEDULER_ET_ERR & scheduled->et) || - // 0 != (GNUNET_SCHEDULER_ET_PRI & scheduled->et) || - // 0 != (GNUNET_SCHEDULER_ET_NVAL & scheduled->et)) - //{ - // // FIXME: other event types not implemented yet - // GNUNET_assert (0); - //} return GNUNET_OK; } -- cgit v1.2.3 From a9a1f2b07fe8b15601b434756ba7ddb263978293 Mon Sep 17 00:00:00 2001 From: lurchi Date: Thu, 24 Aug 2017 20:38:15 +0200 Subject: NULL-initialize array pointers --- src/util/scheduler.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 5e8d0844c..51833a78b 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -1733,6 +1733,10 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, t->read_fd = -1; t->write_fd = -1; t->own_handlers = GNUNET_YES; + read_nhandles = NULL; + write_nhandles = NULL; + read_fhandles = NULL; + write_fhandles = NULL; read_nhandles_len = 0; write_nhandles_len = 0; read_fhandles_len = 0; -- cgit v1.2.3 From fe7759b2428c183fe9595640abece0937ec88bcc Mon Sep 17 00:00:00 2001 From: lurchi Date: Thu, 24 Aug 2017 22:17:46 +0200 Subject: fix behaviour of GNUNET_SCHEDULER_add_select on empty fdsets if GNUNET_SCHEDULER_add_select is called with empty fdsets, the resulting task is now added to the pending_timeout queue instead of the pending queue. This way the driver will not know about the task. --- src/util/scheduler.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 51833a78b..cbb48c3a4 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -1717,8 +1717,7 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, unsigned int read_nhandles_len, write_nhandles_len, read_fhandles_len, write_fhandles_len; - if ( (NULL == rs) && - (NULL == ws) ) + if (((NULL == rs) && (NULL == ws)) || ((0 == rs->nsds) && (0 == ws->nsds))) return GNUNET_SCHEDULER_add_delayed_with_priority (delay, prio, task, @@ -1759,7 +1758,6 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, &write_fhandles, &write_fhandles_len); } - GNUNET_assert (read_nhandles_len + write_nhandles_len > 0); init_fd_info (t, read_nhandles, read_nhandles_len, -- cgit v1.2.3 From ba7ceb320716f8a1b20883fccbdec15fee41002b Mon Sep 17 00:00:00 2001 From: lurchi Date: Fri, 25 Aug 2017 12:39:04 +0200 Subject: Simplify driver callback del; fix shutdown logic The driver callback for deleting a task has been simplified: Now it is only possible to delete a task, not single FdInfos. A logic bug in GNUNET_SCHEDULER_cancel has been fixed (FD-related tasks need to be deleted from the driver, when they are already in the ready queue). --- src/util/scheduler.c | 151 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 92 insertions(+), 59 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index cbb48c3a4..32916d99d 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -220,19 +220,31 @@ struct GNUNET_SCHEDULER_Task }; +/** + * A struct representing an event the select driver is waiting for + */ struct Scheduled { struct Scheduled *prev; struct Scheduled *next; + /** + * the task, the event is related to + */ struct GNUNET_SCHEDULER_Task *task; + /** + * information about the network socket / file descriptor where + * the event is expected to occur + */ struct GNUNET_SCHEDULER_FdInfo *fdi; + /** + * the event types (multiple event types can be ORed) the select + * driver is expected to wait for + */ enum GNUNET_SCHEDULER_EventType et; - - int is_ready; }; @@ -241,10 +253,22 @@ struct Scheduled */ struct DriverContext { + /** + * the head of a DLL containing information about the events the + * select driver is waiting for + */ struct Scheduled *scheduled_head; + /** + * the tail of a DLL containing information about the events the + * select driver is waiting for + */ struct Scheduled *scheduled_tail; + /** + * the time until the select driver will wake up again (after + * calling select) + */ struct GNUNET_TIME_Relative timeout; }; @@ -511,6 +535,10 @@ destroy_task (struct GNUNET_SCHEDULER_Task *t) { unsigned int i; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "destroying task %p\n", + t); + if (GNUNET_YES == t->own_handlers) { for (i = 0; i != t->fds_len; ++i) @@ -819,10 +847,8 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, * @param et the event type to be set in each FdInfo after calling * @a driver_func on it, or -1 if no updating not desired. */ -void scheduler_multi_function_call (struct GNUNET_SCHEDULER_Task *t, - int (*driver_func)(), - int if_not_ready, - enum GNUNET_SCHEDULER_EventType et) +void driver_add_multiple (struct GNUNET_SCHEDULER_Task *t, + enum GNUNET_SCHEDULER_EventType et) { struct GNUNET_SCHEDULER_FdInfo *fdi; int success = GNUNET_YES; @@ -830,19 +856,16 @@ void scheduler_multi_function_call (struct GNUNET_SCHEDULER_Task *t, for (int i = 0; i != t->fds_len; ++i) { fdi = &t->fds[i]; - if ((GNUNET_NO == if_not_ready) || (GNUNET_SCHEDULER_ET_NONE == fdi->et)) + success = scheduler_driver->add (scheduler_driver->cls, t, fdi) && success; + if (et != -1) { - success = driver_func (scheduler_driver->cls, t, fdi) && success; - if (et != -1) - { - fdi->et = et; - } + fdi->et = et; } } if (GNUNET_YES != success) { LOG (GNUNET_ERROR_TYPE_ERROR, - "driver call not successful"); + "driver could not add task\n"); } } @@ -876,38 +899,49 @@ void * GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) { enum GNUNET_SCHEDULER_Priority p; + int is_fd_task; void *ret; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "canceling task %p\n", + task); + /* scheduler must be running */ GNUNET_assert (NULL != scheduler_driver); GNUNET_assert ( (NULL != active_task) || (GNUNET_NO == task->lifeness) ); - if (! task->in_ready_list) + is_fd_task = (NULL != task->fds); + if (is_fd_task) { - if (NULL == task->fds) + int del_result = scheduler_driver->del (scheduler_driver->cls, task); + if (GNUNET_OK != del_result) { - if (GNUNET_YES == task->on_shutdown) - GNUNET_CONTAINER_DLL_remove (shutdown_head, - shutdown_tail, - task); - else - { - GNUNET_CONTAINER_DLL_remove (pending_timeout_head, - pending_timeout_tail, - task); - if (pending_timeout_last == task) - pending_timeout_last = NULL; - } - //TODO check if this is redundant - if (task == pending_timeout_last) - pending_timeout_last = NULL; + LOG (GNUNET_ERROR_TYPE_ERROR, + "driver could not delete task\n"); + GNUNET_assert (0); } - else + } + if (! task->in_ready_list) + { + if (is_fd_task) { GNUNET_CONTAINER_DLL_remove (pending_head, pending_tail, task); - scheduler_multi_function_call(task, scheduler_driver->del, GNUNET_NO, -1); + } + else if (GNUNET_YES == task->on_shutdown) + { + GNUNET_CONTAINER_DLL_remove (shutdown_head, + shutdown_tail, + task); + } + else + { + GNUNET_CONTAINER_DLL_remove (pending_timeout_head, + pending_timeout_tail, + task); + if (pending_timeout_last == task) + pending_timeout_last = NULL; } } else @@ -1341,12 +1375,9 @@ add_without_sets (struct GNUNET_TIME_Relative delay, GNUNET_CONTAINER_DLL_insert (pending_head, pending_tail, t); - scheduler_multi_function_call (t, scheduler_driver->add, GNUNET_NO, GNUNET_SCHEDULER_ET_NONE); + driver_add_multiple (t, GNUNET_SCHEDULER_ET_NONE); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Adding task %p\n", - t); init_backtrace (t); return t; } @@ -1785,7 +1816,7 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, GNUNET_CONTAINER_DLL_insert (pending_head, pending_tail, t); - scheduler_multi_function_call (t, scheduler_driver->add, GNUNET_NO, GNUNET_SCHEDULER_ET_NONE); + driver_add_multiple (t, GNUNET_SCHEDULER_ET_NONE); max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -1890,8 +1921,6 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) if (0 == ready_count) { - LOG (GNUNET_ERROR_TYPE_WARNING, - "no tasks run!\n"); return GNUNET_NO; } @@ -1956,7 +1985,16 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) "Running task %p\n", pos); pos->callback (pos->callback_cls); - scheduler_multi_function_call (pos, scheduler_driver->del, GNUNET_YES, -1); + if (NULL != pos->fds) + { + int del_result = scheduler_driver->del (scheduler_driver->cls, pos); + if (GNUNET_OK != del_result) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + "driver could not delete task\n"); + GNUNET_assert (0); + } + } active_task = NULL; dump_backtrace (pos); destroy_task (pos); @@ -2123,8 +2161,7 @@ select_add (void *cls, int select_del (void *cls, - struct GNUNET_SCHEDULER_Task *task, - struct GNUNET_SCHEDULER_FdInfo *fdi) + struct GNUNET_SCHEDULER_Task *task) { struct DriverContext *context; struct Scheduled *pos; @@ -2134,16 +2171,19 @@ select_del (void *cls, context = cls; ret = GNUNET_SYSERR; - for (pos = context->scheduled_head; NULL != pos; pos = pos->next) + pos = context->scheduled_head; + while (NULL != pos) { - if (pos->task == task && pos->fdi == fdi) + struct Scheduled *next = pos->next; + if (pos->task == task) { GNUNET_CONTAINER_DLL_remove (context->scheduled_head, context->scheduled_tail, pos); + GNUNET_free (pos); ret = GNUNET_OK; - break; } + pos = next; } return ret; } @@ -2170,9 +2210,8 @@ select_loop (void *cls, busy_wait_warning = 0; while (NULL != context->scheduled_head || GNUNET_YES == tasks_ready) { - LOG (GNUNET_ERROR_TYPE_WARNING, - "[%p] timeout = %s\n", - sh, + LOG (GNUNET_ERROR_TYPE_DEBUG, + "select timeout = %s\n", GNUNET_STRINGS_relative_time_to_string (context->timeout, GNUNET_NO)); GNUNET_NETWORK_fdset_zero (rs); @@ -2206,8 +2245,6 @@ select_loop (void *cls, } if (select_result == GNUNET_SYSERR) { - LOG (GNUNET_ERROR_TYPE_WARNING, - "select_result = GNUNET_SYSERR\n"); if (errno == EINTR) continue; @@ -2283,24 +2320,20 @@ select_loop (void *cls, } if (GNUNET_YES == is_ready) { - GNUNET_CONTAINER_DLL_remove (context->scheduled_head, - context->scheduled_tail, - pos); + //GNUNET_CONTAINER_DLL_remove (context->scheduled_head, + // context->scheduled_tail, + // pos); GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi); } } tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); - LOG (GNUNET_ERROR_TYPE_WARNING, - "[%p] tasks_ready: %d\n", - sh, + LOG (GNUNET_ERROR_TYPE_DEBUG, + "tasks_ready: %d\n", tasks_ready); // FIXME: tasks_run is a driver-internal variable! Instead we should increment // a local variable tasks_ready_count everytime we're calling GNUNET_SCHEDULER_task_ready. if (last_tr == tasks_run) { - LOG (GNUNET_ERROR_TYPE_WARNING, - "[%p] no tasks run\n", - sh); short_wait (1); busy_wait_warning++; } -- cgit v1.2.3 From 909c769cc09296f8abccf2a5ee6a6a687b4efc3a Mon Sep 17 00:00:00 2001 From: lurchi Date: Fri, 25 Aug 2017 12:59:28 +0200 Subject: clarify documentation about adding / deleting tasks --- src/include/gnunet_scheduler_lib.h | 20 ++++++++++++-------- src/util/scheduler.c | 5 +++-- 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'src/util') diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h index 119f3c8ed..b6f127f0c 100644 --- a/src/include/gnunet_scheduler_lib.h +++ b/src/include/gnunet_scheduler_lib.h @@ -216,7 +216,8 @@ struct GNUNET_SCHEDULER_TaskContext /** * Function used by event-loop implementations to signal the scheduler - * that a particular @a task is ready due to an event of type @a et. + * that a particular @a task is ready due to an event specified in the + * et field of @a fdi. * * This function will then queue the task to notify the application * that the task is ready (with the respective priority). @@ -268,8 +269,11 @@ struct GNUNET_SCHEDULER_Driver void *cls; /** - * Add a @a task to be run if the conditions given - * in @a fdi are satisfied. + * Add a @a task to be run if the conditions specified in the + * et field of the given @a fdi are satisfied. The et field will + * be cleared after this call and the driver is expected to set + * the type of the actual event before passing @a fdi to + * #GNUNET_SCHEDULER_task_ready. * * @param cls closure * @param task task to add @@ -283,18 +287,18 @@ struct GNUNET_SCHEDULER_Driver struct GNUNET_SCHEDULER_FdInfo *fdi); /** - * Delete a @a task from the set of tasks to be run. + * Delete a @a task from the set of tasks to be run. A task may + * comprise multiple FdInfo entries previously added with the add + * function. The driver is expected to delete them all. * * @param cls closure * @param task task to delete - * @param fdi conditions to watch for (must match @e add call) * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure - * (i.e. @a task or @a fdi do not match prior @e add call) + * (i.e. @a task does not match prior @e add call) */ int (*del)(void *cls, - struct GNUNET_SCHEDULER_Task *task, - struct GNUNET_SCHEDULER_FdInfo *fdi); + struct GNUNET_SCHEDULER_Task *task); /** * Set time at which we definitively want to get a wakeup call. diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 32916d99d..ac9494fa0 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -1829,12 +1829,13 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, /** * Function used by event-loop implementations to signal the scheduler - * that a particular @a task is ready due to an event of type @a et. + * that a particular @a task is ready due to an event specified in the + * et field of @a fdi. * * This function will then queue the task to notify the application * that the task is ready (with the respective priority). * - * @param task the task that is ready, NULL for wake up calls + * @param task the task that is ready * @param fdi information about the related FD */ void -- cgit v1.2.3 From b851ecf1aa048e51439e3be631cd19ca84e4dc5a Mon Sep 17 00:00:00 2001 From: lurchi Date: Mon, 4 Sep 2017 11:56:48 +0200 Subject: Remove busy waiting checks Busy waiting should never happen (at least the shutdown pipe is always there for the driver to wait for). When busy waiting happens, i.e. GNUNET_SCHEDULER_run_from_driver is called without any task ready, it is a programming error (at least I don't know any valid use case for busy waiting). Hence, remove the busy waiting checks and let GNUNET_SCHEDULER_run_from_driver return GNUNET_SYSERR instead in this case. --- src/util/scheduler.c | 79 +++++++++++++++++----------------------------------- 1 file changed, 26 insertions(+), 53 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index ac9494fa0..5f627cfb5 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -595,22 +595,22 @@ sighandler_pipe () #endif -/** - * Wait for a short time. - * Sleeps for @a ms ms (as that should be long enough for virtually all - * modern systems to context switch and allow another process to do - * some 'real' work). - * - * @param ms how many ms to wait - */ -static void -short_wait (unsigned int ms) -{ - struct GNUNET_TIME_Relative timeout; - - timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms); - (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout); -} +///** +// * Wait for a short time. +// * Sleeps for @a ms ms (as that should be long enough for virtually all +// * modern systems to context switch and allow another process to do +// * some 'real' work). +// * +// * @param ms how many ms to wait +// */ +//static void +//short_wait (unsigned int ms) +//{ +// struct GNUNET_TIME_Relative timeout; +// +// timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms); +// (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout); +//} /** @@ -1873,15 +1873,16 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, * there are tasks left to run just to give other tasks a chance as * well. If we return #GNUNET_YES, the driver should call this * function again as soon as possible, while if we return #GNUNET_NO - * it must block until the operating system has more work as the - * scheduler has no more work to do right now. + * it must block until either the operating system has more work (the + * scheduler has no more work to do right now) or the timeout set by + * the scheduler (using the set_wakeup callback) is reached. * * @param sh scheduler handle that was given to the `loop` * @return #GNUNET_OK if there are more tasks that are ready, * and thus we would like to run more (yield to avoid * blocking other activities for too long) * #GNUNET_NO if we are done running tasks (yield to block) - * #GNUNET_SYSERR on error + * #GNUNET_SYSERR on error, e.g. no tasks were ready */ int GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) @@ -1922,7 +1923,9 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) if (0 == ready_count) { - return GNUNET_NO; + LOG (GNUNET_ERROR_TYPE_ERROR, + "GNUNET_SCHEDULER_run_from_driver was called, but no tasks are ready!\n"); + return GNUNET_SYSERR; } /* find out which task priority level we are going to @@ -1985,6 +1988,7 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) LOG (GNUNET_ERROR_TYPE_DEBUG, "Running task %p\n", pos); + GNUNET_assert (NULL != pos->callback); pos->callback (pos->callback_cls); if (NULL != pos->fds) { @@ -2199,16 +2203,12 @@ select_loop (void *cls, struct DriverContext *context; int select_result; int tasks_ready; - unsigned long long last_tr; - unsigned int busy_wait_warning; - + context = cls; GNUNET_assert (NULL != context); rs = GNUNET_NETWORK_fdset_create (); ws = GNUNET_NETWORK_fdset_create (); tasks_ready = GNUNET_NO; - last_tr = 0; - busy_wait_warning = 0; while (NULL != context->scheduled_head || GNUNET_YES == tasks_ready) { LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -2294,16 +2294,6 @@ select_loop (void *cls, GNUNET_assert (0); return GNUNET_SYSERR; } - if ( (0 == select_result) && - (0 == context->timeout.rel_value_us) && - (busy_wait_warning > 16) ) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "[%p] Looks like we're busy waiting...\n", - sh); - //GNUNET_assert (0); - short_wait (100); /* mitigate */ - } for (pos = context->scheduled_head; NULL != pos; pos = pos->next) { int is_ready = GNUNET_NO; @@ -2321,28 +2311,11 @@ select_loop (void *cls, } if (GNUNET_YES == is_ready) { - //GNUNET_CONTAINER_DLL_remove (context->scheduled_head, - // context->scheduled_tail, - // pos); GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi); } } tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "tasks_ready: %d\n", - tasks_ready); - // FIXME: tasks_run is a driver-internal variable! Instead we should increment - // a local variable tasks_ready_count everytime we're calling GNUNET_SCHEDULER_task_ready. - if (last_tr == tasks_run) - { - short_wait (1); - busy_wait_warning++; - } - else - { - last_tr = tasks_run; - busy_wait_warning = 0; - } + GNUNET_assert (GNUNET_SYSERR != tasks_ready); } return GNUNET_OK; } -- cgit v1.2.3 From 023013b657c4f0fa60bcbbf3b795f76226a9485b Mon Sep 17 00:00:00 2001 From: lurchi Date: Mon, 4 Sep 2017 12:23:51 +0200 Subject: remove scheduler->internal code from driver loop --- src/util/scheduler.c | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 5f627cfb5..a2eaab9aa 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -2263,31 +2263,15 @@ select_loop (void *cls, #endif #endif #if DEBUG_FDS - struct GNUNET_SCHEDULER_Task *t; - // FIXME: pending_head is a scheduler-internal variable! - for (t = pending_head; NULL != t; t = t->next) + struct Scheduled *s; + for (s = context->scheduled_head; NULL != s; s = s->next) { - if (-1 != t->read_fd) + int flags = fcntl (s->fdi->sock, F_GETFD); + if ((flags == -1) && (errno == EBADF)) { - int flags = fcntl (t->read_fd, F_GETFD); - if ((flags == -1) && (errno == EBADF)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Got invalid file descriptor %d!\n", - t->read_fd); - dump_backtrace (t); - } - } - if (-1 != t->write_fd) - { - int flags = fcntl (t->write_fd, F_GETFD); - if ((flags == -1) && (errno == EBADF)) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - "Got invalid file descriptor %d!\n", - t->write_fd); - dump_backtrace (t); - } + LOG (GNUNET_ERROR_TYPE_ERROR, + "Got invalid file descriptor %d!\n", + s->fdi->sock); } } #endif -- cgit v1.2.3 From 0cdad12df4123d4b30603d552f1e3c1effab5015 Mon Sep 17 00:00:00 2001 From: lurchi Date: Mon, 4 Sep 2017 12:40:53 +0200 Subject: handles, not handlers --- src/util/scheduler.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index a2eaab9aa..72f2b7230 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -147,11 +147,11 @@ struct GNUNET_SCHEDULER_Task unsigned int ready_fds_len; /** - * Do we own the network and file handlers referenced by the FdInfo + * Do we own the network and file handles referenced by the FdInfo * structs in the fds array. This will only be GNUNET_YES if the * task was created by the #GNUNET_SCHEDULER_add_select function. */ - int own_handlers; + int own_handles; /** * Absolute timeout value for the task, or @@ -539,7 +539,7 @@ destroy_task (struct GNUNET_SCHEDULER_Task *t) "destroying task %p\n", t); - if (GNUNET_YES == t->own_handlers) + if (GNUNET_YES == t->own_handles) { for (i = 0; i != t->fds_len; ++i) { @@ -1762,7 +1762,7 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, t->callback_cls = task_cls; t->read_fd = -1; t->write_fd = -1; - t->own_handlers = GNUNET_YES; + t->own_handles = GNUNET_YES; read_nhandles = NULL; write_nhandles = NULL; read_fhandles = NULL; -- cgit v1.2.3 From 490c41e78c79a18ab683f83299b041564cb4a69b Mon Sep 17 00:00:00 2001 From: lurchi Date: Mon, 4 Sep 2017 15:05:26 +0200 Subject: Fix select loop running conditions The select loop has to keep running as long as the driver has tasks available (indicating that there are file descriptors left to wait for) or the timeout is not FOREVER (indicating that the scheduler has tasks with timeout left). --- src/include/gnunet_scheduler_lib.h | 12 ++++++++---- src/util/scheduler.c | 6 +++++- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'src/util') diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h index b6f127f0c..aded41de8 100644 --- a/src/include/gnunet_scheduler_lib.h +++ b/src/include/gnunet_scheduler_lib.h @@ -242,15 +242,16 @@ struct GNUNET_SCHEDULER_Handle; * there are tasks left to run just to give other tasks a chance as * well. If we return #GNUNET_YES, the driver should call this * function again as soon as possible, while if we return #GNUNET_NO - * it must block until the operating system has more work as the - * scheduler has no more work to do right now. + * it must block until either the operating system has more work (the + * scheduler has no more work to do right now) or the timeout set by + * the scheduler (using the set_wakeup callback) is reached. * * @param sh scheduler handle that was given to the `loop` * @return #GNUNET_OK if there are more tasks that are ready, * and thus we would like to run more (yield to avoid * blocking other activities for too long) * #GNUNET_NO if we are done running tasks (yield to block) - * #GNUNET_SYSERR on error + * #GNUNET_SYSERR on error, e.g. no tasks were ready */ int GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh); @@ -313,7 +314,10 @@ struct GNUNET_SCHEDULER_Driver /** * Event loop's "main" function, to be called from * #GNUNET_SCHEDULER_run_with_driver() to actually - * launch the loop. + * launch the loop. The loop should run as long as + * tasks (added by the add callback) are available + * OR the wakeup time (added by the set_wakeup + * callback) is not FOREVER. * * @param cls closure * @param sh scheduler handle to pass to diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 72f2b7230..4b963209d 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -2209,7 +2209,8 @@ select_loop (void *cls, rs = GNUNET_NETWORK_fdset_create (); ws = GNUNET_NETWORK_fdset_create (); tasks_ready = GNUNET_NO; - while (NULL != context->scheduled_head || GNUNET_YES == tasks_ready) + while (NULL != context->scheduled_head || + GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != context->timeout.rel_value_us) { LOG (GNUNET_ERROR_TYPE_DEBUG, "select timeout = %s\n", @@ -2300,6 +2301,9 @@ select_loop (void *cls, } tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); GNUNET_assert (GNUNET_SYSERR != tasks_ready); + LOG (GNUNET_ERROR_TYPE_WARNING, + "select timeout = %s\n", + GNUNET_STRINGS_relative_time_to_string (context->timeout, GNUNET_NO)); } return GNUNET_OK; } -- cgit v1.2.3 From 11f78ccd0b66e08b8d1084cc335daac99d3f6a7e Mon Sep 17 00:00:00 2001 From: lurchi Date: Mon, 4 Sep 2017 15:10:59 +0200 Subject: cleanup --- src/util/scheduler.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/util') diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 4b963209d..9bd776517 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -2301,9 +2301,6 @@ select_loop (void *cls, } tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); GNUNET_assert (GNUNET_SYSERR != tasks_ready); - LOG (GNUNET_ERROR_TYPE_WARNING, - "select timeout = %s\n", - GNUNET_STRINGS_relative_time_to_string (context->timeout, GNUNET_NO)); } return GNUNET_OK; } -- cgit v1.2.3