src/os/linux/vm/os_linux.cpp

changeset 4471
22ba8c8ce6a6
parent 4392
7d42f3b08300
child 4535
9fae07c31641
     1.1 --- a/src/os/linux/vm/os_linux.cpp	Tue Jan 22 05:55:04 2013 -0800
     1.2 +++ b/src/os/linux/vm/os_linux.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 @@ -5001,11 +5001,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 @@ -5068,40 +5069,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 -  }
    1.50 -  if (v < 0) {
    1.51 -     // Wait for the thread associated with the event to vacate
    1.52 -     int status = pthread_mutex_lock(_mutex);
    1.53 -     assert_status(status == 0, status, "mutex_lock");
    1.54 -     AnyWaiters = _nParked ;
    1.55 -     assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ;
    1.56 -     if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) {
    1.57 -        AnyWaiters = 0 ;
    1.58 -        pthread_cond_signal (_cond);
    1.59 -     }
    1.60 -     status = pthread_mutex_unlock(_mutex);
    1.61 -     assert_status(status == 0, status, "mutex_unlock");
    1.62 -     if (AnyWaiters != 0) {
    1.63 -        status = pthread_cond_signal(_cond);
    1.64 -        assert_status(status == 0, status, "cond_signal");
    1.65 -     }
    1.66 +  // Transitions for _Event:
    1.67 +  //    0 :=> 1
    1.68 +  //    1 :=> 1
    1.69 +  //   -1 :=> either 0 or 1; must signal target thread
    1.70 +  //          That is, we can safely transition _Event from -1 to either
    1.71 +  //          0 or 1. Forcing 1 is slightly more efficient for back-to-back
    1.72 +  //          unpark() calls.
    1.73 +  // See also: "Semaphores in Plan 9" by Mullender & Cox
    1.74 +  //
    1.75 +  // Note: Forcing a transition from "-1" to "1" on an unpark() means
    1.76 +  // that it will take two back-to-back park() calls for the owning
    1.77 +  // thread to block. This has the benefit of forcing a spurious return
    1.78 +  // from the first park() call after an unpark() call which will help
    1.79 +  // shake out uses of park() and unpark() without condition variables.
    1.80 +
    1.81 +  if (Atomic::xchg(1, &_Event) >= 0) return;
    1.82 +
    1.83 +  // Wait for the thread associated with the event to vacate
    1.84 +  int status = pthread_mutex_lock(_mutex);
    1.85 +  assert_status(status == 0, status, "mutex_lock");
    1.86 +  int AnyWaiters = _nParked;
    1.87 +  assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant");
    1.88 +  if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) {
    1.89 +    AnyWaiters = 0;
    1.90 +    pthread_cond_signal(_cond);
    1.91 +  }
    1.92 +  status = pthread_mutex_unlock(_mutex);
    1.93 +  assert_status(status == 0, status, "mutex_unlock");
    1.94 +  if (AnyWaiters != 0) {
    1.95 +    status = pthread_cond_signal(_cond);
    1.96 +    assert_status(status == 0, status, "cond_signal");
    1.97    }
    1.98  
    1.99    // Note that we signal() _after dropping the lock for "immortal" Events.
   1.100 @@ -5187,13 +5192,14 @@
   1.101  }
   1.102  
   1.103  void Parker::park(bool isAbsolute, jlong time) {
   1.104 +  // Ideally we'd do something useful while spinning, such
   1.105 +  // as calling unpackTime().
   1.106 +
   1.107    // Optional fast-path check:
   1.108    // Return immediately if a permit is available.
   1.109 -  if (_counter > 0) {
   1.110 -      _counter = 0 ;
   1.111 -      OrderAccess::fence();
   1.112 -      return ;
   1.113 -  }
   1.114 +  // We depend on Atomic::xchg() having full barrier semantics
   1.115 +  // since we are doing a lock-free update to _counter.
   1.116 +  if (Atomic::xchg(0, &_counter) > 0) return;
   1.117  
   1.118    Thread* thread = Thread::current();
   1.119    assert(thread->is_Java_thread(), "Must be JavaThread");
   1.120 @@ -5234,6 +5240,8 @@
   1.121      _counter = 0;
   1.122      status = pthread_mutex_unlock(_mutex);
   1.123      assert (status == 0, "invariant") ;
   1.124 +    // Paranoia to ensure our locked and lock-free paths interact
   1.125 +    // correctly with each other and Java-level accesses.
   1.126      OrderAccess::fence();
   1.127      return;
   1.128    }
   1.129 @@ -5270,12 +5278,14 @@
   1.130    _counter = 0 ;
   1.131    status = pthread_mutex_unlock(_mutex) ;
   1.132    assert_status(status == 0, status, "invariant") ;
   1.133 +  // Paranoia to ensure our locked and lock-free paths interact
   1.134 +  // correctly with each other and Java-level accesses.
   1.135 +  OrderAccess::fence();
   1.136 +
   1.137    // If externally suspended while waiting, re-suspend
   1.138    if (jt->handle_special_suspend_equivalent_condition()) {
   1.139      jt->java_suspend_self();
   1.140    }
   1.141 -
   1.142 -  OrderAccess::fence();
   1.143  }
   1.144  
   1.145  void Parker::unpark() {

mercurial