[kaffe] CVS kaffe (guilhem): Fixed two race conditions in kaffe's thread system.

Kaffe CVS cvs-commits at kaffe.org
Wed Oct 20 09:52:39 PDT 2004


PatchSet 5315 
Date: 2004/10/20 16:47:11
Author: guilhem
Branch: HEAD
Tag: (none) 
Log:
Fixed two race conditions in kaffe's thread system.

	* kaffe/kaffevm/gc.h
	(KGC_ALLOC_STATIC_THREADDATA): New type.

	* kaffe/kaffevm/gcFuncs.c
	(initCollector): KGC_ALLOC_THREADCTX is now collectable. Register
	KGC_ALLOC_STATIC_THREADDATA.

	* kaffe/kaffevm/ksem.c
	(ksemGet): Doxified ksemGet.

	* kaffe/kaffevm/thread.c
	(thread_start_lock): Removed.
	(createThread): Take the argument of the thread.
	(startThread, createDaemon):
	Use directly ksems to handle the start synchronization.
	(startSpecialThread, firstStartThread): Updated the start
	synchronization to use ksem (retrieve the creating thread from the
	arguments).
	(initNativeThreads): Pass a pointer to the global garbage
	collector directly.

	Synchronization problem reported by Helmer Kraemer
	<hkraemer at freenet.de>.

	* kaffe/kaffevm/systems/unix-jthreads/jthread.c
	(threadCollector): New reference to the collector to use for
	thread handling.
	(allocator, deallocator): Removed.
	(newThreadCtx): Use the collector to allocate the thread context
	and add a static reference to it.
	(jthread_destroy): Remove the static reference to the thread
	context.
	(thread_static_allocator, thread_static_free, thread_reallocator):
	Fixed memory block allocators.
	(jthread_init): Updated prototype.
	Removed various warnings.

	* kaffe/kaffevm/systems/unix-jthreads/jthread.h
	(jthread_init): Updated prototype.

	* kaffe/kaffevm/systems/unix-pthreads/thread-impl.c
	(threadCollector): New reference to the collector to use for
	thread handling.
	(threadDestructor): Handle thread destruction advertising.
	(thread_malloc): Allocate a collectable memory region.
	(tSetupFirstNative, jthread_create): Add a static reference to the
	thread context.
	(jthread_init): Updated prototype.
	(tRun): Signal thread destruction.
	(tDispose): Do not free explicitly the thread context, just delete
	the reference to it.

	* kaffe/kaffevm/systems/unix-pthreads/thread-internal.h
	(jthread_init): Updated prototype.

