Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Au <andrewau@microsoft.com>2017-07-07 18:59:18 +0300
committerAndrew Au <andrewau@microsoft.com>2017-07-07 18:59:18 +0300
commita61fac9dce2b1873a61cbe70489d8c0ecdad3ad4 (patch)
tree9dc81f67e77366aa2c4af1a74cf668b9bb69a518 /src/Native/Runtime/amd64
parentb5be0e6aac9002f171012ee6c48488d7d43448d9 (diff)
(On behalf of Jan Vorlicek) Thread abort stage 1
[tfs-changeset: 1664997]
Diffstat (limited to 'src/Native/Runtime/amd64')
-rw-r--r--src/Native/Runtime/amd64/AsmMacros.inc8
-rw-r--r--src/Native/Runtime/amd64/ExceptionHandling.asm23
-rw-r--r--src/Native/Runtime/amd64/GcProbe.asm36
-rw-r--r--src/Native/Runtime/amd64/PInvoke.S6
-rw-r--r--src/Native/Runtime/amd64/PInvoke.asm57
5 files changed, 110 insertions, 20 deletions
diff --git a/src/Native/Runtime/amd64/AsmMacros.inc b/src/Native/Runtime/amd64/AsmMacros.inc
index b9835375b..799dc2fde 100644
--- a/src/Native/Runtime/amd64/AsmMacros.inc
+++ b/src/Native/Runtime/amd64/AsmMacros.inc
@@ -370,7 +370,15 @@ PTFF_SAVE_RAX equ 00000100h ;; RAX is saved if it contains a GC ref
PTFF_SAVE_ALL_SCRATCH equ 00007F00h
PTFF_RAX_IS_GCREF equ 00010000h ;; iff PTFF_SAVE_RAX: set -> eax is Object, clear -> eax is scalar
PTFF_RAX_IS_BYREF equ 00020000h ;; iff PTFF_SAVE_RAX: set -> eax is ByRef, clear -> eax is Object or scalar
+PTFF_THREAD_ABORT equ 00040000h ;; indicates that ThreadAbortException should be thrown when returning from the transition
+;; These must match the TrapThreadsFlags enum
+TrapThreadsFlags_None equ 0
+TrapThreadsFlags_AbortInProgress equ 1
+TrapThreadsFlags_TrapThreads equ 2
+
+;; This must match HwExceptionCode.STATUS_REDHAWK_THREAD_ABORT
+STATUS_REDHAWK_THREAD_ABORT equ 43h
;;
;; CONSTANTS -- SYMBOLS
diff --git a/src/Native/Runtime/amd64/ExceptionHandling.asm b/src/Native/Runtime/amd64/ExceptionHandling.asm
index ccea8d02d..b2fb7e036 100644
--- a/src/Native/Runtime/amd64/ExceptionHandling.asm
+++ b/src/Native/Runtime/amd64/ExceptionHandling.asm
@@ -353,11 +353,12 @@ endm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NESTED_ENTRY RhpCallCatchFunclet, _TEXT
- FUNCLET_CALL_PROLOGUE 2, 1
+ FUNCLET_CALL_PROLOGUE 3, 0
;; locals
rsp_offsetof_thread = rsp_offsetof_locals
rsp_offsetof_resume_ip = rsp_offsetof_locals + 8;
+ rsp_offsetof_is_handling_thread_abort = rsp_offsetof_locals + 16;
mov [rsp + rsp_offsetof_arguments + 0h], rcx ;; save arguments for later
mov [rsp + rsp_offsetof_arguments + 8h], rdx
@@ -367,6 +368,9 @@ NESTED_ENTRY RhpCallCatchFunclet, _TEXT
INLINE_GETTHREAD rax, rbx ;; rax <- Thread*, rbx is trashed
mov [rsp + rsp_offsetof_thread], rax ;; save Thread* for later
+ cmp rcx, [rax + OFFSETOF__Thread__m_threadAbortException]
+ setz byte ptr [rsp + rsp_offsetof_is_handling_thread_abort]
+
;; Clear the DoNotTriggerGc state before calling out to our managed catch funclet.
lock and dword ptr [rax + OFFSETOF__Thread__m_ThreadStateFlags], NOT TSF_DoNotTriggerGc
@@ -435,7 +439,6 @@ endif
ifdef _DEBUG
;; Call into some C++ code to validate the pop of the ExInfo. We only do this in debug because we
;; have to spill all the preserved registers and then refill them after the call.
-
mov [rsp + rsp_offsetof_resume_ip], rax ;; save resume IP for later
mov rcx, [r8 + OFFSETOF__REGDISPLAY__pRbx]
@@ -498,10 +501,24 @@ endif
@@: mov [rdx + OFFSETOF__Thread__m_pExInfoStackHead], rcx ;; store the new head on the Thread
+ test [RhpTrapThreads], TrapThreadsFlags_AbortInProgress
+ jz @f
+
+ ;; test if the exception handled by the catch was the ThreadAbortException
+ cmp byte ptr [rsp + rsp_offsetof_is_handling_thread_abort], 0
+ je @f
+
+ ;; It was the ThreadAbortException, so rethrow it
+ mov rcx, STATUS_REDHAWK_THREAD_ABORT
+ mov rdx, rax ;; rdx <- continuation address as exception RIP
+ mov rsp, r8 ;; reset the SP to resume SP value
+ jmp RhpThrowHwEx ;; Throw the ThreadAbortException as a special kind of hardware exception
+
;; reset RSP and jump to the continuation address
- mov rsp, r8 ;; reset the SP
+ @@: mov rsp, r8 ;; reset the SP to resume SP value
jmp rax
+
NESTED_END RhpCallCatchFunclet, _TEXT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/src/Native/Runtime/amd64/GcProbe.asm b/src/Native/Runtime/amd64/GcProbe.asm
index 02e977d4f..2f2f2ae58 100644
--- a/src/Native/Runtime/amd64/GcProbe.asm
+++ b/src/Native/Runtime/amd64/GcProbe.asm
@@ -124,14 +124,14 @@ endm
;; All other registers trashed
;;
-EXTERN RhpWaitForGC : PROC
+EXTERN RhpWaitForGCNoAbort : PROC
WaitForGCCompletion macro
test dword ptr [rbx + OFFSETOF__Thread__m_ThreadStateFlags], TSF_SuppressGcStress + TSF_DoNotTriggerGc
jnz @F
mov rcx, [rbx + OFFSETOF__Thread__m_pHackPInvokeTunnel]
- call RhpWaitForGC
+ call RhpWaitForGCNoAbort
@@:
endm
@@ -215,9 +215,11 @@ NESTED_END RhpGcStressProbe, _TEXT
endif ;; FEATURE_GC_STRESS
+EXTERN RhpThrowHwEx : PROC
+
NESTED_ENTRY RhpGcProbe, _TEXT
- cmp [RhpTrapThreads], 0
- jne @f
+ test [RhpTrapThreads], TrapThreadsFlags_TrapThreads
+ jnz @f
ret
@@:
PUSH_PROBE_FRAME rdx, rax, 0, rcx
@@ -226,8 +228,17 @@ NESTED_ENTRY RhpGcProbe, _TEXT
mov rbx, rdx
WaitForGCCompletion
+ mov rax, [rbx + OFFSETOF__Thread__m_pHackPInvokeTunnel]
+ test dword ptr [rax + OFFSETOF__PInvokeTransitionFrame__m_dwFlags], PTFF_THREAD_ABORT
+ jnz Abort
POP_PROBE_FRAME 0
ret
+Abort:
+ POP_PROBE_FRAME 0
+ mov rcx, STATUS_REDHAWK_THREAD_ABORT
+ pop rdx ;; return address as exception RIP
+ jmp RhpThrowHwEx ;; Throw the ThreadAbortException as a special kind of hardware exception
+
NESTED_END RhpGcProbe, _TEXT
@@ -483,8 +494,8 @@ ifdef _DEBUG
;; If we get here, then we have been hijacked for a real GC, and our SyncState must
;; reflect that we've been requested to synchronize.
- cmp [RhpTrapThreads], 0
- jne @F
+ test [RhpTrapThreads], TrapThreadsFlags_TrapThreads
+ jnz @F
call RhDebugBreak
@@:
@@ -730,7 +741,7 @@ ifdef FEATURE_GC_STRESS
endif ;; FEATURE_GC_STRESS
lea rcx, [rsp + sizeof_OutgoingScratchSpace] ; calculate PInvokeTransitionFrame pointer
- call RhpWaitForGC
+ call RhpWaitForGCNoAbort
DoneWaitingForGc:
;; Prepare for our return by stashing a scratch register where we can pop it just before returning
@@ -762,6 +773,8 @@ endif ;; FEATURE_GC_STRESS
DontRestoreXmmAgain:
add rsp, sizeof_OutgoingScratchSpace
+ mov eax, [rsp + OFFSETOF__PInvokeTransitionFrame__m_dwFlags]
+ test eax, PTFF_THREAD_ABORT
pop rax ; m_RIP
pop rbp ; m_FramePointer
pop rax ; m_pThread
@@ -793,6 +806,15 @@ DontRestoreXmmAgain:
;; The final step is to restore eflags, rcx, and return back to the loop target location.
lea rsp, [rcx - 20h]
+ jz @f ;; result of the test instruction before the pops above
+ popfq ;; restore flags
+ pop rcx ;; discard ModuleHeader*
+ pop rcx ;; restore rcx
+ mov rcx, STATUS_REDHAWK_THREAD_ABORT
+ pop rdx ;; return address as exception RIP
+ jmp RhpThrowHwEx ;; Throw the ThreadAbortException as a special kind of hardware exception
+
+@@:
popfq ;; restore flags
pop rcx ;; discard ModuleHeader*
pop rcx ;; restore rcx
diff --git a/src/Native/Runtime/amd64/PInvoke.S b/src/Native/Runtime/amd64/PInvoke.S
index 958da80f5..e1def2bef 100644
--- a/src/Native/Runtime/amd64/PInvoke.S
+++ b/src/Native/Runtime/amd64/PInvoke.S
@@ -33,9 +33,9 @@ NESTED_ENTRY RhpPInvoke, _TEXT, NoHandler
mov qword ptr [rax + OFFSETOF__Thread__m_pTransitionFrame], rbx
- cmp dword ptr [C_VAR(RhpTrapThreads)], 0
+ test dword ptr [C_VAR(RhpTrapThreads)], TrapThreadsFlags_TrapThreads
pop_nonvol_reg rbx
- jne 0f // forward branch - predicted not taken
+ jnz 0f // forward branch - predicted not taken
ret
0:
jmp C_FUNC(RhpWaitForSuspend2)
@@ -50,7 +50,7 @@ NESTED_END RhpPInvoke, _TEXT
LEAF_ENTRY RhpPInvokeReturn, _TEXT
mov rsi, [rdi + OFFSETOF__PInvokeTransitionFrame__m_pThread]
mov qword ptr [rsi + OFFSETOF__Thread__m_pTransitionFrame], 0
- cmp dword ptr [C_VAR(RhpTrapThreads)], 0
+ cmp dword ptr [C_VAR(RhpTrapThreads)], TrapThreadsFlags_None
jne 0f // forward branch - predicted not taken
ret
0:
diff --git a/src/Native/Runtime/amd64/PInvoke.asm b/src/Native/Runtime/amd64/PInvoke.asm
index 9f5be2546..762b3d1dc 100644
--- a/src/Native/Runtime/amd64/PInvoke.asm
+++ b/src/Native/Runtime/amd64/PInvoke.asm
@@ -35,8 +35,12 @@ NESTED_ENTRY RhpWaitForSuspend, _TEXT
END_PROLOGUE
+ test [RhpTrapThreads], TrapThreadsFlags_TrapThreads
+ jz NoWait
+
call RhpWaitForSuspend2
+NoWait:
movdqa xmm0, [rsp + 20h + 0*10h]
movdqa xmm1, [rsp + 20h + 1*10h]
movdqa xmm2, [rsp + 20h + 2*10h]
@@ -55,7 +59,7 @@ NESTED_END RhpWaitForSuspend, _TEXT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
-;; RhpWaitForGC -- rare path for RhpPInvokeReturn
+;; RhpWaitForGCNoAbort -- rare path for RhpPInvokeReturn
;;
;;
;; INPUT: RCX: transition frame
@@ -63,7 +67,7 @@ NESTED_END RhpWaitForSuspend, _TEXT
;; TRASHES: RCX, RDX, R8, R9, R10, R11
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-NESTED_ENTRY RhpWaitForGC, _TEXT
+NESTED_ENTRY RhpWaitForGCNoAbort, _TEXT
push_vol_reg rax ; don't trash the integer return value
alloc_stack 30h
movdqa [rsp + 20h], xmm0 ; don't trash the FP return value
@@ -83,6 +87,45 @@ Done:
pop rax
ret
+NESTED_END RhpWaitForGCNoAbort, _TEXT
+
+EXTERN RhpThrowHwEx : PROC
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; RhpWaitForGC -- rare path for RhpPInvokeReturn
+;;
+;;
+;; INPUT: RCX: transition frame
+;;
+;; TRASHES: RCX, RDX, R8, R9, R10, R11
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+NESTED_ENTRY RhpWaitForGC, _TEXT
+ push_nonvol_reg rbx
+ END_PROLOGUE
+
+ mov rbx, rcx
+
+ test [RhpTrapThreads], TrapThreadsFlags_TrapThreads
+ jz NoWait
+
+ call RhpWaitForGCNoAbort
+NoWait:
+ test [RhpTrapThreads], TrapThreadsFlags_AbortInProgress
+ jz Done
+ test dword ptr [rbx + OFFSETOF__PInvokeTransitionFrame__m_dwFlags], PTFF_THREAD_ABORT
+ jz Done
+
+ mov rcx, STATUS_REDHAWK_THREAD_ABORT
+ pop rbx
+ pop rdx ; return address as exception RIP
+ jmp RhpThrowHwEx ; Throw the ThreadAbortException as a special kind of hardware exception
+
+Done:
+ pop rbx
+ ret
+
NESTED_END RhpWaitForGC, _TEXT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -125,8 +168,8 @@ LEAF_ENTRY RhpReversePInvoke, _TEXT
mov [rax], r11
mov qword ptr [r10 + OFFSETOF__Thread__m_pTransitionFrame], 0
- cmp [RhpTrapThreads], 0
- jne TrapThread
+ test [RhpTrapThreads], TrapThreadsFlags_TrapThreads
+ jnz TrapThread
ret
@@ -221,7 +264,7 @@ LEAF_ENTRY RhpReversePInvokeReturn, _TEXT
mov rcx, [rcx + 0] ; get previous M->U transition frame
mov [rdx + OFFSETOF__Thread__m_pTransitionFrame], rcx
- cmp [RhpTrapThreads], 0
+ cmp [RhpTrapThreads], TrapThreadsFlags_None
jne RhpWaitForSuspend
ret
LEAF_END RhpReversePInvokeReturn, _TEXT
@@ -255,7 +298,7 @@ LEAF_ENTRY RhpPInvoke, _TEXT
mov qword ptr [r10 + OFFSETOF__Thread__m_pTransitionFrame], rcx
- cmp [RhpTrapThreads], 0
+ cmp [RhpTrapThreads], TrapThreadsFlags_None
jne @F ; forward branch - predicted not taken
ret
@@:
@@ -275,7 +318,7 @@ LEAF_END RhpPInvoke, _TEXT
LEAF_ENTRY RhpPInvokeReturn, _TEXT
mov rdx, [rcx + OFFSETOF__PInvokeTransitionFrame__m_pThread]
mov qword ptr [rdx + OFFSETOF__Thread__m_pTransitionFrame], 0
- cmp [RhpTrapThreads], 0
+ cmp [RhpTrapThreads], TrapThreadsFlags_None
jne @F ; forward branch - predicted not taken
ret
@@: