# include "native/include/java_lang_ThreadGroup.h"
#endif
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
# include "native/include/java_lang_VMThread.h"
#endif
#include "threads/lock-common.h"
+#include "threads/mutex.h"
#include "threads/threadlist.h"
#include "threads/thread.h"
#endif
#if !defined(__DARWIN__)
+# include <semaphore.h>
+#endif
# if defined(__LINUX__)
# define GC_LINUX_THREADS
# elif defined(__IRIX__)
# define GC_IRIX_THREADS
+# elif defined(__DARWIN__)
+# define GC_DARWIN_THREADS
# endif
-# include <semaphore.h>
# if defined(ENABLE_GC_BOEHM)
+/* We need to include Boehm's gc.h here because it overrides
+ pthread_create and friends. */
# include "mm/boehm-gc/include/gc.h"
# endif
-#endif
#if defined(ENABLE_JVMTI)
#include "native/jvmti/cacaodbg.h"
sem->value = value;
- if (pthread_mutex_init(&sem->mutex, NULL) < 0)
- return -1;
+ mutex_init(&sem->mutex);
if (pthread_cond_init(&sem->cond, NULL) < 0)
return -1;
static int sem_post(sem_t *sem)
{
- if (pthread_mutex_lock(&sem->mutex) < 0)
- return -1;
+ mutex_lock(&sem->mutex);
sem->value++;
if (pthread_cond_signal(&sem->cond) < 0) {
- pthread_mutex_unlock(&sem->mutex);
+ mutex_unlock(&sem->mutex);
return -1;
}
- if (pthread_mutex_unlock(&sem->mutex) < 0)
- return -1;
+ mutex_unlock(&sem->mutex);
return 0;
}
static int sem_wait(sem_t *sem)
{
- if (pthread_mutex_lock(&sem->mutex) < 0)
- return -1;
+ mutex_lock(&sem->mutex);
while (sem->value == 0) {
pthread_cond_wait(&sem->cond, &sem->mutex);
sem->value--;
- if (pthread_mutex_unlock(&sem->mutex) < 0)
- return -1;
+ mutex_unlock(&sem->mutex);
return 0;
}
if (pthread_cond_destroy(&sem->cond) < 0)
return -1;
- if (pthread_mutex_destroy(&sem->mutex) < 0)
- return -1;
+ mutex_destroy(&sem->mutex);
return 0;
}
#endif
/* global mutex for stop-the-world */
-static pthread_mutex_t stopworldlock;
+static mutex_t stopworldlock;
#if defined(ENABLE_GC_CACAO)
/* global mutex for the GC */
-static pthread_mutex_t mutex_gc;
+static mutex_t mutex_gc;
#endif
/* global mutex and condition for joining threads on exit */
-static pthread_mutex_t mutex_join;
+static mutex_t mutex_join;
static pthread_cond_t cond_join;
-/* XXX We disable that whole bunch of code until we have the exact-GC
- running. */
-
-#if 1
-
/* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
/* being stopped */
static volatile int stopworldwhere;
+#if defined(ENABLE_GC_CACAO)
+
/* semaphore used for acknowleding thread suspension */
static sem_t suspend_ack;
#if defined(__IRIX__)
-static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
+static mutex_t suspend_ack_lock = MUTEX_INITIALIZER;
static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
#endif
-#endif /* 0 */
+#endif /* ENABLE_GC_CACAO */
/* mutexes used by the fake atomic instructions */
#if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
-pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
-pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
+mutex_t _cas_lock = MUTEX_INITIALIZER;
+mutex_t _mb_lock = MUTEX_INITIALIZER;
#endif
void lock_stopworld(int where)
{
- pthread_mutex_lock(&stopworldlock);
+ mutex_lock(&stopworldlock);
/* stopworldwhere = where; */
}
void unlock_stopworld(void)
{
/* stopworldwhere = 0; */
- pthread_mutex_unlock(&stopworldlock);
+ mutex_unlock(&stopworldlock);
}
/* XXX We disable that whole bunch of code until we have the exact-GC
- running. */
+ running. Some of it may only be needed by the old Boehm-based
+ suspension handling. */
#if 0
#if defined(__IRIX__)
static void threads_cast_irixresume(void)
{
- pthread_mutex_lock(&suspend_ack_lock);
+ mutex_lock(&suspend_ack_lock);
pthread_cond_broadcast(&suspend_cond);
- pthread_mutex_unlock(&suspend_ack_lock);
+ mutex_unlock(&suspend_ack_lock);
}
#endif
/* Do as Boehm does. On IRIX a condition variable is used for wake-up
(not POSIX async-safe). */
#if defined(__IRIX__)
- pthread_mutex_lock(&suspend_ack_lock);
+ mutex_lock(&suspend_ack_lock);
threads_sem_post(&suspend_ack);
pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
- pthread_mutex_unlock(&suspend_ack_lock);
+ mutex_unlock(&suspend_ack_lock);
#elif defined(__CYGWIN__)
/* TODO */
assert(0);
}
#endif
-#endif
-
/* threads_stopworld ***********************************************************
*******************************************************************************/
-#if !defined(DISABLE_GC)
void threads_stopworld(void)
{
#if !defined(__DARWIN__) && !defined(__CYGWIN__)
non-signaled NEW threads can't change their state and execute
code. */
}
-#endif /* !defined(DISABLE_GC) */
/* threads_startworld **********************************************************
*******************************************************************************/
-#if !defined(DISABLE_GC)
void threads_startworld(void)
{
#if !defined(__DARWIN__) && !defined(__CYGWIN__)
unlock_stopworld();
}
+
#endif
/* initialize the mutex and the condition */
- result = pthread_mutex_init(&t->flc_lock, NULL);
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_new: pthread_mutex_init failed");
+ mutex_init(&t->flc_lock);
result = pthread_cond_init(&t->flc_cond, NULL);
if (result != 0)
vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
- result = pthread_mutex_init(&(t->waitmutex), NULL);
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_new: pthread_mutex_init failed");
+ mutex_init(&(t->waitmutex));
result = pthread_cond_init(&(t->waitcond), NULL);
if (result != 0)
vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
- result = pthread_mutex_init(&(t->suspendmutex), NULL);
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_new: pthread_mutex_init failed");
+ mutex_init(&(t->suspendmutex));
result = pthread_cond_init(&(t->suspendcond), NULL);
if (result != 0)
/* Destroy the mutex and the condition. */
- result = pthread_mutex_destroy(&(t->flc_lock));
-
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_free: pthread_mutex_destroy failed");
+ mutex_destroy(&(t->flc_lock));
result = pthread_cond_destroy(&(t->flc_cond));
if (result != 0)
vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
- result = pthread_mutex_destroy(&(t->waitmutex));
-
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_free: pthread_mutex_destroy failed");
+ mutex_destroy(&(t->waitmutex));
result = pthread_cond_destroy(&(t->waitcond));
if (result != 0)
vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
- result = pthread_mutex_destroy(&(t->suspendmutex));
-
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_free: pthread_mutex_destroy failed");
+ mutex_destroy(&(t->suspendmutex));
result = pthread_cond_destroy(&(t->suspendcond));
{
int result;
- result = pthread_mutex_init(&stopworldlock, NULL);
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_preinit: pthread_mutex_init failed");
+ mutex_init(&stopworldlock);
/* initialize exit mutex and condition (on exit we join all
threads) */
- result = pthread_mutex_init(&mutex_join, NULL);
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_preinit: pthread_mutex_init failed");
+ mutex_init(&mutex_join);
result = pthread_cond_init(&cond_join, NULL);
if (result != 0)
vm_abort_errnum(result, "threads_impl_preinit: pthread_cond_init failed");
#if defined(ENABLE_GC_CACAO)
- /* initialize the GC mutext */
+ /* initialize the GC mutex & suspend semaphore */
- result = pthread_mutex_init(&mutex_gc, NULL);
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_preinit: pthread_mutex_init failed");
+ mutex_init(&mutex_gc);
+ threads_sem_init(&suspend_ack, 0, 0);
#endif
#if !defined(HAVE___THREAD)
if (result != 0)
vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
#endif
-
- threads_sem_init(&suspend_ack, 0, 0);
}
#if defined(ENABLE_GC_CACAO)
void threads_mutex_gc_lock(void)
{
- int result;
-
- result = pthread_mutex_lock(&mutex_gc);
-
- if (result != 0)
- vm_abort_errnum(result, "threads_mutex_gc_lock: pthread_mutex_lock failed");
+ mutex_lock(&mutex_gc);
}
#endif
#if defined(ENABLE_GC_CACAO)
void threads_mutex_gc_unlock(void)
{
- int result;
-
- result = pthread_mutex_unlock(&mutex_gc);
-
- if (result != 0)
- vm_abort_errnum(result, "threads_mutex_gc_unlock: pthread_mutex_unlock failed");
+ mutex_unlock(&mutex_gc);
}
#endif
void threads_mutex_join_lock(void)
{
- int result;
-
- result = pthread_mutex_lock(&mutex_join);
-
- if (result != 0)
- vm_abort_errnum(result, "threads_mutex_join_lock: pthread_mutex_lock failed");
+ mutex_lock(&mutex_join);
}
void threads_mutex_join_unlock(void)
{
- int result;
-
- result = pthread_mutex_unlock(&mutex_join);
-
- if (result != 0)
- vm_abort_errnum(result, "threads_mutex_join_unlock: pthread_mutex_unlock failed");
+ mutex_unlock(&mutex_join);
}
static void *threads_startup_thread(void *arg)
{
startupinfo *startup;
- threadobject *thread;
+ threadobject *t;
java_lang_Thread *object;
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
java_lang_VMThread *vmt;
#endif
sem_t *psem;
startup = arg;
- thread = startup->thread;
+ t = startup->thread;
function = startup->function;
psem = startup->psem;
threads_sem_wait(startup->psem_first);
#if defined(__DARWIN__)
- thread->mach_thread = mach_thread_self();
+ t->mach_thread = mach_thread_self();
#endif
- /* Store the internal thread data-structure in the TSD. */
+ /* Now that we are in the new thread, we can store the internal
+ thread data-structure in the TSD. */
- thread_set_current(thread);
+ thread_set_current(t);
/* get the java.lang.Thread object for this thread */
- object = (java_lang_Thread *) threads_thread_get_object(thread);
+ object = (java_lang_Thread *) thread_get_object(t);
/* set our priority */
- threads_set_thread_priority(thread->tid, LLNI_field_direct(object, priority));
+ threads_set_thread_priority(t->tid, LLNI_field_direct(object, priority));
- /* thread is completely initialized */
+ /* Thread is completely initialized. */
- threads_thread_state_runnable(thread);
+ thread_set_state_runnable(t);
/* tell threads_startup_thread that we registered ourselves */
/* CAUTION: *startup becomes invalid with this! */
jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
#endif
- DEBUGTHREADS("starting", thread);
+ DEBUGTHREADS("starting", t);
/* find and run the Thread.run()V method if no other function was passed */
if (function == NULL) {
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
/* We need to start the run method of
java.lang.VMThread. Since this is a final class, we can use
the class object directly. */
c = class_java_lang_VMThread;
-#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
LLNI_class_get(object, c);
#else
# error unknown classpath configuration
_Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
/* we need to start the run method of java.lang.VMThread */
LLNI_field_get_ref(object, vmThread, vmt);
- o = (java_handle_t *) vmt;
+ o = (java_handle_t *) vmt;
-#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
- o = (java_handle_t *) object;
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+ o = (java_handle_t *) object;
#else
# error unknown classpath configuration
#endif
- /* run the thread */
+ /* Run the thread. */
(void) vm_call_method(m, o);
}
(function)();
}
- DEBUGTHREADS("stopping", thread);
+ DEBUGTHREADS("stopping", t);
#if defined(ENABLE_JVMTI)
/* fire thread end event */
/* We ignore the return value. */
- (void) threads_detach_thread(thread);
+ (void) threads_detach_thread(t);
/* set ThreadMXBean variables */
DEBUGTHREADS("detaching", t);
- object = (java_lang_Thread *) threads_thread_get_object(t);
+ object = (java_lang_Thread *) thread_get_object(t);
#if defined(ENABLE_JAVASE)
LLNI_field_get_ref(object, group, group);
to build the java_lang_Thread_UncaughtExceptionHandler
header file with cacaoh. */
-# if defined(WITH_CLASSPATH_GNU)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
LLNI_field_get_ref(object, exceptionHandler, handler);
-# elif defined(WITH_CLASSPATH_SUN)
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
LLNI_field_get_ref(object, uncaughtExceptionHandler, handler);
# endif
if (group != NULL) {
LLNI_class_get(group, c);
-# if defined(WITH_CLASSPATH_GNU)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
m = class_resolveclassmethod(c,
utf_removeThread,
utf_java_lang_Thread__V,
class_java_lang_ThreadGroup,
true);
-# elif defined(WITH_CLASSPATH_SUN)
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
m = class_resolveclassmethod(c,
utf_remove,
utf_java_lang_Thread__V,
if (exceptions_get_exception())
return false;
+
+ /* Reset the threadgroup in the Java thread object (Mauve
+ test: gnu/testlet/java/lang/Thread/getThreadGroup). */
+
+ LLNI_field_set_ref(object, group, NULL);
}
#endif
/* Thread has terminated. */
- threads_thread_state_terminated(t);
+ thread_set_state_terminated(t);
/* Notify all threads waiting on this thread. These are joining
this thread. */
/* XXX Care about exceptions? */
(void) lock_monitor_exit(o);
- /* Enter the join-mutex before calling threads_thread_free, so
+ /* Enter the join-mutex before calling thread_free, so
threads_join_all_threads gets the correct number of non-daemon
threads. */
threads_mutex_join_lock();
- /* free the vm internal thread object */
+ /* Free the internal thread data-structure. */
- threads_thread_free(t);
+ thread_free(t);
/* Signal that this thread has finished and leave the mutex. */
}
+#if defined(ENABLE_GC_CACAO)
+
/* threads_suspend_thread ******************************************************
Suspend the passed thread. Execution stops until the thread
bool threads_suspend_thread(threadobject *thread, s4 reason)
{
/* acquire the suspendmutex */
- if (pthread_mutex_lock(&(thread->suspendmutex)) != 0)
- vm_abort("threads_suspend_thread: pthread_mutex_lock failed: %s",
- strerror(errno));
+ mutex_lock(&(thread->suspendmutex));
if (thread->suspended) {
- pthread_mutex_unlock(&(thread->suspendmutex));
+ mutex_unlock(&(thread->suspendmutex));
return false;
}
/* TODO: remember dump memory size */
-#if defined(ENABLE_GC_CACAO)
/* inform the GC about the suspension */
if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
}
}
-#endif
/* mark this thread as suspended and remember the PC */
thread->pc = pc;
/* TODO: free dump memory */
/* release the suspendmutex */
- if (pthread_mutex_unlock(&(thread->suspendmutex)) != 0)
- vm_abort("threads_suspend_ack: pthread_mutex_unlock failed: %s",
- strerror(errno));
+ mutex_unlock(&(thread->suspendmutex));
}
bool threads_resume_thread(threadobject *thread)
{
/* acquire the suspendmutex */
- if (pthread_mutex_lock(&(thread->suspendmutex)) != 0)
- vm_abort("threads_resume_ack: pthread_mutex_unlock failed: %s",
- strerror(errno));
+ mutex_lock(&(thread->suspendmutex));
if (!thread->suspended) {
- pthread_mutex_unlock(&(thread->suspendmutex));
+ mutex_unlock(&(thread->suspendmutex));
return false;
}
pthread_cond_broadcast(&(thread->suspendcond));
/* release the suspendmutex */
- pthread_mutex_unlock(&(thread->suspendmutex));
+ mutex_unlock(&(thread->suspendmutex));
return true;
}
+#endif
/* threads_join_all_threads ****************************************************
t = THREADOBJECT;
- /* this thread is waiting for all non-daemon threads to exit */
+ /* This thread is waiting for all non-daemon threads to exit. */
- threads_thread_state_waiting(t);
+ thread_set_state_waiting(t);
/* enter join mutex */
{
/* acquire the waitmutex */
- pthread_mutex_lock(&t->waitmutex);
+ mutex_lock(&t->waitmutex);
/* mark us as sleeping */
while (!t->interrupted && !t->signaled
&& threads_current_time_is_earlier_than(wakeupTime))
{
- threads_thread_state_timed_waiting(t);
+ thread_set_state_timed_waiting(t);
pthread_cond_timedwait(&t->waitcond, &t->waitmutex,
wakeupTime);
- threads_thread_state_runnable(t);
+ thread_set_state_runnable(t);
}
}
else {
/* no timeout */
while (!t->interrupted && !t->signaled) {
- threads_thread_state_waiting(t);
+ thread_set_state_waiting(t);
pthread_cond_wait(&t->waitcond, &t->waitmutex);
- threads_thread_state_runnable(t);
+ thread_set_state_runnable(t);
}
}
/* release the waitmutex */
- pthread_mutex_unlock(&t->waitmutex);
+ mutex_unlock(&t->waitmutex);
}
/* Signal the thread a "waitcond" and tell it that it has been
interrupted. */
- pthread_mutex_lock(&thread->waitmutex);
+ mutex_lock(&thread->waitmutex);
DEBUGTHREADS("interrupted", thread);
thread->interrupted = true;
- pthread_mutex_unlock(&thread->waitmutex);
+ mutex_unlock(&thread->waitmutex);
}
-/* threads_check_if_interrupted_and_reset **************************************
-
- Check if the current thread has been interrupted and reset the
- interruption flag.
+/* threads_sleep ***************************************************************
- RETURN VALUE:
- true, if the current thread had been interrupted
+ Sleep the current thread for the specified amount of time.
*******************************************************************************/
-bool threads_check_if_interrupted_and_reset(void)
+void threads_sleep(int64_t millis, int32_t nanos)
{
- threadobject *thread;
- bool intr;
-
- thread = THREADOBJECT;
-
- pthread_mutex_lock(&thread->waitmutex);
-
- /* get interrupted flag */
-
- intr = thread->interrupted;
-
- /* reset interrupted flag */
-
- thread->interrupted = false;
-
- pthread_mutex_unlock(&thread->waitmutex);
-
- return intr;
-}
-
-
-/* threads_thread_has_been_interrupted *****************************************
-
- Check if the given thread has been interrupted
-
- IN:
- t............the thread to check
-
- RETURN VALUE:
- true, if the given thread had been interrupted
-
-*******************************************************************************/
+ threadobject *t;
+ struct timespec wakeupTime;
+ bool interrupted;
-bool threads_thread_has_been_interrupted(threadobject *thread)
-{
- return thread->interrupted;
-}
+ if (millis < 0) {
+/* exceptions_throw_illegalargumentexception("timeout value is negative"); */
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+ t = thread_get_current();
-/* threads_sleep ***************************************************************
+ if (thread_is_interrupted(t) && !exceptions_get_exception()) {
+ /* Clear interrupted flag (Mauve test:
+ gnu/testlet/java/lang/Thread/interrupt). */
- Sleep the current thread for the specified amount of time.
+ thread_set_interrupted(t, false);
-*******************************************************************************/
+/* exceptions_throw_interruptedexception("sleep interrupted"); */
+ exceptions_throw_interruptedexception();
+ return;
+ }
-void threads_sleep(s8 millis, s4 nanos)
-{
- threadobject *thread;
- struct timespec wakeupTime;
- bool wasinterrupted;
+ threads_calc_absolute_time(&wakeupTime, millis, nanos);
- thread = THREADOBJECT;
+ threads_wait_with_timeout(t, &wakeupTime);
- threads_calc_absolute_time(&wakeupTime, millis, nanos);
+ interrupted = thread_is_interrupted(t);
- threads_wait_with_timeout(thread, &wakeupTime);
+ if (interrupted) {
+ thread_set_interrupted(t, false);
- wasinterrupted = threads_check_if_interrupted_and_reset();
+ /* An other exception could have been thrown
+ (e.g. ThreadDeathException). */
- if (wasinterrupted)
- exceptions_throw_interruptedexception();
+ if (!exceptions_get_exception())
+ exceptions_throw_interruptedexception();
+ }
}