- prevent multiple threads from trying to do GC (deadlocks)
- change the startWorkerThread flag to an integer, prevents
spurious extra tasks from being started at startup time
* ------------------------------------------------------------------------- */
#if defined(RTS_SUPPORTS_THREADS)
* ------------------------------------------------------------------------- */
#if defined(RTS_SUPPORTS_THREADS)
-static rtsBool startingWorkerThread = rtsFalse;
+static nat startingWorkerThread = 0;
static void
taskStart(void)
{
ACQUIRE_LOCK(&sched_mutex);
static void
taskStart(void)
{
ACQUIRE_LOCK(&sched_mutex);
- startingWorkerThread = rtsFalse;
+ startingWorkerThread--;
schedule(NULL,NULL);
taskStop();
RELEASE_LOCK(&sched_mutex);
schedule(NULL,NULL);
taskStop();
RELEASE_LOCK(&sched_mutex);
{
if ( !EMPTY_RUN_QUEUE()
&& !shutting_down_scheduler // not if we're shutting down
{
if ( !EMPTY_RUN_QUEUE()
&& !shutting_down_scheduler // not if we're shutting down
- && !startingWorkerThread)
+ && startingWorkerThread==0)
{
// we don't want to start another worker thread
// just because the last one hasn't yet reached the
// "waiting for capability" state
{
// we don't want to start another worker thread
// just because the last one hasn't yet reached the
// "waiting for capability" state
- startingWorkerThread = rtsTrue;
+ startingWorkerThread++;
if (!maybeStartNewWorker(taskStart)) {
if (!maybeStartNewWorker(taskStart)) {
- startingWorkerThread = rtsFalse;
+ startingWorkerThread--;
g0s0->blocks == cap->r.rNursery);
g0s0->blocks = bd;
#endif
g0s0->blocks == cap->r.rNursery);
g0s0->blocks = bd;
#endif
+ cap->r.rNursery->blocks = bd;
}
cap->r.rCurrentNursery->u.back = bd;
}
cap->r.rCurrentNursery->u.back = bd;
+ static rtsBool waiting_for_gc;
int n_capabilities = RtsFlags.ParFlags.nNodes - 1;
// subtract one because we're already holding one.
Capability *caps[n_capabilities];
int n_capabilities = RtsFlags.ParFlags.nNodes - 1;
// subtract one because we're already holding one.
Capability *caps[n_capabilities];
// the other tasks to sleep and stay asleep.
//
// the other tasks to sleep and stay asleep.
//
+ // Someone else is already trying to GC
+ if (waiting_for_gc) return;
+ waiting_for_gc = rtsTrue;
+
caps[n_capabilities] = cap;
while (n_capabilities > 0) {
IF_DEBUG(scheduler, sched_belch("ready_to_gc, grabbing all the capabilies (%d left)", n_capabilities));
caps[n_capabilities] = cap;
while (n_capabilities > 0) {
IF_DEBUG(scheduler, sched_belch("ready_to_gc, grabbing all the capabilies (%d left)", n_capabilities));
n_capabilities--;
caps[n_capabilities] = cap;
}
n_capabilities--;
caps[n_capabilities] = cap;
}
+
+ waiting_for_gc = rtsFalse;
#endif
/* Kick any transactions which are invalid back to their
#endif
/* Kick any transactions which are invalid back to their
#if defined(SMP)
/* eagerly start some extra workers */
#if defined(SMP)
/* eagerly start some extra workers */
+ startingWorkerThread = RtsFlags.ParFlags.nNodes;
startTasks(RtsFlags.ParFlags.nNodes, taskStart);
#endif
startTasks(RtsFlags.ParFlags.nNodes, taskStart);
#endif