Using x86 pause instr in SpinPause

David Holmes david.holmes at oracle.com
Thu Aug 16 17:18:03 PDT 2012


On 17/08/2012 9:51 AM, Vitaly Davidovich wrote:
> So the VM thread detects contention of some sort and enters a spin-wait;
> while it's spinning, is it doing anything at all, like re-reading some
> memory? I was assuming, judging by the name, that it simply stalls for
> some period of time before re-checking; notifying CPU of this seems
> legit.  That's wrong though I take it?

If a thread spins it is because it is hoping another thread (hopefully 
on-proc) will soon make the present thread able to proceed. If the 
assumption is wrong then the thread falls back to blocking. Here's an 
example of where SpinPause is used:

void Thread::SpinAcquire (volatile int * adr, const char * LockName) {
   if (Atomic::cmpxchg (1, adr, 0) == 0) {
      return ;   // normal fast-path return
   }

   // Slow-path : We've encountered contention -- Spin/Yield/Block strategy.
   TEVENT (SpinAcquire - ctx) ;
   int ctr = 0 ;
   int Yields = 0 ;
   for (;;) {
      while (*adr != 0) {
         ++ctr ;
         if ((ctr & 0xFFF) == 0 || !os::is_MP()) {
            if (Yields > 5) {
              // Consider using a simple NakedSleep() instead.
              // Then SpinAcquire could be called by non-JVM threads
              Thread::current()->_ParkEvent->park(1) ;
            } else {
              os::NakedYield() ;
              ++Yields ;
            }
         } else {
            SpinPause() ;
         }
      }
      if (Atomic::cmpxchg (1, adr, 0) == 0) return ;
   }
}

I really don't know whether in this context a "pause" instruction could 
potentially do something useful in terms of power use etc.

David
-----

> Thanks
>
> Sent from my phone
>
> On Aug 16, 2012 7:46 PM, "David Holmes" <david.holmes at oracle.com
> <mailto:david.holmes at oracle.com>> wrote:
>
>     On 17/08/2012 9:42 AM, Vitaly Davidovich wrote:
>
>         Why would you not want a pause ins? I thought the point of it was to
>         inform the CPU that you're busy spinning and not doing anything
>         useful
>         so it can make internal adjustments (e.g. scale down frequency on a
>         mobile processor).
>
>
>     That's not really applicable in the contexts in which this is used
>     in the VM. Spins are used as a back-off strategy for contended
>     actions - the fact they are contended indicate there is active work
>     happening in other threads so we are not in an "idle" state.
>
>     David
>
>
>         Thanks
>
>         Sent from my phone
>
>         On Aug 16, 2012 5:22 PM, "Daniel D. Daugherty"
>         <daniel.daugherty at oracle.com
>         <mailto:daniel.daugherty at oracle.com>
>         <mailto:daniel.daugherty at __oracle.com
>         <mailto:daniel.daugherty at oracle.com>>> wrote:
>
>              On Win64, SpinPause() has been "return 0" since mid-2005.
>         Way back
>              when Win64 code was in os_win32_amd64.cpp:
>
>                   SCCS/s.os_win32_amd64.cpp:
>
>                   D 1.9.1.1 05/07/04 03:20:45 dice 12 10  00025/00000/00334
>                   MRs:
>                   COMMENTS:
>                   5030359 -- back-end synchonization improvements - adaptive
>              spinning, etc
>
>              When the i486 and amd64 cpu dirs were merged back in 2007,
>         the code
>              became like it is below (#ifdef'ed):
>
>                   D 1.32 07/09/17 09:11:33 sgoldman 37 35 00264/00008/00218
>                   MRs:
>                   COMMENTS:
>                   5108146 Merge i486 and amd64 cpu directories.
>                   Macro-ized register names. Inserted amd64 specific code.
>
>              Looks like on Linux-X64, the code has used the PAUSE
>         instruction
>              since mid-2005:
>
>                   D 1.3 05/07/04 03:14:09 dice 4 3        00031/00000/00353
>                   MRs:
>                   COMMENTS:
>                   5030359 -- back-end synchonization improvements - adaptive
>              spinning, etc
>
>              We'll have to see if Dave Dice remember why he implemented
>              it this way...
>
>              Dan
>
>
>              On 8/16/12 12:01 PM, Eric Caspole wrote:
>
>                  Hi everybody,
>                  Does anybody know the reason why SpinPause is simply
>         "return 0"
>                  on Win64 but uses PAUSE on Linux in a .s file?
>                  We would like to remove PAUSE from linux too.
>
>                  Thanks,
>                  Eric
>
>
>                  ./src/os_cpu/windows_x86/vm/____os_windows_x86.cpp
>
>                       548 extern "C" int SpinPause () {
>                       549 #ifdef AMD64
>                       550    return 0 ;
>                       551 #else
>                       552    // pause == rep:nop
>                       553    // On systems that don't support pause a
>         rep:nop
>                       554    // is executed as a nop.  The rep: prefix
>         is ignored.
>                       555    _asm {
>                       556       pause ;
>                       557    };
>                       558    return 1 ;
>                       559 #endif // AMD64
>                       560 }
>
>
>                  src/os_cpu/linux_x86/vm/linux_____x86_64.s
>
>                        63         .globl SpinPause
>                        64         .align 16
>                        65         .type  SpinPause, at function
>                        66 SpinPause:
>                        67         rep
>                        68         nop
>                        69         movq   $1, %rax
>                        70         ret
>
>


More information about the hotspot-runtime-dev mailing list