From c4512332ed76f06cfc2c15dd572d667f3a597286 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Tue, 21 Mar 2017 01:00:17 +0200 Subject: [PATCH] [runtime] Defer async requests during abort protected blocks We avoid unnecessary checks for each interruption checkpoint. --- mono/metadata/threads.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index a92dc12f349..86c6b8173ea 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -259,6 +259,10 @@ mono_threads_begin_abort_protected_block (void) new_state = old_state + (1 << ABORT_PROT_BLOCK_SHIFT); } while (InterlockedCompareExchangePointer ((volatile gpointer)&thread->thread_state, (gpointer)new_state, (gpointer)old_state) != (gpointer)old_state); + + /* Defer async request since we won't be able to process until exiting the block */ + if (new_val == 1 && (new_state & INTERRUPT_ASYNC_REQUESTED_BIT)) + InterlockedDecrement (&thread_interruption_requested); } static gboolean @@ -280,17 +284,21 @@ mono_threads_end_abort_protected_block (void) { MonoInternalThread *thread = mono_thread_internal_current (); gsize old_state, new_state; + int new_val; do { old_state = thread->thread_state; //bounds check abort_prot_count - int new_val = ((old_state & ABORT_PROT_BLOCK_MASK) >> ABORT_PROT_BLOCK_SHIFT) - 1; + new_val = ((old_state & ABORT_PROT_BLOCK_MASK) >> ABORT_PROT_BLOCK_SHIFT) - 1; g_assert (new_val >= 0); g_assert (new_val < (1 << ABORT_PROT_BLOCK_BITS)); new_state = old_state - (1 << ABORT_PROT_BLOCK_SHIFT); } while (InterlockedCompareExchangePointer ((volatile gpointer)&thread->thread_state, (gpointer)new_state, (gpointer)old_state) != (gpointer)old_state); + if (new_val == 0 && (new_state & INTERRUPT_ASYNC_REQUESTED_BIT)) + InterlockedIncrement (&thread_interruption_requested); + return mono_thread_state_has_interruption (new_state); } @@ -350,7 +358,8 @@ mono_thread_set_interruption_requested (MonoInternalThread *thread) new_state = old_state | INTERRUPT_ASYNC_REQUESTED_BIT; } while (InterlockedCompareExchangePointer ((volatile gpointer)&thread->thread_state, (gpointer)new_state, (gpointer)old_state) != (gpointer)old_state); - InterlockedIncrement (&thread_interruption_requested); + if (sync || !(new_state & ABORT_PROT_BLOCK_MASK)) + InterlockedIncrement (&thread_interruption_requested); return sync || !(new_state & ABORT_PROT_BLOCK_MASK); } -- 2.11.4.GIT