Applied, thanks!

Mike Kelly, le mar. 10 févr. 2026 07:52:54 +0000, a ecrit:
> Calling task_terminate() (on other than current_task()) risks deadlocking if 
> the task being terminated has multiple threads. Currently, the head of the 
> thread list must terminate successfully before terminating the next in the 
> list. This is not always possible, for example a thread which is not the list 
> head might hold a thread_reference to the thread at the list head. In that 
> case, the list head cannot be terminated until the other thread releases that 
> reference which won't happen if that other thread is TH_SUSP as it is not 
> rescheduled. Instead, task terminate() now attempts thread terminatation in 
> list sequence (rather than just the list head) and keeps doing so until none 
> remain.
> ---
>  kern/task.c | 32 +++++++++++++++++++++++++-------
>  1 file changed, 25 insertions(+), 7 deletions(-)
> 
> diff --git a/kern/task.c b/kern/task.c
> index e78e856f..421c4cd4 100644
> --- a/kern/task.c
> +++ b/kern/task.c
> @@ -405,16 +405,34 @@ kern_return_t task_terminate(
>           *      thread (e.g., the reaper) may have to run to get rid
>           *      of all references to the thread; it won't vanish from
>           *      the task's thread list until the last one is gone.
> +      *
> +      *      Occasionally there are dependencies between threads
> +      *      that require a specific thread to be terminated before
> +      *      others are able to. These dependencies are unknown to
> +      *      the task so repeated iteration over the thread list is
> +      *      required.
>           */
>          task_lock(task);
>          while (!queue_empty(list)) {
> -                thread = (thread_t) queue_first(list);
> -                thread_reference(thread);
> -                task_unlock(task);
> -                thread_force_terminate(thread);
> -                thread_deallocate(thread);
> -                thread_block(thread_no_continuation);
> -                task_lock(task);
> +
> +          thread = (thread_t) queue_first(list);
> +          thread_reference(thread);
> +
> +          do
> +            {
> +              thread_t next = (thread_t) queue_next(&thread->thread_list);
> +
> +              if (!queue_end(list, (queue_entry_t) next))
> +             thread_reference(next);
> +
> +              task_unlock(task);
> +              thread_force_terminate(thread);
> +              thread_deallocate(thread);
> +              thread_block(thread_no_continuation);
> +              thread = next;
> +              task_lock(task);
> +            }
> +          while (!queue_end(list, (queue_entry_t) thread));
>          }
>          task_unlock(task);
>  
> -- 
> 2.47.3
> 
> 

-- 
Samuel
«Tiens, quand j'aurai un peu de temps et une partition libre, je crois
 que je vais essayer de remplacer mes scripts de démarrage par des
 programmes Windows lancés via Wine et binfmt_misc :-)»
-+- AGV in Guide du linuxien pervers - "J'sais pas quoi faire... (air connu)"

Reply via email to