1 /* 2 * Copyright (c) 2017, 2019, Red Hat, Inc. 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_GC_SHENANDOAH_SHENANDOAHLOCK_HPP 26 #define SHARE_GC_SHENANDOAH_SHENANDOAHLOCK_HPP 27 28 #include "gc/shenandoah/shenandoahPadding.hpp" 29 #include "memory/allocation.hpp" 30 #include "runtime/safepoint.hpp" 31 #include "runtime/thread.hpp" 32 33 class ShenandoahLock { 34 private: 35 enum LockState { unlocked = 0, locked = 1 }; 36 37 shenandoah_padding(0); 38 volatile int _state; 39 shenandoah_padding(1); 40 volatile Thread* _owner; 41 shenandoah_padding(2); 42 43 public: 44 ShenandoahLock() : _state(unlocked), _owner(NULL) {}; 45 46 void lock() { 47 #ifdef ASSERT 48 assert(_owner != Thread::current(), "reentrant locking attempt, would deadlock"); 49 #endif 50 Thread::SpinAcquire(&_state, "Shenandoah Heap Lock"); 51 #ifdef ASSERT 52 assert(_state == locked, "must be locked"); 53 assert(_owner == NULL, "must not be owned"); 54 _owner = Thread::current(); 55 #endif 56 } 57 58 void unlock() { 59 #ifdef ASSERT 60 assert (_owner == Thread::current(), "sanity"); 61 _owner = NULL; 62 #endif 63 Thread::SpinRelease(&_state); 64 } 65 66 bool owned_by_self() { 67 #ifdef ASSERT 68 return _state == locked && _owner == Thread::current(); 69 #else 70 ShouldNotReachHere(); 71 return false; 72 #endif 73 } 74 }; 75 76 class ShenandoahLocker : public StackObj { 77 private: 78 ShenandoahLock* const _lock; 79 public: 80 ShenandoahLocker(ShenandoahLock* lock) : _lock(lock) { 81 if (_lock != NULL) { 82 _lock->lock(); 83 } 84 } 85 86 ~ShenandoahLocker() { 87 if (_lock != NULL) { 88 _lock->unlock(); 89 } 90 } 91 }; 92 93 class ShenandoahSimpleLock { 94 private: 95 os::PlatformMonitor _lock; // native lock 96 public: 97 ShenandoahSimpleLock(); 98 99 virtual void lock(); 100 virtual void unlock(); 101 virtual bool try_lock(); 102 }; 103 104 class ShenandoahReentrantLock : public ShenandoahSimpleLock { 105 private: 106 Thread* volatile _owner; 107 uint64_t _count; 108 109 public: 110 ShenandoahReentrantLock(); 111 ~ShenandoahReentrantLock(); 112 113 virtual void lock(); 114 virtual void unlock(); 115 virtual bool try_lock(); 116 117 // If the lock already owned by this thread 118 bool owned_by_self() const ; 119 }; 120 121 class ShenandoahReentrantLocker : public StackObj { 122 private: 123 ShenandoahReentrantLock* const _lock; 124 125 public: 126 ShenandoahReentrantLocker(ShenandoahReentrantLock* lock) : 127 _lock(lock) { 128 if (_lock != NULL) { 129 _lock->lock(); 130 } 131 } 132 133 ~ShenandoahReentrantLocker() { 134 if (_lock != NULL) { 135 assert(_lock->owned_by_self(), "Must be owner"); 136 _lock->unlock(); 137 } 138 } 139 }; 140 141 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHLOCK_HPP