From: sof Date: Tue, 12 Feb 2002 15:38:08 +0000 (+0000) Subject: [project @ 2002-02-12 15:38:08 by sof] X-Git-Tag: Approximately_9120_patches~94 X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=a62d5cd262731e3e67e5f27b197e913d872dc4ad;p=ghc-hetmet.git [project @ 2002-02-12 15:38:08 by sof] Snapshot (before heading into work): - thread_ready_aux_mutex is no more; use sched_mutex instead. - gc_pending_cond only used in SMP mode. - document the condition that thread_ready_cond captures. --- diff --git a/ghc/rts/Schedule.c b/ghc/rts/Schedule.c index 52af386..4430f5a 100644 --- a/ghc/rts/Schedule.c +++ b/ghc/rts/Schedule.c @@ -1,5 +1,5 @@ /* --------------------------------------------------------------------------- - * $Id: Schedule.c,v 1.120 2002/02/08 03:44:01 sof Exp $ + * $Id: Schedule.c,v 1.121 2002/02/12 15:38:08 sof Exp $ * * (c) The GHC Team, 1998-2000 * @@ -294,29 +294,32 @@ Mutex rts_mutex = INIT_MUTEX_VAR; */ static nat threads_waiting = 0; -/* - * thread_ready_aux_mutex is used to handle the scenario where the - * the RTS executing thread runs out of work, but there are - * active external threads. The RTS executing thread gives up - * its RTS mutex, and blocks waiting for the thread_ready_cond. - * Unfortunately, a condition variable needs to be associated - * with a mutex in pthreads, so rts_thread_waiting_mutex is - * used for just this purpose. - * - */ -Mutex thread_ready_aux_mutex = INIT_MUTEX_VAR; #endif -/* thread_ready_cond: when signalled, a thread has - * become runnable. When used? +/* thread_ready_cond: when signalled, a thread has become runnable for a + * task to execute. + * + * In the non-SMP case, it also implies that the thread that is woken up has + * exclusive access to the RTS and all its DS (that are not under sched_mutex's + * control). + * + * thread_ready_cond is signalled whenever COND_NO_THREADS_READY doesn't hold. + * */ Condition thread_ready_cond = INIT_COND_VAR; -Condition gc_pending_cond = INIT_COND_VAR; +#if 0 +/* For documentation purposes only */ +#define COND_NO_THREADS_READY() (noCapabilities() || EMPTY_RUN_QUEUE()) +#endif +#if defined(SMP) +Condition gc_pending_cond = INIT_COND_VAR; nat await_death; #endif +#endif + #if defined(PAR) StgTSO *LastTSO; rtsTime TimeOfLastYield; @@ -621,9 +624,8 @@ schedule( void ) * ToDo: what if another client comes along & requests another * main thread? */ - if (blocked_queue_hd != END_TSO_QUEUE || sleeping_queue != END_TSO_QUEUE) { - awaitEvent( - (run_queue_hd == END_TSO_QUEUE) + if ( !EMPTY_QUEUE(blocked_queue_hd) || !EMPTY_QUEUE(sleeping_queue) ) { + awaitEvent( EMPTY_RUN_QUEUE() #if defined(SMP) && allFreeCapabilities() #endif @@ -644,13 +646,13 @@ schedule( void ) * inform all the main threads. */ #ifndef PAR - if (blocked_queue_hd == END_TSO_QUEUE - && run_queue_hd == END_TSO_QUEUE - && sleeping_queue == END_TSO_QUEUE + if ( EMPTY_QUEUE(blocked_queue_hd) + && EMPTY_RUN_QUEUE() + && EMPTY_QUEUE(sleeping_queue) #if defined(SMP) && allFreeCapabilities() #elif defined(THREADED_RTS) - && suspended_ccalling_threads == END_TSO_QUEUE + && EMPTY_QUEUE(suspended_ccalling_threads) #endif ) { @@ -659,9 +661,9 @@ schedule( void ) GarbageCollect(GetRoots,rtsTrue); ACQUIRE_LOCK(&sched_mutex); IF_DEBUG(scheduler, sched_belch("GC done.")); - if (blocked_queue_hd == END_TSO_QUEUE - && run_queue_hd == END_TSO_QUEUE - && sleeping_queue == END_TSO_QUEUE) { + if ( EMPTY_QUEUE(blocked_queue_hd) + && EMPTY_RUN_QUEUE() + && EMPTY_QUEUE(sleeping_queue) ) { IF_DEBUG(scheduler, sched_belch("still deadlocked, checking for black holes...")); detectBlackHoles(); @@ -671,7 +673,7 @@ schedule( void ) * build, send *all* main threads the deadlock exception, * since none of them can make progress). */ - if (run_queue_hd == END_TSO_QUEUE) { + if ( EMPTY_RUN_QUEUE() ) { StgMainThread *m; #if defined(RTS_SUPPORTS_THREADS) for (m = main_threads; m != NULL; m = m->link) { @@ -703,13 +705,13 @@ schedule( void ) #endif } #if defined(RTS_SUPPORTS_THREADS) - if ( run_queue_hd == END_TSO_QUEUE ) { + if ( EMPTY_RUN_QUEUE() ) { IF_DEBUG(scheduler, sched_belch("all done, it seems...shut down.")); shutdownHaskellAndExit(0); } #endif - ASSERT( run_queue_hd != END_TSO_QUEUE ); + ASSERT( !EMPTY_RUN_QUEUE() ); } } #elif defined(PAR) @@ -730,26 +732,22 @@ schedule( void ) /* block until we've got a thread on the run queue and a free * capability. */ - while ( run_queue_hd == END_TSO_QUEUE - || noFreeCapabilities() - ) { + while ( noCapabilities() || EMPTY_RUN_QUEUE() ) { IF_DEBUG(scheduler, sched_belch("waiting for work")); waitCondition( &thread_ready_cond, &sched_mutex ); IF_DEBUG(scheduler, sched_belch("work now available")); } #elif defined(THREADED_RTS) - if ( run_queue_hd == END_TSO_QUEUE ) { + if ( EMPTY_RUN_QUEUErun_queue_hd == END_TSO_QUEUE ) { /* no work available, wait for external calls to complete. */ IF_DEBUG(scheduler, sched_belch("worker thread (%d): waiting for external thread to complete..", osThreadId())); taskAvailable(); - RELEASE_LOCK(&sched_mutex); RELEASE_LOCK(&rts_mutex); - /* Sigh - need to have a mutex locked in order to wait on the - condition variable. */ - ACQUIRE_LOCK(&thread_ready_aux_mutex); - waitCondition(&thread_ready_cond, &thread_ready_aux_mutex); - RELEASE_LOCK(&thread_ready_aux_mutex); + while ( EMPTY_RUN_QUEUE() ) { + waitCondition(&thread_ready_cond, &sched_mutex); + }; + RELEASE_LOCK(&sched_mutex); IF_DEBUG(scheduler, sched_belch("worker thread (%d): re-awakened from no-work slumber..\n", osThreadId())); /* ToDo: longjmp() */ @@ -1538,9 +1536,10 @@ suspendThread( StgRegTable *reg ) startTask(taskStart); #endif - + + THREAD_RUNNABLE(); RELEASE_LOCK(&sched_mutex); - RELEASE_LOCK(&rts_mutex); + // RELEASE_LOCK(&rts_mutex); return tok; } @@ -1584,8 +1583,8 @@ resumeThread( StgInt tok ) } tso->link = END_TSO_QUEUE; -#if defined(SMP) - while ( noFreeCapabilities() ) { +#if defined(RTS_SUPPORTS_THREADS) + while ( noCapabilities() ) { IF_DEBUG(scheduler, sched_belch("waiting to resume")); waitCondition(&thread_ready_cond, &sched_mutex); IF_DEBUG(scheduler, sched_belch("resuming thread %d", tso->id)); @@ -1976,14 +1975,14 @@ initScheduler(void) #if defined(RTS_SUPPORTS_THREADS) /* Initialise the mutex and condition variables used by * the scheduler. */ - initMutex(&rts_mutex); initMutex(&sched_mutex); initMutex(&term_mutex); + + initCondition(&thread_ready_cond); #if defined(THREADED_RTS) - initMutex(&thread_ready_aux_mutex); + initMutex(&rts_mutex); #endif - initCondition(&thread_ready_cond); initCondition(&gc_pending_cond); #endif