return InterlockedIncrement (&managed_thread_id_counter);
}
+enum {
+ INTERRUPT_REQUESTED_BIT = 0x1,
+ ABORT_PROT_BLOCK_SHIFT = 1,
+ ABORT_PROT_BLOCK_BITS = 8,
+ ABORT_PROT_BLOCK_MASK = (((1 << ABORT_PROT_BLOCK_BITS) - 1) << ABORT_PROT_BLOCK_SHIFT)
+};
+
+static int
+mono_thread_get_abort_prot_block_count (MonoInternalThread *thread)
+{
+ gsize state = thread->thread_state;
+ return (state & ABORT_PROT_BLOCK_MASK) >> ABORT_PROT_BLOCK_SHIFT;
+}
+
+//Don't use this function, use inc/dec below
+static void
+mono_thread_abort_prot_block_count_add (MonoInternalThread *thread, int val)
+{
+ gsize old_state, new_state;
+ do {
+ old_state = thread->thread_state;
+ int new_val = val + ((old_state & ABORT_PROT_BLOCK_MASK) >> ABORT_PROT_BLOCK_SHIFT);
+ //bounds check abort_prot_count
+ g_assert (new_val >= 0);
+ g_assert (new_val < (1 << ABORT_PROT_BLOCK_BITS));
+ new_state = (old_state & ~ABORT_PROT_BLOCK_MASK) | (new_val << ABORT_PROT_BLOCK_SHIFT);
+
+ } while (InterlockedCompareExchangePointer ((volatile gpointer)&thread->thread_state, (gpointer)new_state, (gpointer)old_state) != (gpointer)old_state);
+}
+
+static void
+mono_thread_inc_abort_prot_block_count (MonoInternalThread *thread)
+{
+ mono_thread_abort_prot_block_count_add (thread, 1);
+}
+
+static void
+mono_thread_dec_abort_prot_block_count (MonoInternalThread *thread)
+{
+ mono_thread_abort_prot_block_count_add (thread, -1);
+}
+
+static gboolean
+mono_thread_get_interruption_requested (MonoInternalThread *thread)
+{
+ gsize state = thread->thread_state;
+ return (state & INTERRUPT_REQUESTED_BIT) == INTERRUPT_REQUESTED_BIT;
+}
+
+/* Returns TRUE is there was a state change */
+static gboolean
+mono_thread_clear_interruption_requested (MonoInternalThread *thread)
+{
+ gsize old_state, new_state;
+ do {
+ old_state = thread->thread_state;
+ //Already cleared
+ if (!(old_state & INTERRUPT_REQUESTED_BIT))
+ return FALSE;
+ new_state = old_state & ~INTERRUPT_REQUESTED_BIT;
+ } while (InterlockedCompareExchangePointer ((volatile gpointer)&thread->thread_state, (gpointer)new_state, (gpointer)old_state) != (gpointer)old_state);
+ return TRUE;
+}
+
+/* Returns TRUE is there was a state change */
+static gboolean
+mono_thread_set_interruption_requested (MonoInternalThread *thread)
+{
+ gsize old_state, new_state;
+ do {
+ old_state = thread->thread_state;
+ //Already set
+ if (old_state & INTERRUPT_REQUESTED_BIT)
+ return FALSE;
+ new_state = old_state | INTERRUPT_REQUESTED_BIT;
+ } while (InterlockedCompareExchangePointer ((volatile gpointer)&thread->thread_state, (gpointer)new_state, (gpointer)old_state) != (gpointer)old_state);
+ return TRUE;
+}
+
static inline MonoNativeThreadId
thread_get_tid (MonoInternalThread *thread)
{
Leaving the counter unbalanced will cause a performance degradation since all threads
will now keep checking their local flags all the time.
*/
- if (InterlockedExchange (&thread->interruption_requested, 0) != 0)
+ if (mono_thread_clear_interruption_requested (thread))
InterlockedDecrement (&thread_interruption_requested);
mono_threads_lock ();
LOCK_THREAD (thread);
/* MonoThread::interruption_requested can only be changed with atomics */
- if (InterlockedCompareExchange (&thread->interruption_requested, FALSE, TRUE)) {
+ if (mono_thread_clear_interruption_requested (thread)) {
/* this will consume pending APC calls */
#ifdef HOST_WIN32
WaitForSingleObjectEx (GetCurrentThread(), 0, TRUE);
thread->state & ThreadState_Background)
ExitThread (1);
#endif
- if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 1)
+ if (!mono_thread_set_interruption_requested (thread))
return NULL;
InterlockedIncrement (&thread_interruption_requested);
if (!still_aborting)
return FALSE;
- if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 1)
+ if (!mono_thread_set_interruption_requested (thread))
return NULL;
InterlockedIncrement (&thread_interruption_requested);
MonoInternalThread *thread = mono_thread_internal_current ();
/* The thread may already be stopping */
if (thread != NULL)
- return (thread->interruption_requested);
+ return mono_thread_get_interruption_requested (thread);
}
return FALSE;
}
/* The thread may already be stopping */
if (!thread)
return NULL;
- if (!thread->interruption_requested)
+ if (!mono_thread_get_interruption_requested (thread))
return NULL;
if (!bypass_abort_protection && is_running_protected_wrapper ())
return NULL;
The target thread is running at least one protected block, which must not be interrupted, so we give up.
The protected block code will give them a chance when appropriate.
*/
- if (thread->abort_protected_block_count)
+ if (mono_thread_get_abort_prot_block_count (thread) > 0)
return MonoResumeThread;
/*someone is already interrupting it*/
- if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 1)
+ if (!mono_thread_set_interruption_requested (thread))
return MonoResumeThread;
InterlockedIncrement (&thread_interruption_requested);
return KeepSuspended;
}
} else {
- if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 0)
+ if (mono_thread_set_interruption_requested (thread))
InterlockedIncrement (&thread_interruption_requested);
if (data->interrupt)
data->interrupt_token = mono_thread_info_prepare_interrupt ((MonoThreadInfo *)thread->thread_info);
MonoInternalThread *thread;
thread = mono_thread_internal_current ();
- ++thread->abort_protected_block_count;
+ mono_thread_inc_abort_prot_block_count (thread);
mono_memory_barrier ();
}
thread = mono_thread_internal_current ();
mono_memory_barrier ();
- --thread->abort_protected_block_count;
+ mono_thread_dec_abort_prot_block_count (thread);
}
MonoException*
MonoInternalThread *thread;
thread = mono_thread_internal_current ();
- if (thread->abort_protected_block_count || mono_get_eh_callbacks ()->mono_current_thread_has_handle_block_guard ())
+ if (mono_thread_get_abort_prot_block_count (thread) > 0 || mono_get_eh_callbacks ()->mono_current_thread_has_handle_block_guard ())
return NULL;
return mono_thread_resume_interruption ();
return FALSE;
}
- if (thread->abort_protected_block_count || mono_get_eh_callbacks ()->mono_current_thread_has_handle_block_guard ()) {
+ if (mono_thread_get_abort_prot_block_count (thread) || mono_get_eh_callbacks ()->mono_current_thread_has_handle_block_guard ()) {
UNLOCK_THREAD (thread);
return FALSE;
}