Robert Lougher writes: > Park and unpark are empty stubs, but everything else should be > implemented... If anybody can tell me what park/unpark should do, > I'll implement them too! I'll bite. park() stops a thread until some other thread calls unpark() on that thread or the thread is interrupted. park() may wake up spuriously, or indeed it may return immediately. If unpark() is called before park(), park() returns immediately. Therefore, the order in which park() and unpark() are called makes no difference. So, empty definitions of park() and unpark() are correct but inefficient. I've attached the gcj POSIX definitions. Andrew. /** * Releases the block on a thread created by _Jv_ThreadPark(). This * method can also be used to terminate a blockage caused by a prior * call to park. This operation is unsafe, as the thread must be * guaranteed to be live. * * @param thread the thread to unblock. */ void ParkHelper::unpark () { using namespace ::java::lang; volatile obj_addr_t *ptr = &permit; /* If this thread is in state RUNNING, give it a permit and return immediately. */ if (compare_and_swap (ptr, Thread::THREAD_PARK_RUNNING, Thread::THREAD_PARK_PERMIT)) return; /* If this thread is parked, put it into state RUNNING and send it a signal. */ if (compare_and_swap (ptr, Thread::THREAD_PARK_PARKED, Thread::THREAD_PARK_RUNNING)) { pthread_mutex_lock (&mutex); pthread_cond_signal (&cond); pthread_mutex_unlock (&mutex); } } /** * Sets our state to dead. */ void ParkHelper::deactivate () { permit = ::java::lang::Thread::THREAD_PARK_DEAD; } /** * Blocks the thread until a matching _Jv_ThreadUnpark() occurs, the * thread is interrupted or the optional timeout expires. If an * unpark call has already occurred, this also counts. A timeout * value of zero is defined as no timeout. When isAbsolute is true, * the timeout is in milliseconds relative to the epoch. Otherwise, * the value is the number of nanoseconds which must occur before * timeout. This call may also return spuriously (i.e. for no * apparent reason). * * @param isAbsolute true if the timeout is specified in milliseconds from * the epoch. * @param time either the number of nanoseconds to wait, or a time in * milliseconds from the epoch to wait for. */ void ParkHelper::park (jboolean isAbsolute, jlong time) { using namespace ::java::lang; volatile obj_addr_t *ptr = &permit; /* If we have a permit, return immediately. */ if (compare_and_swap (ptr, Thread::THREAD_PARK_PERMIT, Thread::THREAD_PARK_RUNNING)) return; struct timespec ts; jlong millis = 0, nanos = 0; if (time) { if (isAbsolute) { millis = time; nanos = 0; } else { millis = java::lang::System::currentTimeMillis(); nanos = time; } if (millis > 0 || nanos > 0) { // Calculate the abstime corresponding to the timeout. // Everything is in milliseconds. // // We use `unsigned long long' rather than jlong because our // caller may pass up to Long.MAX_VALUE millis. This would // overflow the range of a timespec. unsigned long long m = (unsigned long long)millis; unsigned long long seconds = m / 1000; ts.tv_sec = seconds; if (ts.tv_sec < 0 || (unsigned long long)ts.tv_sec != seconds) { // We treat a timeout that won't fit into a struct timespec // as a wait forever. millis = nanos = 0; } else { m %= 1000; ts.tv_nsec = m * 1000000 + (unsigned long long)nanos; } } } if (compare_and_swap (ptr, Thread::THREAD_PARK_RUNNING, Thread::THREAD_PARK_PARKED)) { pthread_mutex_lock (&mutex); if (millis == 0 && nanos == 0) pthread_cond_wait (&cond, &mutex); else pthread_cond_timedwait (&cond, &mutex, &ts); pthread_mutex_unlock (&mutex); /* If we were unparked by some other thread, this will already be in state THREAD_PARK_RUNNING. If we timed out, we have to do it ourself. */ compare_and_swap (ptr, Thread::THREAD_PARK_PARKED, Thread::THREAD_PARK_RUNNING); } }