X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=rts%2FCapability.c;h=ffaa372f98abe16f2eecc935c00f09140c73af24;hp=73a3427d7eb2838f5b443b6370de7411849ebea3;hb=c004ec62b41aa2137b5b5e298ca562609b0de92e;hpb=c7c9df49873a5316afac360f9ac2d8da432b40f1 diff --git a/rts/Capability.c b/rts/Capability.c index 73a3427..ffaa372 100644 --- a/rts/Capability.c +++ b/rts/Capability.c @@ -639,7 +639,7 @@ prodOneCapability (void) * ------------------------------------------------------------------------- */ void -shutdownCapability (Capability *cap, Task *task) +shutdownCapability (Capability *cap, Task *task, rtsBool safe) { nat i; @@ -696,8 +696,24 @@ shutdownCapability (Capability *cap, Task *task) 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; }