From: Simon Marlow Date: Thu, 25 Nov 2010 13:57:29 +0000 (+0000) Subject: Keep a maximum of 6 spare worker threads per Capability (#4262) X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=commitdiff_plain;h=150ac5e907ec5096660f90caaa5f076da181d81b Keep a maximum of 6 spare worker threads per Capability (#4262) --- diff --git a/includes/rts/Constants.h b/includes/rts/Constants.h index 140aaa4..e21a893 100644 --- a/includes/rts/Constants.h +++ b/includes/rts/Constants.h @@ -311,4 +311,13 @@ */ #define SPIN_COUNT 1000 +/* ----------------------------------------------------------------------------- + Spare workers per Capability in the threaded RTS + + No more than MAX_SPARE_WORKERS will be kept in the thread pool + associated with each Capability. + -------------------------------------------------------------------------- */ + +#define MAX_SPARE_WORKERS 6 + #endif /* RTS_CONSTANTS_H */ diff --git a/rts/Capability.c b/rts/Capability.c index 2fcd72c..8234359 100644 --- a/rts/Capability.c +++ b/rts/Capability.c @@ -219,6 +219,7 @@ initCapability( Capability *cap, nat i ) initMutex(&cap->lock); cap->running_task = NULL; // indicates cap is free cap->spare_workers = NULL; + cap->n_spare_workers = 0; cap->suspended_ccalls = NULL; cap->returning_tasks_hd = NULL; cap->returning_tasks_tl = NULL; @@ -460,9 +461,24 @@ releaseCapabilityAndQueueWorker (Capability* cap USED_IF_THREADS) // in which case it is not replaced on the spare_worker queue. // This happens when the system is shutting down (see // Schedule.c:workerStart()). - if (!isBoundTask(task) && !task->stopped) { - task->next = cap->spare_workers; - cap->spare_workers = task; + if (!isBoundTask(task) && !task->stopped) + { + if (cap->n_spare_workers < MAX_SPARE_WORKERS) + { + task->next = cap->spare_workers; + cap->spare_workers = task; + cap->n_spare_workers++; + } + else + { + debugTrace(DEBUG_sched, "%d spare workers already, exiting", + cap->n_spare_workers); + releaseCapability_(cap,rtsFalse); + // hold the lock until after workerTaskStop; c.f. scheduleWorker() + workerTaskStop(task); + RELEASE_LOCK(&cap->lock); + shutdownThread(); + } } // Bound tasks just float around attached to their TSOs. @@ -619,7 +635,8 @@ yieldCapability (Capability** pCap, Task *task) } cap->spare_workers = task->next; task->next = NULL; - } + cap->n_spare_workers--; + } cap->running_task = task; RELEASE_LOCK(&cap->lock); break; @@ -708,12 +725,13 @@ shutdownCapability (Capability *cap, Task *task, rtsBool safe) if (!osThreadIsAlive(t->id)) { debugTrace(DEBUG_sched, "worker thread %p has died unexpectedly", (void *)t->id); - if (!prev) { - cap->spare_workers = t->next; - } else { - prev->next = t->next; - } - prev = t; + cap->n_spare_workers--; + if (!prev) { + cap->spare_workers = t->next; + } else { + prev->next = t->next; + } + prev = t; } } } diff --git a/rts/Capability.h b/rts/Capability.h index a32062a..a15ce15 100644 --- a/rts/Capability.h +++ b/rts/Capability.h @@ -79,6 +79,7 @@ struct Capability_ { #if defined(THREADED_RTS) // Worker Tasks waiting in the wings. Singly-linked. Task *spare_workers; + nat n_spare_workers; // count of above // This lock protects running_task, returning_tasks_{hd,tl}, wakeup_queue. Mutex lock; diff --git a/rts/Schedule.c b/rts/Schedule.c index f6a9ef2..8e39814 100644 --- a/rts/Schedule.c +++ b/rts/Schedule.c @@ -1607,7 +1607,8 @@ forkProcess(HsStablePtr *entry // Wipe our spare workers list, they no longer exist. New // workers will be created if necessary. cap->spare_workers = NULL; - cap->returning_tasks_hd = NULL; + cap->n_spare_workers = 0; + cap->returning_tasks_hd = NULL; cap->returning_tasks_tl = NULL; #endif