cleanup: separate process managament from threads

Additionally:

- abstract platform specific functions with file-local macros
This commit is contained in:
Daniel Kochmański 2022-12-05 00:18:21 +01:00
parent 90483505bd
commit 80b74c890d
4 changed files with 83 additions and 110 deletions

View file

@ -499,11 +499,7 @@ cl_boot(int argc, char **argv)
init_alloc();
GC_disable();
env = _ecl_alloc_env(0);
#ifdef ECL_THREADS
init_threads(env);
#else
cl_env_p = env;
#endif
/*
* 1) Initialize symbols and packages

View file

@ -10,6 +10,11 @@
*
*/
#define ECL_INCLUDE_MATH_H
#include <ecl/ecl.h> /* includes ECL_WINDOWS_THREADS */
#include <ecl/internal.h>
#include <ecl/ecl-inl.h>
#ifndef __sun__ /* See unixinit.d for this */
#define _XOPEN_SOURCE 600 /* For pthread mutex attributes */
#endif
@ -17,8 +22,6 @@
#include <time.h>
#include <signal.h>
#include <string.h>
#define ECL_INCLUDE_MATH_H
#include <ecl/ecl.h>
#ifdef ECL_WINDOWS_THREADS
# include <windows.h>
#else
@ -30,62 +33,66 @@
#ifdef HAVE_SCHED_H
# include <sched.h>
#endif
#include <ecl/internal.h>
#include <ecl/ecl-inl.h>
/* -- Macros -------------------------------------------------------- */
#ifdef ECL_WINDOWS_THREADS
DWORD cl_env_key;
# define ecl_process_key_t DWORD
# define ecl_process_key_create(key) key = TlsAlloc()
# define ecl_process_get_tls(key) TlsGetValue(key)
# define ecl_process_set_tls(key,val) (TlsSetValue(key,val)!=0)
# define ecl_process_eq(t1, t2) (GetThreadId(t1) == GetThreadId(t2))
# define ecl_set_process_self(var) \
{ \
HANDLE aux = GetCurrentThread(); \
DuplicateHandle(GetCurrentProcess(), \
aux, \
GetCurrentProcess(), \
&var, \
0, \
FALSE, \
DUPLICATE_SAME_ACCESS); \
}
#else
static pthread_key_t cl_env_key;
#endif /* ECL_WINDOWS_THREADS */
# define ecl_process_key_t static pthread_key_t
# define ecl_process_key_create(key) pthread_key_create(&key, NULL)
# define ecl_process_get_tls(key) pthread_getspecific(key)
# define ecl_process_set_tls(key,val) (pthread_setspecific(key,val)==0)
# define ecl_process_eq(t1, t2) (t1 == t2)
# define ecl_set_process_self(var) (var = pthread_self())
#endif /* ECL_WINDOWS_THREADS */
extern void ecl_init_env(struct cl_env_struct *env);
/* -- Core ---------------------------------------------------------- */
/* Accessing a thread-local variable representing the environment. */
ecl_process_key_t cl_env_key;
cl_env_ptr
ecl_process_env_unsafe(void)
{
#ifdef ECL_WINDOWS_THREADS
return TlsGetValue(cl_env_key);
#else
return pthread_getspecific(cl_env_key);
#endif
return ecl_process_get_tls(cl_env_key);
}
cl_env_ptr
ecl_process_env(void)
{
#ifdef ECL_WINDOWS_THREADS
return TlsGetValue(cl_env_key);
#else
struct cl_env_struct *rv = pthread_getspecific(cl_env_key);
if (rv)
return rv;
ecl_thread_internal_error("pthread_getspecific() failed.");
return NULL;
#endif
cl_env_ptr rv = ecl_process_get_tls(cl_env_key);
if(!rv) {
ecl_thread_internal_error("pthread_getspecific() failed.");
}
return rv;
}
static void
ecl_set_process_env(cl_env_ptr env)
{
#ifdef ECL_WINDOWS_THREADS
TlsSetValue(cl_env_key, env);
#else
if (pthread_setspecific(cl_env_key, env)) {
if(!ecl_process_set_tls(cl_env_key, env)) {
ecl_thread_internal_error("pthread_setspecific() failed.");
}
#endif
}
cl_object
mp_current_process(void)
{
return ecl_process_env()->own_process;
}
/*----------------------------------------------------------------------
* PROCESS LIST
*/
/* Managing the collection of processes. */
static void
extend_process_vector()
@ -166,9 +173,29 @@ ecl_process_list()
return output;
}
/*----------------------------------------------------------------------
* THREAD OBJECT
*/
/* Initialiation */
static void
init_process(void)
{
ecl_process_key_create(cl_env_key);
ecl_mutex_init(&cl_core.processes_lock, 1);
ecl_mutex_init(&cl_core.global_lock, 1);
ecl_mutex_init(&cl_core.error_lock, 1);
ecl_rwlock_init(&cl_core.global_env_lock);
}
/* -- Environment --------------------------------------------------- */
extern void ecl_init_env(struct cl_env_struct *env);
cl_object
mp_current_process(void)
{
return ecl_process_env()->own_process;
}
/* -- Thread object ------------------------------------------------- */
static void
assert_type_process(cl_object o)
@ -223,11 +250,11 @@ thread_cleanup(void *aux)
}
#ifdef ECL_WINDOWS_THREADS
static DWORD WINAPI thread_entry_point(void *arg)
static DWORD WINAPI
#else
static void *
thread_entry_point(void *arg)
static void *
#endif
thread_entry_point(void *arg)
{
cl_object process = (cl_object)arg;
cl_env_ptr env = process->process.env;
@ -333,27 +360,11 @@ ecl_import_current_thread(cl_object name, cl_object bindings)
{
struct cl_env_struct env_aux[1];
cl_object process;
pthread_t current;
ecl_thread_t current;
cl_env_ptr env;
int registered;
struct GC_stack_base stack;
#ifdef ECL_WINDOWS_THREADS
{
HANDLE aux = GetCurrentThread();
if ( !DuplicateHandle(GetCurrentProcess(),
aux,
GetCurrentProcess(),
&current,
0,
FALSE,
DUPLICATE_SAME_ACCESS) )
{
return 0;
}
}
#else
current = pthread_self();
#endif
ecl_set_process_self(current);
#ifdef GBC_BOEHM
GC_get_stack_base(&stack);
switch (GC_register_my_thread(&stack)) {
@ -374,15 +385,9 @@ ecl_import_current_thread(cl_object name, cl_object bindings)
cl_index i, size;
for (i = 0, size = processes->vector.fillp; i < size; i++) {
cl_object p = processes->vector.self.t[i];
if (!Null(p)
&&
#ifdef ECL_WINDOWS_THREADS
GetThreadId(p->process.thread) == GetThreadId(current)
#else
p->process.thread == current
#endif
)
return 0;
if (!Null(p) && ecl_process_eq(p->process.thread, current)) {
return 0;
}
}
}
/* We need a fake env to allow for interrupts blocking and to set up
@ -790,41 +795,18 @@ mp_restore_signals(cl_object sigmask)
#endif
}
/*----------------------------------------------------------------------
* INITIALIZATION
*/
/* -- Initialization ------------------------------------------------ */
void
init_threads(cl_env_ptr env)
{
cl_object process;
pthread_t main_thread;
cl_core.processes = OBJNULL;
ecl_thread_t main_thread;
init_process();
/* We have to set the environment before any allocation takes place,
* so that the interrupt handling code works. */
#if defined(ECL_WINDOWS_THREADS)
cl_env_key = TlsAlloc();
#else
pthread_key_create(&cl_env_key, NULL);
#endif
ecl_set_process_env(env);
#ifdef ECL_WINDOWS_THREADS
{
HANDLE aux = GetCurrentThread();
DuplicateHandle(GetCurrentProcess(),
aux,
GetCurrentProcess(),
&main_thread,
0,
FALSE,
DUPLICATE_SAME_ACCESS);
}
#else
main_thread = pthread_self();
#endif
ecl_set_process_self(main_thread);
process = ecl_alloc_object(t_process);
process->process.phase = ECL_PROCESS_ACTIVE;
process->process.name = @'si::top-level';
@ -837,7 +819,6 @@ init_threads(cl_env_ptr env)
ecl_cond_var_init(&process->process.exit_barrier);
env->own_process = process;
{
cl_object v = si_make_vector(ECL_T, /* Element type */
ecl_make_fixnum(256), /* Size */
@ -846,9 +827,5 @@ init_threads(cl_env_ptr env)
v->vector.self.t[0] = process;
v->vector.fillp = 1;
cl_core.processes = v;
ecl_mutex_init(&cl_core.processes_lock, 1);
ecl_mutex_init(&cl_core.global_lock, 1);
ecl_mutex_init(&cl_core.error_lock, 1);
ecl_rwlock_init(&cl_core.global_env_lock);
}
}

View file

@ -48,6 +48,8 @@ extern void init_unixtime(void);
extern void init_compiler(void);
#ifdef ECL_THREADS
extern void init_threads(cl_env_ptr);
#else
#define init_threads(env) cl_env_p = env
#endif
extern void ecl_init_env(cl_env_ptr);
extern void init_lib_LSP(cl_object);

View file

@ -929,6 +929,7 @@ struct ecl_dummy {
#ifdef ECL_THREADS
#ifdef ECL_WINDOWS_THREADS
typedef HANDLE ecl_thread_t;
typedef HANDLE ecl_mutex_t;
typedef struct ecl_cond_var_t {
HANDLE broadcast_event;
@ -937,6 +938,7 @@ typedef struct ecl_cond_var_t {
} ecl_cond_var_t;
typedef SRWLOCK ecl_rwlock_t;
#else
typedef pthread_t ecl_thread_t;
typedef pthread_mutex_t ecl_mutex_t;
typedef pthread_cond_t ecl_cond_var_t;
# ifdef HAVE_POSIX_RWLOCK
@ -975,11 +977,7 @@ struct ecl_process {
ecl_mutex_t start_stop_lock; /* phase is updated only when we hold this lock */
ecl_cond_var_t exit_barrier; /* process-join waits on this barrier */
cl_index phase;
#ifdef ECL_WINDOWS_THREADS
HANDLE thread;
#else
pthread_t thread;
#endif
ecl_thread_t thread;
int trap_fpe_bits;
};