1 /* 2 * Copyright (c) 1999, 2019, 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_PRIMS_JVMTIRAWMONITOR_HPP 26 #define SHARE_PRIMS_JVMTIRAWMONITOR_HPP 27 28 #include "memory/allocation.hpp" 29 #include "runtime/park.hpp" 30 #include "utilities/growableArray.hpp" 31 32 // 33 // class JvmtiRawMonitor 34 // 35 // Used by JVMTI methods: All RawMonitor methods (CreateRawMonitor, EnterRawMonitor, etc.) 36 // 37 // A simplified version of the ObjectMonitor code. 38 // 39 40 class JvmtiRawMonitor : public CHeapObj<mtSynchronizer> { 41 42 // Helper class to allow Threads to be linked into queues. 43 // This is a stripped down version of ObjectWaiter. 44 class QNode : public StackObj { 45 friend class JvmtiRawMonitor; 46 enum TStates { TS_READY, TS_RUN, TS_WAIT, TS_ENTER }; 47 QNode* volatile _next; 48 QNode* volatile _prev; 49 ParkEvent* _event; 50 volatile int _notified; 51 volatile TStates _t_state; 52 53 QNode(Thread* thread); 54 }; 55 56 Thread* volatile _owner; // pointer to owning thread 57 volatile int _recursions; // recursion count, 0 for first entry 58 QNode* volatile _entry_list; // Threads blocked on entry or reentry. 59 // The list is actually composed of nodes, 60 // acting as proxies for Threads. 61 QNode* volatile _wait_set; // Threads wait()ing on the monitor 62 volatile jint _waiters; // number of waiting threads 63 int _magic; 64 char* _name; 65 // JVMTI_RM_MAGIC is set in contructor and unset in destructor. 66 enum { JVMTI_RM_MAGIC = (int)(('T' << 24) | ('I' << 16) | ('R' << 8) | 'M') }; 67 68 // Helpers for queue management isolation 69 void enqueue_waiter(QNode& node); 70 void dequeue_waiter(QNode& node); 71 72 // Mostly low-level implementation routines 73 void simple_enter(Thread* self); 74 void simple_exit(Thread* self); 75 int simple_wait(Thread* self, jlong millis); 76 void simple_notify(Thread* self, bool all); 77 78 public: 79 80 // return codes 81 enum { 82 M_OK, // no error 83 M_ILLEGAL_MONITOR_STATE, // IllegalMonitorStateException 84 M_INTERRUPTED // Thread.interrupt() 85 }; 86 87 // Non-aborting operator new operator new(size_t size)88 void* operator new(size_t size) throw() { 89 return CHeapObj::operator new(size, std::nothrow); 90 } 91 92 JvmtiRawMonitor(const char* name); 93 ~JvmtiRawMonitor(); 94 owner() const95 Thread* owner() const { return _owner; } set_owner(Thread * owner)96 void set_owner(Thread* owner) { _owner = owner; } recursions() const97 int recursions() const { return _recursions; } 98 void raw_enter(Thread* self); 99 int raw_exit(Thread* self); 100 int raw_wait(jlong millis, Thread* self); 101 int raw_notify(Thread* self); 102 int raw_notifyAll(Thread* self); magic() const103 int magic() const { return _magic; } get_name() const104 const char* get_name() const { return _name; } 105 bool is_valid(); 106 }; 107 108 // Onload pending raw monitors 109 // Class is used to cache onload or onstart monitor enter 110 // which will transition into real monitor when 111 // VM is fully initialized. 112 class JvmtiPendingMonitors : public AllStatic { 113 114 private: 115 static GrowableArray<JvmtiRawMonitor*>* _monitors; // Cache raw monitor enter 116 monitors()117 inline static GrowableArray<JvmtiRawMonitor*>* monitors() { return _monitors; } 118 dispose()119 static void dispose() { 120 delete monitors(); 121 } 122 123 public: enter(JvmtiRawMonitor * monitor)124 static void enter(JvmtiRawMonitor* monitor) { 125 monitors()->append(monitor); 126 } 127 count()128 static int count() { 129 return monitors()->length(); 130 } 131 destroy(JvmtiRawMonitor * monitor)132 static void destroy(JvmtiRawMonitor* monitor) { 133 while (monitors()->contains(monitor)) { 134 monitors()->remove(monitor); 135 } 136 } 137 138 // Return false if monitor is not found in the list. exit(JvmtiRawMonitor * monitor)139 static bool exit(JvmtiRawMonitor* monitor) { 140 if (monitors()->contains(monitor)) { 141 monitors()->remove(monitor); 142 return true; 143 } else { 144 return false; 145 } 146 } 147 148 static void transition_raw_monitors(); 149 }; 150 151 #endif // SHARE_PRIMS_JVMTIRAWMONITOR_HPP 152