From 3039adb9578b01b3649c5c8ae5f4d6d8f8a7d51d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 4 Feb 2020 19:38:38 +0100 Subject: [PATCH] fix task prioritization with recent hack --- src/util/.gitignore | 2 ++ src/util/client.c | 11 ++++------- src/util/scheduler.c | 44 ++++++++++++++++++++++++++++++++------------ src/util/service.c | 13 +++++-------- 4 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/util/.gitignore b/src/util/.gitignore index 84c13708e..05f187869 100644 --- a/src/util/.gitignore +++ b/src/util/.gitignore @@ -77,3 +77,5 @@ test_tun gnunet-timeout python27_location perf_malloc +perf_mq +perf_scheduler diff --git a/src/util/client.c b/src/util/client.c index 93442f0c6..a7b1a2a0f 100644 --- a/src/util/client.c +++ b/src/util/client.c @@ -271,14 +271,11 @@ RETRY: &pos[cstate->msg_off], len - cstate->msg_off); if ( (-1 == ret) && - (EAGAIN == errno) ) + ( (EAGAIN == errno) || + (EINTR == errno) ) ) { - cstate->send_task - = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, - cstate->sock, - &transmit_ready, - cstate); - return; + /* ignore */ + ret = 0; } if (-1 == ret) { diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 4be690d44..3d3e5216d 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -406,6 +406,11 @@ static enum GNUNET_SCHEDULER_Priority max_priority_added; */ static int current_lifeness; +/** + * Priority used currently in #GNUNET_SCHEDULER_do_work(). + */ +static enum GNUNET_SCHEDULER_Priority work_priority; + /** * Function to use as a select() in the scheduler. * If NULL, we use GNUNET_NETWORK_socket_select(). @@ -765,7 +770,6 @@ GNUNET_SCHEDULER_get_task_context () unsigned int GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) { - struct GNUNET_SCHEDULER_Task *pos; unsigned int ret; GNUNET_assert (NULL != active_task); @@ -774,7 +778,9 @@ GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) if (p == GNUNET_SCHEDULER_PRIORITY_KEEP) p = current_priority; ret = 0; - for (pos = ready_head[check_priority (p)]; NULL != pos; pos = pos->next) + for (struct GNUNET_SCHEDULER_Task *pos = ready_head[check_priority (p)]; + NULL != pos; + pos = pos->next) ret++; return ret; } @@ -1111,6 +1117,7 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, struct GNUNET_SCHEDULER_Task *t; struct GNUNET_SCHEDULER_Task *pos; struct GNUNET_SCHEDULER_Task *prev; + struct GNUNET_TIME_Relative left; /* scheduler must be running */ GNUNET_assert (NULL != scheduler_driver); @@ -1127,6 +1134,17 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, t->timeout = at; t->priority = check_priority (priority); t->lifeness = current_lifeness; + init_backtrace (t); + + left = GNUNET_TIME_absolute_get_remaining (at); + if (0 == left.rel_value_us) + { + queue_ready_task (t); + if (priority > work_priority) + work_priority = priority; + return t; + } + /* try tail first (optimization in case we are * appending to a long list of tasks with timeouts) */ if ((NULL == pending_timeout_head) || @@ -1161,11 +1179,9 @@ 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_DEBUG, "Adding task %p\n", t); - init_backtrace (t); return t; } @@ -1988,7 +2004,6 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, int GNUNET_SCHEDULER_do_work (struct GNUNET_SCHEDULER_Handle *sh) { - enum GNUNET_SCHEDULER_Priority p; struct GNUNET_SCHEDULER_Task *pos; struct GNUNET_TIME_Absolute now; @@ -2064,19 +2079,21 @@ GNUNET_SCHEDULER_do_work (struct GNUNET_SCHEDULER_Handle *sh) 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--) + for (work_priority = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; + work_priority > 0; + work_priority--) { - pos = ready_head[p]; + pos = ready_head[work_priority]; if (NULL != pos) break; } GNUNET_assert (NULL != pos); /* ready_count wrong? */ /* process all tasks at this priority level, then yield */ - while (NULL != (pos = ready_head[p])) + while (NULL != (pos = ready_head[work_priority])) { - GNUNET_CONTAINER_DLL_remove (ready_head[p], - ready_tail[p], + GNUNET_CONTAINER_DLL_remove (ready_head[work_priority], + ready_tail[work_priority], pos); ready_count--; current_priority = pos->priority; @@ -2230,9 +2247,12 @@ GNUNET_SCHEDULER_driver_init (const struct GNUNET_SCHEDULER_Driver *driver) /* Setup initial tasks */ current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; current_lifeness = GNUNET_NO; + /* ensure this task runs first, by using a priority level reserved for + the scheduler (not really shutdown, but start-up ;-) */ install_parent_control_task = - GNUNET_SCHEDULER_add_now (&install_parent_control_handler, - NULL); + GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_SHUTDOWN, + &install_parent_control_handler, + NULL); shutdown_pipe_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, pr, diff --git a/src/util/service.c b/src/util/service.c index 21b99547c..999a9e017 100644 --- a/src/util/service.c +++ b/src/util/service.c @@ -506,12 +506,12 @@ do_send (void *cls) LOG (GNUNET_ERROR_TYPE_DEBUG, "service: sending message with type %u\n", ntohs (client->msg->type)); - - client->send_task = NULL; buf = (const char *) client->msg; left = ntohs (client->msg->size) - client->msg_pos; - ret = GNUNET_NETWORK_socket_send (client->sock, &buf[client->msg_pos], left); + ret = GNUNET_NETWORK_socket_send (client->sock, + &buf[client->msg_pos], + left); GNUNET_assert (ret <= (ssize_t) left); if (0 == ret) { @@ -581,11 +581,8 @@ service_mq_send (struct GNUNET_MQ_Handle *mq, ntohs (msg->size)); client->msg = msg; client->msg_pos = 0; - client->send_task = - GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, - client->sock, - &do_send, - client); + client->send_task = GNUNET_SCHEDULER_add_now (&do_send, + client); } -- 2.25.1