< prev index next >

src/hotspot/share/prims/jvmtiRawMonitor.cpp

Print this page

106 }
107 
108 // -------------------------------------------------------------------------
109 // The JVMTI raw monitor subsystem is entirely distinct from normal
110 // java-synchronization or jni-synchronization.  JVMTI raw monitors are not
111 // associated with objects.  They can be implemented in any manner
112 // that makes sense.  The original implementors decided to piggy-back
113 // the raw-monitor implementation on the existing Java ObjectMonitor mechanism.
114 // Now we just use a simplified form of that ObjectMonitor code.
115 //
116 // Note that we use the single RawMonitor_lock to protect queue operations for
117 // _all_ raw monitors.  This is a scalability impediment, but since raw monitor usage
118 // is fairly rare, this is not of concern.  The RawMonitor_lock can not
119 // be held indefinitely.  The critical sections must be short and bounded.
120 //
121 // -------------------------------------------------------------------------
122 
123 void JvmtiRawMonitor::simple_enter(Thread* self) {
124   for (;;) {
125     if (Atomic::replace_if_null(&_owner, self)) {



126       return;
127     }
128 
129     QNode node(self);
130     self->_ParkEvent->reset();     // strictly optional
131     node._t_state = QNode::TS_ENTER;
132 
133     RawMonitor_lock->lock_without_safepoint_check();
134     node._next = _entry_list;
135     _entry_list = &node;
136     OrderAccess::fence();
137     if (_owner == NULL && Atomic::replace_if_null(&_owner, self)) {
138       _entry_list = node._next;
139       RawMonitor_lock->unlock();



140       return;
141     }
142     RawMonitor_lock->unlock();
143     while (node._t_state == QNode::TS_ENTER) {
144       self->_ParkEvent->park();
145     }
146   }
147 }
148 
149 void JvmtiRawMonitor::simple_exit(Thread* self) {
150   guarantee(_owner == self, "invariant");
151   Atomic::release_store(&_owner, (Thread*)NULL);
152   OrderAccess::fence();



153   if (_entry_list == NULL) {
154     return;
155   }
156 
157   RawMonitor_lock->lock_without_safepoint_check();
158   QNode* w = _entry_list;
159   if (w != NULL) {
160     _entry_list = w->_next;
161   }
162   RawMonitor_lock->unlock();
163   if (w != NULL) {
164     guarantee(w ->_t_state == QNode::TS_ENTER, "invariant");
165     // Once we set _t_state to TS_RUN the waiting thread can complete
166     // simple_enter and 'w' is pointing into random stack space. So we have
167     // to ensure we extract the ParkEvent (which is in type-stable memory)
168     // before we set the state, and then don't access 'w'.
169     ParkEvent* ev = w->_event;
170     OrderAccess::loadstore();
171     w->_t_state = QNode::TS_RUN;
172     OrderAccess::fence();

106 }
107 
108 // -------------------------------------------------------------------------
109 // The JVMTI raw monitor subsystem is entirely distinct from normal
110 // java-synchronization or jni-synchronization.  JVMTI raw monitors are not
111 // associated with objects.  They can be implemented in any manner
112 // that makes sense.  The original implementors decided to piggy-back
113 // the raw-monitor implementation on the existing Java ObjectMonitor mechanism.
114 // Now we just use a simplified form of that ObjectMonitor code.
115 //
116 // Note that we use the single RawMonitor_lock to protect queue operations for
117 // _all_ raw monitors.  This is a scalability impediment, but since raw monitor usage
118 // is fairly rare, this is not of concern.  The RawMonitor_lock can not
119 // be held indefinitely.  The critical sections must be short and bounded.
120 //
121 // -------------------------------------------------------------------------
122 
123 void JvmtiRawMonitor::simple_enter(Thread* self) {
124   for (;;) {
125     if (Atomic::replace_if_null(&_owner, self)) {
126       if (self->is_Java_thread()) {
127         Continuation::pin(JavaThread::cast(self));
128       }
129       return;
130     }
131 
132     QNode node(self);
133     self->_ParkEvent->reset();     // strictly optional
134     node._t_state = QNode::TS_ENTER;
135 
136     RawMonitor_lock->lock_without_safepoint_check();
137     node._next = _entry_list;
138     _entry_list = &node;
139     OrderAccess::fence();
140     if (_owner == NULL && Atomic::replace_if_null(&_owner, self)) {
141       _entry_list = node._next;
142       RawMonitor_lock->unlock();
143       if (self->is_Java_thread()) {
144         Continuation::pin(JavaThread::cast(self));
145       }
146       return;
147     }
148     RawMonitor_lock->unlock();
149     while (node._t_state == QNode::TS_ENTER) {
150       self->_ParkEvent->park();
151     }
152   }
153 }
154 
155 void JvmtiRawMonitor::simple_exit(Thread* self) {
156   guarantee(_owner == self, "invariant");
157   Atomic::release_store(&_owner, (Thread*)NULL);
158   OrderAccess::fence();
159   if (self->is_Java_thread()) {
160     Continuation::unpin(JavaThread::cast(self));
161   }
162   if (_entry_list == NULL) {
163     return;
164   }
165 
166   RawMonitor_lock->lock_without_safepoint_check();
167   QNode* w = _entry_list;
168   if (w != NULL) {
169     _entry_list = w->_next;
170   }
171   RawMonitor_lock->unlock();
172   if (w != NULL) {
173     guarantee(w ->_t_state == QNode::TS_ENTER, "invariant");
174     // Once we set _t_state to TS_RUN the waiting thread can complete
175     // simple_enter and 'w' is pointing into random stack space. So we have
176     // to ensure we extract the ParkEvent (which is in type-stable memory)
177     // before we set the state, and then don't access 'w'.
178     ParkEvent* ev = w->_event;
179     OrderAccess::loadstore();
180     w->_t_state = QNode::TS_RUN;
181     OrderAccess::fence();
< prev index next >