From dc7cc90d1c9de64fbc7953a8a6ffce7c0740f712 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Wed, 14 Jan 1998 21:59:43 -0800
Subject: [PATCH] threads now works on NT

Rev: src/Makefile.in:1.51
Rev: src/builtin_functions.c:1.60
Rev: src/error.c:1.9
Rev: src/error.h:1.8
Rev: src/las.c:1.41
Rev: src/main.c:1.33
Rev: src/object.c:1.32
Rev: src/threads.c:1.52
Rev: src/threads.h:1.27
---
 src/Makefile.in         | 12 +++++----
 src/builtin_functions.c | 41 +++++++++++++++++++----------
 src/error.c             |  4 +--
 src/error.h             |  2 +-
 src/las.c               |  4 +--
 src/main.c              |  6 +++--
 src/object.c            | 39 ++++++++++++++++------------
 src/threads.c           | 57 +++++++++++++++++++++++++++++++++++++----
 src/threads.h           | 36 +++++++++++++++++---------
 9 files changed, 142 insertions(+), 59 deletions(-)

diff --git a/src/Makefile.in b/src/Makefile.in
index 6e482b1fbd..1e049c4ee5 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -161,17 +161,17 @@ install:
 	  mv -f "$(exec_prefix)/pike" "$(exec_prefix)/pike.old"; \
 	else : ; fi
 	@echo "$(exec_prefix)/pike"; $(INSTALL) ./pike $(exec_prefix)
-	@if [ -f $(SRCDIR)/../bin/hilfe ]; then \
+	@if [ -f $(TMP_BINDIR)/hilfe ]; then \
 	  echo "$(exec_prefix)/hilfe"; \
 	  if [ "$(exec_prefix)" != "/usr/local/bin" -a \
 	       "$(exec_prefix)" != "/usr/local/bin/" ]; then \
 	    if [ -f $(exec_prefix)/hilfe ]; then \
 	      mv $(exec_prefix)/hilfe $(exec_prefix)/hilfe.old; \
 	    else : ; fi && \
-	    sed -e 's!/usr/local/bin!$(exec_prefix)!' <$(SRCDIR)/../bin/hilfe \
-	      >$(exec_prefix)/hilfe && \
-	    chmod 755 $(exec_prefix)/hilfe; \
-	  else $(INSTALL) $(SRCDIR)/../bin/hilfe $(exec_prefix); fi; \
+	    sed -e 's!/usr/local/bin!$(exec_prefix)!' <$(TMP_BINDIR)/hilfe >./hilfe && \
+	    chmod 755 ./hilfe && \
+            $(INSTALL) ./hilfe $(exec_prefix) ; \
+	  else $(INSTALL) $(TMP_BINDIR)/hilfe $(exec_prefix); fi; \
 	else : ; fi
 	@for a in $(SRCDIR)/*.h *.h ; do $(INSTALL) $$a $(prefix)/include/pike ; done
 	@for f in `cd "$(TMP_LIBDIR)"; find . -type f -print`; do echo "$(lib_prefix)/$$f"; if [ -f "$(lib_prefix)/$$f" ]; then mv -f "$(lib_prefix)/$$f" "$(lib_prefix)/$$f.old"; else : ; fi; cp "$(TMP_LIBDIR)/$$f" "$(lib_prefix)/$$f"; done
@@ -239,6 +239,8 @@ feature_list:
 
 lib: $(LIBDIR_SRC) $(LIBDIR_SRC)/master.pike $(LIBDIR_SRC)/modules $(LIBDIR_SRC)/include
 	cp -r $(LIBDIR_SRC) .
+	-rm -r `find lib -type d -name CVS`
+	-rm `find lib -type f -name '*~'`
 	-touch ./lib
 
 # make export archive (requires compiled Pike)
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 5bacfdb4a2..db58e2d62f 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: builtin_functions.c,v 1.59 1998/01/13 22:56:39 hubbe Exp $");
+RCSID("$Id: builtin_functions.c,v 1.60 1998/01/15 05:59:40 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -351,26 +351,38 @@ void f_add_constant(INT32 args)
   pop_n_elems(args);
 }
 
+#ifndef __NT__
+#define IS_SEP(X) ( (X)=='/' )
+#define IS_ABS(X) (IS_SEP((X)[0])?1:0)
+#define 
+#else   
+#define IS_SEP(X) ( (X) == '/' || (X) == '\\' )
+#define IS_ABS(X) (IS_SEP((X)[0])?1:(isalpha((X)[0]) && (X)[1]==':' && IS_SEP((X)[2]))?3:0)
+#endif
+
 static char *combine_path(char *cwd,char *file)
 {
   /* cwd is supposed to be combined already */
   char *ret;
   register char *from,*to;
   char *my_cwd;
