From 97ffe456f6b89773fd4f00df916adf517fddc83d Mon Sep 17 00:00:00 2001 From: Per Hedbor <ph@opera.com> Date: Sun, 26 Jan 1997 23:49:19 +0100 Subject: [PATCH] Added support for UNIX threads, and a new efun: thread_set_concurrency. Set the number of simultaneous LWP:s on UNIX threads systems. This function exists, but does nothing, when using Posix threads. Rev: src/threads.c:1.14 Rev: src/threads.h:1.8 --- src/threads.c | 42 +++++++++++++++++++++++++++++------- src/threads.h | 59 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 10 deletions(-) diff --git a/src/threads.c b/src/threads.c index 550489c848..e5c8cdb67d 100644 --- a/src/threads.c +++ b/src/threads.c @@ -1,5 +1,5 @@ #include "global.h" -RCSID("$Id: threads.c,v 1.13 1996/12/06 08:30:17 per Exp $"); +RCSID("$Id: threads.c,v 1.14 1997/01/26 22:49:14 per Exp $"); int num_threads = 1; int threads_disabled = 0; @@ -17,7 +17,9 @@ static struct callback *threads_evaluator_callback=0; MUTEX_T interpreter_lock = PTHREAD_MUTEX_INITIALIZER; struct program *mutex_key = 0; struct program *thread_id_prog = 0; +#ifdef POSIX_THREADS pthread_attr_t pattr; +#endif struct thread_starter { @@ -36,15 +38,16 @@ static void check_threads(struct callback *cb, void *arg, void * arg2) void *new_thread_func(void * data) { +/* static int dbt;*/ struct thread_starter arg = *(struct thread_starter *)data; JMP_BUF back; INT32 tmp; - free((char *)data); - +/* fprintf(stderr, "Thread create[%d]...",dbt++);*/ if(tmp=mt_lock( & interpreter_lock)) fatal("Failed to lock interpreter, errno %d\n",tmp); - +/* fprintf(stderr,"Created[%d]...",dbt);*/ + free((char *)data); /* Moved by per, to avoid some bugs.... */ init_interpreter(); thread_id=arg.id; @@ -59,10 +62,10 @@ void *new_thread_func(void * data) UNSET_ONERROR(tmp); } else { INT32 args=arg.args->size; - push_array_items(arg.args); - f_call_function(args); arg.args=0; + f_call_function(args); + pop_stack(); /* Discard the return value. /Per */ } UNSETJMP(back); @@ -79,14 +82,18 @@ void *new_thread_func(void * data) remove_callback(threads_evaluator_callback); threads_evaluator_callback=0; } +/* fprintf(stderr,"Done[%d]\n",dbt--);*/ mt_unlock(& interpreter_lock); th_exit(0); } +#ifdef UNIX_THREADS +int num_lwps = 1; +#endif void f_thread_create(INT32 args) { - pthread_t dummy; + THREAD_T dummy; struct thread_starter *arg; int tmp; arg=ALLOC_STRUCT(thread_starter); @@ -102,7 +109,10 @@ void f_thread_create(INT32 args) threads_evaluator_callback=add_to_callback(&evaluator_callbacks, check_threads, 0,0); } - +#ifdef UNIX_THREADS + if((num_lwps==1) || num_threads/3 > num_lwps) + th_setconcurrency(++num_lwps); +#endif push_object(arg->id); arg->id->refs++; } else { @@ -113,6 +123,16 @@ void f_thread_create(INT32 args) } } +void f_thread_set_concurrency(INT32 args) +{ + int c=1; + if(args) c=sp[-args].u.integer; + else error("No argument to thread_set_concurrency(int concurrency);\n"); + pop_n_elems(args); + num_threads=c; + th_setconcurrency(c); +} + void f_this_thread(INT32 args) { pop_n_elems(args); @@ -123,14 +143,20 @@ void f_this_thread(INT32 args) void th_init() { mt_lock( & interpreter_lock); +#ifdef POSIX_THREADS pthread_attr_init(&pattr); #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE pthread_attr_setstacksize(&pattr, 2 * 1024 * 1204); #endif pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED); +#endif add_efun("thread_create",f_thread_create,"function(mixed ...:object)", OPT_SIDE_EFFECT); +#ifdef UNIX_THREADS + add_efun("thread_set_concurrency",f_thread_set_concurrency, + "function(int:void)", OPT_SIDE_EFFECT); +#endif add_efun("this_thread",f_this_thread,"function(:object)", OPT_EXTERNAL_DEPEND); } diff --git a/src/threads.h b/src/threads.h index 74a73bb57e..6e355f07a2 100644 --- a/src/threads.h +++ b/src/threads.h @@ -7,24 +7,45 @@ #ifdef _REENTRANT +#ifdef HAVE_THREAD_H +#define UNIX_THREADS +#include <thread.h> +#undef HAVE_PTHREAD_H +#undef HAVE_THREAD_H +#endif + #ifdef HAVE_PTHREAD_H +#define POSIX_THREADS #include <pthread.h> #undef HAVE_PTHREAD_H #endif + + extern int num_threads; struct object; extern struct object *thread_id; +#define DEFINE_MUTEX(X) MUTEX_T X + + +#ifdef POSIX_THREADS +#define THREAD_T pthread_t #define MUTEX_T pthread_mutex_t #define mt_init(X) pthread_mutex_init((X),0) #define mt_lock(X) pthread_mutex_lock(X) #define mt_trylock(X) pthread_mutex_trylock(X) #define mt_unlock(X) pthread_mutex_unlock(X) #define mt_destroy(X) pthread_mutex_destroy(X) -#define DEFINE_MUTEX(X) MUTEX_T X -extern MUTEX_T interpreter_lock; +/* SIGH! No setconcurrency in posix threads. This is more or less + * needed to make usable multi-threaded programs on solaris machines + * with only one CPU. Otherwise, only systemcalls are actually + * threaded. + */ +#define th_setconcurrency(X) +#define th_yield() + #define th_create(ID,fun,arg) pthread_create(ID,&pattr,fun,arg) #define th_exit(foo) pthread_exit(foo) @@ -36,6 +57,38 @@ extern MUTEX_T interpreter_lock; #define co_signal(X) pthread_cond_signal(X) #define co_broadcast(X) pthread_cond_broadcast(X) #define co_destroy(X) pthread_cond_destroy(X) +#endif + + + + +#ifdef UNIX_THREADS +#define THREAD_T thread_t +#define PTHREAD_MUTEX_INITIALIZER DEFAULTMUTEX +#define MUTEX_T mutex_t +#define mt_init(X) mutex_init((X),USYNC_THREAD,0) +#define mt_lock(X) mutex_lock(X) +#define mt_trylock(X) mutex_trylock(X) +#define mt_unlock(X) mutex_unlock(X) +#define mt_destroy(X) mutex_destroy(X) + +#define th_setconcurrency(X) thr_setconcurrency(X) + +#define th_create(ID,fun,arg) thr_create(NULL,0,fun,arg,THR_DAEMON,ID) +#define th_exit(foo) thr_exit(foo) +#define th_self() thr_self() +#define th_yield() thr_yield() + +#define COND_T cond_t +#define co_init(X) cond_init((X),USYNC_THREAD,0) +#define co_wait(COND, MUTEX) cond_wait((COND), (MUTEX)) +#define co_signal(X) cond_signal(X) +#define co_broadcast(X) cond_broadcast(X) +#define co_destroy(X) cond_destroy(X) +#endif + +extern MUTEX_T interpreter_lock; + struct svalue; struct frame; @@ -67,6 +120,7 @@ struct thread_state { _tmp.mark_stack_malloced=mark_stack_malloced; \ _tmp.thread_id = thread_id; \ mt_unlock(& interpreter_lock); \ + /*th_yield();*/\ } #define THREADS_DISALLOW() \ @@ -108,6 +162,7 @@ void th_cleanup(); /* Prototypes end here */ #else +#define th_setconcurrency(X) #define DEFINE_MUTEX(X) #define mt_init(X) #define mt_lock(X) -- GitLab