Members: 
	ChangeLog:1.2867->1.2868 
	kaffe/kaffevm/gc.h:1.26->1.27 
	kaffe/kaffevm/gcFuncs.c:1.57->1.58 
	kaffe/kaffevm/ksem.c:1.8->1.9 
	kaffe/kaffevm/thread.c:1.77->1.78 
	kaffe/kaffevm/systems/unix-jthreads/jthread.c:1.122->1.123 
	kaffe/kaffevm/systems/unix-jthreads/jthread.h:1.62->1.63 
	kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:1.48->1.49 
	kaffe/kaffevm/systems/unix-pthreads/thread-internal.h:1.20->1.21 

Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.2867 kaffe/ChangeLog:1.2868
--- kaffe/ChangeLog:1.2867	Wed Oct 20 16:17:48 2004
+++ kaffe/ChangeLog	Wed Oct 20 16:47:11 2004
@@ -1,3 +1,60 @@
+2004-10-20  Guilhem Lavaux  <guilhem at kaffe.org>
+
+	* kaffe/kaffevm/gc.h
+	(KGC_ALLOC_STATIC_THREADDATA): New type.
+
+	* kaffe/kaffevm/gcFuncs.c
+	(initCollector): KGC_ALLOC_THREADCTX is now collectable. Register
+	KGC_ALLOC_STATIC_THREADDATA.
+
+	* kaffe/kaffevm/ksem.c
+	(ksemGet): Doxified ksemGet.
+
+	* kaffe/kaffevm/thread.c
+	(thread_start_lock): Removed.
+	(createThread): Take the argument of the thread.
+	(startThread, createDaemon):
+	Use directly ksems to handle the start synchronization.
+	(startSpecialThread, firstStartThread): Updated the start
+	synchronization to use ksem (retrieve the creating thread from the
+	arguments).
+	(initNativeThreads): Pass a pointer to the global garbage
+	collector directly.
+
+	Synchronization problem reported by Helmer Kraemer
+	<hkraemer at freenet.de>.
+	
+	* kaffe/kaffevm/systems/unix-jthreads/jthread.c
+	(threadCollector): New reference to the collector to use for
+	thread handling.
+	(allocator, deallocator): Removed.
+	(newThreadCtx): Use the collector to allocate the thread context
+	and add a static reference to it.
+	(jthread_destroy): Remove the static reference to the thread
+	context.
+	(thread_static_allocator, thread_static_free, thread_reallocator):
+	Fixed memory block allocators.
+	(jthread_init): Updated prototype.
+	Removed various warnings.
+
+	* kaffe/kaffevm/systems/unix-jthreads/jthread.h
+	(jthread_init): Updated prototype.
+
+	* kaffe/kaffevm/systems/unix-pthreads/thread-impl.c
+	(threadCollector): New reference to the collector to use for
+	thread handling.
+	(threadDestructor): Handle thread destruction advertising.
+	(thread_malloc): Allocate a collectable memory region.
+	(tSetupFirstNative, jthread_create): Add a static reference to the
+	thread context.
+	(jthread_init): Updated prototype.
+	(tRun): Signal thread destruction.
+	(tDispose): Do not free explicitly the thread context, just delete
+	the reference to it.
+
+	* kaffe/kaffevm/systems/unix-pthreads/thread-internal.h
+	(jthread_init): Updated prototype.
+	
 2004-10-20  Helmer Kraemer  <hkraemer at freenet.de>
 
 	* config/arm/sysdepCallMethod.h (sysdepCallMethod): fix
Index: kaffe/kaffe/kaffevm/gc.h
diff -u kaffe/kaffe/kaffevm/gc.h:1.26 kaffe/kaffe/kaffevm/gc.h:1.27
--- kaffe/kaffe/kaffevm/gc.h:1.26	Mon Aug  2 10:44:56 2004
+++ kaffe/kaffe/kaffevm/gc.h	Wed Oct 20 16:47:13 2004
@@ -79,6 +79,7 @@
 	KGC_ALLOC_UTF8CONST,
 	KGC_ALLOC_LOCK,
 	KGC_ALLOC_THREADCTX,
+	KGC_ALLOC_STATIC_THREADDATA,
 	KGC_ALLOC_REF,
 	KGC_ALLOC_JAR,
 	KGC_ALLOC_CODEANALYSE,
Index: kaffe/kaffe/kaffevm/gcFuncs.c
diff -u kaffe/kaffe/kaffevm/gcFuncs.c:1.57 kaffe/kaffe/kaffevm/gcFuncs.c:1.58
--- kaffe/kaffe/kaffevm/gcFuncs.c:1.57	Sun Sep  5 12:24:48 2004
+++ kaffe/kaffe/kaffevm/gcFuncs.c	Wed Oct 20 16:47:13 2004
@@ -609,7 +609,10 @@
 	KGC_registerGcTypeByIndex(gc, KGC_ALLOC_JAVALOADER,
 	    walkLoader, finalizeObject, destroyClassLoader,
 	    "j.l.ClassLoader");
+	KGC_registerGcTypeByIndex(gc, KGC_ALLOC_THREADCTX, 
+	    0, KGC_OBJECT_NORMAL, 0, "thread-ctxts");
 