+  char cwdbuf[10];
   my_cwd=0;
   
 
-  if(file[0]=='/')
+  if(IS_ABS(file))
   {
-    cwd="/";
-    file++;
+    MEMCPY(cwdbuf,file,IS_ABS(file));
+    cwdbuf[IS_ABS(file)]=0;
+    cwd=cwdbuf;
+    file+=IS_ABS(file);
   }
 #ifdef DEBUG    
   if(!cwd)
     fatal("No cwd in combine_path!\n");
 #endif
 
-  if(!*cwd || cwd[strlen(cwd)-1]=='/')
+  if(!*cwd || IS_SEP(cwd[strlen(cwd)-1]))
   {
     ret=(char *)xalloc(strlen(cwd)+strlen(file)+1);
     strcpy(ret,cwd);
@@ -385,11 +397,11 @@ static char *combine_path(char *cwd,char *file)
   from=to=ret;
 
   /* Skip all leading "./" */
-  while(from[0]=='.' && from[1]=='/') from+=2;
+  while(from[0]=='.' && IS_SEP(from[1])) from+=2;
   
   while(( *to = *from ))
   {
-    if(*from == '/')
+    if(IS_SEP(*from))
     {
       while(to>ret && to[-1]=='/') to--;
       if(from[1] == '.')
@@ -397,15 +409,15 @@ static char *combine_path(char *cwd,char *file)
 	switch(from[2])
 	{
 	case '.':
-	  if(from[3] == '/' || from[3] == 0)
+	  if(IS_SEP(from[3]) || !from[3])
 	  {
 	    char *tmp=to;
 	    while(--tmp>=ret)
-	      if(*tmp == '/')
+	      if(IS_SEP(*tmp))
 		break;
 	    tmp++;
 
-	    if(tmp[0]=='.' && tmp[1]=='.' && (tmp[2]=='/' || !tmp[2]))
+	    if(tmp[0]=='.' && tmp[1]=='.' && (IS_SEP(tmp[2]) || !tmp[2]))
 	      break;
 	    
 	    from+=3;
@@ -416,6 +428,9 @@ static char *combine_path(char *cwd,char *file)
 
 	case 0:
 	case '/':
+#ifdef __NT__
+        case '\\':
+#endif
 	  from+=2;
 	  continue;
 	}
@@ -425,12 +440,12 @@ static char *combine_path(char *cwd,char *file)
     to++;
   }
 
-  if(*ret && from[-1]!='/' && to[-1]=='/')
+  if(*ret && !IS_SEP(from[-1]) && IS_SEP(to[-1]))
       *--to=0;
 
   if(!*ret)
   {
-    if(*cwd=='/')
+    if(IS_SEP(*cwd))
     {
       ret[0]='/';
       ret[1]=0;
@@ -598,7 +613,7 @@ void f_throw(INT32 args)
   pop_n_elems(args-1);
   throw_value=sp[-1];
   sp--;
-  throw();
+  pike_throw();
 }
 
 static struct callback_list exit_callbacks;
diff --git a/src/error.c b/src/error.c
index 94b7488867..0f192049c2 100644
--- a/src/error.c
+++ b/src/error.c
@@ -28,7 +28,7 @@ JMP_BUF *init_recovery(JMP_BUF *r)
   return r;
 }
 
-void throw(void) ATTRIBUTE((noreturn))
+void pike_throw(void) ATTRIBUTE((noreturn))
 {
   if(!recoveries)
     fatal("No error recovery context.\n");
@@ -100,7 +100,7 @@ void va_error(char *fmt, va_list args) ATTRIBUTE((noreturn))
   throw_value = *sp;
 
   in_error=0;
-  throw();  /* Hope someone is catching, or we will be out of balls. */
+  pike_throw();  /* Hope someone is catching, or we will be out of balls. */
 }
 
 void exit_on_error(void *msg)
diff --git a/src/error.h b/src/error.h
index e28b84cbfa..4ca1565d50 100644
--- a/src/error.h
+++ b/src/error.h
@@ -67,7 +67,7 @@ extern struct svalue throw_value;
 
 /* Prototypes begin here */
 JMP_BUF *init_recovery(JMP_BUF *r);
-void throw(void) ATTRIBUTE((noreturn));
+void pike_throw(void) ATTRIBUTE((noreturn));
 void va_error(char *fmt, va_list args) ATTRIBUTE((noreturn));
 void exit_on_error(void *msg);
 void fatal_on_error(void *msg);
diff --git a/src/las.c b/src/las.c
index 0f72239e06..d194fa4b59 100644
--- a/src/las.c
+++ b/src/las.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: las.c,v 1.40 1998/01/13 22:56:44 hubbe Exp $");
+RCSID("$Id: las.c,v 1.41 1998/01/15 05:59:41 hubbe Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -1867,7 +1867,7 @@ static void check_evaluation_time(struct callback *cb,void *tmp,void *ignored)
   if(foo->counter-- < 0)
   {
     foo->yes=1;
-    throw();
+    pike_throw();
   }
 }
 
diff --git a/src/main.c b/src/main.c
index 221df21c68..4433abbd1a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: main.c,v 1.32 1998/01/13 22:56:45 hubbe Exp $");
+RCSID("$Id: main.c,v 1.33 1998/01/15 05:59:42 hubbe Exp $");
 #include "fdlib.h"
 #include "backend.h"
 #include "module.h"
@@ -95,6 +95,7 @@ void main(int argc, char **argv)
   master_file = getenv("PIKE_MASTER");
 #endif
 #if __NT__
+  if(!master_file)
   {
     char buffer[4096];
     DWORD len=sizeof(buffer)-1,type=REG_SZ;
@@ -105,7 +106,7 @@ void main(int argc, char **argv)
 		       &type,
 		       buffer,
 		       &len)==ERROR_SUCCESS ||
-       RegQueryValueEx(HKEY_CURRENT_USER,
+       RegQueryValueEx(HKEY_LOCAL_MACHINE,
 		       "SOFTWARE\\Idonex\\Pike\\0.6\\PIKE_MASTER",
 		       0,
 		       &type,
@@ -116,6 +117,7 @@ void main(int argc, char **argv)
     }
   }
 #endif
+
   if(!master_file) master_file = DEFAULT_MASTER;
 
   for(e=1; e<argc; e++)
diff --git a/src/object.c b/src/object.c
index 7498e505a8..9fbae6a701 100644
--- a/src/object.c
+++ b/src/object.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: object.c,v 1.31 1998/01/13 22:56:46 hubbe Exp $");
+RCSID("$Id: object.c,v 1.32 1998/01/15 05:59:42 hubbe Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -177,24 +177,29 @@ struct object *get_master(void)
 
 
     FILE *f=fopen(master_file,"r");
-    fseek(f,0,SEEK_END);
-    len=ftell(f);
-    fseek(f,0,SEEK_SET);
-    s=begin_shared_string(len);
-    fread(s->str,1,len,f);
-    fclose(f);
-    push_string(end_shared_string(s));
-    push_text(master_file);
-    f_cpp(2);
-    f_compile(1);
-
-    if(sp[-1].type != T_PROGRAM)
+    if(f)
     {
-      pop_stack();
-      return 0;
+      fseek(f,0,SEEK_END);
+      len=ftell(f);
+      fseek(f,0,SEEK_SET);
+      s=begin_shared_string(len);
+      fread(s->str,1,len,f);
+      fclose(f);
+      push_string(end_shared_string(s));
+      push_text(master_file);
+      f_cpp(2);
+      f_compile(1);
+      
+      if(sp[-1].type != T_PROGRAM)
+      {
+	pop_stack();
+	return 0;
+      }
+      master_program=sp[-1].u.program;
+      sp--;
+    }else{
+      error("Couldn't load master program. (%s)\n",master_file);
     }
-    master_program=sp[-1].u.program;
-    sp--;
   }
   master_object=clone_object(master_program,0);
 
diff --git a/src/threads.c b/src/threads.c
index 951d67e567..18d7559813 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -1,5 +1,5 @@
 #include "global.h"
-RCSID("$Id: threads.c,v 1.51 1998/01/13 22:56:51 hubbe Exp $");
+RCSID("$Id: threads.c,v 1.52 1998/01/15 05:59:43 hubbe Exp $");
 
 int num_threads = 1;
 int threads_disabled = 0;
@@ -15,16 +15,57 @@ int threads_disabled = 0;
 #include "program.h"
 #include "gc.h"
 
+#ifdef __NT__
+
+#ifdef DEBUG
+static int IsValidHandle(HANDLE h)
+{
+  __try {
+    HANDLE ret;
+    if(DuplicateHandle(GetCurrentProcess(),
+			h,
+			GetCurrentProcess(),
+			&ret,
+			NULL,
+			0,
+			DUPLICATE_SAME_ACCESS))
+    {
+      CloseHandle(ret);
+    }
+  }
+
+  __except (1) {
+    return 0;
+  }
+
+  return 1;
+}
+
+void CheckValidHandle(HANDLE h)
+{
+  if(!IsValidHandle((HANDLE)h))
+    fatal("Invalid handle!\n");
+}
+
+#endif
+
+#endif
+
 #ifdef SIMULATE_COND_WITH_EVENT
 int co_wait(COND_T *c, MUTEX_T *m)
 {
   struct cond_t_queue me;
   event_init(&me.event);
+  me.next=0;
   mt_lock(& c->lock);
 
-  me.next=c->tail;
-  c->tail=&me;
-  if(!c->head) c->head=&me;
+  if(c->tail)
+  {
+    c->tail->next=&me;
+    c->tail=&me;
+  }else{
+    c->head=c->tail=&me;
+  }
 
   mt_unlock(& c->lock);
   mt_unlock(m);
@@ -34,6 +75,11 @@ int co_wait(COND_T *c, MUTEX_T *m)
   event_destroy(& me.event);
   /* Cancellation point?? */
 
+#ifdef DEBUG
+  if(me.next)
+    fatal("Wait on event return prematurely!!\n");
+#endif
+
   return 0;
 }
 
@@ -41,7 +87,7 @@ int co_signal(COND_T *c)
 {
   struct cond_t_queue *t;
   mt_lock(& c->lock);
-  if(t=c->head)
+  if((t=c->head))
   {
     c->head=t->next;
     t->next=0;
@@ -64,6 +110,7 @@ int co_broadcast(COND_T *c)
   while((t=n))
   {
     n=t->next;
+    t->next=0;
     event_signal(& t->event);
   }
 
diff --git a/src/threads.h b/src/threads.h
index 7288210916..2379a30884 100644
--- a/src/threads.h
+++ b/src/threads.h
@@ -161,21 +161,21 @@ extern struct object *thread_id;
 #define th_create(ID,fun,arg)  (!(*(ID)=_beginthread(fun, 2*1024*1024, arg)))
 #define th_exit(foo) _endthread(foo)
 #define th_self() GetCurrentThread()
-#define th_destroy(X) CloseHandle(*(X))
+#define th_destroy(X)
 #define th_yield() Sleep(0)
 
 #define MUTEX_T HANDLE
-#define mt_init(X) (*(X)=CreateMutex(NULL, 0, NULL))
-#define mt_lock(X) WaitForSingleObject(*(X), INFINITE)
-#define mt_trylock(X) WaitForSingleObject(*(X), 0)
-#define mt_unlock(X) ReleaseMutex(*(X))
-#define mt_destroy(X) CloseHandle(*(X))
+#define mt_init(X) CheckValidHandle((*(X)=CreateMutex(NULL, 0, NULL)))
+#define mt_lock(X) (CheckValidHandle(*(X)),WaitForSingleObject(*(X), INFINITE))
+#define mt_trylock(X) (CheckValidHandle(*(X)),WaitForSingleObject(*(X), 0))
+#define mt_unlock(X) (CheckValidHandle(*(X)),ReleaseMutex(*(X)))
+#define mt_destroy(X) (CheckValidHandle(*(X)),CloseHandle(*(X)))
 
 #define EVENT_T HANDLE
-#define event_init(X) (*(X)=CreateEvent(NULL, 1, 0, NULL))
-#define event_signal(X) SetEvent(*(X))
-#define event_destroy(X) CloseHandle(*(X))
-#define event_wait(X) WaitForSingleObject(*(X), INFINITE) 
+#define event_init(X) CheckValidHandle(*(X)=CreateEvent(NULL, 1, 0, NULL))
+#define event_signal(X) (CheckValidHandle(*(X)),SetEvent(*(X)))
+#define event_destroy(X) (CheckValidHandle(*(X)),CloseHandle(*(X)))
+#define event_wait(X) (CheckValidHandle(*(X)),WaitForSingleObject(*(X), INFINITE))
 
 #endif
 
@@ -198,7 +198,7 @@ typedef struct cond_t_s
 
 #define COND_T struct cond_t_s
 
-#define co_init(X) mt_init(& (X)->lock)
+#define co_init(X) do { mt_init(& (X)->lock), (X)->head=(X)->tail=0; }while(0)
 
 int co_wait(COND_T *c, MUTEX_T *m);
 int co_signal(COND_T *c);
@@ -338,8 +338,8 @@ struct thread_state {
 struct thread_starter;
 void *new_thread_func(void * data);
 void f_thread_create(INT32 args);
+void f_thread_set_concurrency(INT32 args);
 void f_this_thread(INT32 args);
-void th_init(void);
 struct mutex_storage;
 struct key_storage;
 void f_mutex_lock(INT32 args);
@@ -353,6 +353,11 @@ void f_cond_signal(INT32 args);
 void f_cond_broadcast(INT32 args);
 void init_cond_obj(struct object *o);
 void exit_cond_obj(struct object *o);
+void f_thread_backtrace(INT32 args);
+void f_thread_id_status(INT32 args);
+void init_thread_obj(struct object *o);
+void exit_thread_obj(struct object *o);
+void th_init(void);
 void th_cleanup(void);
 /* Prototypes end here */
 
@@ -373,6 +378,13 @@ void th_cleanup(void);
 #define th_self() ((void*)0)
 #endif /* _REENTRANT */
 
+#ifdef __NT__
+#ifndef DEBUG
+#define CheckValidHandle(X) 0
+#else
+void CheckValidHandle(HANDLE h);
+#endif
+#endif
 
 extern int threads_disabled;
 
-- 
GitLab