blob: 07fb2231352994a94a3df01d58fe4c8741052910 [file] [log] [blame]
//===-------------- gcthread.cc - Mvm Garbage Collector -------------------===//
//
// Mvm
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <cassert>
#include "MvmGC.h"
using namespace mvm;
void GCThread::waitStacks() {
_stackLock.lock();
while(_nb_collected < _nb_threads)
_stackCond.wait(&_stackLock);
_stackLock.unlock();
}
void GCThread::synchronize() {
if (cooperative) {
mvm::Thread* self = mvm::Thread::get();
assert(self && "No thread local data for this thread");
current_collector = self;
_nb_collected = 0;
// Lock stacks. Changes on the doYield flag of threads must be
// protected, as threads may wake up after being blocked in native code
// and join the collection.
stackLock();
mvm::Thread* cur = self;
do {
cur->stackScanned = false;
cur->doYield = true;
cur = (mvm::Thread*)cur->next();
} while (cur != self);
// Unlock now. Each running thread will scan its stack.
stackUnlock();
// Scan the stacks of currently blocked threads.
for (mvm::Thread* cur = (mvm::Thread*)self->next(); cur != self;
cur = (mvm::Thread*)cur->next()) {
void* val = cur->getLastSP();
// If val is null, this means that the thread woke up, and is
// joining the collection. We are sure the thread will scan its stack.
if (val) Collector::traceForeignThreadStack(cur, val);
}
// Finally, scan my stack too!
Collector::siggc_handler(0);
// And wait for other threads to finish.
waitStacks();
} else {
int signo = Collector::siggc();
mvm::Thread* self = mvm::Thread::get();
self->stackScanned = false;
assert(self && "No thread local data for this thread");
current_collector = self;
_nb_collected = 0;
for (mvm::Thread* cur = (mvm::Thread*)self->next(); cur != self;
cur = (mvm::Thread*)cur->next()) {
cur->stackScanned = false;
cur->kill(signo);
}
Collector::siggc_handler(signo);
waitStacks();
}
}