fix task prioritization with recent hack
authorChristian Grothoff <christian@grothoff.org>
Tue, 4 Feb 2020 18:38:38 +0000 (19:38 +0100)
committerChristian Grothoff <christian@grothoff.org>
Tue, 4 Feb 2020 18:38:38 +0000 (19:38 +0100)
src/util/.gitignore
src/util/client.c
src/util/scheduler.c
src/util/service.c

index 84c13708ec1e8d6aa9e4145d439a70cf25b8cbf9..05f18786938ee9eca1e752fcbe7d3f59497a6d98 100644 (file)
@@ -77,3 +77,5 @@ test_tun
 gnunet-timeout
 python27_location
 perf_malloc
+perf_mq
+perf_scheduler
index 93442f0c61764e641e758ac67b141c31c651a964..a7b1a2a0f534b9419d6083dedfe6f99c5638099f 100644 (file)
@@ -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)
   {
index 4be690d44d70735dc573ed79460c914b9c3f525f..3d3e5216dbac4981e65862ddd14351a074fc1d5d 100644 (file)
@@ -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,
index 21b99547c0dc0066edf1585dfc12be408c0104d6..999a9e0172302c32971a11f127b2323efc20a4ee 100644 (file)
@@ -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);
 }