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
  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 
  95   Thread* owner() const { return _owner; }
  96   void set_owner(Thread* owner) { _owner = owner; }
  97   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);
 103   int magic() const { return _magic; }
 104   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 
 117   inline static GrowableArray<JvmtiRawMonitor*>* monitors() { return _monitors; }
 118 
 119   static void dispose() {
 120     delete monitors();
 121   }
 122 
 123  public:
 124   static void enter(JvmtiRawMonitor* monitor) {
 125     monitors()->append(monitor);
 126   }
 127 
 128   static int count() {
 129     return monitors()->length();
 130   }
 131 
 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.
 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