+	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_STATIC_THREADDATA, "thread-data");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_BYTECODE, "java-bytecode");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_EXCEPTIONTABLE, "exc-table");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_JITCODE, "jitcode");
@@ -622,7 +625,6 @@
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_UTF8CONST, "utf8consts");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_INTERFACE, "interfaces");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_LOCK, "locks");
-	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_THREADCTX, "thread-ctxts");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_REF, "gc-refs");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_JITTEMP, "jit-temp-data");
 	KGC_registerFixedTypeByIndex(gc, KGC_ALLOC_JAR, "jar");
Index: kaffe/kaffe/kaffevm/ksem.c
diff -u kaffe/kaffe/kaffevm/ksem.c:1.8 kaffe/kaffe/kaffevm/ksem.c:1.9
--- kaffe/kaffe/kaffevm/ksem.c:1.8	Wed Sep 29 19:35:43 2004
+++ kaffe/kaffe/kaffevm/ksem.c	Wed Oct 20 16:47:13 2004
@@ -26,14 +26,17 @@
 	sem->count = 0;
 }
 
-/*
+/**
  * Use a stored wakeup from the semaphore.  Block if none
  * are available.  Can wait with a timeout.  (If timeout is 0, then
  * do not timeout in wait.)
- * Returns true if the semaphore was acquired, returns false if
- * we timed-out in wait and semaphore still wasn't available.
- *
  * Spurious wakeups are not handled here.
+ *
+ * @param sem Semaphore to wait for.
+ * @param timeout The number of milliseconds to wait if different of 0.
+ * If timeout is null, wait indefinitely.
+ * @return true if the semaphore was acquired, returns false if
+ * we timed-out in wait and semaphore still wasn't available.
  */
 jboolean
 ksemGet(Ksem* volatile sem, jlong timeout)
Index: kaffe/kaffe/kaffevm/thread.c
diff -u kaffe/kaffe/kaffevm/thread.c:1.77 kaffe/kaffe/kaffevm/thread.c:1.78
--- kaffe/kaffe/kaffevm/thread.c:1.77	Mon Oct 18 07:49:58 2004
+++ kaffe/kaffe/kaffevm/thread.c	Wed Oct 20 16:47:13 2004
@@ -62,8 +62,6 @@
 static void firstStartThread(void*);
 static void runfinalizer(void);
 
-static iStaticLock thread_start_lock = KAFFE_STATIC_LOCK_INITIALIZER;
-
 /*
  * How do I get memory?
  */
@@ -149,7 +147,8 @@
 
 
 static jthread_t
-createThread(Hjava_lang_VMThread* vmtid, void (*func)(void *), size_t stacksize,
+createThread(Hjava_lang_VMThread* vmtid, void (*func)(void *), void *arg,
+	     size_t stacksize,
 	     struct _errorInfo *einfo)
 {
 	jthread_t nativeThread;
@@ -159,14 +158,14 @@
 	  jthread_create(((unsigned char)unhand(tid)->priority),
 			 func,
 			 unhand(tid)->daemon,
-			 vmtid,
+			 arg,
 			 stacksize);
 
 	if (nativeThread == NULL) {
 		postOutOfMemory(einfo);
 		return 0;
 	}
-
+	
 	return nativeThread;
 }
 
@@ -185,19 +184,17 @@
 	 * finished in create.
 	 * See also firstStartThread.
 	 */
-	lockStaticMutex(&thread_start_lock);
-
 	nativeTid = createThread(tid, &firstStartThread,
+				 jthread_current(),
 				 threadStackSize, &info);
-
-	linkNativeAndJavaThread (nativeTid, tid);
-	
-	waitStaticCond(&thread_start_lock, (jlong)0);
-	unlockStaticMutex(&thread_start_lock);
-
 	if (nativeTid == NULL) {
 		throwError(&info);
 	}
+	ksemGet(&THREAD_DATA()->sem, (jlong)0);
+
+	linkNativeAndJavaThread (nativeTid, tid);
+
+	ksemPut(&jthread_get_data(nativeTid)->sem);
 }
 
 /*
@@ -288,6 +285,7 @@
 	void **pointer_args = (void **)arg;
 	void *argument;
 	int iLockRoot;
+	jthread_t calling_thread;
 
 	ksemInit(&THREAD_DATA()->sem);
 
@@ -296,10 +294,14 @@
 	 */
 	func = (void(*)(void*))pointer_args[0];
 	argument = pointer_args[1];
