Files
mercury/runtime/mercury_thread.c
Zoltan Somogyi 090552c993 Make everything in the runtime use MR_ prefixes, and make the compiler
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.
2000-11-23 02:01:11 +00:00

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