From cdb8760fccf2dd09c8ac9dde9dcd11035f05557f Mon Sep 17 00:00:00 2001 From: Alex Shinn Date: Sat, 21 Jul 2012 17:05:05 +0900 Subject: [PATCH] Need to unpause a paused thread if we want to terminate it. --- lib/srfi/18/threads.c | 56 ++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/lib/srfi/18/threads.c b/lib/srfi/18/threads.c index 23d97a97..866a782f 100644 --- a/lib/srfi/18/threads.c +++ b/lib/srfi/18/threads.c @@ -1,5 +1,5 @@ /* threads.c -- SRFI-18 thread primitives */ -/* Copyright (c) 2010-2011 Alex Shinn. All rights reserved. */ +/* Copyright (c) 2010-2012 Alex Shinn. All rights reserved. */ /* BSD-style license: http://synthcode.com/license.txt */ #include @@ -96,20 +96,12 @@ sexp sexp_thread_start (sexp ctx, sexp self, sexp_sint_t n, sexp thread) { if (sexp_pairp(sexp_global(ctx, SEXP_G_THREADS_BACK))) { sexp_cdr(sexp_global(ctx, SEXP_G_THREADS_BACK)) = cell; sexp_global(ctx, SEXP_G_THREADS_BACK) = cell; - } else { /* init queue */ + } else { /* init queue */ sexp_global(ctx, SEXP_G_THREADS_BACK) = sexp_global(ctx, SEXP_G_THREADS_FRONT) = cell; } return thread; } -sexp sexp_thread_terminate (sexp ctx, sexp self, sexp_sint_t n, sexp thread) { - sexp res = sexp_make_boolean(ctx == thread); - for ( ; thread && sexp_contextp(thread); thread=sexp_context_child(thread)) - sexp_context_refuel(thread) = 0; - /* return true if terminating self */ - return res; -} - static int sexp_delete_list (sexp ctx, int global, sexp x) { sexp ls1=NULL, ls2=sexp_global(ctx, global); for ( ; sexp_pairp(ls2) && sexp_car(ls2) != x; ls1=ls2, ls2=sexp_cdr(ls2)) @@ -123,6 +115,20 @@ static int sexp_delete_list (sexp ctx, int global, sexp x) { } } +sexp sexp_thread_terminate (sexp ctx, sexp self, sexp_sint_t n, sexp thread) { + sexp res = sexp_make_boolean(ctx == thread); + /* terminate the thread and all children */ + for ( ; thread && sexp_contextp(thread); thread=sexp_context_child(thread)) { + /* zero the refuel - this tells the scheduler the thread is terminated */ + sexp_context_refuel(thread) = 0; + /* unblock the thread if needed so it can be scheduled and terminated */ + if (sexp_delete_list(ctx, SEXP_G_THREADS_PAUSED, thread)) + sexp_thread_start(ctx, self, 1, thread); + } + /* return true if terminating self, then we can yield */ + return res; +} + static void sexp_insert_timed (sexp ctx, sexp thread, sexp timeout) { #if SEXP_USE_FLONUMS double d; @@ -256,13 +262,13 @@ sexp sexp_condition_variable_signal (sexp ctx, sexp self, sexp_sint_t n, sexp co for ( ; sexp_pairp(ls2); ls1=ls2, ls2=sexp_cdr(ls2)) if (sexp_context_event(sexp_car(ls2)) == condvar) { if (ls1==SEXP_NULL) - sexp_global(ctx, SEXP_G_THREADS_PAUSED) = sexp_cdr(ls2); + sexp_global(ctx, SEXP_G_THREADS_PAUSED) = sexp_cdr(ls2); else - sexp_cdr(ls1) = sexp_cdr(ls2); + sexp_cdr(ls1) = sexp_cdr(ls2); sexp_cdr(ls2) = sexp_global(ctx, SEXP_G_THREADS_FRONT); sexp_global(ctx, SEXP_G_THREADS_FRONT) = ls2; if (! sexp_pairp(sexp_cdr(ls2))) - sexp_global(ctx, SEXP_G_THREADS_BACK) = ls2; + sexp_global(ctx, SEXP_G_THREADS_BACK) = ls2; sexp_context_waitp(sexp_car(ls2)) = sexp_context_timeoutp(sexp_car(ls2)) = 0; return SEXP_TRUE; } @@ -459,12 +465,12 @@ sexp sexp_scheduler (sexp ctx, sexp self, sexp_sint_t n, sexp root_thread) { sexp_cdr(ls1) = sexp_cdr(ls2); tmp = sexp_cdr(ls2); sexp_cdr(ls2) = SEXP_NULL; - if (! sexp_pairp(sexp_global(ctx, SEXP_G_THREADS_BACK))) { - sexp_global(ctx, SEXP_G_THREADS_FRONT) = front = ls2; - } else { - sexp_cdr(sexp_global(ctx, SEXP_G_THREADS_BACK)) = ls2; - } - sexp_global(ctx, SEXP_G_THREADS_BACK) = ls2; + if (! sexp_pairp(sexp_global(ctx, SEXP_G_THREADS_BACK))) { + sexp_global(ctx, SEXP_G_THREADS_FRONT) = front = ls2; + } else { + sexp_cdr(sexp_global(ctx, SEXP_G_THREADS_BACK)) = ls2; + } + sexp_global(ctx, SEXP_G_THREADS_BACK) = ls2; ls2 = tmp; } else { ls1 = ls2; @@ -486,12 +492,12 @@ sexp sexp_scheduler (sexp ctx, sexp self, sexp_sint_t n, sexp root_thread) { } if (sexp_pairp(ls1)) { sexp_cdr(ls1) = SEXP_NULL; - if (! sexp_pairp(sexp_global(ctx, SEXP_G_THREADS_BACK))) { - sexp_global(ctx, SEXP_G_THREADS_FRONT) = front = paused; - } else { - sexp_cdr(sexp_global(ctx, SEXP_G_THREADS_BACK)) = paused; - } - sexp_global(ctx, SEXP_G_THREADS_BACK) = ls1; + if (! sexp_pairp(sexp_global(ctx, SEXP_G_THREADS_BACK))) { + sexp_global(ctx, SEXP_G_THREADS_FRONT) = front = paused; + } else { + sexp_cdr(sexp_global(ctx, SEXP_G_THREADS_BACK)) = paused; + } + sexp_global(ctx, SEXP_G_THREADS_BACK) = ls1; sexp_global(ctx, SEXP_G_THREADS_PAUSED) = paused = ls2; } }