Merge pull request #901 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mono / utils / mono-threads.h
index b30e9ac4c16716c201ce2cb1bf853b177014cadc..e86dc5068267095ecbbd5637555bb3be5d5341a4 100644 (file)
@@ -14,6 +14,7 @@
 #include <mono/utils/mono-stack-unwinding.h>
 #include <mono/utils/mono-linked-list-set.h>
 #include <mono/utils/mono-mutex.h>
+#include <mono/utils/mono-tls.h>
 
 #include <glib.h>
 
@@ -26,6 +27,8 @@ typedef HANDLE MonoNativeThreadHandle; /* unused */
 
 typedef DWORD mono_native_thread_return_t;
 
+#define MONO_NATIVE_THREAD_ID_TO_UINT(tid) (tid)
+
 #else
 
 #include <pthread.h>
@@ -47,6 +50,8 @@ typedef pthread_t MonoNativeThreadId;
 
 typedef void* mono_native_thread_return_t;
 
+#define MONO_NATIVE_THREAD_ID_TO_UINT(tid) (gsize)(tid)
+
 #endif /* #ifdef HOST_WIN32 */
 
 /*
@@ -76,10 +81,10 @@ and reduce the number of casts drastically.
 #endif
 
 enum {
-       STATE_STARTING                  = 0x01,
-       STATE_RUNNING                   = 0x02,
-       STATE_SHUTTING_DOWN             = 0x03,
-       STATE_DEAD                              = 0x04,
+       STATE_STARTING                  = 0x00,
+       STATE_RUNNING                   = 0x01,
+       STATE_SHUTTING_DOWN             = 0x02,
+       STATE_DEAD                              = 0x03,
        RUN_STATE_MASK                  = 0x0F,
 
        STATE_SUSPENDED                 = 0x10,
@@ -87,8 +92,8 @@ enum {
        SUSPEND_STATE_MASK              = 0xF0,
 };
 
-#define mono_thread_info_run_state(info) ((info)->thread_state & RUN_STATE_MASK)
-#define mono_thread_info_suspend_state(info) ((info)->thread_state & SUSPEND_STATE_MASK)
+#define mono_thread_info_run_state(info) (((MonoThreadInfo*)info)->thread_state & RUN_STATE_MASK)
+#define mono_thread_info_suspend_state(info) (((MonoThreadInfo*)info)->thread_state & SUSPEND_STATE_MASK)
 
 typedef struct {
        MonoLinkedListSetNode node;
@@ -99,8 +104,8 @@ typedef struct {
        /*Tells if this thread was created by the runtime or not.*/
        gboolean runtime_thread;
 
-       /* suspend machinery, fields protected by the suspend_lock */
-       mono_mutex_t suspend_lock;
+       /* suspend machinery, fields protected by suspend_semaphore */
+       MonoSemType suspend_semaphore;
        int suspend_count;
 
        MonoSemType finish_resume_semaphore;
