X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FCapability.c;h=345bd39c0fb9560a555d3bb32caf20241b4e1f21;hb=8625c675de45bdb8bcfa795572ce7c47687c147c;hp=f5e77a900faa62c1b4a83684fde35564f84ee814;hpb=5d52d9b64c21dcf77849866584744722f8121389;p=ghc-hetmet.git diff --git a/rts/Capability.c b/rts/Capability.c index f5e77a9..345bd39 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; @@ -455,14 +456,33 @@ releaseCapabilityAndQueueWorker (Capability* cap USED_IF_THREADS) task = cap->running_task; + // If the Task is stopped, we shouldn't be yielding, we should + // be just exiting. + ASSERT(!task->stopped); + // If the current task is a worker, save it on the spare_workers // list of this Capability. A worker can mark itself as stopped, // 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)) + { + 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 +639,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 +729,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; } } } @@ -819,7 +841,7 @@ freeCapabilities (void) void markSomeCapabilities (evac_fn evac, void *user, nat i0, nat delta, - rtsBool prune_sparks USED_IF_THREADS) + rtsBool no_mark_sparks USED_IF_THREADS) { nat i; Capability *cap; @@ -843,9 +865,7 @@ markSomeCapabilities (evac_fn evac, void *user, nat i0, nat delta, } #if defined(THREADED_RTS) - if (prune_sparks) { - pruneSparkQueue (evac, user, cap); - } else { + if (!no_mark_sparks) { traverseSparkQueue (evac, user, cap); } #endif