Re: J2SE compliant RE for Arm Linux

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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);
    }
}



[Index of Archives]     [Linux Kernel]     [Linux Cryptography]     [Fedora]     [Fedora Directory]     [Red Hat Development]

  Powered by Linux