+	calling_thread = (jthread_t) pointer_args[2];
 
-	lockStaticMutex(&thread_start_lock);
-	signalStaticCond(&thread_start_lock);
-	unlockStaticMutex(&thread_start_lock);
+	/* Thread started and arguments retrieved. */
+	ksemPut(&jthread_get_data(calling_thread)->sem);
+	/* We have now to wait the parent to synchronize the data
+	 * and link the thread to the Java VM.
+	 */
+	ksemGet(&THREAD_DATA()->sem, (jlong)0);
 
 	THREAD_DATA()->exceptObj = NULL;
 
@@ -324,7 +326,7 @@
   jthread_t nativeTid;
   int iLockRoot;
   Hjava_lang_String* name;
-  void *specialArgument[2];
+  void *specialArgument[3];
 
 DBG(VMTHREAD,	dprintf("createDaemon %s\n", nm);	)
   
@@ -350,10 +352,9 @@
 				  "getSystemClassLoader",
 				  "()Ljava/lang/ClassLoader;").l;
   
-  lockStaticMutex(&thread_start_lock);
-
   specialArgument[0] = func;
   specialArgument[1] = arg;
+  specialArgument[2] = jthread_current();
   
   nativeTid = 
     jthread_create(((unsigned char)unhand(tid)->priority),
@@ -369,12 +370,12 @@
 
   jthread_get_data(nativeTid)->exceptPtr = NULL;
   jthread_get_data(nativeTid)->exceptObj = NULL;
-  
-  waitStaticCond(&thread_start_lock, (jlong)0);
 
-  linkNativeAndJavaThread (nativeTid, vmtid);
+  ksemGet(&THREAD_DATA()->sem, (jlong)0);
   
-  unlockStaticMutex(&thread_start_lock);
+  linkNativeAndJavaThread (nativeTid, vmtid);
+
+  ksemPut(&jthread_get_data(nativeTid)->sem);
   
   return (tid);
 }
@@ -384,22 +385,24 @@
  */
 static
 void
-firstStartThread(void* arg UNUSED)
+firstStartThread(void* arg)
 {
 	Hjava_lang_VMThread* tid;
 	jthread_t cur;
 	JNIEnv *env;
 	jmethodID runmethod;
 	int iLockRoot;
+	jthread_t calling_thread = (jthread_t) arg;
 
 	cur = jthread_current();
 
 	ksemInit(&jthread_get_data(cur)->sem);
- 
-	lockStaticMutex(&thread_start_lock);
-	signalStaticCond(&thread_start_lock);
-	unlockStaticMutex(&thread_start_lock);
 
+	/* We acknowledge the parent thread that this thread has been started. */
+	ksemPut(&jthread_get_data(calling_thread)->sem);
+	/* Now we must wait the parent to link the thread to the Java VM. */
+	ksemGet(&jthread_get_data(cur)->sem, (jlong)0);
+ 
 	tid = (Hjava_lang_VMThread *)(jthread_get_data(cur)->jlThread);
 	env = &jthread_get_data(cur)->jniEnv;
 
@@ -663,9 +666,7 @@
 		DBGEXPR(JTHREADNOPREEMPT, false, true),
 		java_lang_Thread_MAX_PRIORITY+1,
 		java_lang_Thread_MIN_PRIORITY,
-		thread_malloc,
-		thread_free,
-		thread_realloc,
+		main_collector,
 		broadcastDeath,
 		throwDeath,
 		onDeadlock);
