src/os/bsd/vm/os_bsd.cpp

changeset 4471
22ba8c8ce6a6
parent 4468
c07c102cbad7
child 4564
758935f7c23f
     1.1 --- a/src/os/bsd/vm/os_bsd.cpp	Tue Jan 22 05:55:04 2013 -0800
     1.2 +++ b/src/os/bsd/vm/os_bsd.cpp	Tue Jan 22 05:56:42 2013 -0800
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -4094,11 +4094,12 @@
    1.11       }
    1.12       -- _nParked ;
    1.13  
    1.14 -    // In theory we could move the ST of 0 into _Event past the unlock(),
    1.15 -    // but then we'd need a MEMBAR after the ST.
    1.16      _Event = 0 ;
    1.17       status = pthread_mutex_unlock(_mutex);
    1.18       assert_status(status == 0, status, "mutex_unlock");
    1.19 +    // Paranoia to ensure our locked and lock-free paths interact
    1.20 +    // correctly with each other.
    1.21 +    OrderAccess::fence();
    1.22    }
    1.23    guarantee (_Event >= 0, "invariant") ;
    1.24  }
    1.25 @@ -4161,40 +4162,44 @@
    1.26    status = pthread_mutex_unlock(_mutex);
    1.27    assert_status(status == 0, status, "mutex_unlock");
    1.28    assert (_nParked == 0, "invariant") ;
    1.29 +  // Paranoia to ensure our locked and lock-free paths interact
    1.30 +  // correctly with each other.
    1.31 +  OrderAccess::fence();
    1.32    return ret;
    1.33  }
    1.34  
    1.35  void os::PlatformEvent::unpark() {
    1.36 -  int v, AnyWaiters ;
    1.37 -  for (;;) {
    1.38 -      v = _Event ;
    1.39 -      if (v > 0) {
    1.40 -         // The LD of _Event could have reordered or be satisfied
    1.41 -         // by a read-aside from this processor's write buffer.
    1.42 -         // To avoid problems execute a barrier and then
    1.43 -         // ratify the value.
    1.44 -         OrderAccess::fence() ;
    1.45 -         if (_Event == v) return ;
    1.46 -         continue ;
    1.47 -      }
    1.48 -      if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ;
    1.49 +  // Transitions for _Event:
    1.50 +  //    0 :=> 1
    1.51 +  //    1 :=> 1
    1.52 +  //   -1 :=> either 0 or 1; must signal target thread
    1.53 +  //          That is, we can safely transition _Event from -1 to either
    1.54 +  //          0 or 1. Forcing 1 is slightly more efficient for back-to-back
    1.55 +  //          unpark() calls.
    1.56 +  // See also: "Semaphores in Plan 9" by Mullender & Cox
    1.57 +  //
    1.58 +  // Note: Forcing a transition from "-1" to "1" on an unpark() means
    1.59 +  // that it will take two back-to-back park() calls for the owning
    1.60 +  // thread to block. This has the benefit of forcing a spurious return
    1.61 +  // from the first park() call after an unpark() call which will help
    1.62 +  // shake out uses of park() and unpark() without condition variables.
    1.63 +
    1.64 +  if (Atomic::xchg(1, &_Event) >= 0) return;
    1.65 +
    1.66 +  // Wait for the thread associated with the event to vacate
    1.67 +  int status = pthread_mutex_lock(_mutex);
    1.68 +  assert_status(status == 0, status, "mutex_lock");
    1.69 +  int AnyWaiters = _nParked;
    1.70 +  assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant");
    1.71 +  if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) {
    1.72 +    AnyWaiters = 0;
    1.73 +    pthread_cond_signal(_cond);
    1.74    }
    1.75 -  if (v < 0) {
    1.76 -     // Wait for the thread associated with the event to vacate
    1.77 -     int status = pthread_mutex_lock(_mutex);
    1.78 -     assert_status(status == 0, status, "mutex_lock");
    1.79 -     AnyWaiters = _nParked ;
    1.80 -     assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ;
    1.81 -     if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) {
    1.82 -        AnyWaiters = 0 ;
    1.83 -        pthread_cond_signal (_cond);
    1.84 -     }
    1.85 -     status = pthread_mutex_unlock(_mutex);
    1.86 -     assert_status(status == 0, status, "mutex_unlock");
    1.87 -     if (AnyWaiters != 0) {
    1.88 -        status = pthread_cond_signal(_cond);
    1.89 -        assert_status(status == 0, status, "cond_signal");
    1.90 -     }
    1.91 +  status = pthread_mutex_unlock(_mutex);
    1.92 +  assert_status(status == 0, status, "mutex_unlock");
    1.93 +  if (AnyWaiters != 0) {
    1.94 +    status = pthread_cond_signal(_cond);
    1.95 +    assert_status(status == 0, status, "cond_signal");
    1.96    }
    1.97  
    1.98    // Note that we signal() _after dropping the lock for "immortal" Events.
    1.99 @@ -4280,13 +4285,14 @@
   1.100  }
   1.101  
   1.102  void Parker::park(bool isAbsolute, jlong time) {
   1.103 +  // Ideally we'd do something useful while spinning, such
   1.104 +  // as calling unpackTime().
   1.105 +
   1.106    // Optional fast-path check:
   1.107    // Return immediately if a permit is available.
   1.108 -  if (_counter > 0) {
   1.109 -      _counter = 0 ;
   1.110 -      OrderAccess::fence();
   1.111 -      return ;
   1.112 -  }
   1.113 +  // We depend on Atomic::xchg() having full barrier semantics
   1.114 +  // since we are doing a lock-free update to _counter.
   1.115 +  if (Atomic::xchg(0, &_counter) > 0) return;
   1.116  
   1.117    Thread* thread = Thread::current();
   1.118    assert(thread->is_Java_thread(), "Must be JavaThread");
   1.119 @@ -4327,6 +4333,8 @@
   1.120      _counter = 0;
   1.121      status = pthread_mutex_unlock(_mutex);
   1.122      assert (status == 0, "invariant") ;
   1.123 +    // Paranoia to ensure our locked and lock-free paths interact
   1.124 +    // correctly with each other and Java-level accesses.
   1.125      OrderAccess::fence();
   1.126      return;
   1.127    }
   1.128 @@ -4363,12 +4371,14 @@
   1.129    _counter = 0 ;
   1.130    status = pthread_mutex_unlock(_mutex) ;
   1.131    assert_status(status == 0, status, "invariant") ;
   1.132 +  // Paranoia to ensure our locked and lock-free paths interact
   1.133 +  // correctly with each other and Java-level accesses.
   1.134 +  OrderAccess::fence();
   1.135 +
   1.136    // If externally suspended while waiting, re-suspend
   1.137    if (jt->handle_special_suspend_equivalent_condition()) {
   1.138      jt->java_suspend_self();
   1.139    }
   1.140 -
   1.141 -  OrderAccess::fence();
   1.142  }
   1.143  
   1.144  void Parker::unpark() {

mercurial