1/*
2 * Copyright (c) 2017, 2019, Red Hat, Inc. All rights reserved.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHLOCK_HPP
25#define SHARE_GC_SHENANDOAH_SHENANDOAHLOCK_HPP
26
27#include "memory/allocation.hpp"
28#include "runtime/thread.hpp"
29
30class ShenandoahLock {
31private:
32 enum LockState { unlocked = 0, locked = 1 };
33
34 DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile int));
35 volatile int _state;
36 DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile Thread*));
37 volatile Thread* _owner;
38 DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, 0);
39
40public:
41 ShenandoahLock() : _state(unlocked), _owner(NULL) {};
42
43 void lock() {
44 Thread::SpinAcquire(&_state, "Shenandoah Heap Lock");
45#ifdef ASSERT
46 assert(_state == locked, "must be locked");
47 assert(_owner == NULL, "must not be owned");
48 _owner = Thread::current();
49#endif
50 }
51
52 void unlock() {
53#ifdef ASSERT
54 assert (_owner == Thread::current(), "sanity");
55 _owner = NULL;
56#endif
57 Thread::SpinRelease(&_state);
58 }
59
60#ifdef ASSERT
61 void assert_owned_by_current_thread() {
62 assert(_state == locked, "must be locked");
63 assert(_owner == Thread::current(), "must be owned by current thread");
64 }
65
66 void assert_not_owned_by_current_thread() {
67 assert(_owner != Thread::current(), "must be not owned by current thread");
68 }
69
70 void assert_owned_by_current_thread_or_safepoint() {
71 Thread* thr = Thread::current();
72 assert((_state == locked && _owner == thr) ||
73 (SafepointSynchronize::is_at_safepoint() && thr->is_VM_thread()),
74 "must own heap lock or by VM thread at safepoint");
75 }
76#endif
77};
78
79class ShenandoahLocker : public StackObj {
80private:
81 ShenandoahLock* const _lock;
82public:
83 ShenandoahLocker(ShenandoahLock* lock) : _lock(lock) {
84 if (_lock != NULL) {
85 _lock->lock();
86 }
87 }
88
89 ~ShenandoahLocker() {
90 if (_lock != NULL) {
91 _lock->unlock();
92 }
93 }
94};
95
96#endif // SHARE_GC_SHENANDOAH_SHENANDOAHLOCK_HPP
97