core: factor out process managament from thread managament

This is a preliminary step towards coroutines and for switching global env in
single-threaded builds.
This commit is contained in:
Daniel Kochmański 2025-03-27 15:07:46 +01:00
parent f49cc7f3fd
commit 0f4e9b1e17
13 changed files with 123 additions and 67 deletions

View file

@ -12,7 +12,7 @@ ECL_FPE_CODE=fpe_x86.c
!if "$(ECL_THREADS)" != ""
ECL_THREADS_FLAG=1
THREADS_OBJ= process.obj mutex.obj condition_variable.obj rwlock.obj \
THREADS_OBJ= thread.obj mutex.obj condition_variable.obj rwlock.obj \
semaphore.obj barrier.obj mailbox.obj atomic.obj
!else
ECL_THREADS_FLAG=0
@ -111,7 +111,7 @@ OBJS = main.obj symbol.obj package.obj cons.obj list.obj\
time.obj unixint.obj memory.obj \
mapfun.obj multival.obj hash.obj format.obj pathname.obj\
structure.obj load.obj unixfsys.obj unixsys.obj \
ffi.obj alloc_2.obj tcp.obj $(THREADS_OBJ) serialize.obj \
ffi.obj alloc_2.obj tcp.obj $(THREADS_OBJ) process.obj serialize.obj \
$(ECL_UCD_OBJ) $(ECL_SSE_OBJ)
all: $(DPP) ..\eclmin.lib ..\cinit.obj

2
src/aclocal.m4 vendored
View file

@ -267,7 +267,7 @@ THREAD_CFLAGS=''
THREAD_LIBS=''
THREAD_GC_FLAGS='--enable-threads=posix'
INSTALL_TARGET='install'
THREAD_OBJ="$THREAD_OBJ threads/process threads/mutex threads/condition_variable threads/semaphore threads/barrier threads/mailbox threads/rwlock"
THREAD_OBJ="$THREAD_OBJ threads/thread threads/mutex threads/condition_variable threads/semaphore threads/barrier threads/mailbox threads/rwlock"
clibs='-lm'
SONAME=''
SONAME_LDFLAGS=''

View file

@ -75,7 +75,7 @@ OBJS = main.o symbol.o package.o cons.o list.o apply.o eval.o \
cmpaux.o macros.o backq.o stacks.o time.o unixint.o mapfun.o \
multival.o hash.o format.o pathname.o structure.o load.o \
unixfsys.o unixsys.o serialize.o ffi.o sse2.o @EXTRA_OBJS@ \
threads/atomic.o
threads/atomic.o process.o
.PHONY: all

View file

@ -483,6 +483,7 @@ cl_boot(int argc, char **argv)
setbuf(stdin, stdin_buf);
setbuf(stdout, stdout_buf);
#endif
init_process();
ARGC = argc;
ARGV = argv;
@ -492,7 +493,9 @@ cl_boot(int argc, char **argv)
init_alloc();
GC_disable();
env = cl_core.first_env;
init_threads(env);
#ifdef ECL_THREADS
init_threads();
#endif
/*
* 1) Initialize symbols and packages

104
src/c/process.d Normal file
View file

@ -0,0 +1,104 @@
/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/* vim: set filetype=c tabstop=2 shiftwidth=2 expandtab: */
/*
* process.c - managing the process environment(s)
*
* Copyright (c) 2003 Juan Jose Garcia Ripoll
* Copyright (c) 2023 Daniel Kochmański
*
* See file 'LICENSE' for the copyright details.
*
*/
#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
#include <errno.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#ifdef ECL_WINDOWS_THREADS
# include <windows.h>
#else
# include <pthread.h>
#endif
#ifdef HAVE_GETTIMEOFDAY
# include <sys/time.h>
#endif
#ifdef HAVE_SCHED_H
# include <sched.h>
#endif
/* -- Thread-local variables ------------------------------------------------ */
#ifdef ECL_THREADS
# ifdef ECL_WINDOWS_THREADS
# 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)
# else
# 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)
# endif /* ECL_WINDOWS_THREADS */
/* Accessing a thread-local variable representing the environment. */
ecl_process_key_t cl_env_key;
cl_env_ptr
ecl_process_env_unsafe(void)
{
return ecl_process_get_tls(cl_env_key);
}
cl_env_ptr
ecl_process_env(void)
{
cl_env_ptr rv = ecl_process_get_tls(cl_env_key);
if(!rv) {
ecl_thread_internal_error("pthread_getspecific() failed.");
}
return rv;
}
void
ecl_set_process_env(cl_env_ptr env)
{
if(!ecl_process_set_tls(cl_env_key, env)) {
ecl_thread_internal_error("pthread_setspecific() failed.");
}
}
#else
/* The current global environment for single-threaded builds. */
cl_env_ptr cl_env_p = NULL;
#endif /* ECL_THREADS */
/* -- Initialiation --------------------------------------------------------- */
void
init_process(void)
{
cl_env_ptr env = cl_core.first_env;
#ifdef ECL_THREADS
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);
#endif
ecl_set_process_env(env);
env->default_sigmask = NULL;
env->method_cache = NULL;
env->slot_cache = NULL;
env->interrupt_struct = NULL;
env->disable_interrupts = 1;
}

