cap->mut_lists[g] = NULL;
}
- cap->free_tvar_wait_queues = END_STM_WAIT_QUEUE;
+ cap->free_tvar_watch_queues = END_STM_WATCH_QUEUE;
+ cap->free_invariant_check_queues = END_INVARIANT_CHECK_QUEUE;
cap->free_trec_chunks = END_STM_CHUNK_LIST;
cap->free_trec_headers = NO_TREC;
cap->transaction_tokens = 0;
continue;
}
cap->running_task = task;
+
+ if (cap->spare_workers) {
+ // Look for workers that have died without removing
+ // themselves from the list; this could happen if the OS
+ // summarily killed the thread, for example. This
+ // actually happens on Windows when the system is
+ // terminating the program, and the RTS is running in a
+ // DLL.
+ Task *t, *prev;
+ prev = NULL;
+ for (t = cap->spare_workers; t != NULL; t = t->next) {
+ 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;
+ }
+ }
+ }
+
if (!emptyRunQueue(cap) || cap->spare_workers) {
debugTrace(DEBUG_sched,
"runnable threads or workers still alive, yielding");
continue;
}
debugTrace(DEBUG_sched, "capability %d is stopped.", cap->no);
+ freeCapability(cap);
RELEASE_LOCK(&cap->lock);
break;
}
// we now have the Capability, its run queue and spare workers
// list are both empty.
- // We end up here only in THREADED_RTS
- closeMutex(&cap->lock);
+ // ToDo: we can't drop this mutex, because there might still be
+ // threads performing foreign calls that will eventually try to
+ // return via resumeThread() and attempt to grab cap->lock.
+ // closeMutex(&cap->lock);
}
/* ----------------------------------------------------------------------------
#endif /* THREADED_RTS */
+void
+freeCapability (Capability *cap) {
+ stgFree(cap->mut_lists);
+#if defined(THREADED_RTS) || defined(PARALLEL_HASKELL)
+ freeSparkPool(&cap->r.rSparks);
+#endif
+}