Files
mercury/runtime/mercury_thread.c
Tyson Dowd 376f2c69af An initial implementation of the accurate garbage collector.
Estimated hours taken: 90

An initial implementation of the accurate garbage collector.

WORK_IN_PROGRESS:
	Add an entry for the accurate garbage collector.

library/builtin.m:
library/mercury_builtin.m:
library/std_util.m:
runtime/mercury_tabling.h:
	Deep copy terms using the address of the value instead of
	just the value.

library/io.m:
	Initialize the garbage collector's rootset with the globals.

runtime/Mmakefile:
	Add new files to the Mmakefile.

runtime/mercury_accurate_gc.h:
runtime/mercury_accurate_gc.c:
	The new garbage collector.

runtime/mercury_agc_debug.c:
runtime/mercury_agc_debug.h:
	Debugging utilities for the new garbage collector.

runtime/mercury_deep_copy.c:
runtime/mercury_deep_copy.h:
runtime/mercury_deep_copy_body.h:
	Put the deep copy code in mercury_deep_copy_body.h, and #include
	it with appropriate #defines in order to get a variant for
	deep_copy(), and one for agc_deep_copy().

	agc_deep_copy() forwards pointers as it copies.

	Also, deep_copy (all variants) have been modified to take
	a pointer to the data to be copied, because some variants
	need to be able to modify it.

runtime/mercury_engine.c:
runtime/mercury_engine.h:
	Add a second heap_zone which is the to-space of
	the copying collector.
	Add a debug_heap_zone, which is used as a scratch
	heap for debugging.

runtime/mercury_label.c:
	Instead of
		realloc(entry_table, ....)
	do
		entry_table = realloc(entry_table, ....)
	to avoid horrible bugs.

	Also, make sure the tables get initialized before looking up
	an entry label.

runtime/mercury_imp.h:
	Include mercury_debug.h before most of the modules.
	(mercury_engine.h adds a new MemoryZone only if we are
	debugging accurate GC).

runtime/mercury_memory.c:
	Setup the debug_memory_zone sizes.
	Remove an unnecessary prototype.

runtime/mercury_memory_handlers.c:
	Add code to get the program counter and the stack pointer
	from the signal context.

	Call MR_schedule_agc() from default_handler() if doing accurate gc.

runtime/mercury_memory_zones.c:
	Setup the hardzone regardless of whether redzones are used.

	Add some more debugging information.

runtime/mercury_regorder.h:
runtime/machdeps/alpha_regs.h:
runtime/machdeps/i386_regs.h:
	Add definitions to make the real machine registers name/number
	for MR_sp available.

runtime/mercury_trace_internal.c:
runtime/mercury_trace_util.c:
runtime/mercury_trace_util.h:
	Add MR_trace_write_variable(), which writes terms given their
	value and type_info.

runtime/mercury_wrapper.c:
runtime/mercury_wrapper.h:
	Change the size of the heap redzone when doing accurate GC.
	Use a small heap when debugging agc.

runtime/mercury_debug.h:
runtime/mercury_conf_param.h:
	Add new debugging macros and document them.

runtime/mercury_type_info.c:
	Add const to the pointer arguments of MR_make_type_info.
1998-07-22 07:55:19 +00:00

179 lines
3.0 KiB
C

/*
INIT mercury_scheduler_wrapper
ENDINIT
*/
/*
** Copyright (C) 1997-1998 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/
#include "mercury_imp.h"
#include "mercury_regs.h"
#include "mercury_engine.h"
#include "mercury_memory.h"
#include "mercury_thread.h"
#include <stdio.h>
#include <errno.h>
#ifdef MR_THREAD_SAFE
MercuryThreadKey MR_engine_base_key;
#endif
bool MR_exit_now;
void *init_thread(void *unused);
Declare_entry(do_runnext);
MR_MAKE_STACK_LAYOUT_ENTRY(do_runnext)
#ifdef MR_THREAD_SAFE
MercuryThread *
create_thread(int x)
{
MercuryThread *thread;
pthread_attr_t attrs;
int err;
thread = make(MercuryThread);
pthread_attr_init(&attrs);
err = pthread_create(thread, &attrs, init_thread, (void *) x);
#if 0
fprintf(stderr, "pthread_create returned %d (errno = %d)\n",
err, errno);
#endif
if (err != 0)
fatal_error("error creating thread");
return thread;
}
#endif /* MR_THREAD_SAFE */
void *
init_thread(void *unused)
{
MercuryEngine *eng;
eng = create_engine();
#ifdef MR_THREAD_SAFE
pthread_setspecific(MR_engine_base_key, eng);
#endif
#ifdef MR_ENGINE_BASE_REGISTER
restore_registers();
MR_engine_base = eng;
load_engine_regs(eng);
load_context(eng->this_context);
save_registers();
#else
MR_memcpy((void *) &MR_engine_base, (void *) eng,
sizeof(MercuryEngine));
restore_registers();
load_engine_regs(&MR_engine_base);
load_context(MR_engine_base.this_context);
save_registers();
#endif
#ifdef MR_THREAD_SAFE
MR_ENGINE(owner_thread) = pthread_self();
#endif
if (unused == 0) {
call_engine(ENTRY(do_runnext));
destroy_engine(eng);
}
return NULL;
}
#ifdef MR_THREAD_SAFE
void
destroy_thread(void *eng0)
{
MercuryEngine *eng = eng0;
destroy_engine(eng);
pthread_exit(0);
}
#endif
#ifdef MR_THREAD_SAFE
void
MR_mutex_lock(MercuryLock *lock, const char *from)
{
int err;
#if 0
fprintf(stderr, "%d locking on %p (%s)\n", pthread_self(), lock, from);
#endif
err = pthread_mutex_lock(lock);
assert(err == 0);
}
void
MR_mutex_unlock(MercuryLock *lock, const char *from)
{
int err;
#if 0
fprintf(stderr, "%d unlocking on %p (%s)\n",
pthread_self(), lock, from);
#endif
err = pthread_mutex_unlock(lock);
assert(err == 0);
}
void
MR_cond_signal(MercuryCond *cond)
{
int err;
#if 0
fprintf(stderr, "%d signaling %p\n", pthread_self(), cond);
#endif
err = pthread_cond_broadcast(cond);
assert(err == 0);
}
void
MR_cond_wait(MercuryCond *cond, MercuryLock *lock)
{
int err;
#if 0
fprintf(stderr, "%d waiting on %p (%p)\n", pthread_self(), cond, lock);
#endif
err = pthread_cond_wait(cond, lock);
assert(err == 0);
}
#endif
Define_extern_entry(do_runnext);
BEGIN_MODULE(scheduler_module)
init_entry(do_runnext);
BEGIN_CODE
Define_entry(do_runnext);
runnext();
fatal_error("Execution should never reach here.");
END_MODULE
void mercury_scheduler_wrapper(void); /* suppress gcc warning */
void mercury_scheduler_wrapper(void) {
scheduler_module();
}