mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-14 05:12:33 +00:00
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.
179 lines
3.0 KiB
C
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();
|
|
}
|
|
|