]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: sched: create a new TASK_KILLED task flag
authorWilly Tarreau <w@1wt.eu>
Tue, 30 Jun 2020 09:48:48 +0000 (11:48 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 1 Jul 2020 14:35:49 +0000 (16:35 +0200)
This flag, when set, will be used to indicate that the task must die.
At the moment this may only be placed by the task itself or by the
scheduler when placing it into the TL_NORMAL queue.

include/haproxy/task-t.h
src/task.c

index 88f2bdd945cffe096a94a934c224a95cc53329a0..cf86c0a3ee1476302f772bdf963d43266a87e5fd 100644 (file)
@@ -38,6 +38,7 @@
 #define TASK_SHARED_WQ    0x0008  /* The task's expiration may be updated by other
                                    * threads, must be set before first queue/wakeup */
 #define TASK_SELF_WAKING  0x0010  /* task/tasklet found waking itself */
+#define TASK_KILLED       0x0020  /* task/tasklet killed, may now be freed */
 
 #define TASK_WOKEN_INIT   0x0100  /* woken up for initialisation purposes */
 #define TASK_WOKEN_TIMER  0x0200  /* woken up because of expired timer */
index b65000b8f3a6e1d79e18b155f56802a22411fc0e..7626e6037e74dc57f18714cd1e191b27fa7a4551 100644 (file)
@@ -379,7 +379,7 @@ unsigned int run_tasks_from_lists(unsigned int budgets[])
 
                budgets[queue]--;
                t = (struct task *)LIST_ELEM(tl_queues[queue].n, struct tasklet *, list);
-               state = (t->state & (TASK_SHARED_WQ|TASK_SELF_WAKING));
+               state = t->state & (TASK_SHARED_WQ|TASK_SELF_WAKING|TASK_KILLED);
 
                ti->flags &= ~TI_FL_STUCK; // this thread is still running
                activity[tid].ctxsw++;
@@ -414,11 +414,18 @@ unsigned int run_tasks_from_lists(unsigned int budgets[])
                }
 
                __ha_barrier_store();
-               if (likely(process == process_stream))
+
+               /* Note for below: if TASK_KILLED arrived before we've read the state, we
+                * directly free the task. Otherwise it will be seen after processing and
+                * it's freed on the exit path.
+                */
+               if (likely(!(state & TASK_KILLED) && process == process_stream))
                        t = process_stream(t, ctx, state);
-               else if (process != NULL)
+               else if (!(state & TASK_KILLED) && process != NULL)
                        t = process(t, ctx, state);
                else {
+                       if (task_in_wq(t))
+                               __task_unlink_wq(t);
                        __task_free(t);
                        sched->current = NULL;
                        __ha_barrier_store();
@@ -440,7 +447,12 @@ unsigned int run_tasks_from_lists(unsigned int budgets[])
                        }
 
                        state = _HA_ATOMIC_AND(&t->state, ~TASK_RUNNING);
-                       if (state & TASK_WOKEN_ANY)
+                       if (unlikely(state & TASK_KILLED)) {
+                               if (task_in_wq(t))
+                                       __task_unlink_wq(t);
+                               __task_free(t);
+                       }
+                       else if (state & TASK_WOKEN_ANY)
                                task_wakeup(t, 0);
                        else
                                task_queue(t);