Index: kaffe/kaffe/kaffevm/systems/unix-jthreads/jthread.c
diff -u kaffe/kaffe/kaffevm/systems/unix-jthreads/jthread.c:1.122 kaffe/kaffe/kaffevm/systems/unix-jthreads/jthread.c:1.123
--- kaffe/kaffe/kaffevm/systems/unix-jthreads/jthread.c:1.122	Fri Oct  1 15:02:31 2004
+++ kaffe/kaffe/kaffevm/systems/unix-jthreads/jthread.c	Wed Oct 20 16:47:14 2004
@@ -25,6 +25,7 @@
 #include "kaffe/jni_md.h"
 /* For Hjava_lang_VMThread */
 #include "thread.h"
+#include "gc.h"
 
 /* Flags used for threading I/O calls */
 #define TH_READ                         0
@@ -104,12 +105,13 @@
 static int blockInts;		/* counter that says whether irqs are blocked */
 static int needReschedule;	/* is a change in the current thread required */
 
+/** This is the garbage collector to use to allocate thread data. */
+static Collector *threadCollector;
+
 /*
  * the following variables are set by jthread_init, and show how the
  * threading system is parametrized.
  */
-static void *(*allocator)(size_t); 	/* malloc */
-static void (*deallocator)(void*);	/* free */
 static void (*destructor1)(void*);	/* call when a thread exits */
 static void (*onstop)(void);		/* call when a thread is stopped */
 static void (*ondeadlock)(void);	/* call when we detect deadlock */
@@ -283,7 +285,7 @@
 		}
 		node = KaffePoolNewNode(queuePool);
 		node->next = *tidp;
-		JTHREADQ(node) = jtid;
+		node->element = jtid;
 		*tidp = node;
 		
 		/* If I'm head of alarm list, restart alarm */
@@ -477,7 +479,7 @@
 			wouldlosewakeup++;
 		}
 
-#if KAFFE_SIGNAL_ONE_SHOT
+#if defined(KAFFE_SIGNAL_ONE_SHOT)
 		/*
 		 * On some systems, signal handlers are a one-shot deal.
 		 * Re-install the signal handler for those systems.
@@ -502,7 +504,7 @@
 
 	intsDisable();
 
-#if KAFFE_SIGNAL_ONE_SHOT
+#if defined(KAFFE_SIGNAL_ONE_SHOT)
 	/* Re-enable signal if necessary */
         restoreAsyncSignalHandler(sig, interrupt);
 #endif
