001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.scheduler; 014 015import static org.jikesrvm.runtime.SysCall.sysCall; 016import org.jikesrvm.VM; 017 018import org.vmmagic.pragma.Uninterruptible; 019import org.vmmagic.pragma.Unpreemptible; 020import org.vmmagic.pragma.NonMoving; 021import org.vmmagic.pragma.NoInline; 022import org.vmmagic.pragma.NoOptCompile; 023import org.vmmagic.pragma.BaselineSaveLSRegisters; 024import org.vmmagic.unboxed.Word; 025 026/** 027 * Implementation of a heavy lock and condition variable implemented using 028 * the primitives available from the operating system. Currently we use 029 * a pthread_mutex_t and pthread_cond_it. When instantiated, the mutex 030 * and cond are allocated. There is currently no way to destroy either 031 * (thus, pool and reuse accordingly). 032 * <p> 033 * It is perfectly safe to use this throughout the VM for locking. It is 034 * meant to provide roughly the same functionality as Java monitors, 035 * except: 036 * <ul> 037 * <li>This class provides a faster slow path than Java monitors.</li> 038 * <li>This class provides a slower fast path than Java monitors.</li> 039 * <li>This class does not have any interaction with Thread.interrupt() 040 * or Thread.stop(). Thus, if you block on a lock or a wait and the 041 * calling thread is stopped or interrupted, nothing will happen 042 * until the lock is acquired or the wait is notified.</li> 043 * <li>This class will work in the inner guts of the RVM runtime because 044 * it gives you the ability to lock and unlock, as well as wait and 045 * notify, without using any other VM runtime functionality.</li> 046 * <li>This class allows you to optionally block without letting the thread 047 * system know that you are blocked. The benefit is that you can 048 * perform synchronization without depending on RVM thread subsystem functionality. 049 * However, most of the time, you should use the methods that inform 050 * the thread system that you are blocking. Methods that have the 051 * "WithHandshake" suffix will inform the thread system if you are blocked, 052 * while methods that do not have the suffix will either not block 053 * (as is the case with {@link #unlock()} and {@link #broadcast()}) 054 * or will block without letting anyone know (like {@link #lockNoHandshake()} 055 * and {@link #waitNoHandshake()}). Not letting the threading 056 * system know that you are blocked may cause things like GC to stall 057 * until you unblock.</li> 058 * </ul> 059 */ 060@Uninterruptible 061@NonMoving 062public class Monitor { 063 Word monitor; 064 int holderSlot = -1; // use the slot so that we're even more GC safe 065 int recCount; 066 public int acquireCount; 067 /** 068 * Allocate a heavy condition variable and lock. This involves 069 * allocating stuff in C that gets deallocated only when the finalizer 070 * is run. Thus, don't instantiate too many of these. 071 */ 072 public Monitor() { 073 monitor = sysCall.sysMonitorCreate(); 074 } 075 076 /** 077 * Frees the data structures that were allocated in C code 078 * when the object was created. 079 */ 080 @Override 081 protected void finalize() throws Throwable { 082 sysCall.sysMonitorDestroy(monitor); 083 } 084 085 /** 086 * Wait until it is possible to acquire the lock and then acquire it. 087 * There is no bound on how long you might wait, if someone else is 088 * holding the lock and there is no bound on how long they will hold it. 089 * As well, even if there is a bound on how long a thread might hold a 090 * lock but there are multiple threads contending on its acquisition, 091 * there will not necessarily be a bound on how long any particular 092 * thread will wait until it gets its turn. 093 * <p> 094 * This blocking method method does not notify the threading subsystem 095 * that it is blocking. Thus, if someone (like, say, the GC) requests 096 * that the thread is blocked then their request will block until this 097 * method unblocks. If this sounds like it might be undesirable, call 098 * {@link #lockWithHandshake()} instead. 099 */ 100 @NoInline 101 @NoOptCompile 102 public void lockNoHandshake() { 103 int mySlot = RVMThread.getCurrentThreadSlot(); 104 if (mySlot != holderSlot) { 105 sysCall.sysMonitorEnter(monitor); 106 if (VM.VerifyAssertions) VM._assert(holderSlot == -1); 107 if (VM.VerifyAssertions) VM._assert(recCount == 0); 108 holderSlot = mySlot; 109 } 110 recCount++; 111 acquireCount++; 112 } 113 /** 114 * Relocks the mutex after using {@link #unlockCompletely()}. 115 * 116 * @param recCount the recursion count 117 */ 118 @NoInline 119 @NoOptCompile 120 public void relockNoHandshake(int recCount) { 121 sysCall.sysMonitorEnter(monitor); 122 if (VM.VerifyAssertions) VM._assert(holderSlot == -1); 123 if (VM.VerifyAssertions) VM._assert(this.recCount == 0); 124 holderSlot = RVMThread.getCurrentThreadSlot(); 125 this.recCount = recCount; 126 acquireCount++; 127 } 128 /** 129 * Wait until it is possible to acquire the lock and then acquire it. 130 * There is no bound on how long you might wait, if someone else is 131 * holding the lock and there is no bound on how long they will hold it. 132 * As well, even if there is a bound on how long a thread might hold a 133 * lock but there are multiple threads contending on its acquisition, 134 * there will not necessarily be a bound on how long any particular 135 * thread will wait until it gets its turn. 136 * <p> 137 * This blocking method method notifies the threading subsystem that it 138 * is blocking. Thus, it may be safer than calling lock. But, 139 * its reliance on threading subsystem accounting methods may mean that 140 * it cannot be used in certain contexts (say, the threading subsystem 141 * itself). 142 * <p> 143 * This method will ensure that if it blocks, it does so with the 144 * mutex not held. This is useful for cases where the subsystem that 145 * requested you to block needs to acquire the lock you were trying to 146 * acquire when the blocking request came. 147 * <p> 148 * It is usually not necessary to call this method instead of 149 * {@link #lockNoHandshake()} since most VM locks are held for short 150 * periods of time. 151 */ 152 @Unpreemptible("If the lock cannot be acquired, this method will allow the thread to be asynchronously blocked") 153 @NoInline 154 @NoOptCompile 155 public void lockWithHandshake() { 156 int mySlot = RVMThread.getCurrentThreadSlot(); 157 if (mySlot != holderSlot) { 158 lockWithHandshakeNoRec(); 159 if (VM.VerifyAssertions) VM._assert(holderSlot == -1); 160 if (VM.VerifyAssertions) VM._assert(recCount == 0); 161 holderSlot = mySlot; 162 } 163 recCount++; 164 acquireCount++; 165 } 166 @NoInline 167 @NoOptCompile 168 @BaselineSaveLSRegisters 169 @Unpreemptible 170 private void lockWithHandshakeNoRec() { 171 RVMThread.saveThreadState(); 172 lockWithHandshakeNoRecImpl(); 173 } 174 @NoInline 175 @Unpreemptible 176 @NoOptCompile 177 private void lockWithHandshakeNoRecImpl() { 178 for (;;) { 179 RVMThread.enterNative(); 180 sysCall.sysMonitorEnter(monitor); 181 if (RVMThread.attemptLeaveNativeNoBlock()) { 182 return; 183 } else { 184 sysCall.sysMonitorExit(monitor); 185 RVMThread.leaveNative(); 186 } 187 } 188 } 189 /** 190 * Relocks the mutex after using {@link #unlockCompletely()} and notify 191 * the threading subsystem. 192 * 193 * @param recCount the recursion count 194 */ 195 @NoInline 196 @NoOptCompile 197 @BaselineSaveLSRegisters 198 @Unpreemptible("If the lock cannot be reacquired, this method may allow the thread to be asynchronously blocked") 199 public void relockWithHandshake(int recCount) { 200 RVMThread.saveThreadState(); 201 relockWithHandshakeImpl(recCount); 202 } 203 @NoInline 204 @Unpreemptible 205 @NoOptCompile 206 private void relockWithHandshakeImpl(int recCount) { 207 for (;;) { 208 RVMThread.enterNative(); 209 sysCall.sysMonitorEnter(monitor); 210 if (RVMThread.attemptLeaveNativeNoBlock()) { 211 break; 212 } else { 213 sysCall.sysMonitorExit(monitor); 214 RVMThread.leaveNative(); 215 } 216 } 217 if (VM.VerifyAssertions) VM._assert(holderSlot == -1); 218 if (VM.VerifyAssertions) VM._assert(this.recCount == 0); 219 holderSlot = RVMThread.getCurrentThreadSlot(); 220 this.recCount = recCount; 221 } 222 /** 223 * Release the lock. This method should (in principle) be non-blocking, 224 * and, as such, it does not notify the threading subsystem that it is 225 * blocking. 226 */ 227 @NoInline 228 @NoOptCompile 229 public void unlock() { 230 if (--recCount == 0) { 231 holderSlot = -1; 232 sysCall.sysMonitorExit(monitor); 233 } 234 } 235 236 /** 237 * Completely releases the lock, ignoring recursion. 238 * 239 * @return the recursion count 240 */ 241 @NoInline 242 @NoOptCompile 243 public int unlockCompletely() { 244 int result = recCount; 245 recCount = 0; 246 holderSlot = -1; 247 sysCall.sysMonitorExit(monitor); 248 return result; 249 } 250 /** 251 * Wait until someone calls {@link #broadcast()}. 252 * <p> 253 * This blocking method method does not notify the threading subsystem 254 * that it is blocking. Thus, if someone (like, say, the GC) requests 255 * that the thread is blocked then their request will block until this 256 * method unblocks. If this sounds like it might be undesirable, call 257 * {@link #waitWithHandshake()} instead. 258 */ 259 @NoInline 260 @NoOptCompile 261 public void waitNoHandshake() { 262 int recCount = this.recCount; 263 this.recCount = 0; 264 holderSlot = -1; 265 sysCall.sysMonitorWait(monitor); 266 if (VM.VerifyAssertions) VM._assert(holderSlot == -1); 267 if (VM.VerifyAssertions) VM._assert(this.recCount == 0); 268 this.recCount = recCount; 269 holderSlot = RVMThread.getCurrentThreadSlot(); 270 } 271 /** 272 * Wait until someone calls {@link #broadcast()}, or until the clock 273 * reaches the given time. 274 * <p> 275 * This blocking method method does not notify the threading subsystem 276 * that it is blocking. Thus, if someone (like, say, the GC) requests 277 * that the thread is blocked then their request will block until this 278 * method unblocks. If this sounds like it might be undesirable, call 279 * {@link #timedWaitAbsoluteWithHandshake(long)} instead. 280 * 281 * @param whenWakeupNanos the absolute time point that must be reached 282 * before the wait is over when no call to {@link #broadcast()} occurs 283 * in the meantime 284 */ 285 @NoInline 286 @NoOptCompile 287 public void timedWaitAbsoluteNoHandshake(long whenWakeupNanos) { 288 int recCount = this.recCount; 289 this.recCount = 0; 290 holderSlot = -1; 291 sysCall.sysMonitorTimedWaitAbsolute(monitor, whenWakeupNanos); 292 if (VM.VerifyAssertions) VM._assert(holderSlot == -1); 293 if (VM.VerifyAssertions) VM._assert(this.recCount == 0); 294 this.recCount = recCount; 295 holderSlot = RVMThread.getCurrentThreadSlot(); 296 } 297 /** 298 * Wait until someone calls {@link #broadcast()}, or until at least 299 * the given number of nanoseconds pass. 300 * <p> 301 * This blocking method method does not notify the threading subsystem 302 * that it is blocking. Thus, if someone (like, say, the GC) requests 303 * that the thread is blocked then their request will block until this 304 * method unblocks. If this sounds like it might be undesirable, call 305 * {@link #timedWaitRelativeWithHandshake(long)} instead. 306 * 307 * @param delayNanos the number of nanoseconds that need to pass 308 * from the call of this method until the wait is over when no call 309 * to {@link #broadcast()} occurs in the meantime 310 */ 311 @NoInline 312 @NoOptCompile 313 public void timedWaitRelativeNoHandshake(long delayNanos) { 314 long now = sysCall.sysNanoTime(); 315 timedWaitAbsoluteNoHandshake(now + delayNanos); 316 } 317 /** 318 * Wait until someone calls {@link #broadcast()}. 319 * <p> 320 * This blocking method notifies the threading subsystem that it 321 * is blocking. Thus, it is generally safer than calling 322 * {@link #waitNoHandshake()}. But, its reliance on threading subsystem 323 * accounting methods may mean that it cannot be used in certain contexts 324 * (say, the threading subsystem itself). 325 * <p> 326 * This method will ensure that if it blocks, it does so with the 327 * mutex not held. This is useful for cases where the subsystem that 328 * requested you to block needs to acquire the lock you were trying to 329 * acquire when the blocking request came. 330 */ 331 @NoInline 332 @NoOptCompile 333 @BaselineSaveLSRegisters 334 @Unpreemptible("While the thread is waiting, this method may allow the thread to be asynchronously blocked") 335 public void waitWithHandshake() { 336 RVMThread.saveThreadState(); 337 waitWithHandshakeImpl(); 338 } 339 @NoInline 340 @Unpreemptible 341 @NoOptCompile 342 private void waitWithHandshakeImpl() { 343 RVMThread.enterNative(); 344 waitNoHandshake(); 345 int recCount = unlockCompletely(); 346 RVMThread.leaveNative(); 347 relockWithHandshakeImpl(recCount); 348 } 349 /** 350 * Wait until someone calls {@link #broadcast()}, or until the clock 351 * reaches the given time. 352 * <p> 353 * This blocking method method notifies the threading subsystem that it 354 * is blocking. Thus, it is generally safer than calling 355 * {@link #timedWaitAbsoluteNoHandshake(long)}. But, its reliance on 356 * threading subsystem accounting methods may mean that it cannot be 357 * used in certain contexts (say, the threading subsystem itself). 358 * <p> 359 * This method will ensure that if it blocks, it does so with the 360 * mutex not held. This is useful for cases where the subsystem that 361 * requested you to block needs to acquire the lock you were trying to 362 * acquire when the blocking request came. 363 * 364 * @param whenWakeupNanos the absolute time point that must be reached 365 * before the wait is over when no call to {@link #broadcast()} occurs 366 * in the meantime 367 */ 368 @NoInline 369 @NoOptCompile 370 @BaselineSaveLSRegisters 371 @Unpreemptible("While the thread is waiting, this method may allow the thread to be asynchronously blocked") 372 public void timedWaitAbsoluteWithHandshake(long whenWakeupNanos) { 373 RVMThread.saveThreadState(); 374 timedWaitAbsoluteWithHandshakeImpl(whenWakeupNanos); 375 } 376 @NoInline 377 @Unpreemptible 378 @NoOptCompile 379 private void timedWaitAbsoluteWithHandshakeImpl(long whenWakeupNanos) { 380 RVMThread.enterNative(); 381 timedWaitAbsoluteNoHandshake(whenWakeupNanos); 382 int recCount = unlockCompletely(); 383 RVMThread.leaveNative(); 384 relockWithHandshakeImpl(recCount); 385 } 386 /** 387 * Wait until someone calls {@link #broadcast()}, or until at least the given 388 * number of nanoseconds pass. 389 * <p> 390 * This blocking method method notifies the threading subsystem that it 391 * is blocking. Thus, it is generally safer than calling 392 * {@link #timedWaitRelativeWithHandshake(long)}. But, its reliance on 393 * threading subsystem accounting methods may mean that it cannot be used 394 * in certain contexts (say, the threading subsystem itself). 395 * <p> 396 * This method will ensure that if it blocks, it does so with the 397 * mutex not held. This is useful for cases where the subsystem that 398 * requested you to block needs to acquire the lock you were trying to 399 * acquire when the blocking request came. 400 * 401 * @param delayNanos the number of nanoseconds that need to pass 402 * from the call of this method until the wait is over when no call 403 * to {@link #broadcast()} occurs in the meantime 404 */ 405 @NoInline 406 @NoOptCompile 407 @BaselineSaveLSRegisters 408 @Unpreemptible("While the thread is waiting, this method may allow the thread to be asynchronously blocked") 409 public void timedWaitRelativeWithHandshake(long delayNanos) { 410 RVMThread.saveThreadState(); 411 timedWaitRelativeWithHandshakeImpl(delayNanos); 412 } 413 @NoInline 414 @Unpreemptible 415 @NoOptCompile 416 private void timedWaitRelativeWithHandshakeImpl(long delayNanos) { 417 RVMThread.enterNative(); 418 timedWaitRelativeNoHandshake(delayNanos); 419 int recCount = unlockCompletely(); 420 RVMThread.leaveNative(); 421 relockWithHandshakeImpl(recCount); 422 } 423 424 /** 425 * Send a broadcast, which should awaken anyone who is currently blocked 426 * in any of the wait methods. This method should (in principle) be 427 * non-blocking, and, as such, it does not notify the threading subsystem 428 * that it is blocking. 429 */ 430 @NoInline 431 @NoOptCompile 432 public void broadcast() { 433 sysCall.sysMonitorBroadcast(monitor); 434 } 435 /** 436 * Send a broadcast after first acquiring the lock. Release the lock 437 * after sending the broadcast. In most cases where you want to send 438 * a broadcast but you don't need to acquire the lock to set the 439 * condition that the other thread(s) are waiting on, you want to call 440 * this method instead of {@link #broadcast()}. 441 */ 442 @NoInline 443 @NoOptCompile 444 public void lockedBroadcastNoHandshake() { 445 lockNoHandshake(); 446 broadcast(); 447 unlock(); 448 } 449 450 @NoInline 451 public static boolean lockNoHandshake(Monitor l) { 452 if (l == null) { 453 return false; 454 } else { 455 l.lockNoHandshake(); 456 return true; 457 } 458 } 459 @NoInline 460 public static void unlock(boolean b, Monitor l) { 461 if (b) l.unlock(); 462 } 463 464 @NoInline 465 @NoOptCompile 466 @Unpreemptible 467 public static void lockWithHandshake(Monitor m1,Word priority1, 468 Monitor m2,Word priority2) { 469 if (priority1.LE(priority2)) { 470 m1.lockWithHandshake(); 471 m2.lockWithHandshake(); 472 } else { 473 m2.lockWithHandshake(); 474 m1.lockWithHandshake(); 475 } 476 } 477} 478