BUG/MAJOR: tasks: fix task accounting when killed
After recent commit b81c9390f ("MEDIUM: tasks: Mutualize the TASK_KILLED code between tasks and tasklets"), the task accounting was no longer correct for killed tasks due to the decrement of tasks in list that was no longer done, resulting in infinite loops in process_runnable_tasks(). This just illustrates that this code remains complex and should be further cleaned up. No backport is needed, as this was in 3.2.
This commit is contained in:
parent
faa18c1ad8
commit
45e83e8e81
26
src/task.c
26
src/task.c
@ -613,6 +613,19 @@ unsigned int run_tasks_from_lists(unsigned int budgets[])
|
||||
}
|
||||
} while (!_HA_ATOMIC_CAS(&t->state, &state, (state & TASK_PERSISTENT) | TASK_RUNNING));
|
||||
|
||||
__ha_barrier_atomic_store();
|
||||
|
||||
/* keep the task counter up to date */
|
||||
if (!(t->state & TASK_F_TASKLET))
|
||||
_HA_ATOMIC_DEC(&ha_thread_ctx[tid].tasks_in_list);
|
||||
|
||||
/* From this point, we know that the task or tasklet was properly
|
||||
* dequeued, flagged and accounted for. Let's now check if it was
|
||||
* killed. If TASK_KILLED arrived before we've read the state, we
|
||||
* directly free the task/tasklet. Otherwise for tasks it will be
|
||||
* seen after processing and it's freed on the exit path.
|
||||
*/
|
||||
|
||||
if (unlikely((state & TASK_KILLED) || process == NULL)) {
|
||||
/* Task or tasklet has been killed, let's remove it */
|
||||
if (t->state & TASK_F_TASKLET)
|
||||
@ -627,6 +640,8 @@ unsigned int run_tasks_from_lists(unsigned int budgets[])
|
||||
*/
|
||||
goto next;
|
||||
}
|
||||
|
||||
/* OK now the task or tasklet is well alive and is going to be run */
|
||||
if (t->state & TASK_F_TASKLET) {
|
||||
/* this is a tasklet */
|
||||
|
||||
@ -635,21 +650,14 @@ unsigned int run_tasks_from_lists(unsigned int budgets[])
|
||||
_HA_ATOMIC_AND(&t->state, ~TASK_RUNNING);
|
||||
} else {
|
||||
/* This is a regular task */
|
||||
__ha_barrier_atomic_store();
|
||||
|
||||
_HA_ATOMIC_DEC(&ha_thread_ctx[tid].tasks_in_list);
|
||||
|
||||
/* 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 (process == process_stream)
|
||||
t = process_stream(t, ctx, state);
|
||||
else
|
||||
t = process(t, ctx, state);
|
||||
|
||||
/* If there is a pending state we have to wake up the task
|
||||
* immediately, else we defer it into wait queue
|
||||
/* If there is a pending state, we have to wake up the task
|
||||
* immediately, else we defer it into wait queue.
|
||||
*/
|
||||
if (t != NULL) {
|
||||
state = _HA_ATOMIC_LOAD(&t->state);
|
||||
|
Loading…
x
Reference in New Issue
Block a user