1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_UTILITIES_WAITBARRIER_HPP
  26 #define SHARE_UTILITIES_WAITBARRIER_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "runtime/thread.hpp"
  30 #include "utilities/debug.hpp"
  31 #include "utilities/waitBarrier_generic.hpp"
  32 
  33 #if defined(LINUX)
  34 #include "waitBarrier_linux.hpp"
  35 typedef LinuxWaitBarrier WaitBarrierDefault;
  36 #else
  37 typedef GenericWaitBarrier WaitBarrierDefault;
  38 #endif
  39 
  40 // Platform independent WaitBarrier API.
  41 // An armed WaitBarrier prevents threads from advancing until the
  42 // barrier is disarmed and the waiting threads woken. The barrier is
  43 // armed by setting a non-zero value - the tag.
  44 //
  45 // Expected Usage:
  46 //  - Arming thread:
  47 //     tag = ...;  // non-zero value
  48 //     barrier.arm(tag);
  49 //     <publish tag>
  50 //     <work>
  51 //     barrier.disarm();
  52 //     barrier.wake();
  53 //
  54 //    - After arm(tag) returns any thread calling wait(tag) will block.
  55 //    - After disarm() returns any subsequent calls to wait(tag) will not block.
  56 //    - After wake() returns all blocked threads are unblocked and eligible to
  57 //      execute again.
  58 //    - After calling disarm() and wake() the barrier is ready to be re-armed
  59 //      with a new tag. (may not be re-armed with last used tag)
  60 //
  61 //  - Waiting threads
  62 //     wait(tag); // don't execute following code unless 'safe'
  63 //     <work>
  64 //
  65 //    - A call to wait(tag) will block if the barrier is armed with the value
  66 //      'tag'; else it will return immediately.
  67 //    - A blocked thread is eligible to execute again once the barrier is
  68 //      disarmed and wake() has been called.
  69 //
  70 // A primary goal of the WaitBarrier implementation is to wake all waiting
  71 // threads as fast, and as concurrently, as possible.
  72 //
  73 template <typename WaitBarrierImpl>
  74 class WaitBarrierType : public CHeapObj<mtInternal> {
  75   WaitBarrierImpl _impl;
  76 
  77   // Prevent copying and assignment of WaitBarrier instances.
  78   WaitBarrierType(const WaitBarrierDefault&);
  79   WaitBarrierType& operator=(const WaitBarrierDefault&);
  80 
  81 #ifdef ASSERT
  82   int _last_arm_tag;
  83   Thread* _owner;
  84 #endif
  85 
  86  public:
  87   WaitBarrierType(Thread* owner) : _impl() {
  88 #ifdef ASSERT
  89     _last_arm_tag = 0;
  90     _owner = owner;
  91 #endif
  92   }
  93   ~WaitBarrierType() {}
  94 
  95   // Returns implementation type.
  96   const char* description()    { return _impl.description(); }
  97 
  98   // Guarantees any thread calling wait() with same tag will be blocked.
  99   // Provides a trailing fence.
 100   void arm(int barrier_tag) {
 101 #ifdef ASSERT
 102   assert(_last_arm_tag != barrier_tag, "Re-arming with same tag");
 103   _last_arm_tag = barrier_tag;
 104   assert(_owner == Thread::current(), "Not owner thread");
 105 #endif
 106     _impl.arm(barrier_tag);
 107   }
 108 
 109   // Guarantees any thread calling wait() with any tag will not be blocked.
 110   // Provides a trailing fence.
 111   void disarm() {
 112     assert(_owner == Thread::current(), "Not owner thread");
 113     _impl.disarm();
 114   }
 115 
 116   // Guarantees any thread called wait() will be awake when it returns.
 117   // Provides a trailing fence.
 118   void wake() {
 119     assert(_owner == Thread::current(), "Not owner thread");
 120     _impl.wake();
 121   }
 122 
 123   // Guarantees to return if disarm() and wake() is called.
 124   // Provides a trailing fence.
 125   void wait(int barrier_tag) {
 126     assert(_owner != Thread::current(), "Trying to wait with owner thread");
 127     _impl.wait(barrier_tag);
 128   }
 129 };
 130 
 131 typedef WaitBarrierType<WaitBarrierDefault> WaitBarrier;
 132 
 133 #endif // SHARE_UTILITIES_WAITBARRIER_HPP