[kaffe] CVS kaffe (guilhem): jthread_(un)suspendall updated for openbsd (and maybe other OS too)

Kaffe CVS cvs-commits at kaffe.org
Mon Sep 20 08:54:28 PDT 2004


PatchSet 5187 
Date: 2004/09/20 15:48:40
Author: guilhem
Branch: HEAD
Tag: (none) 
Log:
jthread_(un)suspendall updated for openbsd (and maybe other OS too)

It is forbidden to send a signal in a blocking pthread call on openbsd apparently.

        * kaffe/kaffevm/thread.c
        (startSpecialThread, createDaemon): Better synchronisation with
        waitStaticCond and signalStaticCond.

        * kaffe/kaffevm/systems/unix-pthreads/lock-impl.c
        (setBlockState, clearBlockState): New functions to handle the
        blockState variable.
        (ThreadCondWait): Handles infinite wait for conditions.
        (jmutex_lock, jcondvar_wait): Updated to use the new helper functions.

        * kaffe/kaffevm/systems/unix-pthreads/thread-impl.c
        (incrPointer): New helper function to fix some warnings in
        jthread_relaxstack.
        (KaffePThread_WaitForResume): New helper function to sleep a
        little more if the thread is still in suspend state.
        (jthread_unsuspendall, jthread_suspendall): Now we take care of
        already blocked thread in mutexes or conditions.
        (jthread_create): Initialize suspendLock.
        (tDispose): Destroy suspendLock.

        * kaffe/kaffevm/systems/unix-pthreads/thread-impl.h
        (jthread_t): New field suspendLock.
        (KaffePThread_WaitForResume, detectStackBoundaries): Added prototypes.

Members: 
	ChangeLog:1.2742->1.2743 
	kaffe/kaffevm/thread.c:1.72->1.73 
	kaffe/kaffevm/systems/unix-pthreads/lock-impl.c:1.9->1.10 
	kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:1.40->1.41 
	kaffe/kaffevm/systems/unix-pthreads/thread-internal.h:1.18->1.19 

Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.2742 kaffe/ChangeLog:1.2743
--- kaffe/ChangeLog:1.2742	Mon Sep 20 14:41:36 2004
+++ kaffe/ChangeLog	Mon Sep 20 15:48:40 2004
@@ -1,3 +1,29 @@
+2004-09-20  Guilhem Lavaux  <guilhem at kaffe.org>
+
+	* kaffe/kaffevm/thread.c
+	(startSpecialThread, createDaemon): Better synchronisation with
+	waitStaticCond and signalStaticCond.
+
+	* kaffe/kaffevm/systems/unix-pthreads/lock-impl.c
+	(setBlockState, clearBlockState): New functions to handle the
+	blockState variable.
+	(ThreadCondWait): Handles infinite wait for conditions.
+	(jmutex_lock, jcondvar_wait): Updated to use the new helper functions.
+
+	* kaffe/kaffevm/systems/unix-pthreads/thread-impl.c
+	(incrPointer): New helper function to fix some warnings in
+	jthread_relaxstack.
+	(KaffePThread_WaitForResume): New helper function to sleep a
+	little more if the thread is still in suspend state.
+	(jthread_unsuspendall, jthread_suspendall): Now we take care of
+	already blocked thread in mutexes or conditions.
+	(jthread_create): Initialize suspendLock.
+	(tDispose): Destroy suspendLock.
+
+	* kaffe/kaffevm/systems/unix-pthreads/thread-impl.h
+	(jthread_t): New field suspendLock.
+	(KaffePThread_WaitForResume, detectStackBoundaries): Added prototypes.
+	
 2004-09-20  Dalibor Topic  <robilad at kaffe.org>
 
 	* libraries/clib/awt/classpath-gtk/classpath/Makefile.am:
Index: kaffe/kaffe/kaffevm/thread.c
diff -u kaffe/kaffe/kaffevm/thread.c:1.72 kaffe/kaffe/kaffevm/thread.c:1.73
--- kaffe/kaffe/kaffevm/thread.c:1.72	Tue Aug 24 17:59:41 2004
+++ kaffe/kaffe/kaffevm/thread.c	Mon Sep 20 15:48:45 2004
@@ -285,6 +285,7 @@
 	ksemInit(&THREAD_DATA()->sem);
 
 	lockStaticMutex(&thread_start_lock);