@@ -108,7 +113,7 @@ typedef struct {
 
        /* only needed by the posix backend */ 
 #if (defined(_POSIX_VERSION) || defined(__native_client__)) && !defined (__MACH__)
-       MonoSemType suspend_semaphore;
+       MonoSemType begin_suspend_semaphore;
        gboolean syscall_break_signal;
        gboolean suspend_can_continue;
 #endif
@@ -119,17 +124,56 @@ typedef struct {
        /*async call machinery, thread MUST be suspended before accessing those fields*/
        void (*async_target)(void*);
        void *user_data;
+
+       /*
+       If true, this thread is running a critical region of code and cannot be suspended.
+       A critical session is implicitly started when you call mono_thread_info_safe_suspend_sync
+       and is ended when you call either mono_thread_info_resume or mono_thread_info_finish_suspend.
+       */
+       gboolean inside_critical_region;
+
+       /*
+        * If TRUE, the thread is in async context. Code can use this information to avoid async-unsafe
+        * operations like locking without having to pass an 'async' parameter around.
+        */
+       gboolean is_async_context;
+
+       gboolean create_suspended;
+
+       /* Semaphore used to implement CREATE_SUSPENDED */
+       MonoSemType create_suspended_sem;
+
+       /*
+        * Values of TLS variables for this thread.
+        * This can be used to obtain the values of TLS variable for threads
+        * other than the current one.
+        */
+       gpointer tls [TLS_KEY_NUM];
+
+       /* IO layer handle for this thread */
+       /* Set when the thread is started, or in _wapi_thread_duplicate () */
+       HANDLE handle;
 } MonoThreadInfo;
 
 typedef struct {
        void* (*thread_register)(THREAD_INFO_TYPE *info, void *baseaddr);
        /*
-       This callback is called after @info is removed from the thread list.
+       This callback is called with @info still on the thread list.
+       This call is made while holding the suspend lock, so don't do callbacks.
        SMR remains functional as its small_id has not been reclaimed.
        */
        void (*thread_unregister)(THREAD_INFO_TYPE *info);
+       /*
+       This callback is called right before thread_unregister. This is called
+       without any locks held so it's the place for complicated cleanup.
+
+       The thread must remain operational between this call and thread_unregister.
+       It must be possible to successfully suspend it after thread_unregister completes.
+       */
+       void (*thread_detach)(THREAD_INFO_TYPE *info);
        void (*thread_attach)(THREAD_INFO_TYPE *info);
        gboolean (*mono_method_is_critical) (void *method);
+       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
@@ -144,13 +188,13 @@ typedef struct {
 /*
 Requires the world to be stoped
 */
-#define FOREACH_THREAD(thread) MONO_LLS_FOREACH (mono_thread_info_list_head (), thread, SgenThreadInfo*)
+#define FOREACH_THREAD(thread) MONO_LLS_FOREACH (mono_thread_info_list_head (), thread, THREAD_INFO_TYPE*)
 #define END_FOREACH_THREAD MONO_LLS_END_FOREACH
 
 /*
 Snapshot iteration.
 */
-#define FOREACH_THREAD_SAFE(thread) MONO_LLS_FOREACH_SAFE (mono_thread_info_list_head (), thread, SgenThreadInfo*)
+#define FOREACH_THREAD_SAFE(thread) MONO_LLS_FOREACH_SAFE (mono_thread_info_list_head (), thread, THREAD_INFO_TYPE*)
 #define END_FOREACH_THREAD_SAFE MONO_LLS_END_FOREACH_SAFE
 
 #define mono_thread_info_get_tid(info) ((MonoNativeThreadId)((MonoThreadInfo*)info)->node.key)
@@ -179,7 +223,7 @@ THREAD_INFO_TYPE *
 mono_thread_info_attach (void *baseptr) MONO_INTERNAL;
 
 void
-mono_thread_info_dettach (void) MONO_INTERNAL;
+mono_thread_info_detach (void) MONO_INTERNAL;
 
 THREAD_INFO_TYPE *
 mono_thread_info_current (void) MONO_INTERNAL;
@@ -190,15 +234,18 @@ mono_thread_info_get_small_id (void) MONO_INTERNAL;
 MonoLinkedListSet*
 mono_thread_info_list_head (void) MONO_INTERNAL;
 
-MonoThreadInfo*
+THREAD_INFO_TYPE*
 mono_thread_info_lookup (MonoNativeThreadId id) MONO_INTERNAL;
 
-MonoThreadInfo*
+THREAD_INFO_TYPE*
 mono_thread_info_safe_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel) MONO_INTERNAL;
 
 gboolean
 mono_thread_info_resume (MonoNativeThreadId tid) MONO_INTERNAL;
 
+void
+mono_thread_info_finish_suspend (void) MONO_INTERNAL;
+
 void
 mono_thread_info_self_suspend (void) MONO_INTERNAL;
 
@@ -206,7 +253,7 @@ gboolean
 mono_thread_info_new_interrupt_enabled (void) MONO_INTERNAL;
 
 void
-mono_thread_info_setup_async_call (MonoThreadInfo *info, void (*target_func)(void*), void *user_data) MONO_INTERNAL;
+mono_thread_info_setup_async_call (THREAD_INFO_TYPE *info, void (*target_func)(void*), void *user_data) MONO_INTERNAL;
 
 void
 mono_thread_info_suspend_lock (void) MONO_INTERNAL;
@@ -214,19 +261,40 @@ mono_thread_info_suspend_lock (void) MONO_INTERNAL;
 void
 mono_thread_info_suspend_unlock (void) MONO_INTERNAL;
 
-void
-mono_threads_unregister_current_thread (THREAD_INFO_TYPE *info) MONO_INTERNAL;
-
 void
 mono_thread_info_disable_new_interrupt (gboolean disable) MONO_INTERNAL;
 
 void
 mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid) MONO_INTERNAL;
 
-#if !defined(HOST_WIN32)
+void
+mono_thread_info_set_is_async_context (gboolean async_context) MONO_INTERNAL;
 
-int
-mono_threads_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) MONO_INTERNAL;
+gboolean
+mono_thread_info_is_async_context (void) MONO_INTERNAL;
+
+void
+mono_thread_info_get_stack_bounds (guint8 **staddr, size_t *stsize);
+
+gboolean
+mono_thread_info_yield (void) MONO_INTERNAL;
+
+gpointer
+mono_thread_info_tls_get (THREAD_INFO_TYPE *info, MonoTlsKey key);
+
+void
+mono_thread_info_tls_set (THREAD_INFO_TYPE *info, MonoTlsKey key, gpointer value);
+
+void
+mono_thread_info_exit (void);
+
+HANDLE
+mono_thread_info_open_handle (void);
+
+HANDLE
+mono_threads_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid);
+
+#if !defined(HOST_WIN32)
 
 #if !defined(__MACH__)
 /*Use this instead of pthread_kill */