0
src/c/threads/atomic.d Executable file → Normal file
View file

0
src/c/threads/barrier.d Executable file → Normal file
View file

0
src/c/threads/mailbox.d Executable file → Normal file
View file

0
src/c/threads/mutex.d Executable file → Normal file
View file

64
src/c/threads/process.d → src/c/threads/thread.d Executable file → Normal file
View file

@ -2,7 +2,7 @@
/* vim: set filetype=c tabstop=2 shiftwidth=2 expandtab: */
/*
* process.d - native threads
* thread.d - native threads
*
* Copyright (c) 2003 Juan Jose Garcia Ripoll
*
@ -37,10 +37,6 @@
/* -- Macros -------------------------------------------------------- */
#ifdef ECL_WINDOWS_THREADS
# 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) \
{ \
@ -54,46 +50,12 @@
DUPLICATE_SAME_ACCESS); \
}
#else
# 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 */
/* -- Core ---------------------------------------------------------- */
/* Accessing a thread-local variable representing the environment. */
ecl_process_key_t cl_env_key;
cl_env_ptr
ecl_process_env_unsafe(void)
{
return ecl_process_get_tls(cl_env_key);
}
cl_env_ptr
ecl_process_env(void)
{
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)
{
if(!ecl_process_set_tls(cl_env_key, env)) {
ecl_thread_internal_error("pthread_setspecific() failed.");
}
}
/* Managing the collection of processes. */
static void
extend_process_vector()
{
@ -173,18 +135,6 @@ ecl_process_list()
return output;
}
/* 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);
@ -372,8 +322,7 @@ ecl_import_current_thread(cl_object name, cl_object bindings)
registered = 1;
break;
case GC_DUPLICATE:
/* Thread was probably created using the GC hooks
* for thread creation */
/* Thread was probably created using the GC hooks for thread creation. */
registered = 0;
break;
default:
@ -797,14 +746,13 @@ mp_restore_signals(cl_object sigmask)
/* -- Initialization ------------------------------------------------ */
void
init_threads(cl_env_ptr env)
init_threads()
{
cl_env_ptr the_env = ecl_process_env();
cl_object process;
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. */
ecl_set_process_env(env);
ecl_set_process_self(main_thread);
process = ecl_alloc_object(t_process);
process->process.phase = ECL_PROCESS_ACTIVE;
@ -812,12 +760,12 @@ init_threads(cl_env_ptr env)
process->process.function = ECL_NIL;
process->process.args = ECL_NIL;
process->process.thread = main_thread;
process->process.env = env;
process->process.env = the_env;
process->process.woken_up = ECL_NIL;
ecl_mutex_init(&process->process.start_stop_lock, TRUE);
ecl_cond_var_init(&process->process.exit_barrier);
env->own_process = process;
the_env->own_process = process;
{
cl_object v = si_make_vector(ECL_T, /* Element type */
ecl_make_fixnum(256), /* Size */

2
src/configure vendored
View file

@ -6096,7 +6096,7 @@ THREAD_CFLAGS=''
THREAD_LIBS=''
THREAD_GC_FLAGS='--enable-threads=posix'
INSTALL_TARGET='install'
THREAD_OBJ="$THREAD_OBJ threads/process threads/mutex threads/condition_variable threads/semaphore threads/barrier threads/mailbox threads/rwlock"
THREAD_OBJ="$THREAD_OBJ threads/thread threads/mutex threads/condition_variable threads/semaphore threads/barrier threads/mailbox threads/rwlock"
clibs='-lm'
SONAME=''
SONAME_LDFLAGS=''

View file

@ -161,10 +161,12 @@ struct ecl_interrupt_struct {
# define cl_env (*ecl_process_env())
extern ECL_API cl_env_ptr ecl_process_env(void) __attribute__((const));
extern ECL_API cl_env_ptr ecl_process_env_unsafe(void);
extern ECL_API void ecl_set_process_env(cl_env_ptr env);
#else
# define cl_env (*cl_env_p)
# define ecl_process_env() cl_env_p
# define ecl_process_env_unsafe() cl_env_p
# define ecl_set_process_env(env) cl_env_p = env
extern ECL_API cl_env_ptr cl_env_p;
#endif

View file

@ -40,10 +40,9 @@ extern void init_stacks(cl_env_ptr);
extern void init_unixint(int pass);
extern void init_unixtime(void);
extern void init_compiler(void);
extern void init_process(void);
#ifdef ECL_THREADS
extern void init_threads(cl_env_ptr);
#else
#define init_threads(env) cl_env_p = env
extern void init_threads(void);
#endif
extern void ecl_init_env(cl_env_ptr);
extern void init_lib_LSP(cl_object);