[m-rev.] for review: bug fixes for threads
Peter Wang
wangp at students.csse.unimelb.edu.au
Tue Feb 20 16:09:56 AEDT 2007
Pending bootchecking in more grades.
Branches: main
Some bug fixes to do with threads.
library/io.m:
ML_maybe_make_err_msg() was not thread-safe but was called from some
`thread_safe' foreign_procs. Make ML_maybe_make_err_msg() acquire the
global lock if the caller does not acquire the global lock itself.
library/thread.m:
runtime/mercury_thread.c:
Create threads in the detached state so that resources will be
automatically freed when threads terminate (we don't call
pthread_join() anywhere).
library/thread.semaphore.m:
Wake up waiting threads in FIFO order, instead of LIFO order.
runtime/mercury_context.c:
runtime/mercury_context.h:
runtime/mercury_engine.c:
runtime/mercury_engine.h:
Change the way we enforce that a Mercury context returning from Mercury
code back into a C function runs on the original Mercury engine that
called the C function.
Previously, if a C function called into Mercury code, the Mercury
context would be "owned" by that Mercury engine until the C function
finished. If the Mercury code suspended (e.g. waiting on a semaphore),
it could not be resumed by another Mercury engine. This was
unnecessarily conservative.
Now any Mercury engine can resume a suspended context. Just before
returning into C functions, we check that the context is actually
running on the Mercury engine in which the C function was started. If
not, *then* we reschedule the context so that it will only be picked up
by the right Mercury engine.
Add a comment that none of this is implemented for grades not using gcc
non-local gotos (nor was it implemented before).
runtime/mercury_memory_zones.c:
Fix an off-by-one bug and a thread-safety bug in MR_next_offset().
====================
Here are some numbers for parallel mmc make after this patch.
It's making the standard library on saturn.
asm_fast.gc:
time MERCURY_OPTIONS=-P1 mmc -m libmer_std.a --flags LIB_FLAGS
... 122.08s user 17.27s system 93% cpu 2:29.46 total
rm Mercury/os/*.o
time MERCURY_OPTIONS=-P1 mmc -m libmer_std.a --flags LIB_FLAGS
... 66.04s user 5.91s system 99% cpu 1:11.98 total
asm_fast.par.gc:
rm -r Mercury
time MERCURY_OPTIONS=-P1 mmc -m libmer_std.a --flags LIB_FLAGS
... 145.51s user 20.48s system 101% cpu 2:42.86 total
rm Mercury/os/*.o
time MERCURY_OPTIONS=-P1 mmc -m libmer_std.a --flags LIB_FLAGS
... 66.22s user 5.13s system 100% cpu 1:11.31 total
rm -r Mercury
time MERCURY_OPTIONS=-P2 mmc -m libmer_std.a --flags LIB_FLAGS -j2
... 146.29s user 19.63s system 129% cpu 2:07.99 total
rm Mercury/os/*.o
time MERCURY_OPTIONS=-P2 mmc -m libmer_std.a --flags LIB_FLAGS -j2
... 66.62s user 6.28s system 191% cpu 38.090 total
rm Mercury/os/*.o
time MERCURY_OPTIONS=-P4 mmc -m libmer_std.a --flags LIB_FLAGS -j4
... 66.96s user 7.16s system 197% cpu 37.624 total
Index: library/io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/io.m,v
retrieving revision 1.372
diff -u -r1.372 io.m
--- library/io.m 13 Feb 2007 01:58:53 -0000 1.372
+++ library/io.m 16 Feb 2007 02:31:40 -0000
@@ -2359,7 +2359,7 @@
}
ML_maybe_make_err_msg(RetVal != 0, errno, ""read failed: "",
- MR_PROC_LABEL, RetStr);
+ MR_PROC_LABEL, MR_TRUE, RetStr);
MR_update_io(IO0, IO);
").
@@ -2426,7 +2426,7 @@
[will_not_call_mercury, promise_pure, tabled_for_io,
does_not_affect_liveness],
"
- ML_maybe_make_err_msg(MR_TRUE, Error, Msg0, MR_PROC_LABEL, Msg);
+ ML_maybe_make_err_msg(MR_TRUE, Error, Msg0, MR_PROC_LABEL, MR_FALSE, Msg);
MR_update_io(IO0, IO);
").
@@ -2612,7 +2612,7 @@
Status = 1;
} else {
ML_maybe_make_err_msg(MR_TRUE, errno, ""stat() failed: "",
- MR_PROC_LABEL, Msg);
+ MR_PROC_LABEL, MR_TRUE, Msg);
Status = 0;
}
#else
@@ -3397,7 +3397,7 @@
Status = 1;
} else {
ML_maybe_make_err_msg(MR_TRUE, errno, ""stat() failed: "",
- MR_PROC_LABEL, Msg);
+ MR_PROC_LABEL, MR_TRUE, Msg);
Status = 0;
}
MR_update_io(IO0, IO);
@@ -8046,7 +8046,7 @@
*/
Status = 127;
ML_maybe_make_err_msg(MR_TRUE, errno,
- ""error invoking system command: "", MR_PROC_LABEL, Msg);
+ ""error invoking system command: "", MR_PROC_LABEL, MR_TRUE, Msg);
} else {
Msg = MR_make_string_const("""");
}
@@ -8478,12 +8478,14 @@
num_tries < ML_MAX_TEMPNAME_TRIES);
if (fd == -1) {
ML_maybe_make_err_msg(MR_TRUE, errno,
- ""error opening temporary file: "", MR_PROC_LABEL, ErrorMessage);
+ ""error opening temporary file: "", MR_PROC_LABEL, MR_TRUE,
+ ErrorMessage);
Error = -1;
} else {
err = close(fd);
ML_maybe_make_err_msg(err, errno,
- ""error closing temporary file: "", MR_PROC_LABEL, ErrorMessage);
+ ""error closing temporary file: "", MR_PROC_LABEL, MR_TRUE,
+ ErrorMessage);
Error = err;
}
MR_update_io(IO0, IO);
@@ -8604,9 +8606,11 @@
#include <errno.h>
/*
-** ML_maybe_make_err_msg(was_error, errno, msg, procname, error_msg):
+** ML_maybe_make_err_msg(was_error, errno, msg, procname, req_lock, error_msg):
** if `was_error' is true, then append `msg' and `strerror(errno)'
** to give `error_msg'; otherwise, set `error_msg' to "".
+** `req_lock' must be true iff the caller is marked `thread_safe' as the
+** underlying strerror() function is not thread-safe.
**
** WARNING: this must only be called when the `hp' register is valid.
** That means it must only be called from procedures declared
@@ -8619,13 +8623,17 @@
** stringizes the procname argument.
*/
-#define ML_maybe_make_err_msg(was_error, error, msg, procname, error_msg) \\
+#define ML_maybe_make_err_msg(was_error, error, msg, procname, req_lock, \\
+ error_msg) \\
do { \\
char *errno_msg; \\
size_t total_len; \\
MR_Word tmp; \\
\\
if (was_error) { \\
+ if (req_lock) { \\
+ MR_OBTAIN_GLOBAL_LOCK(procname); \\
+ } \\
errno_msg = strerror(error); \\
total_len = strlen(msg) + strlen(errno_msg); \\
MR_offset_incr_hp_atomic_msg(tmp, 0, \\
@@ -8634,6 +8642,9 @@
(error_msg) = (char *) tmp; \\
strcpy((error_msg), msg); \\
strcat((error_msg), errno_msg); \\
+ if (req_lock) { \\
+ MR_RELEASE_GLOBAL_LOCK(procname); \\
+ } \\
} else { \\
/* \\
** We can't just return NULL here, because otherwise mdb \\
@@ -8733,7 +8744,7 @@
"{
RetVal = remove(FileName);
ML_maybe_make_err_msg(RetVal != 0, errno, ""remove failed: "",
- MR_PROC_LABEL, RetStr);
+ MR_PROC_LABEL, MR_TRUE, RetStr);
MR_update_io(IO0, IO);
}").
@@ -8798,7 +8809,7 @@
"{
RetVal = rename(OldFileName, NewFileName);
ML_maybe_make_err_msg(RetVal != 0, errno, ""rename failed: "",
- MR_PROC_LABEL, RetStr);
+ MR_PROC_LABEL, MR_TRUE, RetStr);
MR_update_io(IO0, IO);
}").
Index: library/thread.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/thread.m,v
retrieving revision 1.5
diff -u -r1.5 thread.m
--- library/thread.m 13 Feb 2007 00:16:57 -0000 1.5
+++ library/thread.m 16 Feb 2007 01:20:11 -0000
@@ -248,6 +248,7 @@
{
ML_ThreadWrapperArgs *args;
pthread_t thread;
+ pthread_attr_t attrs;
/*
** We can't allocate `args' on the stack because this function may return
@@ -259,9 +260,12 @@
args->thread_local_mutables =
MR_clone_thread_local_mutables(MR_THREAD_LOCAL_MUTABLES);
+ pthread_attr_init(&attrs);
+ pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
if (pthread_create(&thread, MR_THREAD_ATTR, ML_thread_wrapper, args)) {
MR_fatal_error(""Unable to create thread."");
}
+ pthread_attr_destroy(&attrs);
/*
** XXX How do we ensure that the parent thread doesn't terminate until
Index: library/thread.semaphore.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/thread.semaphore.m,v
retrieving revision 1.4
diff -u -r1.4 thread.semaphore.m
--- library/thread.semaphore.m 6 Feb 2007 10:52:24 -0000 1.4
+++ library/thread.semaphore.m 16 Feb 2007 01:31:04 -0000
@@ -67,7 +67,8 @@
typedef struct ML_SEMAPHORE_STRUCT {
int count;
#ifndef MR_HIGHLEVEL_CODE
- MR_Context *suspended;
+ MR_Context *suspended_head;
+ MR_Context *suspended_tail;
#else
#ifdef MR_THREAD_SAFE
MercuryCond cond;
@@ -109,7 +110,8 @@
sem = (ML_Semaphore *) sem_mem;
sem->count = 0;
#ifndef MR_HIGHLEVEL_CODE
- sem->suspended = NULL;
+ sem->suspended_head = NULL;
+ sem->suspended_tail = NULL;
#else
#ifdef MR_THREAD_SAFE
pthread_cond_init(&(sem->cond), MR_COND_ATTR);
@@ -181,26 +183,35 @@
MR_LOCK(&(sem->lock), ""semaphore__signal"");
#ifndef MR_HIGHLEVEL_CODE
- if (sem->count >= 0 && sem->suspended != NULL) {
- ctxt = sem->suspended;
- sem->suspended = ctxt->MR_ctxt_next;
+ if (sem->count >= 0 && sem->suspended_head != NULL) {
+ /* Reschedule the context at the start of the queue. */
+ ctxt = sem->suspended_head;
+ sem->suspended_head = ctxt->MR_ctxt_next;
+ if (sem->suspended_tail == ctxt) {
+ sem->suspended_tail = ctxt->MR_ctxt_next;
+ assert(sem->suspended_tail == NULL);
+ }
MR_UNLOCK(&(sem->lock), ""semaphore__signal"");
MR_schedule_context(ctxt);
- /* yield() */
+
+ /* yield() */
MR_save_context(MR_ENGINE(MR_eng_this_context));
MR_ENGINE(MR_eng_this_context)->MR_ctxt_resume =
MR_ENTRY(mercury__thread__semaphore__nop);
MR_schedule_context(MR_ENGINE(MR_eng_this_context));
+
MR_ENGINE(MR_eng_this_context) = NULL;
MR_runnext();
} else {
sem->count++;
MR_UNLOCK(&(sem->lock), ""semaphore__signal"");
- /* yield() */
+
+ /* yield() */
MR_save_context(MR_ENGINE(MR_eng_this_context));
MR_ENGINE(MR_eng_this_context)->MR_ctxt_resume =
MR_ENTRY(mercury__thread__semaphore__nop);
MR_schedule_context(MR_ENGINE(MR_eng_this_context));
+
MR_ENGINE(MR_eng_this_context) = NULL;
MR_runnext();
}
@@ -249,11 +260,21 @@
MR_UNLOCK(&(sem->lock), ""semaphore__wait"");
} else {
MR_save_context(MR_ENGINE(MR_eng_this_context));
- MR_ENGINE(MR_eng_this_context)->MR_ctxt_resume =
- MR_ENTRY(mercury__thread__semaphore__nop);
- MR_ENGINE(MR_eng_this_context)->MR_ctxt_next = sem->suspended;
- sem->suspended = MR_ENGINE(MR_eng_this_context);
+
+ /* Put the current context at the end of the queue. */
+ ctxt = MR_ENGINE(MR_eng_this_context);
+ ctxt->MR_ctxt_resume = MR_ENTRY(mercury__thread__semaphore__nop);
+ ctxt->MR_ctxt_next = NULL;
+ if (sem->suspended_tail) {
+ sem->suspended_tail->MR_ctxt_next = ctxt;
+ sem->suspended_tail = ctxt;
+ } else {
+ sem->suspended_head = ctxt;
+ sem->suspended_tail = ctxt;
+ }
MR_UNLOCK(&(sem->lock), ""semaphore__wait"");
+
+ /* Make the current engine do something else. */
MR_ENGINE(MR_eng_this_context) = NULL;
MR_runnext();
}
Index: runtime/mercury_context.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_context.c,v
retrieving revision 1.54
diff -u -r1.54 mercury_context.c
--- runtime/mercury_context.c 12 Jan 2007 05:00:30 -0000 1.54
+++ runtime/mercury_context.c 16 Feb 2007 02:26:05 -0000
@@ -115,7 +115,9 @@
c->MR_ctxt_next = NULL;
c->MR_ctxt_resume = NULL;
#ifdef MR_THREAD_SAFE
- c->MR_ctxt_owner_thread = (MercuryThread) NULL;
+ c->MR_ctxt_resume_owner_thread = (MercuryThread) NULL;
+ c->MR_ctxt_resume_c_depth = 0;
+ c->MR_ctxt_saved_owners = NULL;
#endif
#ifndef MR_HIGHLEVEL_CODE
@@ -456,7 +458,7 @@
** possibility that a woken thread might not accept this context then
** we wake up all the waiting threads.
*/
- if (ctxt->MR_ctxt_owner_thread == (MercuryThread) NULL) {
+ if (ctxt->MR_ctxt_resume_owner_thread == (MercuryThread) NULL) {
MR_SIGNAL(&MR_runqueue_cond);
} else {
MR_BROADCAST(&MR_runqueue_cond);
@@ -531,12 +533,20 @@
/* XXX check pending io */
prev = NULL;
while (tmp != NULL) {
- if ((depth > 0 && tmp->MR_ctxt_owner_thread == thd) ||
- (tmp->MR_ctxt_owner_thread == (MercuryThread) NULL))
+ if (tmp->MR_ctxt_resume_owner_thread == thd &&
+ tmp->MR_ctxt_resume_c_depth == depth)
{
+ tmp->MR_ctxt_resume_owner_thread = (MercuryThread) NULL;
+ tmp->MR_ctxt_resume_c_depth = 0;
MR_num_idle_engines--;
goto ReadyContext;
}
+
+ if (tmp->MR_ctxt_resume_owner_thread == (MercuryThread) NULL) {
+ MR_num_idle_engines--;
+ goto ReadyContext;
+ }
+
prev = tmp;
tmp = tmp->MR_ctxt_next;
}
@@ -550,7 +560,8 @@
}
/* Nothing to do, go back to sleep. */
- MR_WAIT(&MR_runqueue_cond, &MR_runqueue_lock);
+ while (MR_WAIT(&MR_runqueue_cond, &MR_runqueue_lock) != 0) {
+ }
}
ReadyContext:
Index: runtime/mercury_context.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_context.h,v
retrieving revision 1.39
diff -u -r1.39 mercury_context.h
--- runtime/mercury_context.h 12 Jan 2007 05:00:31 -0000 1.39
+++ runtime/mercury_context.h 16 Feb 2007 03:17:19 -0000
@@ -88,9 +88,21 @@
** resume A pointer to the code at which execution should resume
** when this context is next scheduled.
**
-** 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.
+** resume_owner_thread
+** resume_c_depth
+** These fields are used to ensure that when we enter a
+** Mercury engine from C, we return to the same engine. If
+** resume_owner_thread is NULL then this context can be
+** executed by any engine. Otherwise the resume_owner_thread
+** and resume_c_depth must match the engine's owner_thread
+** and c_depth. See the comments in mercury_engine.h.
+**
+** saved_owners
+** A stack used to record the Mercury engines on which this
+** context executed some C calls that called back into
+** Mercury. We must execute this context in the correct
+** engine when returning to those C calls. See the comments
+** in mercury_engine.h.
**
** succip The succip for this context.
**
@@ -140,6 +152,16 @@
MR_CONTEXT_SIZE_SMALL
} MR_ContextSize;
+#ifdef MR_THREAD_SAFE
+typedef struct MR_SavedOwner_Struct MR_SavedOwner;
+
+struct MR_SavedOwner_Struct {
+ MercuryThread MR_saved_owner_thread;
+ MR_Unsigned MR_saved_owner_c_depth;
+ MR_SavedOwner *MR_saved_owner_next;
+};
+#endif
+
typedef struct MR_MemoryZones_Struct MR_MemoryZones;
struct MR_MemoryZones_Struct {
@@ -153,7 +175,9 @@
MR_Context *MR_ctxt_next;
MR_Code *MR_ctxt_resume;
#ifdef MR_THREAD_SAFE
- MercuryThread MR_ctxt_owner_thread;
+ MercuryThread MR_ctxt_resume_owner_thread;
+ MR_Unsigned MR_ctxt_resume_c_depth;
+ MR_SavedOwner *MR_ctxt_saved_owners;
#endif
#ifndef MR_HIGHLEVEL_CODE
Index: runtime/mercury_engine.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_engine.c,v
retrieving revision 1.55
diff -u -r1.55 mercury_engine.c
--- runtime/mercury_engine.c 11 Dec 2006 03:03:13 -0000 1.55
+++ runtime/mercury_engine.c 16 Feb 2007 04:07:40 -0000
@@ -37,6 +37,7 @@
#ifndef MR_USE_GCC_NONLOCAL_GOTOS
static MR_Code *engine_done(void);
+ static MR_Code *engine_done_2(void);
static MR_Code *engine_init_registers(void);
#endif
@@ -138,7 +139,6 @@
#ifdef MR_THREAD_SAFE
eng->MR_eng_owner_thread = pthread_self();
eng->MR_eng_c_depth = 0;
- eng->MR_eng_saved_owners = NULL;
#endif
/*
@@ -415,6 +415,7 @@
if (!initialized) {
MR_make_label("engine_done", MR_LABEL(engine_done), engine_done);
+ MR_make_label("engine_done_2", MR_LABEL(engine_done_2), engine_done_2);
initialized = MR_TRUE;
}
}
@@ -458,21 +459,20 @@
/*
** Increment the number of times we've entered this engine from C,
- ** and mark the current context as being owned by this thread.
+ ** and push the current engine onto the context's stack of saved owners.
*/
#ifdef MR_THREAD_SAFE
MR_ENGINE(MR_eng_c_depth)++;
- if (MR_ENGINE(MR_eng_this_context)) {
- MercuryThreadList *new_element;
- new_element = MR_GC_NEW(MercuryThreadList);
- new_element->thread =
- MR_ENGINE(MR_eng_this_context)->MR_ctxt_owner_thread;
- new_element->next = MR_ENGINE(MR_eng_saved_owners);
- MR_ENGINE(MR_eng_saved_owners) = new_element;
+ if (MR_ENGINE(MR_eng_this_context)) {
+ MR_SavedOwner *owner;
- MR_ENGINE(MR_eng_this_context)->MR_ctxt_owner_thread =
- MR_ENGINE(MR_eng_owner_thread);
+ owner = MR_GC_NEW(MR_SavedOwner);
+ owner->MR_saved_owner_thread = MR_ENGINE(MR_eng_owner_thread);
+ owner->MR_saved_owner_c_depth = MR_ENGINE(MR_eng_c_depth);
+ owner->MR_saved_owner_next =
+ MR_ENGINE(MR_eng_this_context)->MR_ctxt_saved_owners;
+ MR_ENGINE(MR_eng_this_context)->MR_ctxt_saved_owners = owner;
}
#endif
@@ -484,31 +484,48 @@
MR_define_label(engine_done);
+ assert(MR_ENGINE(MR_eng_this_context));
+
/*
- ** Decrement the number of times we've entered this engine from C
- ** and restore the owning thread in the current context.
+ ** Check that we're reentering C in the correct engine.
+ ** If not, reschedule the context so that it will be picked up by
+ ** the correct engine when it is available.
*/
#ifdef MR_THREAD_SAFE
- if (MR_ENGINE(MR_eng_this_context)) {
- MercuryThreadList *tmp;
- MercuryThread val;
+ {
+ MR_Context *this_ctxt;
+ MR_SavedOwner *owner;
- assert(MR_ENGINE(MR_eng_this_context)->MR_ctxt_owner_thread
- == MR_ENGINE(MR_eng_owner_thread));
- MR_ENGINE(MR_eng_c_depth)--;
-
- tmp = MR_ENGINE(MR_eng_saved_owners);
- if (tmp != NULL) {
- val = tmp->thread;
- MR_ENGINE(MR_eng_saved_owners) = tmp->next;
- MR_GC_free(tmp);
- } else {
- val = 0;
+ this_ctxt = MR_ENGINE(MR_eng_this_context);
+ owner = this_ctxt->MR_ctxt_saved_owners;
+ this_ctxt->MR_ctxt_saved_owners = owner->MR_saved_owner_next;
+
+ if (owner->MR_saved_owner_thread == MR_ENGINE(MR_eng_owner_thread) &&
+ owner->MR_saved_owner_c_depth == MR_ENGINE(MR_eng_c_depth))
+ {
+ MR_GC_free(owner);
+ MR_GOTO_LABEL(engine_done_2);
}
- MR_ENGINE(MR_eng_this_context)->MR_ctxt_owner_thread = val;
+
+ MR_save_context(this_ctxt);
+ this_ctxt->MR_ctxt_resume = MR_LABEL(engine_done_2);
+ this_ctxt->MR_ctxt_resume_owner_thread = owner->MR_saved_owner_thread;
+ this_ctxt->MR_ctxt_resume_c_depth = owner->MR_saved_owner_c_depth;
+ MR_GC_free(owner);
+ MR_schedule_context(this_ctxt);
+
+ MR_ENGINE(MR_eng_this_context) = NULL;
+ MR_runnext();
}
#endif
+MR_define_label(engine_done_2);
+
+#ifdef MR_THREAD_SAFE
+ /* Decrement the number of times we've entered this engine from C. */
+ MR_ENGINE(MR_eng_c_depth)--;
+#endif
+
MR_debugmsg1("in label `engine_done', locals at %p\n", locals);
#ifdef MR_LOWLEVEL_DEBUG
@@ -575,6 +592,11 @@
** engine_init_registers() rather than directly from call_engine_inner()
** because otherwise their value would get mucked up because of the function
** call from call_engine_inner().
+**
+** XXX The portable version does not yet prevent Mercury code returning back
+** into C code on the wrong Mercury engine (see the code involving
+** MR_eng_owner_thread and MR_eng_c_depth in the gcc version). Therefore
+** low-level .par grades without gcc non-local gotos are unsafe.
*/
static MR_Code *
Index: runtime/mercury_engine.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_engine.h,v
retrieving revision 1.45
diff -u -r1.45 mercury_engine.h
--- runtime/mercury_engine.h 27 Dec 2006 04:16:36 -0000 1.45
+++ runtime/mercury_engine.h 16 Feb 2007 01:55:45 -0000
@@ -263,13 +263,6 @@
/*---------------------------------------------------------------------------*/
-#ifdef MR_THREAD_SAFE
-typedef struct MR_mercury_thread_list_struct {
- MercuryThread thread;
- struct MR_mercury_thread_list_struct *next;
-} MercuryThreadList;
-#endif
-
/*
** The Mercury engine structure. Normally there is one of these for each
** Posix thread. It contains the following fields.
@@ -311,21 +304,19 @@
**
** owner_thread
** c_depth
-** saved_owners
-** These three fields are used to ensure that when a thread
+** These 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.
-** The list `saved_owners' is used in call_engine_inner to store
-** the owner of a context across calls into Mercury. At the moment
-** this is only used for sanity checking - that execution never
-** returns into C in the wrong thread.
+** the c_depth is incremented, and the owner_thread and c_depth
+** values of the current engine are pushed onto the "saved_owners"
+** stack of the current context. When a context is about to return
+** from Mercury code back into C code, we pop the top entry off the
+** context's saved_owners stack and check that the context is
+** running on the right engine. If not, we reschedule the context
+** such that it can only be picked up by the correct engine when
+** that engine is available. When the call into the Mercury code
+** finishes, c_depth is decremented.
**
** jmp_buf The jump buffer used by library/exception.m to return to the
** runtime system on otherwise unhandled exceptions.
@@ -372,8 +363,7 @@
#endif
#ifdef MR_THREAD_SAFE
MercuryThread MR_eng_owner_thread;
- unsigned MR_eng_c_depth;
- MercuryThreadList *MR_eng_saved_owners;
+ MR_Unsigned MR_eng_c_depth;
#endif
jmp_buf *MR_eng_jmp_buf;
MR_Word *MR_eng_exception;
Index: runtime/mercury_memory_zones.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_zones.c,v
retrieving revision 1.31
diff -u -r1.31 mercury_memory_zones.c
--- runtime/mercury_memory_zones.c 14 Dec 2006 10:29:58 -0000 1.31
+++ runtime/mercury_memory_zones.c 20 Feb 2007 05:03:19 -0000
@@ -489,8 +489,10 @@
{
size_t offset;
+ MR_OBTAIN_GLOBAL_LOCK("MR_next_offset");
offset = offset_vector[offset_counter];
- offset_counter = (offset_counter + 1) % CACHE_SLICES;
+ offset_counter = (offset_counter + 1) % (CACHE_SLICES - 1);
+ MR_RELEASE_GLOBAL_LOCK("MR_next_offset");
return offset;
}
Index: runtime/mercury_thread.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_thread.c,v
retrieving revision 1.30
diff -u -r1.30 mercury_thread.c
--- runtime/mercury_thread.c 16 Jan 2007 23:45:05 -0000 1.30
+++ runtime/mercury_thread.c 15 Feb 2007 10:37:37 -0000
@@ -49,7 +49,9 @@
thread = MR_GC_NEW(MercuryThread);
pthread_attr_init(&attrs);
+ pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
err = pthread_create(thread, &attrs, MR_create_thread_2, (void *) goal);
+ pthread_attr_destroy(&attrs);
#if 0
fprintf(stderr, "pthread_create returned %d (errno = %d)\n", err, errno);
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list