* ------------------------------------------------------------------------- */
void
-shutdownCapability (Capability *cap, Task *task)
+shutdownCapability (Capability *cap, Task *task, rtsBool safe)
{
nat i;
for (t = cap->spare_workers; t != NULL; t = t->next) {
if (!osThreadIsAlive(t->id)) {
debugTrace(DEBUG_sched,
- "worker thread %p has died unexpectedly", t->id);
+ "worker thread %p has died unexpectedly", (void *)t->id);
if (!prev) {
cap->spare_workers = t->next;
} else {
yieldThread();
continue;
}
+
+ // If "safe", then busy-wait for any threads currently doing
+ // foreign calls. If we're about to unload this DLL, for
+ // example, we need to be sure that there are no OS threads
+ // that will try to return to code that has been unloaded.
+ // We can be a bit more relaxed when this is a standalone
+ // program that is about to terminate, and let safe=false.
+ if (cap->suspended_ccalling_tasks && safe) {
+ debugTrace(DEBUG_sched,
+ "thread(s) are involved in foreign calls, yielding");
+ cap->running_task = NULL;
+ RELEASE_LOCK(&cap->lock);
+ yieldThread();
+ continue;
+ }
+
debugTrace(DEBUG_sched, "capability %d is stopped.", cap->no);
- freeCapability(cap);
+ freeCapability(cap);
RELEASE_LOCK(&cap->lock);
break;
}