for review: independent AND parallelism [runtime]
Thomas Charles CONWAY
conway at cs.mu.OZ.AU
Mon Apr 27 21:28:18 AEST 1998
Hi
This post contains the changes to the runtime for adding independent AND
parallelism.
--
Thomas Conway || conway at cs.mu.oz.au
AD DEUM ET VINUM || Nail here [] for new monitor.
configure.in:
Add a test to find the number of words needed to represent a
synchronization term.
boehm_gc/gc.h:
fix a declaration by replacing the args () with (void).
boehm_gc/solaris_pthreads.c:
add a missing include
check the return values of pthread calls.
compiler/*.m:
Add handling for the new HLDS goal type par_conj.
Add handling for the four new LLDS instructions:
init_sync_term
fork
join_and_terminate
join_and_continue
compiler/code_info.m:
add a new alternative for slot_contents - sync_term.
compiler/handle_options.m:
add .par as part of the grade
compiler/hlds_goal.m:
add the new goal type par_conj.
compiler/instmap.m:
add instmap__unify which takes a list of instmaps
and abstractly unifies them.
add unify_instmap_delta which tajes two instmap deltas
and abstractly unifies them.
compiler/llds.m:
add the new llds instructions.
compiler/mode_info.m:
add par_conj as a lock reason.
library/Makefile:
work around a bug in the solaris version pthread.h
library/benchmarking.m:
reference the stack zones from the engine structure
rather than from global variables.
library/{nc,sp}_builtin.nl:
add an op declaration for &.
library/std_util.m:
change references to global variables to references inside
the engine structure.
runtime/Mmakefile:
add mercury_thread.{c,h}
add THREADLIBS to the libraries
runtime/*.{c,h}
Remove some old junk from the previous processes/shrd-mem
changes that found their way into the repository.
Add MR_ prefixes to lots of names.
runtime/mercury_context.c:
Add init_thread_stuff for creating and initializing a
context structure for the current thread.
runtime/mercury_context.h:
add a field to the mercury context which stores the thread id
of the thread where this context originated.
add various macros for implementing the new llds instructions.
runtime/mercury_engine.c:
initialize the engine structure, rather than a bunch of globals.
runtime/mercury_engine.h:
declare the mercury_engine structure.
runtime/mercury_regorder.h:
if MR_THREAD_SAFE, and there is at least one global register
then use mr0 as a pointer to the mercury engine structure.
scripts/init_grade_options.sh-subr
add thread_safe
scripts/mgnuc.in
add THREAD_OPTS
scripts/ml.in:
add THREAD_LIBS
cvs diff: Diffing profiler
cvs diff: Diffing runtime
Index: runtime/Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/Mmakefile,v
retrieving revision 1.21
diff -u -r1.21 Mmakefile
--- Mmakefile 1997/12/05 15:56:25 1.21
+++ Mmakefile 1998/03/18 23:49:45
@@ -54,6 +54,7 @@
mercury_string.h \
mercury_table.h \
mercury_tags.h \
+ mercury_thread.h \
mercury_timing.h \
mercury_trace.h \
mercury_trail.h \
@@ -94,6 +95,7 @@
mercury_regs.c \
mercury_spinlock.c \
mercury_table.c \
+ mercury_thread.c \
mercury_timing.c \
mercury_trace.c \
mercury_trail.c \
@@ -110,6 +112,11 @@
*.gc*) echo "-lgc" ;; \
esac \
`
+THREADLIBS = \
+ ` case "$(GRADE)" in \
+ *.par*) echo "-lpthread" ;; \
+ esac \
+ `
#-----------------------------------------------------------------------------#
@@ -145,7 +152,7 @@
libmer.so: $(PIC_OBJS)
$(LINK_SHARED_OBJ) -o libmer.so $(PIC_OBJS) \
$(SHLIB_RPATH_OPT)$(FINAL_INSTALL_MERC_GC_LIB_DIR) \
- $(LDFLAGS) $(LDLIBS) \
+ $(LDFLAGS) $(LDLIBS) $(THREADLIBS) \
$(SHARED_LIBS)
runtime.init: $(CFILES)
Index: runtime/mercury_context.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_context.c,v
retrieving revision 1.1
diff -u -r1.1 mercury_context.c
--- mercury_context.c 1997/11/20 01:59:46 1.1
+++ mercury_context.c 1998/03/11 04:52:29
@@ -14,49 +14,62 @@
#include <stdio.h>
#include <unistd.h> /* for getpid() and fork() */
-#ifdef PARALLEL
-#include <signal.h>
+#ifdef MR_THREAD_SAFE
+#include "mercury_thread.h"
#endif
#include "mercury_context.h"
#include "mercury_engine.h" /* for `memdebug' */
-Context *this_context;
+Context *MR_runqueue;
+#ifdef MR_THREAD_SAFE
+MercuryLock *MR_runqueue_lock;
+MercuryCond *MR_runqueue_cond;
+#endif
+
+
static Context *free_context_list = NULL;
+#ifdef MR_THREAD_SAFE
+static MercuryLock *free_context_list_lock;
+#endif
-void
-init_process_context(void)
+void
+init_thread_stuff(void)
{
- init_heap();
+#ifdef MR_THREAD_SAFE
+
+ MR_runqueue_lock = make(MercuryLock);
+ pthread_mutex_init(MR_runqueue_lock, MR_MUTEX_ATTR);
- this_context = new_context();
- /* load the registers so we don't clobber hp */
- restore_transient_registers();
- load_context(this_context);
- save_transient_registers();
+ MR_runqueue_cond = make(MercuryCond);
+ pthread_cond_init(MR_runqueue_cond, MR_COND_ATTR);
- if (memdebug) debug_memory();
+ free_context_list_lock = make(MercuryLock);
+ pthread_mutex_init(free_context_list_lock, MR_MUTEX_ATTR);
+
+ MR_KEY_CREATE(&MR_engine_base_key, NULL);
+
+#endif
}
-Context *
-new_context(void)
+void
+finalize_runqueue(void)
{
- Context *c;
-
- if (free_context_list == NULL) {
- c = (Context *) make(Context);
- c->detstack_zone = NULL;
- c->nondetstack_zone = NULL;
-#ifdef MR_USE_TRAIL
- c->trail_zone = NULL;
+#ifdef MR_THREAD_SAFE
+ pthread_mutex_destroy(MR_runqueue_lock);
+ pthread_cond_destroy(MR_runqueue_cond);
+ pthread_mutex_destroy(free_context_list_lock);
#endif
- } else {
- c = free_context_list;
- free_context_list = c->next;
- }
+}
+void
+init_context(Context *c)
+{
c->next = NULL;
c->resume = NULL;
+#ifdef MR_THREAD_SAFE
+ c->owner_thread = (MercuryThread) NULL;
+#endif
c->context_succip = ENTRY(do_not_reached);
if (c->detstack_zone != NULL) {
@@ -95,15 +108,40 @@
#endif
c->context_hp = NULL;
+}
+
+Context *
+create_context(void)
+{
+ Context *c;
+
+ MR_LOCK(free_context_list_lock, "create_context");
+ if (free_context_list == NULL) {
+ MR_UNLOCK(free_context_list_lock, "create_context i");
+ c = (Context *) make(Context);
+ c->detstack_zone = NULL;
+ c->nondetstack_zone = NULL;
+#ifdef MR_USE_TRAIL
+ c->trail_zone = NULL;
+#endif
+ } else {
+ c = free_context_list;
+ free_context_list = c->next;
+ MR_UNLOCK(free_context_list_lock, "create_context ii");
+ }
+
+ init_context(c);
return c;
}
void
-delete_context(Context *c)
+destroy_context(Context *c)
{
+ MR_LOCK(free_context_list_lock, "destroy_context");
c->next = free_context_list;
free_context_list = c;
+ MR_UNLOCK(free_context_list_lock, "destroy_context");
}
void
Index: runtime/mercury_context.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_context.h,v
retrieving revision 1.3
diff -u -r1.3 mercury_context.h
--- mercury_context.h 1997/11/24 15:51:58 1.3
+++ mercury_context.h 1998/03/11 04:52:29
@@ -45,34 +45,21 @@
#include "mercury_regs.h" /* for hp. Must come before system headers. */
-#include <sys/types.h> /* for pid_t */
+#include <stdio.h>
-#include "mercury_types.h" /* for Word */
-#include "mercury_trail.h" /* for MR_TrailEntry */
+#include "mercury_types.h" /* for Word */
+#include "mercury_trail.h" /* for MR_TrailEntry */
#include "mercury_memory.h" /* for MemoryZone */
-#include "mercury_spinlock.h" /* for SpinLock */
+#include "mercury_thread.h" /* for MercuryLock */
#include "mercury_goto.h" /* for GOTO() */
-/*
-** If we have parallelism switched on (PARALLEL is defined),
-** then we define how many processes should be used.
-** Ultimately this should be configurable through the
-** MERCURY_OPTIONS environment variable.
-*/
-#ifdef PARALLEL
-extern unsigned numprocs;
+#ifdef MR_THREAD_SAFE
+ #define MR_IF_THREAD_SAFE(x) x
+#else
+ #define MR_IF_THREAD_SAFE(x) ((void) 0)
#endif
/*
-** The number of context structures initially allocated.
-** This allocation does not include the stacks that they
-** refer to - only the actual context structures.
-** At the moment if we need more than this number of contexts,
-** we just die. In the longer term, we need to allocate more.
-*/
-#define INITIAL_NUM_CONTEXTS 20
-
-/*
** The field names that correspond to virtual machine registers:
** sp, maxfr & curfr
** are prefixed with `context_' so that they don't get replaced
@@ -96,6 +83,15 @@
** this context is next scheduled.
*/
+#ifdef MR_THREAD_SAFE
+ MercuryThread owner_thread;
+ /*
+ ** The owner_thread field is used to ensure that when we
+ ** enter a mercury engine from C, we return to the same
+ ** engine. See the coments in mercury_engine.h
+ */
+#endif
+
Code *context_succip;
/* succip for this context */
@@ -137,63 +133,48 @@
** need to be reinitialized, but have space allocated to
** them. (see comments in mercury_memory.h about reset_zone())
*/
-extern Context **free_context_list_ptr;
+extern Context *free_context_list;
/*
** the runqueue is a linked list of contexts that are
** runnable.
*/
-extern Context **runqueue_ptr;
-
-/*
-** this_context is a pointer to the currently executing
-** context. the fields of this_context are not necessarily
-** in sync with the real values, since *this_context only
-** gets updated when save_context() gets called.
-*/
-extern Context *this_context;
-/* a pointer to a word used for the spinlock on the runqueue */
-extern SpinLock *runqueue_lock;
+extern Context *MR_runqueue;
+extern Context *MR_suspended_forks;
+#ifdef MR_THREAD_SAFE
+extern MercuryLock *MR_runqueue_lock;
+extern MercuryCond *MR_runqueue_cond;
+#endif
-/*
-** a pointer to a word used for the spinlock on the free
-** context list
-*/
-extern SpinLock *free_context_list_lock;
/*
-** init_processes() forks new process (if necessary), and
-** initializes the data-structures for managing the interactions
-** between them.
+** Initializes a context structure.
*/
-void init_processes(void);
+void init_context(Context *context);
/*
-** shutdown_processes() sends a signal to the other processes
-** to tell them to shut down. (NOT YET IMPLEMENTED - STUB ONLY.)
+** create_context() allocates and initializes a new context
+** structure.
*/
-void shutdown_processes(void);
+Context *create_context(void);
/*
-** init_process_context() creates a top-level context for
-** the original process, and allocates a heap and a solutions-
-** heap for each process.
+** destroy_context(ptr) returns the context structure pointed
+** to by ptr to the free list, and releases resources as
+** necessary.
*/
-void init_process_context(void);
+void destroy_context(Context *context);
/*
-** new_context() allocates and initializes a new context
-** structure.
+** init_thread_stuff() initializes the lock structures for the runqueue.
*/
-Context *new_context(void);
+void init_thread_stuff(void);
/*
-** delete_context(ptr) returns the context structure pointed
-** to by ptr to the free list, and releases resources as
-** necessary.
+** finialize_runqueue() finalizes the lock structures for the runqueue.
*/
-void delete_context(Context *context);
+void finalize_runqueue(void);
/*
** flounder() aborts with a runtime error message. It is called if
@@ -203,46 +184,83 @@
void flounder(void);
/*
-** procid[N] is the process id of the Nth process.
-** procid[my_procnum] == getpid() == my_procid.
-*/
-extern pid_t *procid;
-
-/*
-** procwaiting[N] is true if the process procid[N] is
-** suspended because the runqueue was empty when it
-** called runnext().
-** Although we semantically want bools here, we use
-** words to ensure coherency. Since a bool may be
-** smaller than a word, storing a bool may be implemented
-** in a coherency-breaking manner.
-** (Assuming that Words can be read and written in a
-** coherent manner is sufficiently important in terms of
-** simplifying the synchronization mechanisms, that
-** we really need to do so -- or so says Tom, at least.
-** I remain unconvinced. -Fergus.)
+** schedule(Context *cptr):
*/
-typedef Word AtomicBool;
-extern AtomicBool *procwaiting;
-/*
-** my_procnum is the number of the current process.
-** my_procnum == 0 is the original parent process.
-*/
-extern int my_procnum;
-extern pid_t my_procid;
+#ifdef MR_THREAD_SAFE
+#define schedule(cptr) do { \
+ MR_LOCK(MR_runqueue_lock, "schedule"); \
+ ((Context *)cptr)->next = MR_runqueue; \
+ MR_runqueue = (Context *) (cptr); \
+ MR_SIGNAL(MR_runqueue_cond); \
+ MR_UNLOCK(MR_runqueue_lock, "schedule"); \
+ } while(0)
-/* do a context switch */
-Declare_entry(do_runnext);
-#define runnext() GOTO(ENTRY(do_runnext));
+ /*
+ ** runnext() tries to execute the first context on the
+ ** runqueue. If the context was directly called from C
+ ** it may only be executed in the thread that the C call
+ ** originated in or should the context return to C the
+ ** C stack will be wrong!
+ ** If there are no contexts that the current thread can
+ ** execute, then we suspend until another thread puts something
+ ** into the runqueue. Currently, it is not possible for
+ ** floundering to occur, so we haven't got a check for it.
+ */
+#define runnext() do { \
+ Context *rn_c, *rn_p; \
+ unsigned x; \
+ MercuryThread t; \
+ x = MR_ENGINE(c_depth); \
+ t = MR_ENGINE(owner_thread); \
+ MR_LOCK(MR_runqueue_lock, "runnext i"); \
+ while (1) { \
+ if (MR_exit_now == TRUE) \
+ destroy_thread(MR_engine_base); \
+ rn_c = MR_runqueue; \
+ rn_p = NULL; \
+ while (rn_c != NULL) { \
+ if ( (x > 0 && rn_c->owner_thread == t) \
+ || (rn_c->owner_thread == NULL)) \
+ break; \
+ rn_p = rn_c; \
+ rn_c = rn_c->next; \
+ } \
+ if (rn_c != NULL) \
+ break; \
+ MR_WAIT(MR_runqueue_cond, MR_runqueue_lock); \
+ } \
+ MR_ENGINE(this_context) = rn_c; \
+ if (rn_p == NULL) \
+ MR_runqueue = rn_c->next; \
+ else \
+ rn_p->next = rn_c->next; \
+ MR_UNLOCK(MR_runqueue_lock, "runnext"); \
+ load_context(MR_ENGINE(this_context)); \
+ GOTO(MR_ENGINE(this_context)->resume); \
+ } while(0)
+#else
+#define schedule(cptr) do { \
+ ((Context *)cptr)->next = MR_runqueue; \
+ MR_runqueue = (Context *) (cptr); \
+ } while(0)
-/*
-** schedule(Context *cptr, Code *resume):
-*/
-#define schedule(cptr, resume) do { \
- fatal_error("schedule not implemented"); \
+#define runnext() do { \
+ if (MR_runqueue == NULL) { \
+ fatal_error("empty runqueue"); \
+ } \
+ MR_ENGINE(this_context) = MR_runqueue; \
+ MR_runqueue = MR_runqueue->next; \
+ load_context(MR_ENGINE(this_context)); \
+ GOTO(MR_ENGINE(this_context)->resume); \
} while(0)
+#endif
+#ifdef MR_THREAD_SAFE
+#define IF_MR_THREAD_SAFE(x) x
+#else
+#define IF_MR_THREAD_SAFE(x)
+#endif
/*
** fork_new_context(Code *child, Code *parent, int numslots):
** create a new context to execute the code at `child', and
@@ -250,19 +268,26 @@
** The new context gets put on the runqueue, and the current
** context resumes at `parent'.
*/
-#define fork_new_context(child, parent, numslots) do { \
- Context *fork_new_context_context; \
- int fork_new_context_i; \
- fork_new_context_context = new_context(); \
- for (fork_new_context_i = (numslots) ; \
- fork_new_context_i > 0 ; \
- fork_new_context_i--) { \
- *(fork_new_context_context->context_sp) = \
- detstackvar(fork_new_context_i); \
- fork_new_context_context->context_sp++; \
- } \
- fork_new_context_context->resume = (child); \
- schedule(fork_new_context_context, (parent)); \
+#define fork_new_context(child, parent, numslots) do { \
+ Context *f_n_c_context; \
+ int fork_new_context_i; \
+ MR_LOCK(MR_runqueue_lock, "fork"); \
+ MR_UNLOCK(MR_runqueue_lock, "fork"); \
+ f_n_c_context = create_context(); \
+ IF_MR_THREAD_SAFE( \
+ f_n_c_context->owner_thread = NULL; \
+ ) \
+ for (fork_new_context_i = (numslots) ; \
+ fork_new_context_i > 0 ; \
+ fork_new_context_i--) { \
+ *(f_n_c_context->context_sp) = \
+ detstackvar(fork_new_context_i); \
+ f_n_c_context->context_sp++; \
+ } \
+ f_n_c_context->resume = (child); \
+ schedule(f_n_c_context); \
+ GOTO((parent)); \
+ } \
} while (0)
#ifndef CONSERVATIVE_GC
@@ -331,9 +356,7 @@
Context *load_context_c; \
load_context_c = (cptr); \
MR_succip = load_context_c->context_succip; \
- detstack_zone = load_context_c->detstack_zone; \
- MR_sp = load_context_c->context_sp; \
- nondetstack_zone = load_context_c->nondetstack_zone; \
+ MR_sp = load_context_c->context_sp; \
MR_maxfr = load_context_c->context_maxfr; \
MR_curfr = load_context_c->context_curfr; \
MR_IF_USE_TRAIL( \
@@ -342,16 +365,18 @@
MR_ticket_counter = \
load_context_c->context_ticket_counter; \
) \
- set_min_heap_reclamation_point(load_context_c); \
+ MR_ENGINE(context).detstack_zone = \
+ load_context_c->detstack_zone; \
+ MR_ENGINE(context).nondetstack_zone = \
+ load_context_c->nondetstack_zone; \
+ set_min_heap_reclamation_point(load_context_c); \
} while (0)
#define save_context(cptr) do { \
Context *save_context_c; \
save_context_c = (cptr); \
save_context_c->context_succip = MR_succip; \
- save_context_c->detstack_zone = detstack_zone; \
save_context_c->context_sp = MR_sp; \
- save_context_c->nondetstack_zone = nondetstack_zone; \
save_context_c->context_maxfr = MR_maxfr; \
save_context_c->context_curfr = MR_curfr; \
MR_IF_USE_TRAIL( \
@@ -360,35 +385,67 @@
save_context_c->context_ticket_counter = \
MR_ticket_counter; \
) \
+ save_context_c->detstack_zone = \
+ MR_ENGINE(context).detstack_zone; \
+ save_context_c->nondetstack_zone = \
+ MR_ENGINE(context).nondetstack_zone; \
save_hp_in_context(save_context_c); \
} while (0)
-/*
-** The following two macros join_and_terminate and join_and_continue
-** both take a `sync_term' which has the following structure:
-** sync_term[SYNC_TERM_LOCK] is a SpinLock
-** sync_term[SYNC_TERM_COUNTER] is a counter for the number of
-** processes that need to synchronize before the
-** parent can proceed.
-** sync_term[SYNC_TERM_PARENT] is either NULL or a pointer to the
-** context of the parent process. If it is non-null
-** then the last process to arrive (the one that
-** decrements sync_term[SYNC_TERM_COUNTER] to 0)
-** must wake the parent.
-** These terms are allocated and manipulated as normal Mercury terms by
-** generated Mercury code.
-*/
-
-#define SYNC_TERM_LOCK 0
-#define SYNC_TERM_COUNTER 1
-#define SYNC_TERM_PARENT 2
+typedef struct SYNCTERM SyncTerm;
+struct SYNCTERM {
+#ifdef MR_THREAD_SAFE
+ MercuryLock lock;
+#endif
+ int count;
+ Context *parent;
+};
+
+#ifdef MR_THREAD_SAFE
+#define MR_init_sync_term(sync_term, nbranches) do { \
+ SyncTerm *st = (SyncTerm *) sync_term; \
+ pthread_mutex_init(&(st->lock), MR_MUTEX_ATTR); \
+ st->count = (nbranches); \
+ st->parent = NULL; \
+ } while (0)
+#else
+#define MR_init_sync_term(sync_term, nbranches) do { \
+ SyncTerm *st = (SyncTerm *) sync_term; \
+ st->count = (nbranches); \
+ st->parent = NULL; \
+ } while (0)
+#endif
#define join_and_terminate(sync_term) do { \
- fatal_error("join_and_terminate not implemented"); \
+ SyncTerm *st = (SyncTerm *) sync_term; \
+ MR_LOCK(&(st->lock), "terminate"); \
+ (st->count)--; \
+ if (st->count == 0) { \
+ assert(st->parent != NULL); \
+ MR_UNLOCK(&(st->lock), "terminate i"); \
+ schedule(st->parent); \
+ } else { \
+ assert(st->count > 0); \
+ MR_UNLOCK(&(st->lock), "terminate ii"); \
+ } \
+ destroy_context(MR_ENGINE(this_context)); \
+ runnext(); \
} while (0)
#define join_and_continue(sync_term, where_to) do { \
- fatal_error("join_and_continue not implemented"); \
+ SyncTerm *st = (SyncTerm *) sync_term; \
+ MR_LOCK(&(st->lock), "continue"); \
+ (st->count)--; \
+ if (st->count == 0) { \
+ MR_UNLOCK(&(st->lock), "continue i"); \
+ GOTO((where_to)); \
+ } \
+ assert(st->count > 0); \
+ save_context(MR_ENGINE(this_context)); \
+ MR_ENGINE(this_context)->resume = (where_to); \
+ st->parent = MR_ENGINE(this_context); \
+ MR_UNLOCK(&(st->lock), "continue ii"); \
+ runnext(); \
} while (0)
#endif /* not MERCURY_CONTEXT_H */
Index: runtime/mercury_engine.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_engine.c,v
retrieving revision 1.4
diff -u -r1.4 mercury_engine.c
--- mercury_engine.c 1997/12/05 17:53:51 1.4
+++ mercury_engine.c 1998/03/11 04:52:30
@@ -36,7 +36,9 @@
bool debugflag[MAXFLAG];
-jmp_buf *MR_engine_jmp_buf;
+#ifndef MR_THREAD_SAFE
+MercuryEngine MR_engine_base;
+#endif
/*---------------------------------------------------------------------------*/
@@ -48,25 +50,70 @@
** Next, init_engine() calls init_processes() which fork()s the right
** number of processes, and initializes the data structures for coordinating
** the interaction between multiple processes.
-** Then, init_engine() calls init_process_context() which initializes the
-** local context for this process including the heap and solutions heap.
-** If it is the original process, it allocates the initial context for main.
-**
-** Finally, if there are multiple processes, init_engine calls
-** call_engine(do_runnext) for all but the first one, which makes
-** them sleep until work becomes available. The initial process
-** returns to the caller.
*/
void
-init_engine(void)
+init_engine(MercuryEngine *eng)
{
- init_memory();
+ /* XXX */ init_memory();
+
+#ifndef CONSERVATIVE_GC
+ eng->heap_zone = create_zone("heap", 1, heap_size, next_offset(),
+ heap_zone_size, default_handler);
+ eng->e_hp = eng->heap_zone->min;
+
+ eng->solutions_heap_zone = create_zone("solutions_heap", 1,
+ solutions_heap_size, next_offset(),
+ solutions_heap_zone_size, default_handler);
+ eng->e_sol_hp = eng->solutions_heap_zone->min;
+
+#endif
+#ifndef SPEED
+ /*
+ ** Create the dumpstack, used for debugging stack traces.
+ ** Note that we can just make the dumpstack the same size as
+ ** the detstack and we never have to worry about the dumpstack
+ ** overflowing.
+ */
+
+ dumpstack_zone = create_zone("dumpstack", 1, detstack_size,
+ next_offset(), detstack_zone_size, default_handler);
+#endif
+
+ eng->this_context = create_context();
#ifndef USE_GCC_NONLOCAL_GOTOS
make_label("engine_done", LABEL(engine_done), engine_done);
#endif
- init_process_context();
+#ifdef MR_THREAD_SAFE
+ eng->owner_thread = pthread_self();
+ eng->c_depth = 0;
+#endif
+
+}
+
+/*---------------------------------------------------------------------------*/
+
+void finalize_engine(MercuryEngine *eng)
+{
+
+}
+
+/*---------------------------------------------------------------------------*/
+
+MercuryEngine
+*create_engine(void)
+{
+ MercuryEngine *eng;
+
+ eng = make(MercuryEngine);
+ init_engine(eng);
+ return eng;
+}
+
+void destroy_engine(MercuryEngine *eng)
+{
+ free(eng);
}
/*---------------------------------------------------------------------------*/
@@ -117,25 +164,27 @@
jmp_buf * volatile prev_jmp_buf;
/*
- ** Preserve the value of MR_engine_jmp_buf on the C stack.
+ ** Preserve the value of MR_ENGINE(e_jmp_buf) on the C stack.
** This is so "C calls Mercury which calls C which calls Mercury" etc.
** will work.
*/
- prev_jmp_buf = MR_engine_jmp_buf;
- MR_engine_jmp_buf = &curr_jmp_buf;
+ restore_transient_registers();
+
+ prev_jmp_buf = MR_ENGINE(e_jmp_buf);
+ MR_ENGINE(e_jmp_buf) = &curr_jmp_buf;
/*
** Mark this as the spot to return to.
** On return, restore the registers (since longjmp may clobber
- ** them), restore the saved value of MR_engine_jmp_buf, and then
+ ** them), restore the saved value of MR_ENGINE(e_jmp_buf), and then
** exit.
*/
if (setjmp(curr_jmp_buf)) {
debugmsg0("...caught longjmp\n");
restore_registers();
- MR_engine_jmp_buf = prev_jmp_buf;
+ MR_ENGINE(e_jmp_buf) = prev_jmp_buf;
return;
}
@@ -149,6 +198,9 @@
void
call_engine_inner(Code *entry_point)
{
+#ifdef MR_THREAD_SAFE
+ MercuryThread saved_owner_thread;
+#endif
/*
** Allocate some space for local variables in other
** procedures. This is done because we may jump into the middle
@@ -203,6 +255,17 @@
debugmsg1("in `call_engine', locals at %p\n", (void *)locals);
/*
+ ** Increment the number of times we've entered this
+ ** engine from C, and mark the current context as being
+ ** owned by this thread.
+ */
+#ifdef MR_THREAD_SAFE
+ MR_ENGINE(c_depth)++;
+ saved_owner_thread = MR_ENGINE(this_context)->owner_thread;
+ MR_ENGINE(this_context)->owner_thread = MR_ENGINE(owner_thread);
+#endif
+
+ /*
** Now just call the entry point
*/
@@ -210,6 +273,18 @@
Define_label(engine_done);
/*
+ ** Decrement the number of times we've entered this
+ ** engine from C and restore the owning thread in
+ ** the current context.
+ */
+#ifdef MR_THREAD_SAFE
+ assert(MR_ENGINE(this_context)->owner_thread
+ == MR_ENGINE(owner_thread));
+ MR_ENGINE(c_depth)--;
+ MR_ENGINE(this_context)->owner_thread = saved_owner_thread;
+#endif
+
+ /*
** We need to ensure that there is at least one
** real function call in call_engine(), because
** otherwise gcc thinks that it doesn't need to
@@ -262,7 +337,7 @@
*/
save_registers();
debugmsg0("longjmping out...\n");
- longjmp(*MR_engine_jmp_buf, 1);
+ longjmp(*(MR_ENGINE(e_jmp_buf)), 1);
}} /* end call_engine_inner() */
/* with nonlocal gotos, we don't save the previous locations */
@@ -291,7 +366,7 @@
{
save_registers();
debugmsg0("longjmping out...\n");
- longjmp(*MR_engine_jmp_buf, 1);
+ longjmp(*(MR_ENGINE(e_jmp_buf), 1);
}
static Code *
Index: runtime/mercury_engine.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_engine.h,v
retrieving revision 1.2
diff -u -r1.2 mercury_engine.h
--- mercury_engine.h 1997/11/23 07:21:21 1.2
+++ mercury_engine.h 1998/03/18 04:05:11
@@ -15,10 +15,12 @@
#include <setjmp.h>
+#include "mercury_regs.h" /* for NUM_REAL_REGS */
#include "mercury_std.h" /* for `bool' */
#include "mercury_types.h" /* for `Code *' */
#include "mercury_goto.h" /* for `Define_entry()' */
-#include "mercury_regs.h" /* for NUM_REAL_REGS */
+#include "mercury_thread.h" /* for pthread types */
+#include "mercury_context.h" /* for MR_IF_USE_TRAIL */
#define PROGFLAG 0
#define GOTOFLAG 1
@@ -57,7 +59,7 @@
typedef struct {
jmp_buf *mercury_env; /*
- ** used to save MR_engine_jmp_buf
+ ** used to save MR_ENGINE(e_jmp_buf )
*/
jmp_buf env; /*
** used by calls to setjmp and longjmp
@@ -78,7 +80,7 @@
/*
** MR_setjmp(MR_jmp_buf *env, longjmp_label)
**
- ** Save MR_engine_jmp_buf, save the Mercury state, call setjmp(env),
+ ** Save MR_ENGINE(e_jmp_buf), save the Mercury state, call setjmp(env),
** then fall through.
**
** When setjmp returns via a call to longjmp, control will pass to
@@ -94,9 +96,9 @@
*/
#define MR_setjmp(setjmp_env, longjmp_label) \
do { \
- (setjmp_env)->mercury_env = MR_engine_jmp_buf; \
+ (setjmp_env)->mercury_env = MR_ENGINE(e_jmp_buf); \
save_regs_to_mem((setjmp_env)->regs); \
- (setjmp_env)->saved_succip = succip; \
+ (setjmp_env)->saved_succip = MR_succip; \
(setjmp_env)->saved_sp = sp; \
(setjmp_env)->saved_curfr = curfr; \
(setjmp_env)->saved_maxfr = maxfr; \
@@ -105,9 +107,9 @@
MR_IF_USE_TRAIL((setjmp_env)->saved_ticket_counter = \
MR_ticket_counter); \
if (setjmp((setjmp_env)->env)) { \
- MR_engine_jmp_buf = (setjmp_env)->mercury_env; \
+ MR_ENGINE(e_jmp_buf) = (setjmp_env)->mercury_env; \
restore_regs_from_mem((setjmp_env)->regs); \
- succip = (setjmp_env)->saved_succip; \
+ MR_succip = (setjmp_env)->saved_succip; \
sp = (setjmp_env)->saved_sp; \
curfr = (setjmp_env)->saved_curfr; \
maxfr = (setjmp_env)->saved_maxfr; \
@@ -126,15 +128,131 @@
*/
#define MR_longjmp(setjmp_env) longjmp((setjmp_env)->env, 1)
- /*
- ** engine_jmp_buf should only be referred to in engine.c
- ** and the MR_setjmp and MR_longjmp macros defined above.
+extern bool debugflag[];
+
+typedef struct MR_MERCURY_ENGINE {
+ Word fake_reg[MAX_FAKE_REG];
+ /* The fake reg vector for this engine. */
+#ifndef CONSERVATIVE_GC
+ Word *e_hp;
+ /* The heap pointer for this engine */
+ Word *e_sol_hp;
+ /* The solutions heap pointer for this engine */
+#endif
+ Context *this_context;
+ /*
+ ** this_context points to the context currently
+ ** executing in this engine.
+ */
+ Context context;
+ /*
+ ** context stores all the context information
+ ** for the context executing in this engine.
+ */
+#ifdef MR_THREAD_SAFE
+ MercuryThread owner_thread;
+ unsigned c_depth;
+ /*
+ ** These two fields are used to ensure that when a
+ ** thread executing C code calls the Mercury engine
+ ** associated with that thread, the Mercury code
+ ** will finish in the same engine and return appropriately.
+ ** Each time C calls Mercury in a thread, the c_depth
+ ** is incremented, and the owner_thread field of the current
+ ** context is set to the id of the thread. While the
+ ** owner_thread is set, the context will not be scheduled
+ ** for execution by any other thread. When the call to
+ ** the Mercury engine finishes, c_depth is decremented and
+ ** the owner_thread field of the current context is restored
+ ** to its previous value.
+ */
+#endif
+ jmp_buf *e_jmp_buf;
+#ifndef CONSERVATIVE_GC
+ MemoryZone *heap_zone;
+ MemoryZone *solutions_heap_zone;
+#endif
+#ifndef SPEED
+ MemoryZone *dumpstack_zone;
+ int dumpindex;
+#endif
+} MercuryEngine;
+
+/*
+** MR_engine_base refers to the engine in which execution is taking place.
+** In the non-thread-safe situation, it is just a global variable.
+** In the thread-safe situation, MR_engine_base is either a global
+** register (if one is available), or a macro that accesses thread-local
+** storage.
+*/
+
+#ifdef MR_THREAD_SAFE
+
+ extern MercuryThreadKey MR_engine_base_key;
+
+ #define MR_thread_engine_base ((MercuryEngine *) \
+ MR_GETSPECIFIC(MR_engine_base_key))
+
+ #if NUM_REAL_REGS > 0
+ #define MR_ENGINE_BASE_REGISTER
+ /*
+ ** MR_engine_base is defined in machdeps/{arch}.h
*/
-extern jmp_buf *MR_engine_jmp_buf;
+ #else
+ #define MR_engine_base MR_thread_engine_base
+ #endif
-extern bool debugflag[];
+ #define MR_ENGINE(x) (((MercuryEngine *)MR_engine_base)->x)
+ #define MR_get_engine() MR_thread_engine_base
+
+ #ifndef CONSERVATIVE_GC
+ #define IF_NOT_CONSERVATIVE_GC(x) x
+ #else
+ #define IF_NOT_CONSERVATIVE_GC(x)
+ #endif
+
+ #define load_engine_regs(eng) do { \
+ IF_NOT_CONSERVATIVE_GC(MR_hp = (eng)->e_hp;) \
+ IF_NOT_CONSERVATIVE_GC(MR_sol_hp = (eng)->e_sol_hp;) \
+ } while (0)
+
+ #define save_engine_regs(eng) do { \
+ IF_NOT_CONSERVATIVE_GC((eng)->e_hp = MR_hp;) \
+ IF_NOT_CONSERVATIVE_GC((eng)->e_sol_hp = MR_sol_hp;) \
+ } while (0)
+
+#else /* !MR_THREAD_SAFE */
+
+ extern MercuryEngine MR_engine_base;
+ #define MR_ENGINE(x) (MR_engine_base.x)
+ #define MR_get_engine() (&MR_engine_base)
+
+ #ifndef CONSERVATIVE_GC
+ #define IF_NOT_CONSERVATIVE_GC(x) x
+ #else
+ #define IF_NOT_CONSERVATIVE_GC(x)
+ #endif
+
+ #define load_engine_regs(eng) do { \
+ IF_NOT_CONSERVATIVE_GC(MR_hp = (eng)->e_hp;) \
+ IF_NOT_CONSERVATIVE_GC(MR_sol_hp = (eng)->e_sol_hp;) \
+ } while (0)
+
+ #define save_engine_regs(eng) do { \
+ IF_NOT_CONSERVATIVE_GC((eng)->e_hp = MR_hp;) \
+ IF_NOT_CONSERVATIVE_GC((eng)->e_sol_hp = MR_sol_hp;) \
+ } while (0)
+
+
+#endif /* !MR_THREAD_SAFE */
+
+
+extern MercuryEngine *create_engine(void);
+extern void destroy_engine(MercuryEngine *engine);
+
+extern void init_engine(MercuryEngine *engine);
+extern void finalize_engine(MercuryEngine *engine);
-extern void init_engine(void);
extern void call_engine(Code *entry_point);
extern void terminate_engine(void);
extern void dump_prev_locations(void);
Index: runtime/mercury_heap.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_heap.h,v
retrieving revision 1.4
diff -u -r1.4 mercury_heap.h
--- mercury_heap.h 1997/12/10 02:07:35 1.4
+++ mercury_heap.h 1998/03/11 04:52:30
@@ -95,33 +95,33 @@
#define tag_incr_hp_atomic(dest, tag, count) \
tag_incr_hp((dest), (tag), (count))
- #define mark_hp(dest) \
- ( \
- (dest) = (Word) MR_hp, \
- (void)0 \
- )
+ #define mark_hp(dest) ((dest) = (Word) MR_hp)
/*
** When restoring hp, we must make sure that we don't truncate the heap
** further than it is safe to. We can only truncate it as far as
- ** min_heap_reclamation_point. See the comments in mercury_context.h next
- ** to the set_min_heap_reclamation_point() macro.
+ ** min_heap_reclamation_point. See the comments in mercury_context.h next to
+ ** the set_min_heap_reclamation_point() macro.
*/
- #define restore_hp(src) \
- ( \
- LVALUE_CAST(Word, MR_hp) = \
- ( (Word) MR_min_hp_rec < (src) \
- ? (src) \
- : (Word) MR_min_hp_rec \
- ), \
- (void)0 \
- )
+ #define restore_hp(src) ( \
+ LVALUE_CAST(Word,MR_hp) = (src), \
+ (void)0 \
+ )
- #define hp_alloc(count) incr_hp(hp, count)
+ /*
+ #define restore_hp(src) ( \
+ LVALUE_CAST(Word,MR_hp) = \
+ ( (Word) MR_min_hp_rec < (src) ? \
+ (src) : (Word) MR_min_hp_rec ), \
+ (void)0 \
+ )
+ */
+
+ #define hp_alloc(count) incr_hp(hp,count)
#define hp_alloc_atomic(count) incr_hp_atomic(count)
-
-#endif /* not CONSERVATIVE_GC */
-
+
+ #endif /* not CONSERVATIVE_GC */
+
#ifdef PROFILE_MEMORY
#define tag_incr_hp_msg(dest, tag, count, proclabel, type) \
( \
Index: runtime/mercury_imp.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_imp.h,v
retrieving revision 1.4
diff -u -r1.4 mercury_imp.h
--- mercury_imp.h 1997/12/05 15:56:38 1.4
+++ mercury_imp.h 1998/03/11 04:52:31
@@ -55,7 +55,9 @@
#include "mercury_label.h"
#include "mercury_wrapper.h"
+#include "mercury_engine.h"
#include "mercury_context.h"
+#include "mercury_thread.h"
#include "mercury_type_info.h"
#ifdef MR_USE_TRAIL
#include "mercury_trail.h"
Index: runtime/mercury_memory.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_memory.c,v
retrieving revision 1.3
diff -u -r1.3 mercury_memory.c
--- mercury_memory.c 1997/11/23 09:31:49 1.3
+++ mercury_memory.c 1998/03/11 04:52:31
@@ -163,23 +163,18 @@
static void setup_signal(void);
-Word fake_reg[MAX_FAKE_REG];
-
Word virtual_reg_map[MAX_REAL_REG] = VIRTUAL_REG_MAP_BODY;
unsigned long num_uses[MAX_RN];
-MemoryZone *zone_table;
-
-MemoryZone *used_memory_zones;
-MemoryZone *free_memory_zones;
+MemoryZone *zone_table=NULL;
-MemoryZone *detstack_zone;
-MemoryZone *nondetstack_zone;
-#ifndef CONSERVATIVE_GC
- MemoryZone *heap_zone;
- MemoryZone *solutions_heap_zone;
+MemoryZone *used_memory_zones=NULL;
+MemoryZone *free_memory_zones=NULL;
+#ifdef MR_THREAD_SAFE
+MercuryLock *free_memory_zones_lock;
#endif
+
#ifndef SPEED
MemoryZone *dumpstack_zone;
int dumpindex;
@@ -202,16 +197,20 @@
#define CACHE_SLICES 8
static size_t *offset_vector;
-static int *offset_counter;
-static SpinLock *offset_lock;
+static int offset_counter;
size_t next_offset(void);
-static void init_memory_arena(void);
-static void init_zones(void);
+static void init_offsets(void);
void
init_memory(void)
{
+ static first_time_only=0;
+
+ if (first_time_only != 0)
+ return;
+ first_time_only = 1;
+
/*
** Convert all the sizes are from kilobytes to bytes and
** make sure they are multiples of the page and cache sizes.
@@ -274,8 +273,12 @@
}
#endif
- init_memory_arena();
- init_zones();
+#ifdef MR_THREAD_SAFE
+ free_memory_zones_lock = make(MercuryLock);
+ pthread_mutex_init(free_memory_zones_lock, MR_MUTEX_ATTR);
+#endif
+
+ init_offsets();
setup_signal();
if (memdebug) debug_memory();
} /* end init_memory() */
@@ -294,11 +297,11 @@
(unsigned long) unit, (unsigned long) unit);
fprintf(stderr, "\n");
- fprintf(stderr, "fake_reg = %p (offset %ld)\n",
- (void *) fake_reg, (long) fake_reg & (unit-1));
+ fprintf(stderr, "MR_fake_reg = %p (offset %ld)\n",
+ (void *) MR_fake_reg, (long) MR_fake_reg & (unit-1));
fprintf(stderr, "\n");
- for (zone = used_memory_zones; zone; zone = zone->next)
+ for (zone = used_memory_zones; zone != NULL ; zone = zone->next)
{
fprintf(stderr, "%-16s#%d-base = %p\n",
zone->name, zone->id, (void *) zone->bottom);
@@ -325,115 +328,25 @@
}
}
-/*
-** init_memory_arena() allocates (if necessary) the top-level memory pool
-** from which all allocations should come. If PARALLEL is defined, then
-** this pool should be shared memory. In the absence of PARALLEL, it
-** doesn't need to do anything, since with CONSERVATIVE_GC, the collector
-** manages the heap, and without GC, we can allocate memory using memalign
-** or malloc.
-*/
-static void
-init_memory_arena()
-{
-#ifdef PARALLEL
- #ifndef CONSERVATIVE_GC
- if (numprocs > 1) {
- fatal_error("shared memory not implemented");
- }
- #else
- if (numprocs > 1) {
- fatal_error("shared memory not implemented with conservative gc");
- }
- #endif
-#endif
-}
-
static void
-init_zones()
+init_offsets()
{
int i;
size_t fake_reg_offset;
- /*
- ** Allocate the MemoryZone table.
- */
- zone_table = allocate_array(MemoryZone, MAX_ZONES);
-
- /*
- ** Initialize the MemoryZone table.
- */
- used_memory_zones = NULL;
- free_memory_zones = zone_table;
- for(i = 0; i < MAX_ZONES; i++) {
- zone_table[i].name = "unused";
- zone_table[i].id = i;
- zone_table[i].bottom = NULL;
- zone_table[i].top = NULL;
- zone_table[i].min = NULL;
-#ifndef SPEED
- zone_table[i].max = NULL;
-#endif
-#ifdef HAVE_MPROTECT
- #ifdef HAVE_SIGINFO
- zone_table[i].redzone = NULL;
- #endif
- zone_table[i].hardmax = NULL;
-#endif
- if (i+1 < MAX_ZONES) {
- zone_table[i].next = &(zone_table[i+1]);
- } else {
- zone_table[i].next = NULL;
- }
- }
-
- offset_counter = allocate_object(int);
- *offset_counter = 0;
+ offset_counter = 0;
offset_vector = allocate_array(size_t, CACHE_SLICES - 1);
- fake_reg_offset = (Unsigned) fake_reg % pcache_size;
+ fake_reg_offset = (Unsigned) MR_fake_reg % pcache_size;
for (i = 0; i < CACHE_SLICES - 1; i++) {
offset_vector[i] =
(fake_reg_offset + pcache_size / CACHE_SLICES)
% pcache_size;
}
-} /* end init_zones() */
-
-
-void
-init_heap(void)
-{
-#ifndef CONSERVATIVE_GC
- heap_zone = create_zone("heap", 1, heap_size, next_offset(),
- heap_zone_size, default_handler);
+} /* end init_offsets() */
- restore_transient_registers();
- MR_hp = heap_zone->min;
- save_transient_registers();
-
- solutions_heap_zone = create_zone("solutions_heap", 1,
- solutions_heap_size, next_offset(),
- solutions_heap_zone_size, default_handler);
- restore_transient_registers();
- MR_sol_hp = solutions_heap_zone->min;
- save_transient_registers();
-
-#endif
-
-#ifndef SPEED
- /*
- ** Create the dumpstack, used for debugging stack traces.
- ** Note that we can just make the dumpstack the same size as
- ** the detstack and we never have to worry about the dumpstack
- ** overflowing.
- */
-
- dumpstack_zone = create_zone("dumpstack", 1, detstack_size,
- next_offset(), detstack_zone_size, default_handler);
-#endif
-} /* end init_heap() */
MemoryZone *
get_zone(void)
@@ -444,14 +357,17 @@
** unlink the first zone on the free-list,
** link it onto the used-list and return it.
*/
- zone = free_memory_zones;
- if (zone == NULL) {
- fatal_error("no more memory zones");
+ MR_LOCK(free_memory_zones_lock, "get_zone");
+ if (free_memory_zones == NULL) {
+ zone = (MemoryZone *) make(MemoryZone);
+ } else {
+ zone = free_memory_zones;
+ free_memory_zones = free_memory_zones->next;
}
- free_memory_zones = free_memory_zones->next;
zone->next = used_memory_zones;
used_memory_zones = zone;
+ MR_UNLOCK(free_memory_zones_lock, "get_zone");
return zone;
}
@@ -465,6 +381,7 @@
** Find the zone on the used list, and unlink it from
** the list, then link it onto the start of the free-list.
*/
+ MR_LOCK(free_memory_zones_lock, "unget_zone");
for(prev = NULL, tmp = used_memory_zones;
tmp && tmp != zone; prev = tmp, tmp = tmp->next)
{
@@ -481,6 +398,7 @@
zone->next = free_memory_zones;
free_memory_zones = zone;
+ MR_UNLOCK(free_memory_zones_lock, "unget_zone");
}
/*
@@ -498,13 +416,9 @@
{
size_t offset;
- get_lock(offset_lock);
+ offset = offset_vector[offset_counter];
- offset = offset_vector[*offset_counter];
-
- *offset_counter = (*offset_counter + 1) % (CACHE_SLICES - 1);
-
- release_lock(offset_lock);
+ offset_counter = (offset_counter + 1) % (CACHE_SLICES - 1);
return offset;
}
@@ -530,11 +444,6 @@
total_size = size + unit;
#endif
-#ifdef PARALLEL
- if (numprocs > 1) {
- fatal_error("shared memory not supported yet");
- }
-#endif
base = memalign(unit, total_size);
if (base == NULL) {
char buf[2560];
@@ -613,6 +522,9 @@
reset_zone(MemoryZone *zone)
{
#if defined(HAVE_MPROTECT) && defined(HAVE_SIGINFO)
+ if (zone->redzone == zone->redzone_base)
+ return;
+
zone->redzone = zone->redzone_base;
if (mprotect((char *)zone->redzone,
@@ -627,6 +539,34 @@
#endif
}
+void destroy_zone(MemoryZone *zone)
+{
+ size_t zone_size;
+
+ /*
+ ** We'd better unprotect the memory, so that if we allocate
+ ** it again later, we don't get into problems...
+ */
+ zone_size = ((char *) zone->top) - ((char *) zone->redzone);
+ if (mprotect((char *)zone->redzone, zone_size,
+ PROT_READ|PROT_WRITE) < 0)
+ {
+ char buf[2560];
+ sprintf(buf, "Mercury runtime: cannot unprotect %s#%d zone",
+ zone->name, zone->id);
+ perror(buf);
+ exit(1);
+ }
+
+ free(zone->bottom);
+
+ /*
+ ** At the moment, we don't release the memory zone structure,
+ ** we just put the zone on the free list.
+ */
+ unget_zone(zone);
+}
+
#define STDERR 2
#ifdef SPEED
@@ -1150,12 +1090,6 @@
{
void *tmp;
- #ifdef PARALLEL
- if (numprocs > 1) {
- fatal_error("shared memory not supported (yet)");
- }
- #endif
-
tmp = GC_MALLOC(numbytes);
if (tmp == NULL) {
@@ -1165,23 +1099,13 @@
return tmp;
}
-#elif defined(PARALLEL)
-
- #error "shared memory not implemented"
-
-#else /* not CONSERVATIVE_GC && not PARALLEL */
+#else /* not CONSERVATIVE_GC */
void *
allocate_bytes(size_t numbytes)
{
void *tmp;
- #ifdef PARALLEL
- if (numprocs > 1) {
- fatal_error("shared memory not supported (yet)");
- }
- #endif
-
tmp = malloc(numbytes);
if (tmp == NULL) {
@@ -1197,19 +1121,9 @@
deallocate_memory(void *ptr)
{
#ifdef CONSERVATIVE_GC
- #ifdef PARALLEL
- if (numprocs > 1) {
- fatal_error("shared memory not supported");
- }
- #endif
GC_FREE(ptr);
#else
- #ifdef PARALLEL
- if (numprocs > 1) {
- fatal_error("shared memory not supported");
- }
- #endif
free(ptr);
#endif
}
Index: runtime/mercury_memory.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_memory.h,v
retrieving revision 1.2
diff -u -r1.2 mercury_memory.h
--- mercury_memory.h 1997/11/23 07:21:28 1.2
+++ mercury_memory.h 1998/03/11 04:52:31
@@ -40,9 +40,6 @@
#define MAX_FAKE_REG (NUM_SPECIAL_REG + MAX_VIRTUAL_REG)
/* mr0 .. mr36, mr(37) ... mr(1028) */
-/* reserve MAX_FAKE_REG virtual regs, numbered from 0 to MAX_FAKE_REG-1 */
-extern Word fake_reg[MAX_FAKE_REG];
-
/* used to lookup the fake_reg for a given real reg */
extern Word virtual_reg_map[MAX_REAL_REG];
@@ -126,18 +123,6 @@
/* A linked list of all the used zones */
extern MemoryZone *used_memory_zones;
-extern MemoryZone *detstack_zone;
-extern MemoryZone *nondetstack_zone;
-#ifndef CONSERVATIVE_GC
-extern MemoryZone *heap_zone;
-extern MemoryZone *solutions_heap_zone;
-#endif
-
-#ifndef SPEED
-extern MemoryZone *dumpstack_zone;
-extern int dumpindex;
-#endif
-
/*
** create_zone(Name, Id, Size, Offset, RedZoneSize, FaultHandler)
** allocates a new memory zone with name Name, and number Id, size
@@ -155,6 +140,12 @@
MemoryZone *create_zone(const char *name, int id,
size_t size, size_t offset, size_t redsize,
ZoneHandler *handler);
+
+/*
+** destroy_zone(Zone) destroys a memory zone.
+*/
+
+void destroy_zone(MemoryZone *zone);
/*
** construct_zone(Name, Id, Base, Size, Offset, RedZoneSize, FaultHandler)
Index: runtime/mercury_misc.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_misc.c,v
retrieving revision 1.3
diff -u -r1.3 mercury_misc.c
--- mercury_misc.c 1998/01/23 15:26:33 1.3
+++ mercury_misc.c 1998/03/18 23:48:42
@@ -488,6 +488,13 @@
return p;
}
+void
+MR_copy_structure(char *dest, const char *src, size_t nbytes)
+{
+ while (nbytes-- > 0)
+ *dest++ = *src++;
+}
+
/*
** Note that hash_string is actually defined as a macro in mercury_imp.h,
** if we're using GNU C. We define it here whether or not we're using
@@ -502,3 +509,4 @@
{
HASH_STRING_FUNC_BODY
}
+
Index: runtime/mercury_misc.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_misc.h,v
retrieving revision 1.3
diff -u -r1.3 mercury_misc.h
--- mercury_misc.h 1998/01/23 15:26:35 1.3
+++ mercury_misc.h 1998/03/18 23:45:05
@@ -4,7 +4,12 @@
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/
-/* mercury_misc.h - debugging messages, fatal_error(), and checked_malloc() */
+/*
+** mercury_misc.h - debugging messages,
+** fatal_error(),
+** checked_malloc(),
+** MR_copy_structure
+*/
#ifndef MERCURY_MISC_H
#define MERCURY_MISC_H
@@ -68,5 +73,7 @@
*/
#include <stddef.h> /* for size_t */
void *checked_malloc(size_t n);
+
+void MR_copy_structure(char *dest, const char *src, size_t nbytes);
#endif /* not MERCURY_MISC_H */
Index: runtime/mercury_regorder.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_regorder.h,v
retrieving revision 1.2
diff -u -r1.2 mercury_regorder.h
--- mercury_regorder.h 1997/11/23 07:21:32 1.2
+++ mercury_regorder.h 1998/03/11 04:52:31
@@ -22,6 +22,99 @@
#ifndef MERCURY_REGORDER_H
#define MERCURY_REGORDER_H
+#if defined(MR_THREAD_SAFE) && NUM_REAL_REGS > 0
+
+#define r1 count_usage(R_RN(1), mr3)
+#define r2 count_usage(R_RN(2), mr4)
+#define r3 count_usage(R_RN(3), mr5)
+#define r4 count_usage(R_RN(4), mr7)
+#define r5 count_usage(R_RN(5), mr8)
+#define r6 count_usage(R_RN(6), mr11)
+#define r7 count_usage(R_RN(7), mr12)
+#define r8 count_usage(R_RN(8), mr13)
+#define r9 count_usage(R_RN(9), mr14)
+#define r10 count_usage(R_RN(10), mr15)
+#define r11 count_usage(R_RN(11), mr16)
+#define r12 count_usage(R_RN(12), mr17)
+#define r13 count_usage(R_RN(13), mr19)
+#define r14 count_usage(R_RN(14), mr19)
+#define r15 count_usage(R_RN(15), mr20)
+#define r16 count_usage(R_RN(16), mr21)
+#define r17 count_usage(R_RN(17), mr22)
+#define r18 count_usage(R_RN(18), mr23)
+#define r19 count_usage(R_RN(19), mr24)
+#define r20 count_usage(R_RN(20), mr25)
+#define r21 count_usage(R_RN(21), mr26)
+#define r22 count_usage(R_RN(22), mr27)
+#define r23 count_usage(R_RN(23), mr28)
+#define r24 count_usage(R_RN(24), mr29)
+#define r25 count_usage(R_RN(25), mr30)
+#define r26 count_usage(R_RN(26), mr31)
+#define r27 count_usage(R_RN(27), mr32)
+#define r28 count_usage(R_RN(28), mr33)
+#define r29 count_usage(R_RN(29), mr34)
+#define r30 count_usage(R_RN(30), mr35)
+#define r31 count_usage(R_RN(31), mr36)
+#define r32 count_usage(R_RN(32), mr37)
+
+#define MR_engine_base LVALUE_CAST(Word *, count_usage(MR_SP_RN, mr0))
+
+#define MR_succip LVALUE_CAST(Code *, count_usage(MR_SI_RN, mr2))
+#define succip MR_succip
+#define MR_hp LVALUE_CAST(Word *, count_usage(MR_HP_RN, mr6))
+#define hp MR_hp
+#define MR_sp LVALUE_CAST(Word *, count_usage(MR_SP_RN, mr1))
+#define sp MR_sp
+#define MR_curfr LVALUE_CAST(Word *, count_usage(MR_CF_RN, mr9))
+#define curfr MR_curfr
+#define MR_maxfr LVALUE_CAST(Word *, count_usage(MR_MF_RN, mr10))
+#define maxfr MR_maxfr
+#define MR_sol_hp LVALUE_CAST(Word *, count_usage(MR_SOL_HP_RN, mr(38)))
+#define MR_min_hp_rec LVALUE_CAST(Word *, count_usage(MR_MIN_HP_REC, mr(39)))
+#define MR_min_sol_hp_rec LVALUE_CAST(Word *, \
+ count_usage(MR_MIN_HP_REC, mr40))
+
+#define MR_trail_ptr count_usage(MR_TRAIL_PTR_RN, MR_trail_ptr_var)
+#define MR_ticket_counter \
+ count_usage(MR_TICKET_COUNTER_RN, MR_ticket_counter_var)
+
+#define VIRTUAL_REG_MAP_BODY { \
+ 3, \
+ 4, \
+ 5, \
+ 7, \
+ 8, \
+ 11, \
+ 12, \
+ 13, \
+ 14, \
+ 15, \
+ 16, \
+ 17, \
+ 18, \
+ 19, \
+ 20, \
+ 21, \
+ 22, \
+ 23, \
+ 24, \
+ 25, \
+ 26, \
+ 27, \
+ 28, \
+ 29, \
+ 30, \
+ 31, \
+ 32, \
+ 33, \
+ 34, \
+ 35, \
+ 36, \
+ 37, \
+}
+
+#else /* !MR_THREAD_SAFE or NUM_REAL_REGS == 0 */
+
#define r1 count_usage(R_RN(1), mr2)
#define r2 count_usage(R_RN(2), mr3)
#define r3 count_usage(R_RN(3), mr4)
@@ -108,5 +201,7 @@
35, \
36, \
}
+
+#endif
#endif /* not MERCURY_REGORDER_H */
Index: runtime/mercury_regs.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_regs.h,v
retrieving revision 1.5
diff -u -r1.5 mercury_regs.h
--- mercury_regs.h 1998/02/04 03:55:27 1.5
+++ mercury_regs.h 1998/03/11 04:52:31
@@ -28,6 +28,7 @@
#define LVALUE_COND(expr, x, y) (*((expr)?&(x):&(y)))
#endif
+#define MR_fake_reg (MR_ENGINE(fake_reg))
/*
** The registers of the Mercury virtual machine are built up using
** three levels of abstraction.
@@ -83,7 +84,7 @@
#define mr(n) LVALUE_SEQ(MR_assert((n) >= MAX_REAL_REG + NUM_SPECIAL_REG && \
(n) < MAX_FAKE_REG),\
- fake_reg[n])
+ MR_fake_reg[n])
#ifdef MEASURE_REGISTER_USAGE
#define count_usage(num,reg) LVALUE_SEQ(num_uses[num]++, reg)
@@ -99,17 +100,28 @@
/*
** the save_registers() macro copies the physical machine registers
-** to their corresponding slots in the fake_reg array
+** to their corresponding slots in the MR_fake_reg array
*/
-#define save_registers() save_regs_to_mem(fake_reg)
+#define save_registers() save_regs_to_mem(MR_fake_reg)
/*
** the restore_registers() macro sets the physical machine registers
** to the values in their corresponding slots in the fake_reg array
+** If we're using a register for the engine base, then we'd better
+** restore that from the thread specific data area, since the fake_reg
+** array is accessed via that register.
*/
-#define restore_registers() restore_regs_from_mem(fake_reg)
+#if defined(MR_THREAD_SAFE) && NUM_REAL_REGS > 0
+#define restore_registers() do { \
+ MR_engine_base = MR_thread_engine_base; \
+ MR_fake_reg[0] = (Word) MR_engine_base; \
+ restore_regs_from_mem(MR_fake_reg); \
+ } while (0)
+#else
+#define restore_registers() restore_regs_from_mem(MR_fake_reg)
+#endif
/*
** the save_transient_registers() and restore_transient_registers()
@@ -119,15 +131,24 @@
** by sliding register windows on SPARCs).
*/
-#define save_transient_registers() save_transient_regs_to_mem(fake_reg)
-#define restore_transient_registers() restore_transient_regs_from_mem(fake_reg)
+#define save_transient_registers() save_transient_regs_to_mem(MR_fake_reg)
+#if defined(MR_THREAD_SAFE) && NUM_REAL_REGS > 0
+#define restore_transient_registers() do { \
+ MR_engine_base = MR_thread_engine_base; \
+ MR_fake_reg[0] = (Word) MR_engine_base; \
+ restore_transient_regs_from_mem(MR_fake_reg); \
+ } while (0)
+#else
+#define restore_transient_registers() \
+ restore_transient_regs_from_mem(MR_fake_reg)
+#endif
/* virtual_reg(n) accesses the underlying fake_reg for register n */
#define virtual_reg(n) \
LVALUE_COND((n) > MAX_REAL_REG, \
r(n), \
- fake_reg[virtual_reg_map[(n) - 1]])
+ MR_fake_reg[virtual_reg_map[(n) - 1]])
/* saved_reg(save_area, n) is like virtual_reg, except in that */
/* it accesses the given save area instead of the machine regs and fake_reg */
Index: runtime/mercury_trace.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_trace.c,v
retrieving revision 1.7
diff -u -r1.7 mercury_trace.c
--- mercury_trace.c 1998/02/04 03:55:31 1.7
+++ mercury_trace.c 1998/03/11 04:52:32
@@ -351,7 +351,7 @@
save_regs_to_mem(MR_saved_regs);
for (i = NUM_REAL_REGS; i < MAX_FAKE_REG; i++)
- MR_saved_regs[i] = fake_reg[i];
+ MR_saved_regs[i] = MR_ENGINE(fake_reg)[i];
for (i = 0; i < var_count; i++) {
if (vars->MR_slvs_names != NULL &&
@@ -365,7 +365,7 @@
restore_regs_from_mem(MR_saved_regs);
for (i = NUM_REAL_REGS; i < MAX_FAKE_REG; i++)
- fake_reg[i] = MR_saved_regs[i];
+ MR_ENGINE(fake_reg)[i] = MR_saved_regs[i];
}
/* if you want to debug this code, you may want to set this var to 1 */
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.6
diff -u -r1.6 mercury_wrapper.c
--- mercury_wrapper.c 1998/02/03 08:17:31 1.6
+++ mercury_wrapper.c 1998/03/11 04:52:33
@@ -74,6 +74,8 @@
static bool use_own_timer = FALSE;
static int repeats = 1;
+unsigned MR_num_threads = 1;
+
/* timing */
int time_at_last_stat;
int time_at_start;
@@ -196,7 +198,7 @@
/* double-check that the garbage collector knows about
global variables in shared libraries */
- GC_is_visible(fake_reg);
+ GC_is_visible(&MR_runqueue);
/* The following code is necessary to tell the conservative */
/* garbage collector that we are using tagged pointers */
@@ -222,7 +224,18 @@
(*address_of_mercury_init_io)();
/* start up the Mercury engine */
- init_engine();
+#ifndef MR_THREAD_SAFE
+ init_thread((void *) 1);
+#else
+ {
+ int i;
+ init_thread_stuff();
+ init_thread((void *)1);
+ MR_exit_now = FALSE;
+ for (i = 1 ; i < MR_num_threads ; i++)
+ create_thread(0);
+ }
+#endif
/* initialize profiling */
if (MR_profiling) MR_prof_init();
@@ -240,6 +253,8 @@
/* initialize the Mercury library */
(*MR_library_initializer)();
+ save_context(&(MR_ENGINE(context)));
+
/*
** Restore the callee-save registers before returning,
** since they may be used by the C code that called us.
@@ -531,12 +546,12 @@
MR_profiling = FALSE;
break;
-#ifdef PARALLEL
+#ifdef MR_THREAD_SAFE
case 'P':
- if (sscanf(optarg, "%u", &numprocs) != 1)
+ if (sscanf(optarg, "%u", &MR_num_threads) != 1)
usage();
- if (numprocs < 1)
+ if (MR_num_threads < 1)
usage();
break;
@@ -963,6 +978,11 @@
(*MR_library_finalizer)();
if (MR_profiling) MR_prof_finish();
+
+#ifdef MR_THREAD_SAFE
+ MR_exit_now = TRUE;
+ pthread_cond_broadcast(MR_runqueue_cond);
+#endif
terminate_engine();
cvs diff: Diffing runtime/machdeps
Index: runtime/machdeps/alpha_regs.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/machdeps/alpha_regs.h,v
retrieving revision 1.8
diff -u -r1.8 alpha_regs.h
--- alpha_regs.h 1997/07/27 15:09:06 1.8
+++ alpha_regs.h 1998/03/11 04:52:33
@@ -57,35 +57,36 @@
#define save_transient_regs_to_mem(save_area) ((void)0)
#define restore_transient_regs_from_mem(save_area) ((void)0)
-#define mr7 fake_reg[7]
-#define mr8 fake_reg[8]
-#define mr9 fake_reg[9]
-#define mr10 fake_reg[10]
-#define mr11 fake_reg[11]
-#define mr12 fake_reg[12]
-#define mr13 fake_reg[13]
-#define mr14 fake_reg[14]
-#define mr15 fake_reg[15]
-#define mr16 fake_reg[16]
-#define mr17 fake_reg[17]
-#define mr18 fake_reg[18]
-#define mr19 fake_reg[19]
-#define mr20 fake_reg[20]
-#define mr21 fake_reg[21]
-#define mr22 fake_reg[22]
-#define mr23 fake_reg[23]
-#define mr24 fake_reg[24]
-#define mr25 fake_reg[25]
-#define mr26 fake_reg[26]
-#define mr27 fake_reg[27]
-#define mr28 fake_reg[28]
-#define mr29 fake_reg[29]
-#define mr30 fake_reg[30]
-#define mr31 fake_reg[31]
-#define mr32 fake_reg[32]
-#define mr33 fake_reg[33]
-#define mr34 fake_reg[34]
-#define mr35 fake_reg[35]
-#define mr36 fake_reg[36]
+#define mr7 MR_fake_reg[7]
+#define mr8 MR_fake_reg[8]
+#define mr9 MR_fake_reg[9]
+#define mr10 MR_fake_reg[10]
+#define mr11 MR_fake_reg[11]
+#define mr12 MR_fake_reg[12]
+#define mr13 MR_fake_reg[13]
+#define mr14 MR_fake_reg[14]
+#define mr15 MR_fake_reg[15]
+#define mr16 MR_fake_reg[16]
+#define mr17 MR_fake_reg[17]
+#define mr18 MR_fake_reg[18]
+#define mr19 MR_fake_reg[19]
+#define mr20 MR_fake_reg[20]
+#define mr21 MR_fake_reg[21]
+#define mr22 MR_fake_reg[22]
+#define mr23 MR_fake_reg[23]
+#define mr24 MR_fake_reg[24]
+#define mr25 MR_fake_reg[25]
+#define mr26 MR_fake_reg[26]
+#define mr27 MR_fake_reg[27]
+#define mr28 MR_fake_reg[28]
+#define mr29 MR_fake_reg[29]
+#define mr30 MR_fake_reg[30]
+#define mr31 MR_fake_reg[31]
+#define mr32 MR_fake_reg[32]
+#define mr33 MR_fake_reg[33]
+#define mr34 MR_fake_reg[34]
+#define mr35 MR_fake_reg[35]
+#define mr36 MR_fake_reg[36]
+#define mr37 MR_fake_reg[37]
#endif /* not ALPHA_REGS_H */
Index: runtime/machdeps/i386_regs.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/machdeps/i386_regs.h,v
retrieving revision 1.13
diff -u -r1.13 i386_regs.h
--- i386_regs.h 1997/07/27 15:09:07 1.13
+++ i386_regs.h 1998/03/18 03:48:41
@@ -62,7 +62,7 @@
register Word mr1 __asm__("edi"); /* succip */
#if PIC_REG
- #define mr2 fake_reg[2]
+ #define mr2 MR_fake_reg[2]
#else
register Word mr2 __asm__("ebx"); /* r1 */
#endif
@@ -102,39 +102,40 @@
#define save_transient_regs_to_mem(save_area) ((void)0)
#define restore_transient_regs_from_mem(save_area) ((void)0)
-#define mr3 fake_reg[3]
-#define mr4 fake_reg[4]
-#define mr5 fake_reg[5]
-#define mr6 fake_reg[6]
-#define mr7 fake_reg[7]
-#define mr8 fake_reg[8]
-#define mr9 fake_reg[9]
-#define mr10 fake_reg[10]
-#define mr11 fake_reg[11]
-#define mr12 fake_reg[12]
-#define mr13 fake_reg[13]
-#define mr14 fake_reg[14]
-#define mr15 fake_reg[15]
-#define mr16 fake_reg[16]
-#define mr17 fake_reg[17]
-#define mr18 fake_reg[18]
-#define mr19 fake_reg[19]
-#define mr20 fake_reg[20]
-#define mr21 fake_reg[21]
-#define mr22 fake_reg[22]
-#define mr23 fake_reg[23]
-#define mr24 fake_reg[24]
-#define mr25 fake_reg[25]
-#define mr26 fake_reg[26]
-#define mr27 fake_reg[27]
-#define mr28 fake_reg[28]
-#define mr29 fake_reg[29]
-#define mr30 fake_reg[30]
-#define mr31 fake_reg[31]
-#define mr32 fake_reg[32]
-#define mr33 fake_reg[33]
-#define mr34 fake_reg[34]
-#define mr35 fake_reg[35]
-#define mr36 fake_reg[36]
+#define mr3 MR_fake_reg[3]
+#define mr4 MR_fake_reg[4]
+#define mr5 MR_fake_reg[5]
+#define mr6 MR_fake_reg[6]
+#define mr7 MR_fake_reg[7]
+#define mr8 MR_fake_reg[8]
+#define mr9 MR_fake_reg[9]
+#define mr10 MR_fake_reg[10]
+#define mr11 MR_fake_reg[11]
+#define mr12 MR_fake_reg[12]
+#define mr13 MR_fake_reg[13]
+#define mr14 MR_fake_reg[14]
+#define mr15 MR_fake_reg[15]
+#define mr16 MR_fake_reg[16]
+#define mr17 MR_fake_reg[17]
+#define mr18 MR_fake_reg[18]
+#define mr19 MR_fake_reg[19]
+#define mr20 MR_fake_reg[20]
+#define mr21 MR_fake_reg[21]
+#define mr22 MR_fake_reg[22]
+#define mr23 MR_fake_reg[23]
+#define mr24 MR_fake_reg[24]
+#define mr25 MR_fake_reg[25]
+#define mr26 MR_fake_reg[26]
+#define mr27 MR_fake_reg[27]
+#define mr28 MR_fake_reg[28]
+#define mr29 MR_fake_reg[29]
+#define mr30 MR_fake_reg[30]
+#define mr31 MR_fake_reg[31]
+#define mr32 MR_fake_reg[32]
+#define mr33 MR_fake_reg[33]
+#define mr34 MR_fake_reg[34]
+#define mr35 MR_fake_reg[35]
+#define mr36 MR_fake_reg[36]
+#define mr37 MR_fake_reg[37]
#endif /* not I386_REGS_H */
Index: runtime/machdeps/m68k.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/machdeps/m68k.h,v
retrieving revision 1.1
diff -u -r1.1 m68k.h
--- m68k.h 1997/08/15 15:32:08 1.1
+++ m68k.h 1998/03/11 04:52:33
@@ -62,37 +62,38 @@
#define save_transient_regs_to_mem(save_area) ((void)0)
#define restore_transient_regs_from_mem(save_area) ((void)0)
-#define mr5 fake_reg[5]
-#define mr6 fake_reg[6]
-#define mr7 fake_reg[7]
-#define mr8 fake_reg[8]
-#define mr9 fake_reg[9]
-#define mr10 fake_reg[10]
-#define mr11 fake_reg[11]
-#define mr12 fake_reg[12]
-#define mr13 fake_reg[13]
-#define mr14 fake_reg[14]
-#define mr15 fake_reg[15]
-#define mr16 fake_reg[16]
-#define mr17 fake_reg[17]
-#define mr18 fake_reg[18]
-#define mr19 fake_reg[19]
-#define mr20 fake_reg[20]
-#define mr21 fake_reg[21]
-#define mr22 fake_reg[22]
-#define mr23 fake_reg[23]
-#define mr24 fake_reg[24]
-#define mr25 fake_reg[25]
-#define mr26 fake_reg[26]
-#define mr27 fake_reg[27]
-#define mr28 fake_reg[28]
-#define mr29 fake_reg[29]
-#define mr30 fake_reg[30]
-#define mr31 fake_reg[31]
-#define mr32 fake_reg[32]
-#define mr33 fake_reg[33]
-#define mr34 fake_reg[34]
-#define mr35 fake_reg[35]
-#define mr36 fake_reg[36]
+#define mr5 MR_fake_reg[5]
+#define mr6 MR_fake_reg[6]
+#define mr7 MR_fake_reg[7]
+#define mr8 MR_fake_reg[8]
+#define mr9 MR_fake_reg[9]
+#define mr10 MR_fake_reg[10]
+#define mr11 MR_fake_reg[11]
+#define mr12 MR_fake_reg[12]
+#define mr13 MR_fake_reg[13]
+#define mr14 MR_fake_reg[14]
+#define mr15 MR_fake_reg[15]
+#define mr16 MR_fake_reg[16]
+#define mr17 MR_fake_reg[17]
+#define mr18 MR_fake_reg[18]
+#define mr19 MR_fake_reg[19]
+#define mr20 MR_fake_reg[20]
+#define mr21 MR_fake_reg[21]
+#define mr22 MR_fake_reg[22]
+#define mr23 MR_fake_reg[23]
+#define mr24 MR_fake_reg[24]
+#define mr25 MR_fake_reg[25]
+#define mr26 MR_fake_reg[26]
+#define mr27 MR_fake_reg[27]
+#define mr28 MR_fake_reg[28]
+#define mr29 MR_fake_reg[29]
+#define mr30 MR_fake_reg[30]
+#define mr31 MR_fake_reg[31]
+#define mr32 MR_fake_reg[32]
+#define mr33 MR_fake_reg[33]
+#define mr34 MR_fake_reg[34]
+#define mr35 MR_fake_reg[35]
+#define mr36 MR_fake_reg[36]
+#define mr37 MR_fake_reg[37]
#endif /* not M68K_REGS_H */
Index: runtime/machdeps/mips_regs.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/machdeps/mips_regs.h,v
retrieving revision 1.11
diff -u -r1.11 mips_regs.h
--- mips_regs.h 1997/07/27 15:09:08 1.11
+++ mips_regs.h 1998/03/11 04:52:33
@@ -54,34 +54,35 @@
#define save_transient_regs_to_mem(save_area) ((void)0)
#define restore_transient_regs_from_mem(save_area) ((void)0)
-#define mr8 fake_reg[8]
-#define mr9 fake_reg[9]
-#define mr10 fake_reg[10]
-#define mr11 fake_reg[11]
-#define mr12 fake_reg[12]
-#define mr13 fake_reg[13]
-#define mr14 fake_reg[14]
-#define mr15 fake_reg[15]
-#define mr16 fake_reg[16]
-#define mr17 fake_reg[17]
-#define mr18 fake_reg[18]
-#define mr19 fake_reg[19]
-#define mr20 fake_reg[20]
-#define mr21 fake_reg[21]
-#define mr22 fake_reg[22]
-#define mr23 fake_reg[23]
-#define mr24 fake_reg[24]
-#define mr25 fake_reg[25]
-#define mr26 fake_reg[26]
-#define mr27 fake_reg[27]
-#define mr28 fake_reg[28]
-#define mr29 fake_reg[29]
-#define mr30 fake_reg[30]
-#define mr31 fake_reg[31]
-#define mr32 fake_reg[32]
-#define mr33 fake_reg[33]
-#define mr34 fake_reg[34]
-#define mr35 fake_reg[35]
-#define mr36 fake_reg[36]
+#define mr8 MR_fake_reg[8]
+#define mr9 MR_fake_reg[9]
+#define mr10 MR_fake_reg[10]
+#define mr11 MR_fake_reg[11]
+#define mr12 MR_fake_reg[12]
+#define mr13 MR_fake_reg[13]
+#define mr14 MR_fake_reg[14]
+#define mr15 MR_fake_reg[15]
+#define mr16 MR_fake_reg[16]
+#define mr17 MR_fake_reg[17]
+#define mr18 MR_fake_reg[18]
+#define mr19 MR_fake_reg[19]
+#define mr20 MR_fake_reg[20]
+#define mr21 MR_fake_reg[21]
+#define mr22 MR_fake_reg[22]
+#define mr23 MR_fake_reg[23]
+#define mr24 MR_fake_reg[24]
+#define mr25 MR_fake_reg[25]
+#define mr26 MR_fake_reg[26]
+#define mr27 MR_fake_reg[27]
+#define mr28 MR_fake_reg[28]
+#define mr29 MR_fake_reg[29]
+#define mr30 MR_fake_reg[30]
+#define mr31 MR_fake_reg[31]
+#define mr32 MR_fake_reg[32]
+#define mr33 MR_fake_reg[33]
+#define mr34 MR_fake_reg[34]
+#define mr35 MR_fake_reg[35]
+#define mr36 MR_fake_reg[36]
+#define mr37 MR_fake_reg[37]
#endif /* not MIPS_REGS_H */
Index: runtime/machdeps/no_regs.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/machdeps/no_regs.h,v
retrieving revision 1.10
diff -u -r1.10 no_regs.h
--- no_regs.h 1997/07/27 15:09:09 1.10
+++ no_regs.h 1998/03/11 04:52:34
@@ -38,46 +38,47 @@
#define restore_transient_regs_from_mem(save_area) ((void)0)
/* mr0, ..., mr36 are macros that map to either the underlying physical
- machine register, if there is one, or otherwise to fake_reg[n].
+ machine register, if there is one, or otherwise to MR_fake_reg[n].
For register numbers greater than 36, use mr(n).
*/
-#define mr0 fake_reg[0]
-#define mr1 fake_reg[1]
-#define mr2 fake_reg[2]
-#define mr3 fake_reg[3]
-#define mr4 fake_reg[4]
-#define mr5 fake_reg[5]
-#define mr6 fake_reg[6]
-#define mr7 fake_reg[7]
-#define mr8 fake_reg[8]
-#define mr9 fake_reg[9]
-#define mr10 fake_reg[10]
-#define mr11 fake_reg[11]
-#define mr12 fake_reg[12]
-#define mr13 fake_reg[13]
-#define mr14 fake_reg[14]
-#define mr15 fake_reg[15]
-#define mr16 fake_reg[16]
-#define mr17 fake_reg[17]
-#define mr18 fake_reg[18]
-#define mr19 fake_reg[19]
-#define mr20 fake_reg[20]
-#define mr21 fake_reg[21]
-#define mr22 fake_reg[22]
-#define mr23 fake_reg[23]
-#define mr24 fake_reg[24]
-#define mr25 fake_reg[25]
-#define mr26 fake_reg[26]
-#define mr27 fake_reg[27]
-#define mr28 fake_reg[28]
-#define mr29 fake_reg[29]
-#define mr30 fake_reg[30]
-#define mr31 fake_reg[31]
-#define mr32 fake_reg[32]
-#define mr33 fake_reg[33]
-#define mr34 fake_reg[34]
-#define mr35 fake_reg[35]
-#define mr36 fake_reg[36]
+#define mr0 MR_fake_reg[0]
+#define mr1 MR_fake_reg[1]
+#define mr2 MR_fake_reg[2]
+#define mr3 MR_fake_reg[3]
+#define mr4 MR_fake_reg[4]
+#define mr5 MR_fake_reg[5]
+#define mr6 MR_fake_reg[6]
+#define mr7 MR_fake_reg[7]
+#define mr8 MR_fake_reg[8]
+#define mr9 MR_fake_reg[9]
+#define mr10 MR_fake_reg[10]
+#define mr11 MR_fake_reg[11]
+#define mr12 MR_fake_reg[12]
+#define mr13 MR_fake_reg[13]
+#define mr14 MR_fake_reg[14]
+#define mr15 MR_fake_reg[15]
+#define mr16 MR_fake_reg[16]
+#define mr17 MR_fake_reg[17]
+#define mr18 MR_fake_reg[18]
+#define mr19 MR_fake_reg[19]
+#define mr20 MR_fake_reg[20]
+#define mr21 MR_fake_reg[21]
+#define mr22 MR_fake_reg[22]
+#define mr23 MR_fake_reg[23]
+#define mr24 MR_fake_reg[24]
+#define mr25 MR_fake_reg[25]
+#define mr26 MR_fake_reg[26]
+#define mr27 MR_fake_reg[27]
+#define mr28 MR_fake_reg[28]
+#define mr29 MR_fake_reg[29]
+#define mr30 MR_fake_reg[30]
+#define mr31 MR_fake_reg[31]
+#define mr32 MR_fake_reg[32]
+#define mr33 MR_fake_reg[33]
+#define mr34 MR_fake_reg[34]
+#define mr35 MR_fake_reg[35]
+#define mr36 MR_fake_reg[36]
+#define mr37 MR_fake_reg[37]
#endif /* not NO_REGS_H */
Index: runtime/machdeps/pa_regs.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/machdeps/pa_regs.h,v
retrieving revision 1.4
diff -u -r1.4 pa_regs.h
--- pa_regs.h 1997/07/27 15:09:10 1.4
+++ pa_regs.h 1998/03/11 04:52:34
@@ -54,34 +54,35 @@
#define save_transient_regs_to_mem(save_area) ((void)0)
#define restore_transient_regs_from_mem(save_area) ((void)0)
-#define mr8 fake_reg[8]
-#define mr9 fake_reg[9]
-#define mr10 fake_reg[10]
-#define mr11 fake_reg[11]
-#define mr12 fake_reg[12]
-#define mr13 fake_reg[13]
-#define mr14 fake_reg[14]
-#define mr15 fake_reg[15]
-#define mr16 fake_reg[16]
-#define mr17 fake_reg[17]
-#define mr18 fake_reg[18]
-#define mr19 fake_reg[19]
-#define mr20 fake_reg[20]
-#define mr21 fake_reg[21]
-#define mr22 fake_reg[22]
-#define mr23 fake_reg[23]
-#define mr24 fake_reg[24]
-#define mr25 fake_reg[25]
-#define mr26 fake_reg[26]
-#define mr27 fake_reg[27]
-#define mr28 fake_reg[28]
-#define mr29 fake_reg[29]
-#define mr30 fake_reg[30]
-#define mr31 fake_reg[31]
-#define mr32 fake_reg[32]
-#define mr33 fake_reg[33]
-#define mr34 fake_reg[34]
-#define mr35 fake_reg[35]
-#define mr36 fake_reg[36]
+#define mr8 MR_fake_reg[8]
+#define mr9 MR_fake_reg[9]
+#define mr10 MR_fake_reg[10]
+#define mr11 MR_fake_reg[11]
+#define mr12 MR_fake_reg[12]
+#define mr13 MR_fake_reg[13]
+#define mr14 MR_fake_reg[14]
+#define mr15 MR_fake_reg[15]
+#define mr16 MR_fake_reg[16]
+#define mr17 MR_fake_reg[17]
+#define mr18 MR_fake_reg[18]
+#define mr19 MR_fake_reg[19]
+#define mr20 MR_fake_reg[20]
+#define mr21 MR_fake_reg[21]
+#define mr22 MR_fake_reg[22]
+#define mr23 MR_fake_reg[23]
+#define mr24 MR_fake_reg[24]
+#define mr25 MR_fake_reg[25]
+#define mr26 MR_fake_reg[26]
+#define mr27 MR_fake_reg[27]
+#define mr28 MR_fake_reg[28]
+#define mr29 MR_fake_reg[29]
+#define mr30 MR_fake_reg[30]
+#define mr31 MR_fake_reg[31]
+#define mr32 MR_fake_reg[32]
+#define mr33 MR_fake_reg[33]
+#define mr34 MR_fake_reg[34]
+#define mr35 MR_fake_reg[35]
+#define mr36 MR_fake_reg[36]
+#define mr37 MR_fake_reg[37]
#endif /* not PA_REGS_H */
Index: runtime/machdeps/rs6000_regs.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/machdeps/rs6000_regs.h,v
retrieving revision 1.7
diff -u -r1.7 rs6000_regs.h
--- rs6000_regs.h 1997/12/18 03:15:50 1.7
+++ rs6000_regs.h 1998/03/11 04:52:34
@@ -61,32 +61,33 @@
#define save_transient_regs_to_mem(save_area) ((void)0)
#define restore_transient_regs_from_mem(save_area) ((void)0)
-#define mr10 fake_reg[10]
-#define mr11 fake_reg[11]
-#define mr12 fake_reg[12]
-#define mr13 fake_reg[13]
-#define mr14 fake_reg[14]
-#define mr15 fake_reg[15]
-#define mr16 fake_reg[16]
-#define mr17 fake_reg[17]
-#define mr18 fake_reg[18]
-#define mr19 fake_reg[19]
-#define mr20 fake_reg[20]
-#define mr21 fake_reg[21]
-#define mr22 fake_reg[22]
-#define mr23 fake_reg[23]
-#define mr24 fake_reg[24]
-#define mr25 fake_reg[25]
-#define mr26 fake_reg[26]
-#define mr27 fake_reg[27]
-#define mr28 fake_reg[28]
-#define mr29 fake_reg[29]
-#define mr30 fake_reg[30]
-#define mr31 fake_reg[31]
-#define mr32 fake_reg[32]
-#define mr33 fake_reg[33]
-#define mr34 fake_reg[34]
-#define mr35 fake_reg[35]
-#define mr36 fake_reg[36]
+#define mr10 MR_fake_reg[10]
+#define mr11 MR_fake_reg[11]
+#define mr12 MR_fake_reg[12]
+#define mr13 MR_fake_reg[13]
+#define mr14 MR_fake_reg[14]
+#define mr15 MR_fake_reg[15]
+#define mr16 MR_fake_reg[16]
+#define mr17 MR_fake_reg[17]
+#define mr18 MR_fake_reg[18]
+#define mr19 MR_fake_reg[19]
+#define mr20 MR_fake_reg[20]
+#define mr21 MR_fake_reg[21]
+#define mr22 MR_fake_reg[22]
+#define mr23 MR_fake_reg[23]
+#define mr24 MR_fake_reg[24]
+#define mr25 MR_fake_reg[25]
+#define mr26 MR_fake_reg[26]
+#define mr27 MR_fake_reg[27]
+#define mr28 MR_fake_reg[28]
+#define mr29 MR_fake_reg[29]
+#define mr30 MR_fake_reg[30]
+#define mr31 MR_fake_reg[31]
+#define mr32 MR_fake_reg[32]
+#define mr33 MR_fake_reg[33]
+#define mr34 MR_fake_reg[34]
+#define mr35 MR_fake_reg[35]
+#define mr36 MR_fake_reg[36]
+#define mr37 MR_fake_reg[37]
#endif /* not RS6000_REGS_H */
Index: runtime/machdeps/sparc_regs.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/machdeps/sparc_regs.h,v
retrieving revision 1.18
diff -u -r1.18 sparc_regs.h
--- sparc_regs.h 1997/07/27 15:09:12 1.18
+++ sparc_regs.h 1998/03/11 04:52:34
@@ -82,33 +82,34 @@
#define restore_transient_regs_from_mem(save_area) \
restore_regs_from_mem(save_area)
-#define mr10 fake_reg[10]
-#define mr11 fake_reg[11]
-#define mr12 fake_reg[12]
-#define mr13 fake_reg[13]
-#define mr14 fake_reg[14]
-#define mr15 fake_reg[15]
-#define mr16 fake_reg[16]
-#define mr17 fake_reg[17]
-#define mr18 fake_reg[18]
-#define mr19 fake_reg[19]
-#define mr20 fake_reg[20]
-#define mr21 fake_reg[21]
-#define mr22 fake_reg[22]
-#define mr23 fake_reg[23]
-#define mr24 fake_reg[24]
-#define mr25 fake_reg[25]
-#define mr26 fake_reg[26]
-#define mr27 fake_reg[27]
-#define mr28 fake_reg[28]
-#define mr29 fake_reg[29]
-#define mr30 fake_reg[30]
-#define mr31 fake_reg[31]
-#define mr32 fake_reg[32]
-#define mr33 fake_reg[33]
-#define mr34 fake_reg[34]
-#define mr35 fake_reg[35]
-#define mr36 fake_reg[36]
+#define mr10 MR_fake_reg[10]
+#define mr11 MR_fake_reg[11]
+#define mr12 MR_fake_reg[12]
+#define mr13 MR_fake_reg[13]
+#define mr14 MR_fake_reg[14]
+#define mr15 MR_fake_reg[15]
+#define mr16 MR_fake_reg[16]
+#define mr17 MR_fake_reg[17]
+#define mr18 MR_fake_reg[18]
+#define mr19 MR_fake_reg[19]
+#define mr20 MR_fake_reg[20]
+#define mr21 MR_fake_reg[21]
+#define mr22 MR_fake_reg[22]
+#define mr23 MR_fake_reg[23]
+#define mr24 MR_fake_reg[24]
+#define mr25 MR_fake_reg[25]
+#define mr26 MR_fake_reg[26]
+#define mr27 MR_fake_reg[27]
+#define mr28 MR_fake_reg[28]
+#define mr29 MR_fake_reg[29]
+#define mr30 MR_fake_reg[30]
+#define mr31 MR_fake_reg[31]
+#define mr32 MR_fake_reg[32]
+#define mr33 MR_fake_reg[33]
+#define mr34 MR_fake_reg[34]
+#define mr35 MR_fake_reg[35]
+#define mr36 MR_fake_reg[36]
+#define mr37 MR_fake_reg[37]
#endif
%------------------------------------------------------------------------------%
#ifndef MERCURY_THREAD_H
#define MERCURY_THREAD_H
#ifdef MR_THREAD_SAFE
#include <signal.h> /* for sigset_t on the SPARC */
#include <pthread.h>
#include "mercury_std.h"
#if defined(__alpha__)
#define MR_MUTEX_ATTR pthread_mutexattr_default
#define MR_COND_ATTR pthread_condattr_default
#define MR_THREAD_ATTR pthread_attr_default
#else
#define MR_MUTEX_ATTR NULL
#define MR_COND_ATTR NULL
#define MR_THREAD_ATTR NULL
#endif
typedef pthread_t MercuryThread;
typedef pthread_key_t MercuryThreadKey;
typedef pthread_mutex_t MercuryLock;
typedef pthread_cond_t MercuryCond;
#if 0
#define MR_LOCK(lck, from) pthread_mutex_lock((lck))
#define MR_UNLOCK(lck, from) pthread_mutex_unlock((lck))
#define MR_SIGNAL(cnd) pthread_cond_signal((cnd))
#define MR_WAIT(cnd, mtx) pthread_cond_wait((cnd), (mtx))
#else
void MR_mutex_lock(MercuryLock *lock, const char *from);
void MR_mutex_unlock(MercuryLock *lock, const char *from);
void MR_cond_signal(MercuryCond *cond);
void MR_cond_wait(MercuryCond *cond, MercuryLock *lock);
#define MR_LOCK(lck, from) MR_mutex_lock((lck), (from))
#define MR_UNLOCK(lck, from) MR_mutex_unlock((lck), (from))
#define MR_SIGNAL(cnd) MR_cond_signal((cnd))
#define MR_WAIT(cnd, mtx) MR_cond_wait((cnd), (mtx))
#endif
#if defined(__alpha__)
#define MR_GETSPECIFIC(key) ({ \
pthread_addr_t gstmp; \
pthread_getspecific((key), &gstmp); \
(void *) gstmp; \
})
#define MR_KEY_CREATE pthread_keycreate
#else
#define MR_GETSPECIFIC(key) pthread_getspecific((key))
#define MR_KEY_CREATE pthread_key_create
#endif
MercuryThread *create_thread(int x);
void destroy_thread(void *eng);
extern bool MR_exit_now;
#else
#define MR_LOCK(nothing, from) do { } while (0)
#define MR_UNLOCK(nothing, from) do { } while (0)
#define MR_SIGNAL(nothing) do { } while (0)
#define MR_WAIT(no, thing) do { } while (0)
#endif
void *init_thread(void *);
#endif
%------------------------------------------------------------------------------%
/*
INIT mercury_scheduler_wrapper
ENDINIT
*/
/*
** Copyright (C) 1997 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);
#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
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_engine_base = *eng;
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;
#ifdef 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;
#ifdef 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();
}
More information about the developers
mailing list