@@ -234,23 +302,24 @@ int
 mono_threads_pthread_kill (THREAD_INFO_TYPE *info, int signum) MONO_INTERNAL;
 #endif
 
-#else  /* !defined(HOST_WIN32) */
-
-HANDLE
-       mono_threads_CreateThread (LPSECURITY_ATTRIBUTES attributes, SIZE_T stack_size, LPTHREAD_START_ROUTINE start_routine, LPVOID arg, DWORD creation_flags, LPDWORD thread_id);
-
-
 #endif /* !defined(HOST_WIN32) */
 
 /* Plartform specific functions DON'T use them */
 void mono_threads_init_platform (void) MONO_INTERNAL; //ok
-gboolean mono_threads_core_suspend (MonoThreadInfo *info) MONO_INTERNAL;
-gboolean mono_threads_core_resume (MonoThreadInfo *info) MONO_INTERNAL;
-void mono_threads_platform_register (MonoThreadInfo *info) MONO_INTERNAL; //ok
-void mono_threads_platform_free (MonoThreadInfo *info) MONO_INTERNAL;
-void mono_threads_core_interrupt (MonoThreadInfo *info) MONO_INTERNAL;
-void mono_threads_core_abort_syscall (MonoThreadInfo *info) MONO_INTERNAL;
+gboolean mono_threads_core_suspend (THREAD_INFO_TYPE *info) MONO_INTERNAL;
+gboolean mono_threads_core_resume (THREAD_INFO_TYPE *info) MONO_INTERNAL;
+void mono_threads_platform_register (THREAD_INFO_TYPE *info) MONO_INTERNAL; //ok
+void mono_threads_platform_free (THREAD_INFO_TYPE *info) MONO_INTERNAL;
+void mono_threads_core_interrupt (THREAD_INFO_TYPE *info) MONO_INTERNAL;
+void mono_threads_core_abort_syscall (THREAD_INFO_TYPE *info) MONO_INTERNAL;
 gboolean mono_threads_core_needs_abort_syscall (void) MONO_INTERNAL;
+HANDLE mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid) MONO_INTERNAL;
+void mono_threads_core_resume_created (THREAD_INFO_TYPE *info, MonoNativeThreadId tid) MONO_INTERNAL;
+void mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize) MONO_INTERNAL;
+gboolean mono_threads_core_yield (void) MONO_INTERNAL;
+void mono_threads_core_exit (int exit_code) MONO_INTERNAL;
+void mono_threads_core_unregister (THREAD_INFO_TYPE *info) MONO_INTERNAL;
+HANDLE mono_threads_core_open_handle (void) MONO_INTERNAL;
 
 MonoNativeThreadId mono_native_thread_id_get (void) MONO_INTERNAL;