@@ -804,7 +806,7 @@
 		}
 		else if (threadQhead[jtid->priority] == 0) {
 			threadQhead[jtid->priority] = KaffePoolNewNode(queuePool);
-			JTHREADQ(threadQhead[jtid->priority]) = jtid;
+			threadQhead[jtid->priority]->element = jtid;
 			threadQtail[jtid->priority] = threadQhead[jtid->priority];
 			if (jtid->priority > currentJThread->priority) {
 				needReschedule = true;
@@ -813,7 +815,7 @@
 		else {
 		        KaffeNodeQueue *queue = KaffePoolNewNode(queuePool);
 			
-			JTHREADQ(queue) = jtid;
+			queue->element = jtid;
 			threadQtail[jtid->priority]->next = queue;
 			threadQtail[jtid->priority] = queue;
 		}
@@ -840,7 +842,7 @@
 	/* Insert onto head of lock wait Q */
 	node = KaffePoolNewNode(queuePool);
 	node->next = *queue;
-	JTHREADQ(node) = jtid;
+	node->element = jtid;
 	*queue = node;
 	
 	/* Add the new queue to the list of registered blocking queues */
@@ -1044,10 +1046,12 @@
 {
 	jthread *ct;
 
-	ct = allocator(sizeof(jthread) + 16 + stackSize);
+	ct = KGC_malloc(threadCollector, sizeof(jthread) + 16 + stackSize, KGC_ALLOC_THREADCTX);
 	if (ct == 0) {
 		return 0;
 	}
+
+	KGC_addRef(threadCollector, ct);
 #if defined(__ia64__)
 	/* (gb) Align jmp_buf on 16-byte boundaries */
 	ct = (jthread *)((((unsigned long)(ct)) & 15) ^ (unsigned long)(ct));
@@ -1076,7 +1080,8 @@
 		for (x = liveThreads; x; x = x->next)
 			assert(JTHREADQ(x) != jtid);
 	}
-	deallocator(jtid);
+	/* We do not free explicitly as it should be done by the GC. */
+	KGC_rmRef(threadCollector, jtid);
 }
 
 /*
@@ -1229,15 +1234,31 @@
 static void deactivate_time_slicing(void) { }
 #endif
 
+/**
+ * Thread allocation function alias.
+ */
+static void *thread_static_allocator(size_t bytes)
+{
+	return KGC_malloc(threadCollector, bytes, KGC_ALLOC_STATIC_THREADDATA);
+}
+
+static void thread_static_free(void *p)
+{
+	return KGC_free(threadCollector, p);
+}
+
+static void *thread_reallocator(void *p, size_t bytes)
+{
+	return KGC_realloc(threadCollector, p, bytes, KGC_ALLOC_STATIC_THREADDATA);
+}
+
 /*
  * Initialize the threading system. 
  */
 void
 jthread_init(int pre,
 	int maxpr, int minpr,
-	void *(*_allocator)(size_t), 
-	void (*_deallocator)(void*),
-	void *(*_reallocator)(void*,size_t),
+	Collector *collector,
 	void (*_destructor1)(void*),
 	void (*_onstop)(void),
 	void (*_ondeadlock)(void))
@@ -1245,6 +1266,8 @@
         jthread *jtid; 
 	int i;
 
+	threadCollector = collector;
+
 	/* XXX this is f***ed.  On BSD, we get a SIGHUP if we try to put
 	 * a process that has a pseudo-tty in async mode in the background
 	 * So we'll just ignore it and keep running.  Note that this will
@@ -1252,7 +1275,7 @@
 	 */
 	ignoreSignal(SIGHUP);
 
-	KaffeSetDefaultAllocator(_allocator, _deallocator, _reallocator);
+	KaffeSetDefaultAllocator(thread_static_allocator, thread_static_free, thread_reallocator);
 	queuePool = KaffeCreatePool();
 
 #if defined(SIGVTALRM)
@@ -1300,13 +1323,11 @@
 	preemptive = pre;
 	max_priority = maxpr;
 	min_priority = minpr;
-	allocator = _allocator;
-	deallocator = _deallocator;
 	onstop = _onstop;
 	ondeadlock = _ondeadlock;
 	destructor1 = _destructor1;
-	threadQhead = (KaffeNodeQueue **)allocator((maxpr + 1) * sizeof (KaffeNodeQueue *));
-	threadQtail = (KaffeNodeQueue **)allocator((maxpr + 1) * sizeof (KaffeNodeQueue *));
+	threadQhead = (KaffeNodeQueue **)thread_static_allocator((maxpr + 1) * sizeof (KaffeNodeQueue *));
+	threadQtail = (KaffeNodeQueue **)thread_static_allocator((maxpr + 1) * sizeof (KaffeNodeQueue *));
 	for (i=0;i<FD_SETSIZE;i++) {
 	  readQ[i] = writeQ[i] = NULL;
 	  blockingFD[i] = true;
@@ -1346,7 +1367,7 @@
         jtid->func = (void (*)(void*))jthread_init;
         
 	liveThreads = KaffePoolNewNode(queuePool);
-	JTHREADQ(liveThreads) = jtid;
+	liveThreads->element = jtid;
         jtid->time = 0;
 
         talive++;
@@ -1532,7 +1553,7 @@
 
 	liveQ = KaffePoolNewNode(queuePool);
 	liveQ->next = liveThreads;
-	JTHREADQ(liveQ) = jtid;
+	liveQ->element = jtid;
 	liveThreads = liveQ;
 
         talive++;       
@@ -1585,7 +1606,7 @@
 	 * grows downward. Both stacks start in the middle and grow outward
 	 * from each other.
 	 */
-	(char *) newstack -= (threadStackSize >> 1);
+	newstack = (void *)((uintp)newstack - (threadStackSize >> 1));
 	newbsp = newstack;
 	/* Make register stack 64-byte aligned */
 	if ((unsigned long)newbsp & 0x3f)
@@ -1593,7 +1614,7 @@
 	newbsp += STACK_COPY;
 	memcpy(newbsp-STACK_COPY, oldbsp-STACK_COPY, STACK_COPY);
 #endif
-	(char *) newstack -= STACK_COPY;
+	newstack = (void *)((uintp)newstack - STACK_COPY);
 	memcpy(newstack, oldstack, STACK_COPY);
 #endif /* !STACK_GROWS_UP */
 
Index: kaffe/kaffe/kaffevm/systems/unix-jthreads/jthread.h
diff -u kaffe/kaffe/kaffevm/systems/unix-jthreads/jthread.h:1.62 kaffe/kaffe/kaffevm/systems/unix-jthreads/jthread.h:1.63
--- kaffe/kaffe/kaffevm/systems/unix-jthreads/jthread.h:1.62	Mon Aug  2 10:45:04 2004
+++ kaffe/kaffe/kaffevm/systems/unix-jthreads/jthread.h	Wed Oct 20 16:47:14 2004
@@ -133,14 +133,13 @@
 /* 
  * initialize the threading system
  */
+struct _Collector;
 void 
 jthread_init(
 	int preemptive,				/* preemptive scheduling */
 	int maxpr, 				/* maximum priority */
 	int minpr, 				/* minimum priority */
-        void *(*_allocator)(size_t),		/* memory allocator */
-	void (*_deallocator)(void*),		/* memory deallocator */
-	void *(*_reallocator)(void*,size_t),	/* memory reallocator */
+	struct _Collector *collector,
 	void (*_destructor1)(void*),		/* called when a thread exits */ 
 	void (*_onstop)(void),			/* called when a thread is stopped */
 	void (*_ondeadlock)(void));		/* called when we detect deadlock */
Index: kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c
diff -u kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:1.48 kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:1.49
--- kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:1.48	Sun Oct 17 22:54:32 2004
+++ kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c	Wed Oct 20 16:47:14 2004
@@ -21,6 +21,8 @@
 #include "thread-impl.h"
 #include "debug.h"
 #include "md.h"
+#include "gc.h"
+#include "thread.h"
 #ifdef KAFFE_BOEHM_GC
 #include "boehm-gc/boehm/include/gc.h"
 #endif
@@ -96,6 +98,11 @@
 static int psigRestart;
 static int psigCancel;
 
+/**
+ * This variable holds a pointer to the garbage collector which
+ * will be used to allocate thread data.
+ */
+static Collector *threadCollector;
 
 /***********************************************************************
  * global data
@@ -148,6 +155,9 @@
 /** Signal set which contains important signals for suspending threads. */
 static sigset_t		suspendSet;
 
+/** This callback is to be called when a thread exits. */
+static void (*threadDestructor)(void *);
+
 #ifdef KAFFE_VMDEBUG
 /** an optional deadlock watchdog thread (not in the activeThread list),
  * activated by KAFFE_VMDEBUG topic JTHREAD */
@@ -165,8 +175,11 @@
 static void resume_signal_handler ( int sig );
 static void tDispose ( jthread_t nt );
 
-static void* (*thread_malloc)(size_t);
-static void (*thread_free)(void*);
+static void *
+thread_malloc(size_t bytes)
+{
+	return KGC_malloc(threadCollector, bytes, KGC_ALLOC_THREADCTX);
+}
 
 static inline void
 protectThreadList(jthread_t cur)
@@ -487,6 +500,7 @@
    * We need to have a native thread context available as soon as possible.
    */
   nt = thread_malloc( sizeof(struct _jthread));
+  KGC_addRef(threadCollector, nt);
   nt->tid = pthread_self();
   pthread_setspecific( ntKey, nt);
   nt->stackMin  = (void*)0;
@@ -500,24 +514,22 @@
 void
 jthread_init(UNUSED int pre,
         int maxpr, int minpr,
-        void *(*_allocator)(size_t),
-        void (*_deallocator)(void*),
-        void *(*_reallocator)(void*,size_t) UNUSED,
-        void (*_destructor1)(void*) UNUSED,
+	Collector *thread_collector,
+	void (*destructor)(void *),
         void (*_onstop)(void) UNUSED,
         void (*_ondeadlock)(void) UNUSED)
 {
   DBG(JTHREAD, dprintf("initialized\n"))
 
-  thread_malloc = _allocator;
-  thread_free = _deallocator;
+  threadCollector = thread_collector;
+  threadDestructor = destructor;
 
   tInitSignals();
 
   pthread_key_create( &ntKey, NULL);
   sem_init( &critSem, 0, 0);
 
-  priorities = (int *)_allocator ((maxpr+1) * sizeof(int));
+  priorities = (int *)KGC_malloc (threadCollector, (maxpr+1) * sizeof(int), KGC_ALLOC_STATIC_THREADDATA);
 
   tMapPriorities(maxpr+1);
   tInitSignalHandlers();
@@ -689,6 +701,9 @@
 
 	DBG( JTHREAD, TMSG_LONG( "exiting user func of: ", cur))
 
+	if (threadDestructor)
+	  threadDestructor(cur->data.jlThread);
+
 	protectThreadList(cur);
 
 	/* remove from active list */
@@ -819,6 +834,7 @@
 	int creation_succeeded;
 
 	nt = thread_malloc( sizeof(struct _jthread) );
+	KGC_addRef(threadCollector, nt);
 
 	pthread_attr_init( &nt->attr);
 	pthread_attr_setschedparam( &nt->attr, &sp);
@@ -876,7 +892,7 @@
 
 	  sem_destroy( &nt->sem);
 	  unprotectThreadList(cur);
-	  thread_free(nt);
+	  KGC_rmRef(threadCollector, nt);
 	  return 0;
 	}
 
@@ -901,12 +917,19 @@
 static
 void tDispose ( jthread_t nt )
 {
+  /* Remove the static reference so the thread context may be freed. */
+  KGC_rmRef(threadCollector, nt);
+
   pthread_detach( nt->tid);
   pthread_mutex_destroy (&nt->suspendLock);
 
   sem_destroy( &nt->sem);
 
-  thread_free( nt);
+  /* The context is not freed explictly as it may cause troubles
+   * with the locking system which is invoked by the GC in that case.
+   * The thread context will be automatically freed by the GC in its 
+   * thread context.
+   */
 }
 
 /*
Index: kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-internal.h
diff -u kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-internal.h:1.20 kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-internal.h:1.21
--- kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-internal.h:1.20	Tue Oct 12 08:45:02 2004
+++ kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-internal.h	Wed Oct 20 16:47:14 2004
@@ -300,12 +300,11 @@
  * Initialize the thread subsystem.
  *
  */
+struct _Collector;
 void jthread_init(int preemptive,                	/* preemptive scheduling */
 		  int maxpr,                     	/* maximum priority */
 		  int minpr,                     	/* minimum priority */
-		  void *(*_allocator)(size_t),   	/* memory allocator */
-		  void (*_deallocator)(void*),    	/* memory deallocator */
-		  void *(*_reallocator)(void*,size_t),  /* memory reallocator */
+		  struct _Collector *collector,
 		  void (*_destructor1)(void*),		/* called when a thread exits */
 		  void (*_onstop)(void),		/* called when a thread is stopped */
 		  void (*_ondeadlock)(void));		/* called when we detect deadlock */



More information about the kaffe mailing list