Merge pull request #1952 from esdrubal/proc_name
[mono.git] / mono / utils / mono-threads.h
index 8535646cc44817e0a5403da79f21564feae443bf..7e00c04659582cd3a6a99db597974827f95029e2 100644 (file)
 #include <mono/utils/mono-linked-list-set.h>
 #include <mono/utils/mono-mutex.h>
 #include <mono/utils/mono-tls.h>
+#include <mono/utils/mono-threads-coop.h>
 
 #include <glib.h>
-
+#include <config.h>
 #ifdef HOST_WIN32
 
 #include <windows.h>
@@ -87,7 +88,7 @@ and reduce the number of casts drastically.
 /* Logging - enable them below if you need specific logging for the category you need */
 #define MOSTLY_ASYNC_SAFE_PRINTF(...) do { \
        char __buff[1024];      __buff [0] = '\0'; \
-       snprintf (__buff, sizeof (__buff), __VA_ARGS__);        \
+       g_snprintf (__buff, sizeof (__buff), __VA_ARGS__);      \
        write (1, __buff, strlen (__buff));     \
 } while (0)
 
@@ -116,17 +117,34 @@ and reduce the number of casts drastically.
 #define THREADS_STATE_MACHINE_DEBUG MOSTLY_ASYNC_SAFE_PRINTF
 #endif
 
+#if 1
+#define THREADS_INTERRUPT_DEBUG(...)
+#else
+#define THREADS_INTERRUPT_DEBUG MOSTLY_ASYNC_SAFE_PRINTF
+#endif
+
 /* If this is defined, use the signals backed on Mach. Debug only as signals can't be made usable on OSX. */
 // #define USE_SIGNALS_ON_MACH
 
-#if defined (_POSIX_VERSION) || defined (__native_client__)
+
+#if defined (USE_COOP_GC)
+#define USE_COOP_BACKEND
+#define MONO_THREADS_PLATFORM_REQUIRES_UNIFIED_SUSPEND 1
+
+#elif defined (_POSIX_VERSION) || defined (__native_client__)
+#define MONO_THREADS_PLATFORM_REQUIRES_UNIFIED_SUSPEND 0
+
 #if defined (__MACH__) && !defined (USE_SIGNALS_ON_MACH)
 #define USE_MACH_BACKEND
 #else
 #define USE_POSIX_BACKEND
 #endif
-#endif
 
