[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