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