[m-dev.] for review: independent AND parallelism [runtime]
Fergus Henderson
fjh at cs.mu.OZ.AU
Mon Apr 27 23:14:14 AEST 1998
Hi Tom,
Thanks for those changes.
On 27-Apr-1998, Thomas Charles CONWAY <conway at cs.mu.OZ.AU> wrote:
> 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.
s/tajes/takes/
> library/Makefile:
> work around a bug in the solaris version pthread.h
s/version/version of/ ?
> library/{nc,sp}_builtin.nl:
> add an op declaration for &.
Shouldn't you also modify library/ops.m and
compiler/mercury_to_mercury.m?
> diff -u -r1.1 mercury_context.c
...
> +#ifdef MR_THREAD_SAFE
> +#include "mercury_thread.h"
> #endif
Please indent the #include by two spaces,
since it's inside an #ifdef.
> +#ifdef MR_THREAD_SAFE
> +MercuryLock *MR_runqueue_lock;
> +MercuryCond *MR_runqueue_cond;
> +#endif
Ditto here. Probably also in lots of other places
in runtime/*.[ch].
> +#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)
That macro is pretty complicated. I think that most of that stuff
probably should go in a function, rather than a macro.
> +#ifdef MR_THREAD_SAFE
> +#define IF_MR_THREAD_SAFE(x) x
> +#else
> +#define IF_MR_THREAD_SAFE(x)
> +#endif
Hmm, that's the second occurrence of that...
> +#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)); \
> + } \
This is another complicated macro; does all of this
really need to be in a macro rather than a function?
I don't understand the call to MR_LOCK immediately
followed by a corresponding call to MR_UNLOCK.
> +#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
You could use MR_IF_THREAD_SAFE() to avoid the code dupliation here.
> +++ mercury_engine.c 1998/03/11 04:52:30
> void
> +init_engine(MercuryEngine *eng)
> {
> - init_memory();
> + /* XXX */ init_memory();
You should explain the XXX.
> +void finalize_engine(MercuryEngine *eng)
> +{
> +
> +}
Hmm, maybe this needs an XXX comment?
> Index: runtime/mercury_engine.h
> /*
> ** 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.
> */
> + #define restore_hp(src) ( \
> + LVALUE_CAST(Word,MR_hp) = (src), \
> + (void)0 \
> + )
>
> + /*
> + #define restore_hp(src) ( \
> + LVALUE_CAST(Word,MR_hp) = \
> + ( (Word) MR_min_hp_rec < (src) ? \
> + (src) : (Word) MR_min_hp_rec ), \
> + (void)0 \
> + )
> + */
You need to explain why the second version is commented out.
> Index: runtime/mercury_imp.h
> void
> init_memory(void)
> {
> + static first_time_only=0;
>
> + if (first_time_only != 0)
> + return;
> + first_time_only = 1;
You should avoid implicit int declarations --
as well as being bad style, they're banned by C9X.
And some whitespace around the `=' would be a good idea.
But I think it would be better to use `bool' instead of `int'
and `TRUE' and `FALSE' instead of `0' and `1'
(perhaps changing the name from `first_time_only' to
`already_done').
> Index: runtime/mercury_memory.h
...
> +/*
> +** destroy_zone(Zone) destroys a memory zone.
> +*/
How about
> --- mercury_misc.c 1998/01/23 15:26:33 1.3
> +++ mercury_misc.c 1998/03/18 23:48:42
> +void
> +MR_copy_structure(char *dest, const char *src, size_t nbytes)
> +{
> + while (nbytes-- > 0)
> + *dest++ = *src++;
> +}
I think `MR_memcpy()' would be a better name.
There should be a comment explaining why you don't just use memcpy().
Also please use {}.
> Index: runtime/mercury_wrapper.c
...
> /* start up the Mercury engine */
> - init_engine();
> +#ifndef MR_THREAD_SAFE
> + init_thread((void *) 1);
What is this `(void *)1' doing here?
What's the magic number `1' indicate?
> #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
`__alpha__' is not the right test -- no doubt this will break on Linux/Alpha.
Ideally of course it should be autoconf'ed.
But at very least you should add a level of indirection:
/* this code should go in mercury_conf_param.h.in */
#if defined(__alpha__) && defined(OSF or something like that)
#define MR_USE_ALPHA_STYLE_PTHREADS
#endif
/* in mercury_thread.h */
#ifdef MR_USE_ALPHA_STYLE_PTHREADS
#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
> #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
Please explain the `#if 0'.
> #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
Again you shouldn't test `__alpha__' here.
> bool MR_exit_now;
Shouldn't that be `volatile'?
> 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();
> }
I think you need a
/*
** INIT mercury_scheduler_wrapper
*/
comment somewhere.
Apart from that, the changes in this email look fine.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list