78 |
77 |
79 owningProcess |
78 owningProcess |
80 "Return the process that has acquired (entered) the receiver or |
79 "Return the process that has acquired (entered) the receiver or |
81 nil if no process currently has the monitor." |
80 nil if no process currently has the monitor." |
82 |
81 |
83 ^ owningProcess |
82 ^ process |
84 |
83 |
85 "Created: / 12-08-2017 / 23:11:44 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
84 "Created: / 12-08-2017 / 23:11:44 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
86 ! |
85 ! |
87 |
86 |
88 processesEntered |
87 processesEntered |
89 "Return a alist of processes that entered the monitor. For testing / debugging purposes only!!" |
88 "Return a alist of processes that entered the monitor. For testing / debugging purposes only!!" |
90 |
89 |
91 ^ owningProcess isNil |
90 ^ process isNil |
92 ifTrue:[ #() ] |
91 ifTrue:[ #() ] |
93 ifFalse:[ (Array with: owningProcess) , monitorSema waitingProcesses ] |
92 ifFalse:[ (Array with: process) , sema waitingProcesses ] |
94 |
93 |
95 "Created: / 20-11-2011 / 13:22:15 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
94 "Created: / 20-11-2011 / 13:22:15 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
96 "Modified (format): / 03-06-2017 / 23:10:31 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
95 "Modified (format): / 03-06-2017 / 23:10:31 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
97 ! ! |
96 ! ! |
98 |
97 |
134 |
133 |
135 "Created: / 30-11-2011 / 20:39:31 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
134 "Created: / 30-11-2011 / 20:39:31 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
136 "Modified: / 26-08-2012 / 17:25:55 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
135 "Modified: / 26-08-2012 / 17:25:55 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
137 ! |
136 ! |
138 |
137 |
139 initializeFor:owningObject thread:threadId nestedLockCount:cnt |
138 initializeFor:owningObject thread:threadId nestedLockCount:cnt |
140 |
139 |
141 "/ self assert: (owningObject isJavaObject or:[owningObject isJavaClass]). |
140 "/ self assert: (owningObject isJavaObject or:[owningObject isJavaClass]). |
142 |
141 |
143 waitEnabled := true. |
142 waitEnabled := true. |
144 waitingSema := Semaphore new:0. |
143 waitingSema := Semaphore new:0. |
145 ownerPrintString := owningObject class name , '@' , owningObject identityHash printString. |
144 ownerPrintString := owningObject class name , '@' , owningObject identityHash printString. |
146 |
145 |
147 "/Not locked... |
146 "/Not locked... |
148 threadId == 0 ifTrue:[ |
147 threadId == 0 ifTrue:[ |
149 monitorSema := Semaphore new:1. |
148 sema := Semaphore new:1. |
150 count := 0. |
149 count := 0. |
151 ^self. |
150 ^self. |
152 ] ifFalse: [ |
151 ] ifFalse: [ |
153 "threadId is not zero (zero is threadId of scheduler process, which will never try to acquire the monitor)" |
152 "threadId is not zero (zero is threadId of scheduler process, which will never try to acquire the monitor)" |
154 "so it means it is possible that the thin lock is already locked for other thread, we must be careful " |
153 "so it means it is possible that the thin lock is already locked for other thread, we must be careful " |
155 |
154 |
156 owningProcess := ObjectMemory processesKnownInVM detect:[:p|p id == threadId] ifNone:[nil]. |
155 process := ObjectMemory processesKnownInVM detect:[:p|p id == threadId] ifNone:[nil]. |
157 self assert: owningProcess notNil. |
156 self assert: process notNil. |
158 cnt timesRepeat:[ |
157 cnt timesRepeat:[ |
159 "/ JavaVM enteredMonitorsOf: owningProcess add: owningObject. |
158 "/ JavaVM enteredMonitorsOf: owningProcess add: owningObject. |
160 "/ JavaVM acquiredMonitorsOf: owningProcess add: owningObject. |
159 "/ JavaVM acquiredMonitorsOf: owningProcess add: owningObject. |
161 ]. |
160 ]. |
162 monitorSema := Semaphore new: 0. |
161 sema := Semaphore new: 0. |
163 count := cnt. |
162 count := cnt. |
164 ]. |
163 ]. |
165 |
164 |
166 "Created: / 26-08-2012 / 17:02:29 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
165 "Created: / 26-08-2012 / 17:02:29 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
167 "Modified: / 03-06-2017 / 23:10:47 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
166 "Modified: / 03-06-2017 / 23:10:47 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
172 acquire |
171 acquire |
173 "Acquire (enter) the monitor and return `true`. |
172 "Acquire (enter) the monitor and return `true`. |
174 |
173 |
175 See JVM spec, section 4.5, MONITORENTER. |
174 See JVM spec, section 4.5, MONITORENTER. |
176 " |
175 " |
177 | thisProcess wasBlocked hasAcquired | |
176 | active wasBlocked acquired | |
178 hasAcquired := nil. |
177 acquired := nil. |
179 thisProcess := Processor activeProcess. |
178 active := Processor activeProcess. |
180 owningProcess == thisProcess ifTrue:[ |
179 process == active ifTrue:[ |
181 "/ Process already ackquired the monitor, increase the |
180 "/ Process already ackquired the monitor, increase the |
182 "/ count and continue... |
181 "/ count and continue... |
183 count := count + 1. |
182 count := count + 1. |
184 ^self. |
183 ^true. |
185 ]. |
184 ]. |
186 wasBlocked := OperatingSystem blockInterrupts. |
185 wasBlocked := OperatingSystem blockInterrupts. |
187 [ |
186 [ |
188 (owningProcess notNil and:[ owningProcess isDead ]) ifTrue:[ |
187 (process notNil and:[ process isDead ]) ifTrue:[ |
189 "/ Process that acquired the monitor died without releasing it. |
188 "/ Process that acquired the monitor died without releasing it. |
190 "/ This should not happen. |
189 "/ This should not happen. |
191 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
190 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
192 self assert: false description: 'Process that acquired the monitor died without releasing it'. |
191 self assert: false description: 'Process that acquired the monitor died without releasing it'. |
193 owningProcess := nil. |
192 process := nil. |
194 count := 0. |
193 count := 0. |
195 ]. |
194 ]. |
196 "/ We need to know that we already waited on and got semaphore |
195 "/ We need to know that we already waited on and got semaphore |
197 "/ in case the Semaphore >> #wait is prematurely terminated. |
196 "/ in case the Semaphore >> #wait is prematurely terminated. |
198 "/ Q: Can this actually happen? If so, how? |
197 "/ Q: Can this actually happen? If so, how? |
199 hasAcquired := monitorSema wait. |
198 acquired := sema wait. |
200 owningProcess := thisProcess. |
199 process := active. |
201 count := 1. |
200 count := 1. |
202 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
201 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
203 ] ifCurtailed:[ |
202 ] ifCurtailed:[ |
204 hasAcquired notNil ifTrue:[ |
203 acquired notNil ifTrue:[ |
205 OperatingSystem blockInterrupts. |
204 OperatingSystem blockInterrupts. |
206 count := 0. |
205 count := 0. |
207 owningProcess := nil. |
206 process := nil. |
208 monitorSema signal. |
207 sema signal. |
209 ]. |
208 ]. |
210 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
209 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
211 ] |
210 ]. |
|
211 ^true. |
212 |
212 |
213 "Created: / 20-11-2011 / 13:21:46 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
213 "Created: / 20-11-2011 / 13:21:46 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
214 "Modified: / 11-08-2017 / 22:08:16 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
214 "Modified: / 11-08-2017 / 22:08:16 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
215 "Modified (comment): / 14-08-2017 / 09:34:16 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
215 "Modified (comment): / 14-08-2017 / 09:34:16 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
216 ! |
216 ! |
217 |
217 |
218 enter |
218 enter |
219 <resource: #obsolete> |
219 <resource: #obsolete> |
220 self obsoleteMethodWarning: 'Use #acquire instead'. |
220 self obsoleteMethodWarning: 'Use #acquire instead'. |
221 ^ self acquire. |
221 ^ self acquire. |
222 |
222 |
223 "Created: / 20-11-2011 / 13:21:42 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
223 "Created: / 20-11-2011 / 13:21:42 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
224 "Modified: / 14-08-2017 / 10:20:31 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
224 "Modified: / 14-08-2017 / 10:20:31 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
225 ! |
225 ! |
226 |
226 |
227 exit |
227 exit |
228 <resource: #obsolete> |
228 <resource: #obsolete> |
229 self obsoleteMethodWarning: 'Use #release instead'. |
229 self obsoleteMethodWarning: 'Use #release instead'. |
230 ^ self release. |
230 ^ self release. |
231 |
231 |
232 "Created: / 20-11-2011 / 13:21:54 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
232 "Created: / 20-11-2011 / 13:21:54 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
233 "Modified: / 14-08-2017 / 10:20:43 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
233 "Modified: / 14-08-2017 / 10:20:43 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
234 ! |
234 ! |
244 |
244 |
245 notify: all |
245 notify: all |
246 " |
246 " |
247 An implementation of java.lang.Object#notify() and #notifyAll(). If `all` is |
247 An implementation of java.lang.Object#notify() and #notifyAll(). If `all` is |
248 `true` then all waiting threads are notified (see #norifyAll()) otherwise only |
248 `true` then all waiting threads are notified (see #norifyAll()) otherwise only |
249 one thread is notified (see #notify()). Returns `true` after when threads have |
249 one thread is notified (see #notify()). Returns `true` after when threads have |
250 been notified or `false` if calling thread does not own the monitor. |
250 been notified or `false` if calling thread does not own the monitor. |
251 |
251 |
252 See Java API documentation for java.lang.Object#notify() and #notifyAll(). |
252 See Java API documentation for java.lang.Object#notify() and #notifyAll(). |
253 https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#notify() |
253 https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#notify() |
254 https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#notifyAll() |
254 https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#notifyAll() |
255 " |
255 " |
256 |
256 |
257 | thisProcess | |
257 | active | |
258 thisProcess := Processor activeProcess. |
258 active := Processor activeProcess. |
259 owningProcess == thisProcess ifFalse:[ |
259 process == active ifFalse:[ |
260 "/ Oops, calling thread does not own the monitor. return false |
260 "/ Oops, calling thread does not own the monitor. return false |
261 "/ immediately. The caller is responsible for throwing |
261 "/ immediately. The caller is responsible for throwing |
262 "/ IllegalMonitorStateException... |
262 "/ IllegalMonitorStateException... |
263 ^ false. |
263 ^ false. |
264 ]. |
264 ]. |
265 JavaVM monitorTrace ifTrue:[ |
265 JavaVM monitorTrace ifTrue:[ |
266 Logger |
266 Logger |
267 log: ('%1: notifying %1%2 processes' bindWith: thisProcess printString |
267 log: ('%1: notifying %1%2 processes' bindWith: active printString |
268 with: (all ifTrue:[ 'all ' ] ifFalse:[ '' ]) |
268 with: (all ifTrue:[ 'all ' ] ifFalse:[ '' ]) |
269 with: waitingSema waitingProcesses size) |
269 with: waitingSema waitingProcesses size) |
270 severity: Logger severityDEBUG |
270 severity: Logger severityDEBUG |
271 facility: #JVM. |
271 facility: #JVM. |
272 ]. |
272 ]. |
289 release |
289 release |
290 "Release (leave) the monitor and return `true` if |
290 "Release (leave) the monitor and return `true` if |
291 monitor was release, `false` if monitor has not |
291 monitor was release, `false` if monitor has not |
292 been released (because calling thread does not own it). |
292 been released (because calling thread does not own it). |
293 |
293 |
294 See JVM spec, section 4.5, MONITOREXIT. |
294 See JVM spec, section 4.5, MONITOREXIT. |
295 " |
295 " |
296 | thisProcess wasBlocked | |
296 | active wasBlocked | |
297 |
297 |
298 thisProcess := Processor activeProcess. |
298 active := Processor activeProcess. |
299 owningProcess == thisProcess ifFalse:[ |
299 process == active ifFalse:[ |
300 "/ Oops, calling thread does not own the monitor. return false |
300 "/ Oops, calling thread does not own the monitor. return false |
301 "/ immediately. The caller is responsible for throwing |
301 "/ immediately. The caller is responsible for throwing |
302 "/ IllegalMonitorStateException... |
302 "/ IllegalMonitorStateException... |
303 ^ false. |
303 ^ false. |
304 ]. |
304 ]. |
305 wasBlocked := OperatingSystem blockInterrupts. |
305 wasBlocked := OperatingSystem blockInterrupts. |
306 count == 1 ifTrue:[ |
306 count == 1 ifTrue:[ |
307 owningProcess := nil. |
307 process := nil. |
308 count := 0. |
308 count := 0. |
309 monitorSema signal. |
309 sema signal. |
310 ] ifFalse:[ |
310 ] ifFalse:[ |
311 count := count - 1. |
311 count := count - 1. |
312 ]. |
312 ]. |
313 wasBlocked ifFalse:[ OperatingSystem unblockInterrupts ]. |
313 wasBlocked ifFalse:[ OperatingSystem unblockInterrupts ]. |
314 ^ true |
314 ^ true |
315 |
315 |
317 "Modified: / 12-08-2017 / 21:28:38 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
317 "Modified: / 12-08-2017 / 21:28:38 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
318 "Modified (comment): / 14-08-2017 / 09:35:36 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
318 "Modified (comment): / 14-08-2017 / 09:35:36 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
319 ! |
319 ! |
320 |
320 |
321 wait |
321 wait |
322 <resource: #obsolete> |
322 <resource: #obsolete> |
323 self obsoleteFeatureWarning: 'Use `waitForMilliseconds: nil` insteead'. |
323 self obsoleteFeatureWarning: 'Use `waitForMilliseconds: nil` insteead'. |
324 ^ self waitForMilliseconds: nil. |
324 ^ self waitForMilliseconds: nil. |
325 |
325 |
326 "Created: / 22-11-2011 / 11:57:56 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
326 "Created: / 22-11-2011 / 11:57:56 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
327 "Modified: / 14-08-2017 / 09:37:18 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
327 "Modified: / 14-08-2017 / 09:37:18 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
328 ! |
328 ! |
329 |
329 |
330 waitForMilliseconds: timeOut |
330 waitForMilliseconds: timeOut |
331 " |
331 " |
332 An implementation of java.lang.Object#wait(long). Returns `true` |
332 An implementation of java.lang.Object#wait(long). Returns `true` |
333 after waiting or `false` immediately (i.e., won't block) if calling |
333 after waiting or `false` immediately (i.e., won't block) if calling |
334 thread does not own the monitor. |
334 thread does not own the monitor. |
335 |
335 |
336 See Java API documentation for java.lang.Object#wait(long): |
336 See Java API documentation for java.lang.Object#wait(long): |
337 https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait(long) |
337 https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait(long) |
338 " |
338 " |
339 |
339 |
340 | thisProcess countBeforeWait | |
340 | active countBeforeWait | |
341 thisProcess := Processor activeProcess. |
341 active := Processor activeProcess. |
342 owningProcess == thisProcess ifFalse:[ |
342 process == active ifFalse:[ |
343 "/ Oops, calling thread does not own the monitor. return false |
343 "/ Oops, calling thread does not own the monitor. return false |
344 "/ immediately. The caller is responsible for throwing |
344 "/ immediately. The caller is responsible for throwing |
345 "/ IllegalMonitorStateException... |
345 "/ IllegalMonitorStateException... |
346 ^ false. |
346 ^ false. |
347 ]. |
347 ]. |
348 self waitEnabled ifFalse: [ |
348 self waitEnabled ifFalse: [ |
349 JavaVM monitorTrace ifTrue:[ |
349 JavaVM monitorTrace ifTrue:[ |
350 Logger |
350 Logger |
351 log: ('%1 wanted to go to sleep, but it cant, this monitor is for %2 which is already dead' |
351 log: ('%1 wanted to go to sleep, but it cant, this monitor is for %2 which is already dead' |
352 bindWith: thisProcess printString |
352 bindWith: active printString |
353 with: ownerPrintString) |
353 with: ownerPrintString) |
354 severity: Logger severityDEBUG |
354 severity: Logger severityDEBUG |
355 facility: #JVM. |
355 facility: #JVM. |
356 ]. |
356 ]. |
357 ^ true. |
357 ^ true. |
358 ]. |
358 ]. |
359 JavaVM monitorTrace ifTrue:[ |
359 JavaVM monitorTrace ifTrue:[ |
360 Logger |
360 Logger |
361 log: ('%1 is going to wait on %3 for timeout: %2' |
361 log: ('%1 is going to wait on %3 for timeout: %2' |
362 bindWith: thisProcess printString |
362 bindWith: active printString |
363 with: timeOut |
363 with: timeOut |
364 with: ownerPrintString printString) |
364 with: ownerPrintString printString) |
365 severity: #debug |
365 severity: #debug |
366 facility: #JVM. |
366 facility: #JVM. |
367 ]. |
367 ]. |
374 "/ Monitor released, wait... |
374 "/ Monitor released, wait... |
375 "JV@2011-11-25: zero timeout means wait without timeout!!!!!!" |
375 "JV@2011-11-25: zero timeout means wait without timeout!!!!!!" |
376 timeOut == 0 ifTrue: [ waitingSema wait ] ifFalse: [ |
376 timeOut == 0 ifTrue: [ waitingSema wait ] ifFalse: [ |
377 waitingSema waitWithTimeoutMs: timeOut |
377 waitingSema waitWithTimeoutMs: timeOut |
378 ]. |
378 ]. |
379 JavaVM monitorTrace ifTrue:[ |
379 JavaVM monitorTrace ifTrue:[ |
380 Logger |
380 Logger |
381 log: ('%1 has been notified and is trying to acquire monitor for %2 which is owned by %3' |
381 log: ('%1 has been notified and is trying to acquire monitor for %2 which is owned by %3' |
382 bindWith: thisProcess printString with: ownerPrintString printString with: owningProcess printString) |
382 bindWith: active printString with: ownerPrintString printString with: process printString) |
383 severity: #debug |
383 severity: #debug |
384 facility: #JVM. |
384 facility: #JVM. |
385 ]. |
385 ]. |
386 "/ We have been notified, re-acquire the monitor |
386 "/ We have been notified, re-acquire the monitor |
387 self acquire. |
387 self acquire. |