From 4f60a817e3ea408a176c74ec0f0ea5e9f151dd61 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Tue, 30 Aug 2016 03:23:53 +0100 Subject: [PATCH] Monitor.TryEnter asm timeout != 0 before spin (#6951) * JIT_MonTryEnter_Slow timeout != 0 before spin * JIT_MonTryEnter_InlineGetThread timeout != 0 before spin --- src/vm/amd64/JitHelpers_InlineGetThread.asm | 52 ++++++++++++++++------------- src/vm/amd64/JitHelpers_Slow.asm | 20 ++++++----- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/vm/amd64/JitHelpers_InlineGetThread.asm b/src/vm/amd64/JitHelpers_InlineGetThread.asm index 2a5e3b9..700c3b3 100644 --- a/src/vm/amd64/JitHelpers_InlineGetThread.asm +++ b/src/vm/amd64/JitHelpers_InlineGetThread.asm @@ -960,6 +960,10 @@ endif ret PrepareToWaitThinLock: + ; Return failure if timeout is zero + cmp dword ptr [rsp + 10h], 0 + je TimeoutZero + ; If we are on an MP system, we try spinning for a certain number of iterations cmp dword ptr [g_SystemInfo + OFFSETOF__g_SystemInfo__dwNumberOfProcessors], 1 jle FramedLockHelper @@ -982,6 +986,16 @@ endif RetryHelperThinLock: jmp RetryThinLock + TimeoutZero: + ; Did not acquire, return FALSE + mov byte ptr [r8], 0 +ifdef MON_DEBUG +ifdef TRACK_SYNC + add rsp, MON_ENTER_STACK_SIZE_INLINEGETTHREAD +endif +endif + ret + HaveHashOrSyncBlockIndex: ; If we have a hash code already, we need to create a sync block test eax, BIT_SBLK_IS_HASHCODE @@ -1067,9 +1081,21 @@ endif ret PrepareToWait: + ; Return failure if timeout is zero + cmp dword ptr [rsp + 10h], 0 +ifdef MON_DEBUG +ifdef TRACK_SYNC + ; if we are using the _DEBUG stuff then rsp has been adjusted + ; so compare the value at the adjusted position + ; there's really little harm in the extra stack read + cmp dword ptr [rsp + MON_ENTER_STACK_SIZE_INLINEGETTHREAD + 10h] +endif +endif + je TimeoutZero + ; If we are on an MP system, we try spinning for a certain number of iterations cmp dword ptr [g_SystemInfo + OFFSETOF__g_SystemInfo__dwNumberOfProcessors], 1 - jle WouldBlock + jle Block ; Exponential backoff; delay by approximately 2*r10d clock cycles mov eax, r10d @@ -1084,29 +1110,7 @@ endif cmp r10d, dword ptr [g_SpinConstants + OFFSETOF__g_SpinConstants__dwMaximumDuration] jle RetrySyncBlock - ; We would need to block to enter the section. Return failure if - ; timeout is zero, else call the farmed helper to do the blocking - ; form of TryEnter. - WouldBlock: - mov rdx, [rsp + 10h] - ; if we are using the _DEBUG stuff then rsp has been adjusted - ; just overwrite the wrong RDX value that we already retrieved - ; there's really little harm in the extra stack read -ifdef MON_DEBUG -ifdef TRACK_SYNC - mov rdx, [rsp + MON_ENTER_STACK_SIZE_INLINEGETTHREAD + 10h] -endif -endif - test rdx, rdx - jnz Block - ; Return FALSE - mov byte ptr [r8], 0 -ifdef MON_DEBUG -ifdef TRACK_SYNC - add rsp, MON_ENTER_STACK_SIZE_INLINEGETTHREAD -endif -endif - ret + jmp Block RetryHelperSyncBlock: jmp RetrySyncBlock diff --git a/src/vm/amd64/JitHelpers_Slow.asm b/src/vm/amd64/JitHelpers_Slow.asm index 66b0e90..7deed49 100644 --- a/src/vm/amd64/JitHelpers_Slow.asm +++ b/src/vm/amd64/JitHelpers_Slow.asm @@ -1452,6 +1452,10 @@ NESTED_ENTRY JIT_MonTryEnter_Slow, _TEXT ret PrepareToWaitThinLock: + ; Return failure if timeout is zero + test rsi, rsi + jz TimeoutZero + ; If we are on an MP system, we try spinning for a certain number of iterations cmp dword ptr [g_SystemInfo + OFFSETOF__g_SystemInfo__dwNumberOfProcessors], 1 jle FramedLockHelper @@ -1553,9 +1557,13 @@ endif ret PrepareToWait: + ; Return failure if timeout is zero + test rsi, rsi + jz TimeoutZero + ; If we are on an MP system, we try spinning for a certain number of iterations cmp dword ptr [g_SystemInfo + OFFSETOF__g_SystemInfo__dwNumberOfProcessors], 1 - jle WouldBlock + jle Block ; Exponential backoff; delay by approximately 2*r10d clock cycles mov eax, r10d @@ -1570,15 +1578,11 @@ endif cmp r10d, dword ptr [g_SpinConstants + OFFSETOF__g_SpinConstants__dwMaximumDuration] jle RetrySyncBlock - ; We would need to block to enter the section. Return failure if - ; timeout is zero, else call the farmed helper to do the blocking - ; form of TryEnter. - WouldBlock: - test rsi, rsi - jnz Block + jmp Block + TimeoutZero: ; Return FALSE - mov byte ptr [r8], 0 + mov byte ptr [r8], 0 add rsp, MON_ENTER_STACK_SIZE pop rsi ret -- 2.7.4