mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-18 23:35:25 +00:00
Estimated hours taken: 10 Make everything in the runtime use MR_ prefixes, and make the compiler bootstrap with -DMR_NO_BACKWARDS_COMPAT. runtime/mercury_*.[ch] Add MR_ prefixes to all functions, global variables and almost all macros that could pollute the namespace. The (intentional) exceptions are 1. some function, variable, type and label names that already start with MR_, mercury_, Mercury or _entry; 2. some standard C macros in mercury_std.h; 3. the macros used in autoconfiguration (since they are used in scripts as well as the runtime, the MR_ prefix may not be appropriate for those). In some cases, I deleted things instead of adding prefixes if the "things" were obsolete and not user visible. runtime/mercury_bootstrap.h: Provide MR_-less forms of the macros for bootstrapping and for backward compatibility for user code. runtime/mercury_debug.[ch]: Add a FILE * parameter to a function that needs it. compiler/code_info.m: compiler/export.m: compiler/fact_table.m: compiler/llds.m: compiler/llds_out.m: compiler/pragma_c_gen.m: compiler/trace.m: Add MR_ prefixes to the C code generated by the compiler. library/*.m: Add MR_ prefixes to handwritten code. trace/mercury_trace_*.c: util/mkinit.c: Add MR_ prefixes as necessary. extras/concurrency/semaphore.m: Add MR_ prefixes as necessary.
197 lines
3.7 KiB
C
197 lines
3.7 KiB
C
/*
|
|
** Copyright (C) 1997-2000 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_context.h" /* for do_runnext */
|
|
#include "mercury_thread.h"
|
|
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
|
|
#ifdef MR_THREAD_SAFE
|
|
MercuryThreadKey MR_engine_base_key;
|
|
MercuryLock MR_global_lock;
|
|
#endif
|
|
|
|
bool MR_exit_now;
|
|
|
|
#ifdef MR_THREAD_SAFE
|
|
|
|
static void *
|
|
MR_create_thread_2(void *goal);
|
|
|
|
MercuryThread *
|
|
MR_create_thread(MR_ThreadGoal *goal)
|
|
{
|
|
MercuryThread *thread;
|
|
pthread_attr_t attrs;
|
|
int err;
|
|
|
|
thread = MR_GC_NEW(MercuryThread);
|
|
pthread_attr_init(&attrs);
|
|
err = pthread_create(thread, &attrs, MR_create_thread_2,
|
|
(void *) goal);
|
|
|
|
#if 0
|
|
fprintf(stderr, "pthread_create returned %d (errno = %d)\n",
|
|
err, errno);
|
|
#endif
|
|
|
|
if (err != 0)
|
|
MR_fatal_error("error creating thread");
|
|
|
|
return thread;
|
|
}
|
|
|
|
static void *
|
|
MR_create_thread_2(void *goal0)
|
|
{
|
|
MR_ThreadGoal *goal;
|
|
|
|
goal = (MR_ThreadGoal *) goal0;
|
|
if (goal != NULL) {
|
|
MR_init_thread(MR_use_now);
|
|
(goal->func)(goal->arg);
|
|
} else {
|
|
MR_init_thread(MR_use_later);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#endif /* MR_THREAD_SAFE */
|
|
|
|
MR_Bool
|
|
MR_init_thread(MR_when_to_use when_to_use)
|
|
{
|
|
MercuryEngine *eng;
|
|
|
|
#ifdef MR_THREAD_SAFE
|
|
/*
|
|
** Check to see whether there is already an engine
|
|
** that is initialized in this thread. If so we just
|
|
** return, there's nothing for us to do.
|
|
*/
|
|
if (MR_GETSPECIFIC(MR_engine_base_key)) {
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
eng = MR_create_engine();
|
|
|
|
#ifdef MR_THREAD_SAFE
|
|
pthread_setspecific(MR_engine_base_key, eng);
|
|
MR_restore_registers();
|
|
#ifdef MR_ENGINE_BASE_REGISTER
|
|
MR_engine_base = eng;
|
|
#endif
|
|
#else
|
|
MR_memcpy(&MR_engine_base, eng,
|
|
sizeof(MercuryEngine));
|
|
MR_restore_registers();
|
|
#endif
|
|
MR_load_engine_regs(MR_cur_engine());
|
|
MR_load_context(MR_ENGINE(this_context));
|
|
|
|
MR_save_registers();
|
|
|
|
#ifdef MR_THREAD_SAFE
|
|
MR_ENGINE(owner_thread) = pthread_self();
|
|
#endif
|
|
|
|
switch (when_to_use) {
|
|
case MR_use_later :
|
|
(void) MR_call_engine(MR_ENTRY(do_runnext), FALSE);
|
|
|
|
MR_destroy_engine(eng);
|
|
return FALSE;
|
|
|
|
case MR_use_now :
|
|
return TRUE;
|
|
|
|
default:
|
|
MR_fatal_error("init_thread was passed a bad value");
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Release resources associated with this thread.
|
|
*/
|
|
void
|
|
MR_finalize_thread_engine(void)
|
|
{
|
|
#ifdef MR_THREAD_SAFE
|
|
MercuryEngine *eng;
|
|
|
|
eng = MR_GETSPECIFIC(MR_engine_base_key);
|
|
pthread_setspecific(MR_engine_base_key, NULL);
|
|
/*
|
|
** XXX calling destroy_engine(eng) here appears to segfault.
|
|
** This should probably be investigated and fixed.
|
|
*/
|
|
MR_finalize_engine(eng);
|
|
#endif
|
|
}
|
|
|
|
#ifdef MR_THREAD_SAFE
|
|
|
|
void
|
|
MR_destroy_thread(void *eng0)
|
|
{
|
|
MercuryEngine *eng = eng0;
|
|
MR_destroy_engine(eng);
|
|
pthread_exit(0);
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined(MR_THREAD_SAFE) && defined(MR_DEBUG_THREADS)
|
|
|
|
void
|
|
MR_mutex_lock(MercuryLock *lock, const char *from)
|
|
{
|
|
int err;
|
|
|
|
fprintf(stderr, "%d locking on %p (%s)\n", pthread_self(), lock, from);
|
|
err = pthread_mutex_lock(lock);
|
|
assert(err == 0);
|
|
}
|
|
|
|
void
|
|
MR_mutex_unlock(MercuryLock *lock, const char *from)
|
|
{
|
|
int err;
|
|
|
|
fprintf(stderr, "%d unlocking on %p (%s)\n",
|
|
pthread_self(), lock, from);
|
|
err = pthread_mutex_unlock(lock);
|
|
assert(err == 0);
|
|
}
|
|
|
|
void
|
|
MR_cond_signal(MercuryCond *cond)
|
|
{
|
|
int err;
|
|
|
|
fprintf(stderr, "%d signaling %p\n", pthread_self(), cond);
|
|
err = pthread_cond_broadcast(cond);
|
|
assert(err == 0);
|
|
}
|
|
|
|
void
|
|
MR_cond_wait(MercuryCond *cond, MercuryLock *lock)
|
|
{
|
|
int err;
|
|
|
|
fprintf(stderr, "%d waiting on %p (%p)\n", pthread_self(), cond, lock);
|
|
err = pthread_cond_wait(cond, lock);
|
|
assert(err == 0);
|
|
}
|
|
|
|
#endif
|