blob: dc41a60d5e0002922924369c6230e5cec96569c3 [file] [log] [blame]
//===--------------- gcinit.cc - Mvm Garbage Collector -------------------===//
//
// Mvm
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <signal.h>
#include "gccollector.h"
using namespace mvm;
static const size_t def_collect_freq_auto = 4*1024*1024;
static const size_t def_collect_freq_maybe = 512*1024;
#if defined(__MACH__)
# define SIGGC SIGXCPU
#else
# define SIGGC SIGPWR
#endif
int GCCollector::siggc() {
return SIGGC;
}
void GCCollector::initialise(gc::markerFn marker) {
used_nodes = new GCChunkNode();
unused_nodes = new GCChunkNode();
#ifdef HAVE_PTHREAD
threads = new GCThread();
#endif
struct sigaction sa;
sigset_t mask;
#ifdef HAVE_PTHREAD
on_fatal = unlock_dont_recovery;
#endif
sigaction(SIGGC, 0, &sa);
sigfillset(&mask);
sa.sa_mask = mask;
sa.sa_handler = siggc_handler;
sa.sa_flags |= SA_RESTART;
sigaction(SIGGC, &sa, 0);
allocator = new GCAllocator();
// GCCollector::GCCollector(void (*marker)(void *)) {
_marker = marker;
used_nodes->alone();
current_mark = 0;
_collect_freq_auto = def_collect_freq_auto;
_collect_freq_maybe = def_collect_freq_maybe;
_since_last_collection = _collect_freq_auto;
_enable_auto = 1;
_enable_collection = 1;
_enable_maybe = 1;
status = stat_alloc;
}
void GCCollector::destroy() {
delete allocator;
allocator = 0;
}
static void *get_curr_fp(void)
{
register void *fp;
asm(
# if defined(__ppc__) || defined(__PPC__)
# if defined(__MACH__)
" mr %0, r1 "
# else
" mr %0, 1 "
# endif
# elif defined(__i386__)
" movl %%ebp, %0 "
# else
# error:
# error: I do not know how to read the frame pointer on this machine
# error:
# endif
:"=r"(fp):);
return fp;
}
static void *get_base_sp(void)
{
void *fp= 0;
for (fp= get_curr_fp(); (*(void **)fp); fp= *(void **)fp);
return fp;
}
#ifdef HAVE_PTHREAD
void GCCollector::inject_my_thread(void *base_sp) {
if(!base_sp)
base_sp = get_base_sp();
threads->inject(base_sp, current_mark);
}
#endif