+	signalStaticCond(&thread_start_lock);
 	unlockStaticMutex(&thread_start_lock);
 
 	func = (void *)THREAD_DATA()->exceptPtr;
@@ -347,6 +348,8 @@
   
   jthread_get_data(nativeTid)->exceptPtr = func;
   jthread_get_data(nativeTid)->exceptObj = arg;
+
+  waitStaticCond(&thread_start_lock, (jlong)0);
   
   unlockStaticMutex(&thread_start_lock);
   
Index: kaffe/kaffe/kaffevm/systems/unix-pthreads/lock-impl.c
diff -u kaffe/kaffe/kaffevm/systems/unix-pthreads/lock-impl.c:1.9 kaffe/kaffe/kaffevm/systems/unix-pthreads/lock-impl.c:1.10
--- kaffe/kaffe/kaffevm/systems/unix-pthreads/lock-impl.c:1.9	Mon Aug  2 10:45:05 2004
+++ kaffe/kaffe/kaffevm/systems/unix-pthreads/lock-impl.c	Mon Sep 20 15:48:45 2004
@@ -20,17 +20,54 @@
 #include "boehm-gc/boehm/include/gc.h"
 #endif
 
+static inline void
+setBlockState(jthread_t cur, unsigned int newState, void *sp)
+{
+  pthread_mutex_lock(&cur->suspendLock);
+  cur->blockState |= newState;
+  cur->stackCur  = sp;
+  pthread_mutex_unlock(&cur->suspendLock);
+}
+
+static inline void
+clearBlockState(jthread_t cur, unsigned int newState)
+{
+  pthread_mutex_lock(&cur->suspendLock);
+  cur->blockState &= ~newState;
+  if (cur->suspendState == SS_SUSPENDED)
+    {
+      DBG(JTHREADDETAIL, dprintf("Changing blockstate of %p to %d while in suspend, block again\n",  cur, newState))
+
+      KaffePThread_WaitForResume(true);
+    }
+  else
+    {
+      cur->stackCur = NULL;
+      pthread_mutex_unlock(&cur->suspendLock);
+    }
+}
+
 void
 jmutex_lock( jmutex* lk )
 {
   jthread_t cur = jthread_current ();
 
-  cur->stackCur  = (void*)&cur;
-  cur->blockState |= BS_MUTEX;
-
+  setBlockState(cur, BS_MUTEX, (void*)&cur);
   pthread_mutex_lock( lk );
+  clearBlockState(cur, BS_MUTEX);
+}
+
+
+static inline int
+ThreadCondWait(jthread_t cur, jcondvar *cv, jmutex *mux)
+{
+  int status;
 
-  cur->blockState &= ~BS_MUTEX;
+  setBlockState(cur, BS_CV, (void*)&cur);
+  status = pthread_cond_wait( cv, mux );
+  clearBlockState(cur, BS_CV);
+
+  return status;
 }
 
 /*
@@ -44,43 +81,42 @@
   int             status;
   struct timespec abst;
   struct timeval  now;
-
   //CHECK_LOCK( cur,lk);
 
-  cur->stackCur  = (void*)&cur;
-  jthread_current()->interrupting = 0;
+  cur->interrupting = 0;
 
-  if ( timeout == NOTIMEOUT ) {
-	/* we handle this as "wait forever"	*/
-	cur->blockState |= BS_CV;
-	status = pthread_cond_wait( cv, mux );
-	cur->blockState &= ~BS_CV;
-  }
-  else {
-	/* timeout is in millisecs, timeval in microsecs, and timespec in nanosecs */
-	gettimeofday( &now, 0);
-	abst.tv_sec = now.tv_sec + (timeout / 1000);
-	if( abst.tv_sec < now.tv_sec ) {
-	    /* huge timeout value, we handle this as "wait forever" */
-	    cur->blockState |= BS_CV;
-	    status = pthread_cond_wait( cv, mux );
-	    cur->blockState &= ~BS_CV;
+  if ( timeout == NOTIMEOUT )
+    {
+      /* we handle this as "wait forever"	*/
+      status = ThreadCondWait(cur, cv, mux);
+    }
+  else
+    {
+      /* timeout is in millisecs, timeval in microsecs, and timespec in nanosecs */
+      gettimeofday( &now, 0);
+      abst.tv_sec = now.tv_sec + (timeout / 1000);
+      if( abst.tv_sec < now.tv_sec )
+	{
+	  /* huge timeout value, we handle this as "wait forever" */
+	  status = ThreadCondWait(cur, cv, mux);
 	}
-	else {
-	    abst.tv_nsec = (now.tv_usec * 1000) + (timeout % 1000) * 1000000;
-	    
-	    if (abst.tv_nsec > 1000000000) {
-                abst.tv_sec  += 1;
-                abst.tv_nsec -= 1000000000;
+      else
+	{
+	  abst.tv_nsec = (now.tv_usec * 1000) + (timeout % 1000) * 1000000;
+	  
+	  if (abst.tv_nsec > 1000000000)
+	    {
+	      abst.tv_sec  += 1;
+	      abst.tv_nsec -= 1000000000;
 	    }
-	    
-	    cur->blockState |= BS_CV_TO;
-	    status = pthread_cond_timedwait( cv, mux, &abst);
-	    cur->blockState &= ~BS_CV_TO;
+
+	  setBlockState(cur, BS_CV_TO, (void*)&cur);
+	  status = pthread_cond_timedwait( cv, mux, &abst);
+	  clearBlockState(cur, BS_CV_TO);
 	}
+    }
 
-  }
-  jthread_current()->interrupting = (status == EINTR);
+  cur->interrupting = (status == EINTR);
   
   return (status == 0);
 }
Index: kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c
diff -u kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:1.40 kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:1.41
--- kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:1.40	Sun Aug 29 23:43:23 2004
+++ kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c	Mon Sep 20 15:48:45 2004
@@ -821,7 +821,8 @@
 	nt->stackMax     = 0;
 	nt->stackCur     = 0;
 	nt->daemon	 = isDaemon;
-
+	pthread_mutex_init(&nt->suspendLock, NULL);
+	
 	DBG( JTHREAD, TMSG_SHORT( "create new ", nt))
 
 	/* init our cv and mux fields for locking */
@@ -888,6 +889,7 @@
 void tDispose ( jthread_t nt )
 {
   pthread_detach( nt->tid);
+  pthread_mutex_destroy (&nt->suspendLock);
 
   sem_destroy( &nt->sem);
 
@@ -1035,6 +1037,36 @@
  * the suspend/resume mechanism
  */
 
+void KaffePThread_WaitForResume(int releaseMutex)
+{
+  volatile jthread_t cur = jthread_current();
+  int s;
+  sigset_t oldset;
+
+  if (releaseMutex)
+    {
+      pthread_sigmask(SIG_SETMASK, &suspendSet, &oldset);
+      pthread_mutex_unlock(&cur->suspendLock);
+    }
+
+  /* freeze until we get a subsequent sigResume */
+  while( cur->suspendState == SS_SUSPENDED )
+    sigwait( &suspendSet, &s);
+  
+  DBG( JTHREADDETAIL, dprintf("sigwait return: %p\n", cur))
+    
+  cur->stackCur     = 0;
+  cur->suspendState = 0;
+  
+  /* notify the critSect owner we are leaving the handler */
+  sem_post( &critSem);
+
+  if (releaseMutex)
+    {
+      pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+    }
+}
+
 /*
  * The suspend signal handler, which we need to implement critical sections.
  * It is used for two purposes: (a) to block all active threads which might
@@ -1049,7 +1081,7 @@
 {
   volatile jthread_t   cur = jthread_current();
 
-  DBG( JTHREADDETAIL, dprintf("suspend signal handler: %p\n", cur))
+  DBG( JTHREAD, dprintf("suspend signal handler: %p\n", cur))
 
   /* signals are global things and might come from everywhere, anytime */
   if ( !cur || !cur->active )
@@ -1057,7 +1089,6 @@
 
   if ( cur->suspendState == SS_PENDING_SUSPEND ){
 	JTHREAD_JMPBUF env;
-	int s;
 
 	/*
 	 * Note: We're not gonna do a longjmp to this place, we just want
@@ -1072,17 +1103,7 @@
 	/* notify the critSect owner that we are now suspending in the handler */
 	sem_post( &critSem);
 
-	/* freeze until we get a subsequent sigResume */
-	while( cur->suspendState == SS_SUSPENDED )
-		sigwait( &suspendSet, &s);
-
-	DBG( JTHREADDETAIL, dprintf("sigwait return: %p\n", cur))
-
-	cur->stackCur     = 0;
-	cur->suspendState = 0;
-
-	/* notify the critSect owner we are leaving the handler */
-	sem_post( &critSem);
+	KaffePThread_WaitForResume(false);
   }
 }
 
@@ -1096,7 +1117,6 @@
   /* we don't do anything, here - all the action is in the suspend handler */
 }
 
-
 /*
  * Temporarily suspend all threads but the current one. This is
  * a dangerous operation, but it is more safe than to rely on
@@ -1111,7 +1131,7 @@
 {
   int		status;
   jthread_t	cur = jthread_current();
-  jthread_t	t;
+  volatile jthread_t	t;
   int		iLockRoot;
  
   /* don't allow any new thread to be created or recycled until this is done */
@@ -1129,21 +1149,36 @@
 	   * signals handled by threads which are blocked on someting else
 	   * than the thread lock (which we soon release)
 	   */
-	  if ( (t != cur) && (t->suspendState == 0) && (t->active) ) {
-		DBG( JTHREADDETAIL, dprintf("signal suspend: %p (susp: %d blk: %d)\n",
-					    t, t->suspendState, t->blockState))
+	  if ( (t != cur) && (t->suspendState == 0) && (t->active != 0) ) {
+		DBG( JTHREAD, dprintf("signal suspend: %p (susp: %d blk: %d)\n",
+				      t, t->suspendState, t->blockState))
+
+		pthread_mutex_lock(&t->suspendLock);
 		t->suspendState = SS_PENDING_SUSPEND;
 
-		if ( (status = pthread_kill( t->tid, sigSuspend)) ){
-		  DBG( JTHREAD, dprintf("error sending SUSPEND signal to %p: %d\n", t, status))
-		}
-		else {
-		  /* BAD: Empirical workaround for lost signals (with accumulative syncing)
-		   * It shouldn't be necessary (posix sems are accumulative), and it
-		   * is bad, performancewise (at least n*2 context switches per suspend)
-		   * but it works more reliably on linux 2.2.x */
-		  sem_wait( &critSem);
-		}
+		if ((t->blockState & (BS_CV|BS_MUTEX|BS_CV_TO)) != 0)
+		  {
+		    /* The thread is already stopped.
+		     */
+		    assert(t->stackCur != NULL);
+		    t->suspendState = SS_SUSPENDED;
+		  }
+		else
+		  {
+		    if ((status = pthread_kill( t->tid, sigSuspend)) != 0)
+		      {
+			DBG( JTHREAD, dprintf("error sending SUSPEND signal to %p: %d\n", t, status));
+		      }
+		    else
+		      {
+			/* BAD: Empirical workaround for lost signals (with accumulative syncing)
+			 * It shouldn't be necessary (posix sems are accumulative), and it
+			 * is bad, performancewise (at least n*2 context switches per suspend)
+			 * but it works more reliably on linux 2.2.x */
+			sem_wait( &critSem);
+		      }
+		  }
+		pthread_mutex_unlock(&t->suspendLock);
 	  }
 	}
 
@@ -1191,26 +1226,38 @@
 
 #if !defined(KAFFE_BOEHM_GC)
 	for ( t=activeThreads; t; t = t->next ){
-	  if ( t->suspendState & (SS_PENDING_SUSPEND | SS_SUSPENDED) ){
-
-		DBG( JTHREAD, dprintf("signal resume: %p (sus: %d blk: %d)\n",
-				      t, t->suspendState, t->blockState))
-
-		t->suspendState = SS_PENDING_RESUME;
-		status = pthread_kill( t->tid, sigResume);
-		if ( status ) {
-		  DBG( JTHREAD, dprintf("error sending RESUME signal to %p: %d\n", t, status))
+	  pthread_mutex_lock(&t->suspendLock);
+	  if ( (t->suspendState & (SS_PENDING_SUSPEND | SS_SUSPENDED)) != 0 )
+	    {
+	      
+	      DBG( JTHREAD, dprintf("signal resume: %p (sus: %d blk: %d)\n",
+				    t, t->suspendState, t->blockState))
+
+	      t->suspendState = SS_PENDING_RESUME;
+	      if ((t->blockState & (BS_CV|BS_CV_TO|BS_MUTEX)) == 0)
+		{
+		  DBG (JTHREADDETAIL, dprintf("  sending sigResume\n"))
+		  status = pthread_kill( t->tid, sigResume);
+		  if ( status )
+		    {
+		      DBG( JTHREAD, dprintf("error sending RESUME signal to %p: %d\n", t, status))
+		    }		  
+		  /* ack wait workaround, see TentercritSect remarks */
+		  sem_wait( &critSem);
 		}
-
-		/* ack wait workaround, see TentercritSect remarks */
-		sem_wait( &critSem);
-	  }
+	      else
+		{
+		  DBG (JTHREADDETAIL, dprintf("  clearing suspendState\n"))
+		  t->suspendState = 0;
+		}
+	    }
+	  pthread_mutex_unlock(&t->suspendLock);
 	}
 
 #else
 	for ( t=activeThreads; t; t = t->next ){
 	  if ( t->suspendState & (SS_PENDING_SUSPEND | SS_SUSPENDED) ){
-		t->suspendState = SS_PENDING_RESUME;
+		t->suspendState = 0;
 	  }
 	}
 
@@ -1218,14 +1265,6 @@
 
 #endif
 
-#ifdef NEVER
-	/* wait until all signals we've sent out have been handled */
-	while ( nResumes ){
-	  sem_wait( &critSem);
-	  nResumes--;
-	}
-#endif
-
 	TUNLOCK( cur); /*----------------------------------------------------- tLock */
   }
 
@@ -1300,22 +1339,28 @@
  * Get the current stack limit.
  * Adapted from kaffe/kaffevm/systems/unix-jthreads/jthread.h
  */
+
+static inline void incrPointer(void **p, int inc)
+{
+  *p = (void *)((uintp)*p + inc);
+}
+
 void jthread_relaxstack(int yes)
 {
   if( yes )
     {
 #if defined(STACK_GROWS_UP)
-      (uintp)jthread_current()->stackMax += STACKREDZONE;
+      incrPointer(&jthread_current()->stackMax, STACKREDZONE);
 #else
-      (uintp)jthread_current()->stackMin -= STACKREDZONE;
+      incrPointer(&jthread_current()->stackMin, -STACKREDZONE);
 #endif
     }
   else
     {
 #if defined(STACK_GROWS_UP)
-      (uintp)jthread_current()->stackMax -= STACKREDZONE;
+      incrPointer(&jthread_current()->stackMax, -STACKREDZONE);
 #else
-      (uintp)jthread_current()->stackMin += STACKREDZONE;
+      incrPointer(&jthread_current()->stackMin, STACKREDZONE);
 #endif
     }
 }
Index: kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-internal.h
diff -u kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-internal.h:1.18 kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-internal.h:1.19
--- kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-internal.h:1.18	Tue Aug 24 11:34:46 2004
+++ kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-internal.h	Mon Sep 20 15:48:45 2004
@@ -55,6 +55,9 @@
   pthread_t             tid;
   pthread_attr_t        attr;
 
+  /* To release the lock */
+  pthread_mutex_t       suspendLock;
+
   /* wether this is a daemon thread */
   int			daemon;
   int                   interrupting;
@@ -420,5 +423,9 @@
 int jthread_is_interrupted(jthread_t jt);
 
 int jthread_interrupted(jthread_t jt);
+
+void KaffePThread_WaitForResume(int releaseMutex);
+
+void detectStackBoundaries(jthread_t jtid, int mainThreadStackSize);
 
 #endif /* __thread_impl_h */




More information about the kaffe mailing list