X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fthreads%2Fposix%2Fthread-posix.cpp;h=bcc25c9f137b8f6d765ab08195506ab18080b46f;hb=604774fc98d7df7e702ce77dfd7e247cbe15ebc7;hp=2e0ac45b590658415a9649d8b69149c60831755d;hpb=7a6b3cc54e28b4e89a229d05f4f1df089674b46a;p=cacao.git diff --git a/src/threads/posix/thread-posix.cpp b/src/threads/posix/thread-posix.cpp index 2e0ac45b5..bcc25c9f1 100644 --- a/src/threads/posix/thread-posix.cpp +++ b/src/threads/posix/thread-posix.cpp @@ -27,6 +27,8 @@ /* XXX cleanup these includes */ +#define __STDC_LIMIT_MACROS + #include #include #include @@ -43,41 +45,39 @@ #include "arch.h" #include "mm/gc.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #if defined(ENABLE_GC_CACAO) # include "mm/cacao-gc/gc.h" #endif -#include "native/jni.h" #include "native/llni.h" -#include "native/native.h" +#include "native/native.hpp" #include "threads/condition.hpp" -#include "threads/lock-common.h" +#include "threads/lock.hpp" #include "threads/mutex.hpp" -#include "threads/threadlist.h" +#include "threads/threadlist.hpp" #include "threads/thread.hpp" -#include "toolbox/logging.h" +#include "toolbox/logging.hpp" -#include "vm/builtin.h" +#include "vm/jit/builtin.hpp" #include "vm/exceptions.hpp" #include "vm/global.h" -#include "vm/signallocal.h" +#include "vm/globals.hpp" +#include "vm/javaobjects.hpp" +#include "vm/options.h" +#include "vm/signallocal.hpp" #include "vm/string.hpp" #include "vm/vm.hpp" -#include "vm/jit/asmpart.h" - -#include "vmcore/globals.hpp" -#include "vmcore/javaobjects.hpp" -#include "vmcore/options.h" - #if defined(ENABLE_STATISTICS) -# include "vmcore/statistics.h" +# include "vm/statistics.h" #endif +#include "vm/jit/asmpart.h" + #if !defined(__DARWIN__) # include #endif @@ -101,18 +101,15 @@ #endif -// FIXME For now we export everything as C functions. -extern "C" { - #if defined(__DARWIN__) /* Darwin has no working semaphore implementation. This one is taken from Boehm-GC. */ /* - This is a very simple semaphore implementation for darwin. It + This is a very simple semaphore implementation for Darwin. It is implemented in terms of pthreads calls so it isn't async signal safe. This isn't a problem because signals aren't used to - suspend threads on darwin. + suspend threads on Darwin. */ static int sem_init(sem_t *sem, int pshared, int value) @@ -120,12 +117,9 @@ static int sem_init(sem_t *sem, int pshared, int value) if (pshared) assert(0); - sem->value = value; - sem->mutex = new Mutex(); - - if (pthread_cond_init(&sem->cond, NULL) < 0) - return -1; + sem->cond = new Condition(); + sem->value = value; return 0; } @@ -133,14 +127,8 @@ static int sem_init(sem_t *sem, int pshared, int value) static int sem_post(sem_t *sem) { sem->mutex->lock(); - sem->value++; - - if (pthread_cond_signal(&sem->cond) < 0) { - sem->mutex->unlock(); - return -1; - } - + sem->cond->signal(); sem->mutex->unlock(); return 0; @@ -151,12 +139,10 @@ static int sem_wait(sem_t *sem) sem->mutex->lock(); while (sem->value == 0) { -#error We cannot call pthread_cond_wait on a Mutex-class pointer. - pthread_cond_wait(&sem->cond, &sem->mutex); + sem->cond->wait(sem->mutex); } sem->value--; - sem->mutex->unlock(); return 0; @@ -164,9 +150,7 @@ static int sem_wait(sem_t *sem) static int sem_destroy(sem_t *sem) { - if (pthread_cond_destroy(&sem->cond) < 0) - return -1; - + delete sem->cond; delete sem->mutex; return 0; @@ -447,33 +431,6 @@ void threads_startworld(void) #endif -/* threads_impl_thread_init **************************************************** - - Initialize OS-level locking constructs in threadobject. - - IN: - t....the threadobject - -*******************************************************************************/ - -void threads_impl_thread_init(threadobject *t) -{ - /* initialize the mutex and the condition */ - - t->flc_lock = new Mutex(); - t->flc_cond = new Condition(); - - t->waitmutex = new Mutex(); - t->waitcond = new Condition(); - - t->suspendmutex = new Mutex(); - t->suspendcond = new Condition(); - -#if defined(ENABLE_TLH) - tlh_init(&(t->tlh)); -#endif -} - /* threads_impl_thread_clear *************************************************** Clears all fields in threadobject the way an MZERO would have @@ -524,7 +481,7 @@ void threads_impl_thread_clear(threadobject *t) t->es = NULL; #endif - MZERO(&t->dumpinfo, dumpinfo_t, 1); + // Simply reuse the existing dump memory. } /* threads_impl_thread_reuse *************************************************** @@ -1337,7 +1294,7 @@ void threads_join_all_threads(void) compare against 1 because the current (main thread) is also a non-daemon thread. */ - while (threadlist_get_non_daemons() > 1) + while (ThreadList::get_number_of_non_daemon_threads() > 1) cond_join->wait(mutex_join); /* leave join mutex */ @@ -1414,7 +1371,7 @@ static bool threads_current_time_is_earlier_than(const struct timespec *tv) *******************************************************************************/ -static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime) +static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime, bool parking) { // Acquire the waitmutex. t->waitmutex->lock(); @@ -1423,10 +1380,13 @@ static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTi if (wakeupTime->tv_sec || wakeupTime->tv_nsec) { /* with timeout */ - while (!t->interrupted && !t->signaled + while (!t->interrupted && !(parking ? t->park_permit : t->signaled) && threads_current_time_is_earlier_than(wakeupTime)) { - thread_set_state_timed_waiting(t); + if (parking) + thread_set_state_timed_parked(t); + else + thread_set_state_timed_waiting(t); t->waitcond->timedwait(t->waitmutex, wakeupTime); @@ -1435,8 +1395,11 @@ static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTi } else { /* no timeout */ - while (!t->interrupted && !t->signaled) { - thread_set_state_waiting(t); + while (!t->interrupted && !(parking ? t->park_permit : t->signaled)) { + if (parking) + thread_set_state_parked(t); + else + thread_set_state_waiting(t); t->waitcond->wait(t->waitmutex); @@ -1444,6 +1407,9 @@ static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTi } } + if (parking) + t->park_permit = false; + // Release the waitmutex. t->waitmutex->unlock(); } @@ -1472,7 +1438,7 @@ void threads_wait_with_timeout_relative(threadobject *thread, s8 millis, /* wait */ - threads_wait_with_timeout(thread, &wakeupTime); + threads_wait_with_timeout(thread, &wakeupTime, false); } @@ -1491,20 +1457,26 @@ void threads_wait_with_timeout_relative(threadobject *thread, s8 millis, static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos) { - if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) { + // (at least with GNU classpath) we know that 0 <= nanos <= 999999 + do { + if (!millis && !nanos) + break; struct timeval tv; - long nsec; gettimeofday(&tv, NULL); - tv.tv_sec += millis / 1000; + s8 secs = tv.tv_sec + millis / 1000; + if (secs > INT32_MAX) // integer overflow + break; + tv.tv_sec = secs; millis %= 1000; - nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos; + long nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos; tm->tv_sec = tv.tv_sec + nsec / 1000000000; + if (tm->tv_sec < tv.tv_sec) // integer overflow + break; tm->tv_nsec = nsec % 1000000000; - } - else { - tm->tv_sec = 0; - tm->tv_nsec = 0; - } + return; + } while (0); + tm->tv_sec = 0; + tm->tv_nsec = 0; } @@ -1531,7 +1503,7 @@ void threads_thread_interrupt(threadobject *t) /* Interrupt blocking system call using a signal. */ - pthread_kill(t->tid, Signal_THREAD_INTERRUPT); + pthread_kill(t->tid, Signal_INTERRUPT_SYSTEM_CALL); t->waitcond->signal(); @@ -1583,7 +1555,7 @@ void threads_sleep(int64_t millis, int32_t nanos) else { threads_calc_absolute_time(&wakeupTime, millis, nanos); - threads_wait_with_timeout(t, &wakeupTime); + threads_wait_with_timeout(t, &wakeupTime, false); interrupted = thread_is_interrupted(t); @@ -1598,6 +1570,47 @@ void threads_sleep(int64_t millis, int32_t nanos) } } +/** + * Park the current thread for the specified amount of time or until a + * specified deadline. + * + * @param absolute Is the time in nanos a deadline or a duration? + * @param nanos Nanoseconds to park (absolute=false) + * or deadline in milliseconds (absolute=true) + */ +void threads_park(bool absolute, int64_t nanos) +{ + threadobject *t; + struct timespec wakeupTime; + + t = thread_get_current(); + + if (absolute) { + wakeupTime.tv_nsec = 0; + wakeupTime.tv_sec = nanos / 1000; /* milliseconds */ + } + else + threads_calc_absolute_time(&wakeupTime, nanos / 1000000, nanos % 1000000); + + threads_wait_with_timeout(t, &wakeupTime, true); +} + +/** + * Unpark the specified thread. + * + * @param t The thread to unpark. + */ +void threads_unpark(threadobject *t) +{ + t->waitmutex->lock(); + + t->waitcond->signal(); + + t->park_permit = true; + + t->waitmutex->unlock(); +} + /* threads_yield *************************************************************** @@ -1622,8 +1635,6 @@ void threads_tlh_remove_frame() { #endif -} // extern "C" - /* * These are local overrides for various environment variables in Emacs.