+#elif HOST_WIN32
+#define MONO_THREADS_PLATFORM_REQUIRES_UNIFIED_SUSPEND 0
+#define USE_WINDOWS_BACKEND
+
+#endif
 
 enum {
        STATE_STARTING                          = 0x00,
@@ -137,14 +155,18 @@ enum {
        STATE_SELF_SUSPENDED                    = 0x04,
        STATE_ASYNC_SUSPEND_REQUESTED   = 0x05,
        STATE_SELF_SUSPEND_REQUESTED    = 0x06,
-       STATE_SUSPEND_IN_PROGRESS               = 0x07,
-       STATE_SUSPEND_PROMOTED_TO_ASYNC = 0x08,
+       STATE_BLOCKING                                  = 0x07,
+       STATE_BLOCKING_AND_SUSPENDED    = 0x8,
+
        STATE_MAX                                               = 0x08,
 
        THREAD_STATE_MASK                       = 0x00FF,
        THREAD_SUSPEND_COUNT_MASK       = 0xFF00,
        THREAD_SUSPEND_COUNT_SHIFT      = 8,
-       THREAD_SUSPEND_COUNT_MAX        = 0xFF
+       THREAD_SUSPEND_COUNT_MAX        = 0xFF,
+
+       SELF_SUSPEND_STATE_INDEX = 0,
+       ASYNC_SUSPEND_STATE_INDEX = 1,
 };
 
 /*
@@ -154,6 +176,8 @@ typedef enum {
        MONO_SERVICE_REQUEST_SAMPLE = 1,
 } MonoAsyncJob;
 
+typedef struct _MonoThreadInfoInterruptToken MonoThreadInfoInterruptToken;
+
 typedef struct {
        MonoLinkedListSetNode node;
        guint32 small_id; /*Used by hazard pointers */
@@ -173,7 +197,6 @@ typedef struct {
        MonoSemType suspend_semaphore;
        int suspend_count;
 
-       // MonoSemType suspend_semaphore;
        MonoSemType resume_semaphore;
 
        /* only needed by the posix backend */ 
@@ -186,7 +209,7 @@ typedef struct {
 #endif
 
        /*In theory, only the posix backend needs this, but having it on mach/win32 simplifies things a lot.*/
-       MonoThreadUnwindState suspend_state;
+       MonoThreadUnwindState thread_saved_state [2]; //0 is self suspend, 1 is async suspend.
 
        /*async call machinery, thread MUST be suspended before accessing those fields*/
        void (*async_target)(void*);
@@ -226,6 +249,10 @@ typedef struct {
         * In the future the signaling should be part of the API, but for now, it's only for massaging the bits.
         */
        volatile gint32 service_requests;
+
+       void *jit_data;
+
+       MonoThreadInfoInterruptToken *interrupt_token;
 } MonoThreadInfo;
 
 typedef struct {
@@ -247,18 +274,23 @@ typedef struct {
        void (*thread_attach)(THREAD_INFO_TYPE *info);
        gboolean (*mono_method_is_critical) (void *method);
        gboolean (*mono_thread_in_critical_region) (THREAD_INFO_TYPE *info);
-       void (*thread_exit)(void *retval);
-#ifndef HOST_WIN32
-       int (*mono_gc_pthread_create) (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
-#endif
 } MonoThreadInfoCallbacks;
 
 typedef struct {
        void (*setup_async_callback) (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data);
        gboolean (*thread_state_init_from_sigctx) (MonoThreadUnwindState *state, void *sigctx);
        gboolean (*thread_state_init_from_handle) (MonoThreadUnwindState *tctx, MonoThreadInfo *info);
+       void (*thread_state_init) (MonoThreadUnwindState *tctx);
 } MonoThreadInfoRuntimeCallbacks;
 
+//Not using 0 and 1 to ensure callbacks are not returning bad data
+typedef enum {
+       MonoResumeThread = 0x1234,
+       KeepSuspended = 0x4321,
+} SuspendThreadResult;
+
+typedef SuspendThreadResult (*MonoSuspendThreadCallback) (THREAD_INFO_TYPE *info, gpointer user_data);
+
 static inline gboolean
 mono_threads_filter_tools_threads (THREAD_INFO_TYPE *info)
 {
@@ -290,9 +322,6 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t thread_info_size);
 void
 mono_threads_runtime_init (MonoThreadInfoRuntimeCallbacks *callbacks);
 
-MonoThreadInfoCallbacks *
-mono_threads_get_callbacks (void);
-
 MonoThreadInfoRuntimeCallbacks *
 mono_threads_get_runtime_callbacks (void);
 
@@ -311,6 +340,9 @@ mono_thread_info_is_exiting (void);
 THREAD_INFO_TYPE *
 mono_thread_info_current (void);
 
+THREAD_INFO_TYPE*
+mono_thread_info_current_unchecked (void);
+
 int
 mono_thread_info_get_small_id (void);
 
@@ -330,10 +362,7 @@ void
 mono_thread_info_set_name (MonoNativeThreadId tid, const char *name);
 
 void
-mono_thread_info_finish_suspend (MonoThreadInfo *info);
-
-void
-mono_thread_info_finish_suspend_and_resume (MonoThreadInfo *info);
+mono_thread_info_safe_suspend_and_run (MonoNativeThreadId id, gboolean interrupt_kernel, MonoSuspendThreadCallback callback, gpointer user_data);
 
 //XXX new API, fix the world
 void
@@ -344,9 +373,6 @@ mono_thread_info_end_self_suspend (void);
 
 //END of new API
 
-gboolean
-mono_thread_info_new_interrupt_enabled (void);
-
 gboolean
 mono_thread_info_unified_management_enabled (void);
 
@@ -359,9 +385,6 @@ mono_thread_info_suspend_lock (void);
 void
 mono_thread_info_suspend_unlock (void);
 
-void
-mono_thread_info_disable_new_interrupt (gboolean disable);
-
 void
 mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid);
 
@@ -389,20 +412,29 @@ mono_thread_info_exit (void);
 HANDLE
 mono_thread_info_open_handle (void);
 
-gpointer
-mono_thread_info_prepare_interrupt (HANDLE thread_handle);
+void
+mono_thread_info_install_interrupt (void (*callback) (gpointer data), gpointer data, gboolean *interrupted);
 
 void
-mono_thread_info_finish_interrupt (gpointer wait_handle);
+mono_thread_info_uninstall_interrupt (gboolean *interrupted);
+
+MonoThreadInfoInterruptToken*
+mono_thread_info_prepare_interrupt (THREAD_INFO_TYPE *info);
 
 void
-mono_thread_info_interrupt (HANDLE thread_handle);
+mono_thread_info_finish_interrupt (MonoThreadInfoInterruptToken *token);
 
 void
 mono_thread_info_self_interrupt (void);
 
 void
-mono_thread_info_clear_interruption (void);
+mono_thread_info_clear_self_interrupt (void);
+
+gboolean
+mono_thread_info_is_interrupt_state (THREAD_INFO_TYPE *info);
+
+void
+mono_thread_info_describe_interrupt_token (THREAD_INFO_TYPE *info, GString *text);
 
 gboolean
 mono_thread_info_is_live (THREAD_INFO_TYPE *info);
@@ -445,7 +477,6 @@ gboolean mono_threads_core_suspend (THREAD_INFO_TYPE *info, gboolean interrupt_k
 gboolean mono_threads_core_resume (THREAD_INFO_TYPE *info);
 void mono_threads_platform_register (THREAD_INFO_TYPE *info); //ok
 void mono_threads_platform_free (THREAD_INFO_TYPE *info);
-void mono_threads_core_interrupt (THREAD_INFO_TYPE *info);
 void mono_threads_core_abort_syscall (THREAD_INFO_TYPE *info);
 gboolean mono_threads_core_needs_abort_syscall (void);
 HANDLE mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid);
@@ -458,6 +489,9 @@ HANDLE mono_threads_core_open_handle (void);
 HANDLE mono_threads_core_open_thread_handle (HANDLE handle, MonoNativeThreadId tid);
 void mono_threads_core_set_name (MonoNativeThreadId tid, const char *name);
 
+void mono_threads_core_begin_global_suspend (void);
+void mono_threads_core_end_global_suspend (void);
+
 /* Internal API between mono-threads and its backends. */
 
 /* Backend functions - a backend must implement all of the following */
@@ -508,10 +542,6 @@ void mono_threads_core_unregister (THREAD_INFO_TYPE *info);
 HANDLE mono_threads_core_open_handle (void);
 HANDLE mono_threads_core_open_thread_handle (HANDLE handle, MonoNativeThreadId tid);
 void mono_threads_core_set_name (MonoNativeThreadId tid, const char *name);
-gpointer mono_threads_core_prepare_interrupt (HANDLE thread_handle);
-void mono_threads_core_finish_interrupt (gpointer wait_handle);
-void mono_threads_core_self_interrupt (void);
-void mono_threads_core_clear_interruption (void);
 
 MonoNativeThreadId mono_native_thread_id_get (void);
 
@@ -534,6 +564,11 @@ This tells the resume initiator that we completed resume duties and will return
 */
 void mono_threads_notify_initiator_of_resume (THREAD_INFO_TYPE* info);
 
+/*
+This tells the resume initiator that we completed abort duties and will return to previous state.
+*/
+void mono_threads_notify_initiator_of_abort (THREAD_INFO_TYPE* info);
+
 /* Thread state machine functions */
 
 typedef enum {
@@ -541,6 +576,7 @@ typedef enum {
        ResumeOk,
        ResumeInitSelfResume,
        ResumeInitAsyncResume,
+       ResumeInitBlockingResume,
 } MonoResumeResult;
 
 typedef enum {
@@ -555,21 +591,48 @@ typedef enum {
        AsyncSuspendInitSuspend,
 } MonoRequestAsyncSuspendResult;
 
+typedef enum {
+       DoBlockingContinue, //in blocking mode, continue
+       DoBlockingPollAndRetry, //async suspend raced blocking and won, pool and retry
+} MonoDoBlockingResult;
+
+typedef enum {
+       DoneBlockingAborted, //blocking was aborted and not properly restored, poll the state
+       DoneBlockingOk, //exited blocking fine
+       DoneBlockingWait, //thread should end suspended
+} MonoDoneBlockingResult;
+
+
+typedef enum {
+       AbortBlockingIgnore, //Ignore
+       AbortBlockingIgnoreAndPoll, //Ignore and pool
+       AbortBlockingOk, //Abort worked
+       AbortBlockingOkAndPool, //Abort worked, but pool before
+} MonoAbortBlockingResult;
+
+
 void mono_threads_transition_attach (THREAD_INFO_TYPE* info);
 gboolean mono_threads_transition_detach (THREAD_INFO_TYPE *info);
 void mono_threads_transition_request_self_suspension (THREAD_INFO_TYPE *info);
 MonoRequestAsyncSuspendResult mono_threads_transition_request_async_suspension (THREAD_INFO_TYPE *info);
-gboolean mono_threads_transition_state_poll (THREAD_INFO_TYPE *info);
+MonoSelfSupendResult mono_threads_transition_state_poll (THREAD_INFO_TYPE *info);
 MonoResumeResult mono_threads_transition_request_resume (THREAD_INFO_TYPE* info);
-MonoSelfSupendResult mono_threads_transition_finish_self_suspend (THREAD_INFO_TYPE* info);
 gboolean mono_threads_transition_finish_async_suspend (THREAD_INFO_TYPE* info);
-void mono_threads_transition_async_suspend_compensation (MonoThreadInfo* info);
+void mono_threads_transition_async_suspend_compensation (THREAD_INFO_TYPE* info);
+MonoDoBlockingResult mono_threads_transition_do_blocking (THREAD_INFO_TYPE* info);
+MonoDoneBlockingResult mono_threads_transition_done_blocking (THREAD_INFO_TYPE* info);
+MonoAbortBlockingResult mono_threads_transition_abort_blocking (THREAD_INFO_TYPE* info);
+
+MonoThreadUnwindState* mono_thread_info_get_suspend_state (THREAD_INFO_TYPE *info);
 
 
+void mono_thread_info_wait_for_resume (THREAD_INFO_TYPE *info);
 /* Advanced suspend API, used for suspending multiple threads as once. */
 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);