hotspot/src/os/windows/vm/os_windows.cpp
changeset 27458 eb5f1b4f01e1
parent 27400 c5955f4b7c84
child 27459 7fce477785a3
equal deleted inserted replaced
27457:adbe834be3a0 27458:eb5f1b4f01e1
  4790 // 2.  Consider wrapping the WaitForSingleObject(Ex) calls in SEH try/finally blocks
  4790 // 2.  Consider wrapping the WaitForSingleObject(Ex) calls in SEH try/finally blocks
  4791 //     to recover from (or at least detect) the dreaded Windows 841176 bug.
  4791 //     to recover from (or at least detect) the dreaded Windows 841176 bug.
  4792 // 3.  Collapse the interrupt_event, the JSR166 parker event, and the objectmonitor ParkEvent
  4792 // 3.  Collapse the interrupt_event, the JSR166 parker event, and the objectmonitor ParkEvent
  4793 //     into a single win32 CreateEvent() handle.
  4793 //     into a single win32 CreateEvent() handle.
  4794 //
  4794 //
       
  4795 // Assumption:
       
  4796 //    Only one parker can exist on an event, which is why we allocate
       
  4797 //    them per-thread. Multiple unparkers can coexist.
       
  4798 //
  4795 // _Event transitions in park()
  4799 // _Event transitions in park()
  4796 //   -1 => -1 : illegal
  4800 //   -1 => -1 : illegal
  4797 //    1 =>  0 : pass - return immediately
  4801 //    1 =>  0 : pass - return immediately
  4798 //    0 => -1 : block
  4802 //    0 => -1 : block; then set _Event to 0 before returning
  4799 //
  4803 //
  4800 // _Event serves as a restricted-range semaphore :
  4804 // _Event transitions in unpark()
  4801 //    -1 : thread is blocked
  4805 //    0 => 1 : just return
  4802 //     0 : neutral  - thread is running or ready
  4806 //    1 => 1 : just return
  4803 //     1 : signaled - thread is running or ready
  4807 //   -1 => either 0 or 1; must signal target thread
       
  4808 //         That is, we can safely transition _Event from -1 to either
       
  4809 //         0 or 1.
  4804 //
  4810 //
  4805 // Another possible encoding of _Event would be
  4811 // _Event serves as a restricted-range semaphore.
  4806 // with explicit "PARKED" and "SIGNALED" bits.
  4812 //   -1 : thread is blocked, i.e. there is a waiter
       
  4813 //    0 : neutral: thread is running or ready,
       
  4814 //        could have been signaled after a wait started
       
  4815 //    1 : signaled - thread is running or ready
       
  4816 //
       
  4817 // Another possible encoding of _Event would be with
       
  4818 // explicit "PARKED" == 01b and "SIGNALED" == 10b bits.
       
  4819 //
  4807 
  4820 
  4808 int os::PlatformEvent::park(jlong Millis) {
  4821 int os::PlatformEvent::park(jlong Millis) {
       
  4822   // Transitions for _Event:
       
  4823   //   -1 => -1 : illegal
       
  4824   //    1 =>  0 : pass - return immediately
       
  4825   //    0 => -1 : block; then set _Event to 0 before returning
       
  4826 
  4809   guarantee(_ParkHandle != NULL , "Invariant");
  4827   guarantee(_ParkHandle != NULL , "Invariant");
  4810   guarantee(Millis > 0          , "Invariant");
  4828   guarantee(Millis > 0          , "Invariant");
  4811   int v;
       
  4812 
  4829 
  4813   // CONSIDER: defer assigning a CreateEvent() handle to the Event until
  4830   // CONSIDER: defer assigning a CreateEvent() handle to the Event until
  4814   // the initial park() operation.
  4831   // the initial park() operation.
  4815 
  4832   // Consider: use atomic decrement instead of CAS-loop
       
  4833 
       
  4834   int v;
  4816   for (;;) {
  4835   for (;;) {
  4817     v = _Event;
  4836     v = _Event;
  4818     if (Atomic::cmpxchg(v-1, &_Event, v) == v) break;
  4837     if (Atomic::cmpxchg(v-1, &_Event, v) == v) break;
  4819   }
  4838   }
  4820   guarantee((v == 0) || (v == 1), "invariant");
  4839   guarantee((v == 0) || (v == 1), "invariant");
  4858   // Implementor's license -- returning OS_TIMEOUT would be equally valid, however.
  4877   // Implementor's license -- returning OS_TIMEOUT would be equally valid, however.
  4859   return (v >= 0) ? OS_OK : OS_TIMEOUT;
  4878   return (v >= 0) ? OS_OK : OS_TIMEOUT;
  4860 }
  4879 }
  4861 
  4880 
  4862 void os::PlatformEvent::park() {
  4881 void os::PlatformEvent::park() {
       
  4882   // Transitions for _Event:
       
  4883   //   -1 => -1 : illegal
       
  4884   //    1 =>  0 : pass - return immediately
       
  4885   //    0 => -1 : block; then set _Event to 0 before returning
       
  4886 
  4863   guarantee(_ParkHandle != NULL, "Invariant");
  4887   guarantee(_ParkHandle != NULL, "Invariant");
  4864   // Invariant: Only the thread associated with the Event/PlatformEvent
  4888   // Invariant: Only the thread associated with the Event/PlatformEvent
  4865   // may call park().
  4889   // may call park().
       
  4890   // Consider: use atomic decrement instead of CAS-loop
  4866   int v;
  4891   int v;
  4867   for (;;) {
  4892   for (;;) {
  4868     v = _Event;
  4893     v = _Event;
  4869     if (Atomic::cmpxchg(v-1, &_Event, v) == v) break;
  4894     if (Atomic::cmpxchg(v-1, &_Event, v) == v) break;
  4870   }
  4895   }
  4889 
  4914 
  4890 void os::PlatformEvent::unpark() {
  4915 void os::PlatformEvent::unpark() {
  4891   guarantee(_ParkHandle != NULL, "Invariant");
  4916   guarantee(_ParkHandle != NULL, "Invariant");
  4892 
  4917 
  4893   // Transitions for _Event:
  4918   // Transitions for _Event:
  4894   //    0 :=> 1
  4919   //    0 => 1 : just return
  4895   //    1 :=> 1
  4920   //    1 => 1 : just return
  4896   //   -1 :=> either 0 or 1; must signal target thread
  4921   //   -1 => either 0 or 1; must signal target thread
  4897   //          That is, we can safely transition _Event from -1 to either
  4922   //         That is, we can safely transition _Event from -1 to either
  4898   //          0 or 1.
  4923   //         0 or 1.
  4899   // See also: "Semaphores in Plan 9" by Mullender & Cox
  4924   // See also: "Semaphores in Plan 9" by Mullender & Cox
  4900   //
  4925   //
  4901   // Note: Forcing a transition from "-1" to "1" on an unpark() means
  4926   // Note: Forcing a transition from "-1" to "1" on an unpark() means
  4902   // that it will take two back-to-back park() calls for the owning
  4927   // that it will take two back-to-back park() calls for the owning
  4903   // thread to block. This has the benefit of forcing a spurious return
  4928   // thread to block. This has the benefit of forcing a spurious return