[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