175 ! ! |
175 ! ! |
176 |
176 |
177 !JavaMonitor methodsFor:'public'! |
177 !JavaMonitor methodsFor:'public'! |
178 |
178 |
179 acquire |
179 acquire |
180 | thisProcess | |
180 | thisProcess wasBlocked hasAcquired | |
181 thisProcess := Processor activeProcess. |
181 hasAcquired := nil. |
182 (self isOwnedBy: thisProcess) ifTrue: [ |
182 thisProcess := Processor activeProcess. |
183 "/ the lock is probably not helping here to protect against problems with |
183 owningProcess == thisProcess ifTrue:[ |
184 "/ increment/decrement: |
184 "/ Process already ackquired the monitor, increase the |
185 "/ the write-access (in reinitCOunter) will be either done before incrementing/decrementing or after. |
185 "/ count and continue... |
186 "/ if after, everything is ok; |
186 count := count + 1. |
187 "/ if before, the decremented value will be zero, which is probably wrong. |
187 ^self. |
188 |
188 ]. |
189 "/ without the critical region, we might also get possible inconsistencies: |
189 wasBlocked := OperatingSystem blockInterrupts. |
190 "/ if written before, the counter will drop to zero |
190 [ |
191 "/ if written in-between, the counter wil ahve the old value decremented; |
191 (owningProcess notNil and:[ owningProcess isDead ]) ifTrue:[ |
192 "/ if written afterwards, everything is ok. |
192 "/ Process that acquired the monitor died without releasing it. |
193 |
193 "/ This should not happen. |
194 "/ so, the lock should be really elsewhere, making sure that noone will count |
194 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
195 "/ the monitor at-all and the monitor is reininialized without anyone depending on the |
195 self assert: false description: 'Process that acquired the monitor died without releasing it'. |
196 "/ count at all. |
196 owningProcess := nil. |
197 "/ but then, no critical section is needed in reinitCounter!!. |
197 count := 0. |
198 |
198 ]. |
199 self instVarAccessCritical: [ count := count + 1 ]. |
199 "/ We need to know that we already waited on and got semaphore |
200 ^ self |
200 "/ in case the Semaphore >> #wait is prematurely terminated. |
201 ]. |
201 "/ Q: Can this actually happen? If so, how? |
202 monitorSema wait. |
202 hasAcquired := monitorSema wait. |
203 owningProcess := thisProcess. |
203 owningProcess := thisProcess. |
204 count := 1. |
204 count := 1. |
|
205 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
206 ] ifCurtailed:[ |
|
207 hasAcquired notNil ifTrue:[ |
|
208 OperatingSystem blockInterrupts. |
|
209 count := 0. |
|
210 owningProcess := nil. |
|
211 monitorSema signal. |
|
212 ]. |
|
213 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
214 ] |
205 |
215 |
206 "Created: / 20-11-2011 / 13:21:46 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
216 "Created: / 20-11-2011 / 13:21:46 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
207 "Modified: / 03-06-2017 / 22:36:04 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
217 "Modified: / 11-08-2017 / 22:08:16 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
208 ! |
218 ! |
209 |
219 |
210 enter |
220 enter |
211 self acquire. |
221 self acquire. |
212 |
222 |
230 notify |
240 notify |
231 "wakeup one waiting process" |
241 "wakeup one waiting process" |
232 |
242 |
233 | thisProcess | |
243 | thisProcess | |
234 thisProcess := Processor activeProcess. |
244 thisProcess := Processor activeProcess. |
235 self assert: (self isOwnedBy: thisProcess). |
245 self assert: owningProcess == thisProcess. |
236 JavaVM monitorTrace ifTrue:[ |
246 JavaVM monitorTrace ifTrue:[ |
237 Logger |
247 Logger |
238 log: ('%1: notifying %2 processes' bindWith: thisProcess printString |
248 log: ('%1: notifying %2 processes' bindWith: thisProcess printString |
239 with: waitingSema waitingProcesses size) |
249 with: waitingSema waitingProcesses size) |
240 severity: Logger severityDEBUG |
250 severity: Logger severityDEBUG |
242 ]. |
252 ]. |
243 waitingSema signal. |
253 waitingSema signal. |
244 Processor yield. |
254 Processor yield. |
245 |
255 |
246 "Created: / 22-11-2011 / 12:14:23 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
256 "Created: / 22-11-2011 / 12:14:23 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
247 "Modified: / 05-05-2017 / 17:27:49 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
257 "Modified: / 11-08-2017 / 22:25:44 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
248 ! |
258 ! |
249 |
259 |
250 notifyAll |
260 notifyAll |
251 "wakeup one waiting process" |
261 "wakeup one waiting process" |
252 |
262 |
253 | thisProcess | |
263 | thisProcess | |
254 thisProcess := Processor activeProcess. |
264 thisProcess := Processor activeProcess. |
255 self assert: (self isOwnedBy: thisProcess). |
265 self assert: owningProcess == thisProcess. |
256 JavaVM monitorTrace ifTrue:[ |
266 JavaVM monitorTrace ifTrue:[ |
257 Logger |
267 Logger |
258 log: ('%1: notifying all %2 processes' bindWith: thisProcess printString |
268 log: ('%1: notifying all %2 processes' bindWith: thisProcess printString |
259 with: waitingSema waitingProcesses size) |
269 with: waitingSema waitingProcesses size) |
260 severity: Logger severityDEBUG |
270 severity: Logger severityDEBUG |
262 ]. |
272 ]. |
263 waitingSema signalForAll. |
273 waitingSema signalForAll. |
264 Processor yield. |
274 Processor yield. |
265 |
275 |
266 "Created: / 22-11-2011 / 12:14:36 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
276 "Created: / 22-11-2011 / 12:14:36 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
267 "Modified: / 05-05-2017 / 17:28:00 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
277 "Modified: / 11-08-2017 / 22:26:01 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
268 ! |
278 ! |
269 |
279 |
270 release |
280 release |
|
281 | wasBlocked | |
|
282 |
271 self assert: (self isOwnedBy: owningProcess). |
283 self assert: (self isOwnedBy: owningProcess). |
272 count == 1 ifTrue: [ |
284 wasBlocked := OperatingSystem blockInterrupts. |
273 self instVarAccessCritical: [ owningProcess := nil ]. |
285 count == 1 ifTrue:[ |
|
286 owningProcess := nil. |
274 count := 0. |
287 count := 0. |
275 monitorSema signal. |
288 monitorSema signal. |
276 ] ifFalse: [ |
289 ] ifFalse:[ |
277 "/ the lock is probably not helping here to protect against problems with |
290 count := count - 1. |
278 "/ increment/decrement: |
291 ]. |
279 "/ the write-access (in reinitCOunter) will be either done before incrementing/decrementing or after. |
292 OperatingSystem unblockInterrupts. |
280 "/ if after, everything is ok; |
|
281 "/ if before, the decremented value will be zero, which is probably wrong. |
|
282 |
|
283 "/ without the critical region, we might also get possible inconsistencies: |
|
284 "/ if written before, the counter will drop to zero |
|
285 "/ if written in-between, the counter wil ahve the old value decremented; |
|
286 "/ if written afterwards, everything is ok. |
|
287 |
|
288 "/ so, the lock should be really elsewhere, making sure that noone will count |
|
289 "/ the monitor at-all and the monitor is reininialized without anyone depending on the |
|
290 "/ count at all. |
|
291 "/ but then, no critical section is needed in reinitCounter!!. |
|
292 |
|
293 self instVarAccessCritical: [ count := count - 1 ]. |
|
294 ] |
|
295 |
293 |
296 "Created: / 20-11-2011 / 13:21:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
294 "Created: / 20-11-2011 / 13:21:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
297 "Modified: / 03-06-2017 / 22:24:35 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
295 "Modified: / 11-08-2017 / 22:18:06 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
298 ! |
296 ! |
299 |
297 |
300 wait |
298 wait |
301 "make owning process to go to wait" |
299 "make owning process to go to wait" |
302 |
300 |
308 waitForMilliseconds: timeOut |
306 waitForMilliseconds: timeOut |
309 "make owning process to go to wait, but not longer than timeout" |
307 "make owning process to go to wait, but not longer than timeout" |
310 |
308 |
311 | thisProcess countBeforeWait | |
309 | thisProcess countBeforeWait | |
312 thisProcess := Processor activeProcess. |
310 thisProcess := Processor activeProcess. |
313 self assert: (self isOwnedBy: thisProcess). |
311 self assert: owningProcess == thisProcess. |
314 self waitEnabled ifFalse: [ |
312 self waitEnabled ifFalse: [ |
315 JavaVM monitorTrace ifTrue:[ |
313 JavaVM monitorTrace ifTrue:[ |
316 Logger |
314 Logger |
317 log: ('%1 wanted to go to sleep, but it cant, this monitor is for %2 which is already dead' |
315 log: ('%1 wanted to go to sleep, but it cant, this monitor is for %2 which is already dead' |
318 bindWith: thisProcess printString |
316 bindWith: thisProcess printString |
329 with: timeOut |
327 with: timeOut |
330 with: ownerPrintString printString) |
328 with: ownerPrintString printString) |
331 severity: #debug |
329 severity: #debug |
332 facility: #JVM. |
330 facility: #JVM. |
333 ]. |
331 ]. |
334 countBeforeWait := count. |
332 countBeforeWait := count. |
335 count timesRepeat: [self release]. |
333 "/ Release the monitor so other thread can acquire it |
|
334 "/ and call #notify or #notifyAll |
|
335 count := 1. "/ note that at this point we still own the monitor |
|
336 self release. |
|
337 |
|
338 "/ Monitor released, wait... |
336 "JV@2011-11-25: zero timeout means wait without timeout!!!!!!" |
339 "JV@2011-11-25: zero timeout means wait without timeout!!!!!!" |
337 timeOut == 0 ifTrue: [ waitingSema wait ] ifFalse: [ |
340 timeOut == 0 ifTrue: [ waitingSema wait ] ifFalse: [ |
338 waitingSema waitWithTimeoutMs: timeOut |
341 waitingSema waitWithTimeoutMs: timeOut |
339 ]. |
342 ]. |
340 JavaVM monitorTrace ifTrue:[ |
343 JavaVM monitorTrace ifTrue:[ |
342 log: ('%1 has been notified and is trying to acquire monitor for %2 which is owned by %3' |
345 log: ('%1 has been notified and is trying to acquire monitor for %2 which is owned by %3' |
343 bindWith: thisProcess printString with: ownerPrintString printString with: owningProcess printString) |
346 bindWith: thisProcess printString with: ownerPrintString printString with: owningProcess printString) |
344 severity: #debug |
347 severity: #debug |
345 facility: #JVM. |
348 facility: #JVM. |
346 ]. |
349 ]. |
|
350 "/ We have been notified, re-acquire the monitor |
347 self acquire. |
351 self acquire. |
348 count := countBeforeWait. |
352 count := countBeforeWait. "/ note that at this point we already own the monitor |
349 |
353 |
350 "Created: / 22-11-2011 / 12:52:45 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
354 "Created: / 22-11-2011 / 12:52:45 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
351 "Modified: / 01-12-2011 / 10:57:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
355 "Modified: / 01-12-2011 / 10:57:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>" |
352 "Modified: / 03-06-2017 / 22:52:46 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
356 "Modified: / 11-08-2017 / 23:04:45 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
353 ! ! |
357 ! ! |
354 |
358 |
355 !JavaMonitor methodsFor:'queries'! |
359 !JavaMonitor methodsFor:'queries'! |
356 |
360 |
357 isAcquired |
361 isAcquired |