blob: f48ec94e9710c0d526aeb80b032714d79181c510 [file] [log] [blame]
//===--------------- gcthread.h - Mvm Garbage Collector -------------------===//
//
// Mvm
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef _GC_THREAD_H_
#define _GC_THREAD_H_
#include "mvm/Threads/Cond.h"
#include "mvm/Threads/Locks.h"
#include "mvm/Threads/Thread.h"
namespace mvm {
class GCThread {
/// _globalLock - Global lock for gcmalloc.
SpinLock _globalLock;
/// _stackLock - Stack lock for synchronization.
LockNormal _stackLock;
/// _stackCond - Condition for unlocking other tasks (write protect).
Cond _stackCond;
/// _collectionCond - Condition for unblocking the collector.
Cond _collectionCond;
/// _nb_threads - Number of active threads.
unsigned int _nb_threads;
/// _nb_collected - Number of threads collected.
unsigned int _nb_collected;
/// current_collector - The initiating thread for collection. Don't
/// synchonize this one.
mvm::Thread* current_collector;
public:
mvm::Thread* base;
bool cooperative;
mvm::Thread* getCurrentCollector() {
return current_collector;
}
GCThread() {
_nb_threads = 0;
_nb_collected = 0;
current_collector = 0;
base = 0;
cooperative = false;
}
inline unsigned int get_nb_threads() {
return _nb_threads;
}
inline void lock() { _globalLock.lock(); }
inline void unlock() { _globalLock.unlock(); }
inline void stackLock() { _stackLock.lock(); }
inline void stackUnlock() { _stackLock.unlock(); }
void waitStacks();
void waitCollection();
inline void collectionFinished() {
if (cooperative) {
// We lock here to make sure no previously blocked in native threads
// will join the collection and never go back to running code.
stackLock();
mvm::Thread* cur = current_collector;
do {
cur->doYield = false;
cur = (mvm::Thread*)cur->next();
} while (cur != current_collector);
_collectionCond.broadcast();
stackUnlock();
} else {
_collectionCond.broadcast();
}
current_collector->inGC = false;
}
inline void collectorGo() { _stackCond.broadcast(); }
inline void cancel() {
// all stacks have been collected
_nb_collected = _nb_threads;
// unblock all threads in stack collection
collectorGo();
// unblock mutators
collectionFinished();
}
inline void another_mark() { _nb_collected++; }
void synchronize();
inline void remove(mvm::Thread* th) {
lock();
th->remove();
_nb_threads--;
if (!_nb_threads) base = 0;
#ifdef SERVICE
th->MyVM->numThreads--;
#endif
unlock();
}
inline void inject(mvm::Thread* th) {
lock();
#ifdef SERVICE
if (th->MyVM->numThreads + 1 > th->MyVM->threadLimit) {
unlock();
th->MyVM->stopService();
}
th->MyVM->numThreads++;
#endif
if (base)
th->append(base);
else
base = th;
_nb_threads++;
unlock();
}
};
}
#endif