This allows a piece of code to handle the cases where it's called in running and blocker context
and must always be in blocking context.
This probably makes code more modular at the expense of an easy to follow and debug execution model.
Since we don't currently annotate all icalls with blocking sections we do it with locks but they can
nest and recurse which requires this support for try block.
mono_threads_prepare_blocking ();
}
+void*
+mono_threads_try_prepare_blocking (void)
+{
+ MonoThreadInfo *info;
+
+ info = mono_thread_info_current_unchecked ();
+ /* If the thread is not attached, it doesn't make sense prepare for suspend. */
+ if (!info || !mono_thread_info_is_live (info) || mono_thread_info_current_state (info) == STATE_BLOCKING) {
+ THREADS_SUSPEND_DEBUG ("PREPARE-TRY-BLOCKING failed %p\n", mono_thread_info_get_tid (info));
+ return NULL;
+ }
+
+retry:
+ /*The JIT might not be able to save*/
+ if (!mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX], NULL)) {
+ THREADS_SUSPEND_DEBUG ("PREPARE-TRY-BLOCKING failed %p to save thread state\n", mono_thread_info_get_tid (info));
+ return NULL;
+ }
+
+ switch (mono_threads_transition_do_blocking (info)) {
+ case DoBlockingContinue:
+ break;
+ case DoBlockingPollAndRetry:
+ mono_threads_state_poll ();
+ goto retry;
+ }
+
+ return info;
+}
+
+void
+mono_threads_finish_try_blocking (void* cookie)
+{
+ mono_threads_finish_blocking (cookie);
+}
void
mono_threads_core_abort_syscall (MonoThreadInfo *info)
#define MONO_FINISH_RESET_BLOCKING \
mono_threads_reset_blocking_end (__reset_cookie); \
}
+
+#define MONO_TRY_BLOCKING \
+{ \
+ void *__try_block_cookie = mono_threads_try_prepare_blocking ();
+
+#define MONO_FINISH_TRY_BLOCKING \
+ mono_threads_finish_try_blocking (__try_block_cookie); \
+}
+
/* Internal API */
extern volatile size_t mono_threads_polling_required;
void* mono_threads_reset_blocking_start (void);
void mono_threads_reset_blocking_end (void* cookie);
+void* mono_threads_try_prepare_blocking (void);
+void mono_threads_finish_try_blocking (void* cookie);
+
#else
#define MONO_SUSPEND_CHECK do { } while (0);
#define MONO_FINISH_BLOCKING }
#define MONO_PREPARE_RESET_BLOCKING {
#define MONO_FINISH_RESET_BLOCKING }
+#define MONO_TRY_BLOCKING {
+#define MONO_FINISH_TRY_BLOCKING }
#endif /* USE_COOP_GC */
{
return get_thread_suspend_count (info->thread_state);
}
+
+int
+mono_thread_info_current_state (MonoThreadInfo *info)
+{
+ return get_thread_state (info->thread_state);
+}
gboolean mono_thread_info_is_running (THREAD_INFO_TYPE *info);
gboolean mono_thread_info_is_live (THREAD_INFO_TYPE *info);
int mono_thread_info_suspend_count (THREAD_INFO_TYPE *info);
+int mono_thread_info_current_state (THREAD_INFO_TYPE *info);
+
gboolean mono_thread_info_in_critical_location (THREAD_INFO_TYPE *info);
gboolean mono_thread_info_begin_suspend (THREAD_INFO_TYPE *info, gboolean interrupt_kernel);
gboolean mono_thread_info_begin_resume (THREAD_INFO_TYPE *info);