Merge pull request #2034 from alexrp/ctx-cleanup
authorRodrigo Kumpera <kumpera@gmail.com>
Tue, 22 Dec 2015 16:05:30 +0000 (11:05 -0500)
committerRodrigo Kumpera <kumpera@gmail.com>
Tue, 22 Dec 2015 16:05:30 +0000 (11:05 -0500)
[runtime] Actually clean up context-static data segments.

1  2 
mcs/class/corlib/System/Environment.cs
mono/metadata/appdomain.c
mono/metadata/domain-internals.h
mono/metadata/threads.c

index 2553a400be58081e176f67775efca560b44ee7fb,e2edf0cb84d92b06768ad45a6e1b0cb841dcca12..d463fb1285854b57d6354ca64464e57a5a92d0c4
@@@ -57,7 -57,7 +57,7 @@@ namespace System 
                 * of icalls, do not require an increment.
                 */
  #pragma warning disable 169
-               private const int mono_corlib_version = 138;
+               private const int mono_corlib_version = 139;
  #pragma warning restore 169
  
                [ComVisible (true)]
                        return GetFolderPath (folder, SpecialFolderOption.None);
                }
  
 -// for monotouch, not monotouch_runtime
 -#if !(MONOTOUCH && FULL_AOT_RUNTIME)
 +#if !MONOTOUCH
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                private extern static string GetWindowsFolderPath (int folder);
  
index 89c163c83ee5e7f52538738000a3882499852f28,1e6fd0c6f7544abef18ef5c21820a4e4780cfc20..ca424f3268ad4ef93ad76fd1c381747866d19586
@@@ -32,7 -32,7 +32,7 @@@
  #endif
  #endif
  
 -#include <mono/metadata/gc-internal.h>
 +#include <mono/metadata/gc-internals.h>
  #include <mono/metadata/object.h>
  #include <mono/metadata/domain-internals.h>
  #include "mono/metadata/metadata-internals.h"
@@@ -42,7 -42,7 +42,7 @@@
  #include <mono/metadata/threadpool-ms.h>
  #include <mono/metadata/socket-io.h>
  #include <mono/metadata/tabledefs.h>
 -#include <mono/metadata/gc-internal.h>
 +#include <mono/metadata/gc-internals.h>
  #include <mono/metadata/mono-gc.h>
  #include <mono/metadata/marshal.h>
  #include <mono/metadata/monitor.h>
@@@ -56,7 -56,7 +56,7 @@@
  #include <mono/metadata/tokentype.h>
  #include <mono/metadata/profiler-private.h>
  #include <mono/utils/mono-uri.h>
 -#include <mono/utils/mono-logger-internal.h>
 +#include <mono/utils/mono-logger-internals.h>
  #include <mono/utils/mono-path.h>
  #include <mono/utils/mono-stdlib.h>
  #include <mono/utils/mono-io-portability.h>
@@@ -79,7 -79,7 +79,7 @@@
   * Changes which are already detected at runtime, like the addition
   * of icalls, do not require an increment.
   */
- #define MONO_CORLIB_VERSION 138
+ #define MONO_CORLIB_VERSION 139
  
  typedef struct
  {
@@@ -225,7 -225,7 +225,7 @@@ mono_runtime_init (MonoDomain *domain, 
  {
        MonoAppDomainSetup *setup;
        MonoAppDomain *ad;
 -      MonoClass *class;
 +      MonoClass *klass;
  
        mono_portability_helpers_init ();
        
        mono_install_assembly_refonly_preload_hook (mono_domain_assembly_preload, GUINT_TO_POINTER (TRUE));
        mono_install_assembly_search_hook (mono_domain_assembly_search, GUINT_TO_POINTER (FALSE));
        mono_install_assembly_refonly_search_hook (mono_domain_assembly_search, GUINT_TO_POINTER (TRUE));
 -      mono_install_assembly_postload_search_hook ((void*)mono_domain_assembly_postload_search, GUINT_TO_POINTER (FALSE));
 -      mono_install_assembly_postload_refonly_search_hook ((void*)mono_domain_assembly_postload_search, GUINT_TO_POINTER (TRUE));
 +      mono_install_assembly_postload_search_hook ((MonoAssemblySearchFunc)mono_domain_assembly_postload_search, GUINT_TO_POINTER (FALSE));
 +      mono_install_assembly_postload_refonly_search_hook ((MonoAssemblySearchFunc)mono_domain_assembly_postload_search, GUINT_TO_POINTER (TRUE));
        mono_install_assembly_load_hook (mono_domain_fire_assembly_load, NULL);
        mono_install_lookup_dynamic_token (mono_reflection_lookup_dynamic_token);
  
        mono_thread_init (start_cb, attach_cb);
  
 -      class = mono_class_from_name (mono_defaults.corlib, "System", "AppDomainSetup");
 -      setup = (MonoAppDomainSetup *) mono_object_new_pinned (domain, class);
 +      klass = mono_class_from_name (mono_defaults.corlib, "System", "AppDomainSetup");
 +      setup = (MonoAppDomainSetup *) mono_object_new_pinned (domain, klass);
  
 -      class = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
 -      ad = (MonoAppDomain *) mono_object_new_pinned (domain, class);
 +      klass = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
 +      ad = (MonoAppDomain *) mono_object_new_pinned (domain, klass);
        ad->data = domain;
        domain->domain = ad;
        domain->setup = setup;
@@@ -327,11 -327,11 +327,11 @@@ mono_check_corlib_version (void
  void
  mono_context_init (MonoDomain *domain)
  {
 -      MonoClass *class;
 +      MonoClass *klass;
        MonoAppContext *context;
  
 -      class = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Contexts", "Context");
 -      context = (MonoAppContext *) mono_object_new_pinned (domain, class);
 +      klass = mono_class_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Contexts", "Context");
 +      context = (MonoAppContext *) mono_object_new_pinned (domain, klass);
        context->domain_id = domain->domain_id;
        context->context_id = 0;
        ves_icall_System_Runtime_Remoting_Contexts_Context_RegisterContext (context);
@@@ -394,10 -394,10 +394,10 @@@ mono_domain_create_appdomain (char *fri
  {
        MonoAppDomain *ad;
        MonoAppDomainSetup *setup;
 -      MonoClass *class;
 +      MonoClass *klass;
  
 -      class = mono_class_from_name (mono_defaults.corlib, "System", "AppDomainSetup");
 -      setup = (MonoAppDomainSetup *) mono_object_new (mono_domain_get (), class);
 +      klass = mono_class_from_name (mono_defaults.corlib, "System", "AppDomainSetup");
 +      setup = (MonoAppDomainSetup *) mono_object_new (mono_domain_get (), klass);
        setup->configuration_file = configuration_file != NULL ? mono_string_new (mono_domain_get (), configuration_file) : NULL;
  
        ad = mono_domain_create_appdomain_internal (friendly_name, setup);
@@@ -647,7 -647,7 +647,7 @@@ ves_icall_System_AppDomain_GetData (Mon
        else if (!strcmp (str, "FORCE_CACHE_INSTALL"))
                o = (MonoObject *)add->setup->shadow_copy_files;
        else 
 -              o = mono_g_hash_table_lookup (add->env, name);
 +              o = (MonoObject *)mono_g_hash_table_lookup (add->env, name);
  
        mono_domain_unlock (add);
        g_free (str);
@@@ -731,7 -731,7 +731,7 @@@ start_element (GMarkupParseContext *con
               gpointer             user_data,
               GError             **error)
  {
 -      RuntimeConfig *runtime_config = user_data;
 +      RuntimeConfig *runtime_config = (RuntimeConfig *)user_data;
        
        if (strcmp (element_name, "runtime") == 0) {
                runtime_config->runtime_count++;
@@@ -764,7 -764,7 +764,7 @@@ end_element (GMarkupParseContext *conte
             gpointer             user_data,
             GError             **error)
  {
 -      RuntimeConfig *runtime_config = user_data;
 +      RuntimeConfig *runtime_config = (RuntimeConfig *)user_data;
        if (strcmp (element_name, "runtime") == 0)
                runtime_config->runtime_count--;
        else if (strcmp (element_name, "assemblyBinding") == 0)
  static void
  parse_error   (GMarkupParseContext *context, GError *error, gpointer user_data)
  {
 -      RuntimeConfig *state = user_data;
 +      RuntimeConfig *state = (RuntimeConfig *)user_data;
        const gchar *msg;
        const gchar *filename;
  
@@@ -827,7 -827,7 +827,7 @@@ mono_set_private_bin_path_from_config (
        if (len > 3 && text [0] == '\xef' && text [1] == (gchar) '\xbb' && text [2] == '\xbf')
                offset = 3; /* Skip UTF-8 BOM */
  
 -      context = g_markup_parse_context_new (&mono_parser, 0, &runtime_config, NULL);
 +      context = g_markup_parse_context_new (&mono_parser, (GMarkupParseFlags)0, &runtime_config, NULL);
        if (g_markup_parse_context_parse (context, text + offset, len - offset, NULL))
                g_markup_parse_context_end_parse (context, NULL);
        g_markup_parse_context_free (context);
@@@ -878,7 -878,7 +878,7 @@@ ves_icall_System_AppDomain_GetAssemblie
        /* Need to skip internal assembly builders created by remoting */
        mono_domain_assemblies_lock (domain);
        for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
 -              ass = tmp->data;
 +              ass = (MonoAssembly *)tmp->data;
                if (refonly != ass->ref_only)
                        continue;
                if (ass->corlib_internal)
  
        res = mono_array_new (domain, System_Reflection_Assembly, assemblies->len);
        for (i = 0; i < assemblies->len; ++i) {
 -              ass = g_ptr_array_index (assemblies, i);
 +              ass = (MonoAssembly *)g_ptr_array_index (assemblies, i);
                mono_array_setref (res, i, mono_assembly_get_object (domain, ass));
        }
  
@@@ -1142,7 -1142,7 +1142,7 @@@ set_domain_search_path (MonoDomain *dom
        if (domain->search_path)
                g_strfreev (domain->search_path);
  
 -      tmp = g_malloc ((npaths + 1) * sizeof (gchar *));
 +      tmp = (gchar **)g_malloc ((npaths + 1) * sizeof (gchar *));
        tmp [npaths] = NULL;
  
        *tmp = mono_string_to_utf8_checked (setup->application_base, &error);
@@@ -1521,7 -1521,7 +1521,7 @@@ shadow_copy_create_ini (const char *sha
        if (!u16_ini) {
                return FALSE;
        }
 -      handle = CreateFile (u16_ini, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
 +      handle = (void **)CreateFile (u16_ini, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
                                NULL, CREATE_NEW, FileAttributes_Normal, NULL);
        g_free (u16_ini);
        if (handle == INVALID_HANDLE_VALUE) {
@@@ -1864,7 -1864,7 +1864,7 @@@ mono_domain_assembly_search (MonoAssemb
  
        mono_domain_assemblies_lock (domain);
        for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
 -              ass = tmp->data;
 +              ass = (MonoAssembly *)tmp->data;
                /* Dynamic assemblies can't match here in MS.NET */
                if (assembly_is_dynamic (ass) || refonly != ass->ref_only || !mono_assembly_names_equal (aname, &ass->aname))
                        continue;
@@@ -2221,9 -2221,9 +2221,9 @@@ deregister_reflection_info_roots_from_l
        GSList *list = image->reflection_info_unregister_classes;
  
        while (list) {
 -              MonoClass *class = list->data;
 +              MonoClass *klass = (MonoClass *)list->data;
  
 -              mono_class_free_ref_info (class);
 +              mono_class_free_ref_info (klass);
  
                list = list->next;
        }
@@@ -2238,7 -2238,7 +2238,7 @@@ deregister_reflection_info_roots (MonoD
  
        mono_domain_assemblies_lock (domain);
        for (list = domain->domain_assemblies; list; list = list->next) {
 -              MonoAssembly *assembly = list->data;
 +              MonoAssembly *assembly = (MonoAssembly *)list->data;
                MonoImage *image = assembly->image;
                int i;
  
@@@ -2310,11 -2310,11 +2310,11 @@@ unload_thread_main (void *arg
         * the collection there won't be any more remsets.
         */
        for (i = 0; i < domain->class_vtable_array->len; ++i)
 -              zero_static_data (g_ptr_array_index (domain->class_vtable_array, i));
 +              zero_static_data ((MonoVTable *)g_ptr_array_index (domain->class_vtable_array, i));
        mono_gc_collect (0);
  #endif
        for (i = 0; i < domain->class_vtable_array->len; ++i)
 -              clear_cached_vtable (g_ptr_array_index (domain->class_vtable_array, i));
 +              clear_cached_vtable ((MonoVTable *)g_ptr_array_index (domain->class_vtable_array, i));
        deregister_reflection_info_roots (domain);
  
        mono_assembly_cleanup_domain_bindings (domain->domain_id);
@@@ -2405,12 -2405,12 +2405,12 @@@ mono_domain_try_unload (MonoDomain *dom
        MonoDomain *caller_domain = mono_domain_get ();
        char *name;
  
 -      /* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, GetCurrentThreadId ()); */
 +      /* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, mono_native_thread_id_get ()); */
  
        /* Atomically change our state to UNLOADING */
 -      prev_state = InterlockedCompareExchange ((gint32*)&domain->state,
 -                                                                                       MONO_APPDOMAIN_UNLOADING_START,
 -                                                                                       MONO_APPDOMAIN_CREATED);
 +      prev_state = (MonoAppDomainState)InterlockedCompareExchange ((gint32*)&domain->state,
 +              MONO_APPDOMAIN_UNLOADING_START,
 +              MONO_APPDOMAIN_CREATED);
        if (prev_state != MONO_APPDOMAIN_CREATED) {
                switch (prev_state) {
                case MONO_APPDOMAIN_UNLOADING_START:
index 2159f50f0e6dfcd04852820981aef3e040099614,0eed290a2d28125e84d068bd7a61f2a200eb4f81..4cb4af6c02d1aca82dfca8f81fd08e5c0a867688
@@@ -9,6 -9,7 +9,6 @@@
  #include <mono/metadata/mempool.h>
  #include <mono/metadata/lock-tracer.h>
  #include <mono/utils/mono-codeman.h>
 -#include <mono/utils/mono-mutex.h>
  #include <mono/metadata/mono-hash.h>
  #include <mono/utils/mono-compiler.h>
  #include <mono/utils/mono-internal-hash.h>
@@@ -85,10 -86,6 +85,10 @@@ typedef struct 
         * associated with this handler.
         */
        int clause_index;
 +      uint32_t try_offset;
 +      uint32_t try_len;
 +      uint32_t handler_offset;
 +      uint32_t handler_len;
        union {
                MonoClass *catch_class;
                gpointer filter;
@@@ -238,11 -235,17 +238,17 @@@ struct _MonoJitInfo 
  
  #define MONO_SIZEOF_JIT_INFO (offsetof (struct _MonoJitInfo, clauses))
  
+ typedef struct {
+       gpointer *static_data; /* Used to free the static data without going through the MonoAppContext object itself. */
+       uint32_t gc_handle;
+ } ContextStaticData;
  struct _MonoAppContext {
        MonoObject obj;
        gint32 domain_id;
        gint32 context_id;
        gpointer *static_data;
+       ContextStaticData *data;
  };
  
  /* Lock-free allocator */
@@@ -284,7 -287,7 +290,7 @@@ struct _MonoDomain 
         * i.e. if both are taken by the same thread, the loader lock
         * must taken first.
         */
 -      mono_mutex_t    lock;
 +      MonoCoopMutex    lock;
        MonoMemPool        *mp;
        MonoCodeManager    *code_mp;
        /*
@@@ -420,10 -423,10 +426,10 @@@ typedef struct  
        const AssemblyVersionSet version_sets [4];
  } MonoRuntimeInfo;
  
 -#define mono_domain_assemblies_lock(domain) mono_locks_acquire(&(domain)->assemblies_lock, DomainAssembliesLock)
 -#define mono_domain_assemblies_unlock(domain) mono_locks_release(&(domain)->assemblies_lock, DomainAssembliesLock)
 -#define mono_domain_jit_code_hash_lock(domain) mono_locks_acquire(&(domain)->jit_code_hash_lock, DomainJitCodeHashLock)
 -#define mono_domain_jit_code_hash_unlock(domain) mono_locks_release(&(domain)->jit_code_hash_lock, DomainJitCodeHashLock)
 +#define mono_domain_assemblies_lock(domain) mono_locks_os_acquire(&(domain)->assemblies_lock, DomainAssembliesLock)
 +#define mono_domain_assemblies_unlock(domain) mono_locks_os_release(&(domain)->assemblies_lock, DomainAssembliesLock)
 +#define mono_domain_jit_code_hash_lock(domain) mono_locks_os_acquire(&(domain)->jit_code_hash_lock, DomainJitCodeHashLock)
 +#define mono_domain_jit_code_hash_unlock(domain) mono_locks_os_release(&(domain)->jit_code_hash_lock, DomainJitCodeHashLock)
  
  typedef MonoDomain* (*MonoLoadFunc) (const char *filename, const char *runtime_version);
  
diff --combined mono/metadata/threads.c
index 75bdcb3d0e5dae3e3e04b65baa9f08964d7a1b6e,6dc723925b13e48635351bb6a9b24463d2b6c7fe..112c8779454ed5ef48ce13245dd4e04ada9483d5
@@@ -24,7 -24,7 +24,7 @@@
  #include <mono/metadata/exception.h>
  #include <mono/metadata/environment.h>
  #include <mono/metadata/monitor.h>
 -#include <mono/metadata/gc-internal.h>
 +#include <mono/metadata/gc-internals.h>
  #include <mono/metadata/marshal.h>
  #include <mono/metadata/runtime.h>
  #include <mono/io-layer/io-layer.h>
@@@ -41,7 -41,7 +41,7 @@@
  #include <mono/utils/atomic.h>
  #include <mono/utils/mono-memory-model.h>
  
 -#include <mono/metadata/gc-internal.h>
 +#include <mono/metadata/gc-internals.h>
  
  #ifdef HAVE_SIGNAL_H
  #include <signal.h>
@@@ -128,11 -128,11 +128,11 @@@ typedef struct 
  /* Controls access to the 'threads' hash table */
  static void mono_threads_lock (void);
  static void mono_threads_unlock (void);
 -static mono_mutex_t threads_mutex;
 +static MonoCoopMutex threads_mutex;
  
  /* Controls access to the 'joinable_threads' hash table */
 -#define joinable_threads_lock() mono_mutex_lock (&joinable_threads_mutex)
 -#define joinable_threads_unlock() mono_mutex_unlock (&joinable_threads_mutex)
 +#define joinable_threads_lock() mono_os_mutex_lock (&joinable_threads_mutex)
 +#define joinable_threads_unlock() mono_os_mutex_unlock (&joinable_threads_mutex)
  static mono_mutex_t joinable_threads_mutex;
  
  /* Holds current status of static data heap */
@@@ -149,6 -149,9 +149,9 @@@ static MonoGHashTable *threads=NULL
   */
  static GHashTable *contexts = NULL;
  
+ /* Cleanup queue for contexts. */
+ static MonoReferenceQueue *context_queue;
  /*
   * Threads which are starting up and they are not in the 'threads' hash yet.
   * When handle_store is called for a thread, it will be removed from this hash table.
@@@ -204,13 -207,14 +207,13 @@@ static gboolean mono_thread_resume (Mon
  static void abort_thread_internal (MonoInternalThread *thread, gboolean can_raise_exception, gboolean install_async_abort);
  static void suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt);
  static void self_suspend_internal (MonoInternalThread *thread);
 -static gboolean resume_thread_internal (MonoInternalThread *thread);
  
  static MonoException* mono_thread_execute_interruption ();
  static void ref_stack_destroy (gpointer rs);
  
  /* Spin lock for InterlockedXXX 64 bit functions */
 -#define mono_interlocked_lock() mono_mutex_lock (&interlocked_mutex)
 -#define mono_interlocked_unlock() mono_mutex_unlock (&interlocked_mutex)
 +#define mono_interlocked_lock() mono_os_mutex_lock (&interlocked_mutex)
 +#define mono_interlocked_unlock() mono_os_mutex_unlock (&interlocked_mutex)
  static mono_mutex_t interlocked_mutex;
  
  /* global count of thread interruptions requested */
@@@ -226,13 -230,15 +229,13 @@@ static gint32 managed_thread_id_counte
  static void
  mono_threads_lock (void)
  {
 -      MONO_TRY_BLOCKING;
 -      mono_locks_acquire (&threads_mutex, ThreadsLock);
 -      MONO_FINISH_TRY_BLOCKING;
 +      mono_locks_coop_acquire (&threads_mutex, ThreadsLock);
  }
  
  static void
  mono_threads_unlock (void)
  {
 -      mono_locks_release (&threads_mutex, ThreadsLock);
 +      mono_locks_coop_release (&threads_mutex, ThreadsLock);
  }
  
  
@@@ -346,19 -352,19 +349,19 @@@ static gboolean handle_remove(MonoInter
  
  static void ensure_synch_cs_set (MonoInternalThread *thread)
  {
 -      mono_mutex_t *synch_cs;
 +      MonoCoopMutex *synch_cs;
  
        if (thread->synch_cs != NULL) {
                return;
        }
  
 -      synch_cs = g_new0 (mono_mutex_t, 1);
 -      mono_mutex_init_recursive (synch_cs);
 +      synch_cs = g_new0 (MonoCoopMutex, 1);
 +      mono_coop_mutex_init_recursive (synch_cs);
  
        if (InterlockedCompareExchangePointer ((gpointer *)&thread->synch_cs,
                                               synch_cs, NULL) != NULL) {
                /* Another thread must have installed this CS */
 -              mono_mutex_destroy (synch_cs);
 +              mono_coop_mutex_destroy (synch_cs);
                g_free (synch_cs);
        }
  }
@@@ -371,13 -377,15 +374,13 @@@ lock_thread (MonoInternalThread *thread
  
        g_assert (thread->synch_cs);
  
 -      MONO_TRY_BLOCKING;
 -      mono_mutex_lock (thread->synch_cs);
 -      MONO_FINISH_TRY_BLOCKING;
 +      mono_coop_mutex_lock (thread->synch_cs);
  }
  
  static inline void
  unlock_thread (MonoInternalThread *thread)
  {
 -      mono_mutex_unlock (thread->synch_cs);
 +      mono_coop_mutex_unlock (thread->synch_cs);
  }
  
  /*
@@@ -476,7 -484,6 +479,7 @@@ static void thread_cleanup (MonoInterna
                MONO_GC_UNREGISTER_ROOT (thread->thread_pinning_ref);
                thread->thread_pinning_ref = NULL;
        }
 +
  }
  
  /*
@@@ -550,7 -557,7 +553,7 @@@ get_current_thread_ptr_for_domain (Mono
        mono_domain_unlock (domain);
        g_assert (offset);
  
 -      return get_thread_static_data (thread, offset);
 +      return (MonoThread **)get_thread_static_data (thread, offset);
  }
  
  static void
@@@ -588,8 -595,8 +591,8 @@@ create_internal_thread (void
        vt = mono_class_vtable (mono_get_root_domain (), mono_defaults.internal_thread_class);
        thread = (MonoInternalThread*)mono_gc_alloc_mature (vt);
  
 -      thread->synch_cs = g_new0 (mono_mutex_t, 1);
 -      mono_mutex_init_recursive (thread->synch_cs);
 +      thread->synch_cs = g_new0 (MonoCoopMutex, 1);
 +      mono_coop_mutex_init_recursive (thread->synch_cs);
  
        thread->apartment_state = ThreadApartmentState_Unknown;
        thread->managed_id = get_next_managed_thread_id ();
@@@ -628,7 -635,7 +631,7 @@@ static guint32 WINAPI start_wrapper_int
        MonoObject *start_delegate = start_info->delegate;
        MonoDomain *domain = start_info->obj->obj.vtable->domain;
  
 -      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Start wrapper", __func__, GetCurrentThreadId ()));
 +      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Start wrapper", __func__, mono_native_thread_id_get ()));
  
        /* We can be sure start_info->obj->tid and
         * start_info->obj->handle have been set, because the thread
         */
        mono_thread_new_init (tid, &tid, start_func);
        internal->stack_ptr = &tid;
 +      if (domain != mono_get_root_domain ())
 +              set_current_thread_for_domain (domain, internal, start_info->obj);
  
 -      LIBGC_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT",%d) Setting thread stack to %p", __func__, GetCurrentThreadId (), getpid (), thread->stack_ptr));
 +      LIBGC_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT",%d) Setting thread stack to %p", __func__, mono_native_thread_id_get (), getpid (), thread->stack_ptr));
  
 -      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Setting current_object_key to %p", __func__, GetCurrentThreadId (), internal));
 +      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Setting current_object_key to %p", __func__, mono_native_thread_id_get (), internal));
  
        /* On 2.0 profile (and higher), set explicitly since state might have been
           Unknown */
         * call thread_cleanup() on this thread's behalf.
         */
  
 -      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Start wrapper terminating", __func__, GetCurrentThreadId ()));
 +      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Start wrapper terminating", __func__, mono_native_thread_id_get ()));
  
        /* Do any cleanup needed for apartment state. This
         * cannot be done in thread_cleanup since thread_cleanup could be 
@@@ -812,8 -817,10 +815,8 @@@ create_thread (MonoThread *thread, Mono
         */
        create_flags = CREATE_SUSPENDED;
  
 -      MONO_PREPARE_BLOCKING;
        thread_handle = mono_threads_create_thread ((LPTHREAD_START_ROUTINE)start_wrapper, start_info,
                                                                                                stack_size, create_flags, &tid);
 -      MONO_FINISH_BLOCKING;
  
        if (thread_handle == NULL) {
                /* The thread couldn't be created, so throw an exception */
        if (threadpool_thread)
                mono_thread_set_state (internal, ThreadState_Background);
  
 -      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Launching thread %p (%"G_GSIZE_FORMAT")", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
 +      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Launching thread %p (%"G_GSIZE_FORMAT")", __func__, mono_native_thread_id_get (), internal, (gsize)internal->tid));
  
        /* Only store the handle when the thread is about to be
         * launched, to avoid the main thread deadlocking while trying
        if (!handle_store (thread, FALSE))
                return FALSE;
  
 -      MONO_PREPARE_BLOCKING;
        mono_thread_info_resume (tid);
 -      MONO_FINISH_BLOCKING;
  
        if (internal->start_notify) {
                /*
                 * to look up the data believing the thread has
                 * started
                 */
 -              THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for thread %p (%"G_GSIZE_FORMAT") to start", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
 +              THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for thread %p (%"G_GSIZE_FORMAT") to start", __func__, mono_native_thread_id_get (), internal, (gsize)internal->tid));
  
                MONO_PREPARE_BLOCKING;
                WaitForSingleObjectEx (internal->start_notify, INFINITE, FALSE);
                internal->start_notify = NULL;
        }
  
 -      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Done launching thread %p (%"G_GSIZE_FORMAT")", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
 +      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Done launching thread %p (%"G_GSIZE_FORMAT")", __func__, mono_native_thread_id_get (), internal, (gsize)internal->tid));
  
        return TRUE;
  }
@@@ -904,7 -913,7 +907,7 @@@ mono_thread_create_internal (MonoDomai
        MONO_OBJECT_SETREF (thread, internal_thread, internal);
  
        start_info = g_new0 (StartInfo, 1);
 -      start_info->func = func;
 +      start_info->func = (guint32 (*)(void *))func;
        start_info->obj = thread;
        start_info->start_arg = arg;
  
                return NULL;
  
        /* Check that the managed and unmanaged layout of MonoInternalThread matches */
 +#ifndef MONO_CROSS_COMPILE
        if (mono_check_corlib_version () == NULL)
                g_assert (((char*)&internal->unused2 - (char*)internal) == mono_defaults.internal_thread_class->fields [mono_defaults.internal_thread_class->field.count - 1].offset);
 +#endif
  
        return internal;
  }
@@@ -940,7 -947,7 +943,7 @@@ mono_thread_attach_full (MonoDomain *do
        MonoInternalThread *thread;
        MonoThread *current_thread;
        HANDLE thread_handle;
 -      gsize tid;
 +      MonoNativeThreadId tid;
  
        if ((thread = mono_thread_internal_current ())) {
                if (domain != mono_domain_get ())
        }
  
        if (!mono_gc_register_thread (&domain)) {
 -              g_error ("Thread %"G_GSIZE_FORMAT" calling into managed code is not registered with the GC. On UNIX, this can be fixed by #include-ing <gc.h> before <pthread.h> in the file containing the thread creation code.", GetCurrentThreadId ());
 +              g_error ("Thread %"G_GSIZE_FORMAT" calling into managed code is not registered with the GC. On UNIX, this can be fixed by #include-ing <gc.h> before <pthread.h> in the file containing the thread creation code.", mono_native_thread_id_get ());
        }
  
        thread = create_internal_thread ();
        thread_handle = mono_thread_info_open_handle ();
        g_assert (thread_handle);
  
 -      tid=GetCurrentThreadId ();
 +      tid=mono_native_thread_id_get ();
  
        thread->handle = thread_handle;
 -      thread->tid = tid;
 +      thread->tid = MONO_NATIVE_THREAD_ID_TO_UINT (tid);
        thread->stack_ptr = &tid;
  
        THREAD_DEBUG (g_message ("%s: Attached thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread_handle));
        if (!handle_store (current_thread, force_attach)) {
                /* Mono is shutting down, so just wait for the end */
                for (;;)
 -                      Sleep (10000);
 +                      mono_thread_info_sleep (10000, NULL);
        }
  
 -      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Setting current_object_key to %p", __func__, GetCurrentThreadId (), thread));
 +      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Setting current_object_key to %p", __func__, mono_native_thread_id_get (), thread));
  
        SET_CURRENT_OBJECT (thread);
        mono_domain_set (domain, TRUE);
                mono_thread_info_get_stack_bounds (&staddr, &stsize);
  
                if (staddr == NULL)
 -                      mono_thread_attach_cb (tid, &tid);
 +                      mono_thread_attach_cb (MONO_NATIVE_THREAD_ID_TO_UINT (tid), &tid);
                else
 -                      mono_thread_attach_cb (tid, staddr + stsize);
 +                      mono_thread_attach_cb (MONO_NATIVE_THREAD_ID_TO_UINT (tid), staddr + stsize);
        }
  
        // FIXME: Need a separate callback
 -      mono_profiler_thread_start (tid);
 +      mono_profiler_thread_start (MONO_NATIVE_THREAD_ID_TO_UINT (tid));
  
        return current_thread;
  }
@@@ -1079,7 -1086,7 +1082,7 @@@ ves_icall_System_Threading_Thread_Const
  
        internal->state = ThreadState_Unstarted;
  
 -      InterlockedCompareExchangePointer ((gpointer)&this_obj->internal_thread, internal, NULL);
 +      InterlockedCompareExchangePointer ((volatile gpointer *)&this_obj->internal_thread, internal, NULL);
  }
  
  HANDLE
@@@ -1147,9 -1154,9 +1150,9 @@@ ves_icall_System_Threading_InternalThre
                CloseHandle (thread);
  
        if (this_obj->synch_cs) {
 -              mono_mutex_t *synch_cs = this_obj->synch_cs;
 +              MonoCoopMutex *synch_cs = this_obj->synch_cs;
                this_obj->synch_cs = NULL;
 -              mono_mutex_destroy (synch_cs);
 +              mono_coop_mutex_destroy (synch_cs);
                g_free (synch_cs);
        }
  
@@@ -1169,17 -1176,17 +1172,17 @@@ ves_icall_System_Threading_Thread_Sleep
        THREAD_DEBUG (g_message ("%s: Sleeping for %d ms", __func__, ms));
  
        mono_thread_current_check_pending_interrupt ();
 -      
 +
        while (TRUE) {
 +              gboolean alerted = FALSE;
 +
                mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
 -      
 -              MONO_PREPARE_BLOCKING;
 -              res = SleepEx(ms,TRUE);
 -              MONO_FINISH_BLOCKING;
 -      
 +
 +              res = mono_thread_info_sleep (ms, &alerted);
 +
                mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
  
 -              if (res == WAIT_IO_COMPLETION) { /* we might have been interrupted */
 +              if (alerted) {
                        MonoException* exc = mono_thread_execute_interruption ();
                        if (exc) {
                                mono_raise_exception (exc);
@@@ -1298,7 -1305,7 +1301,7 @@@ ves_icall_System_Threading_Thread_SetNa
  }
  
  int
 -ves_icall_System_Threading_Thread_GetPriority (MonoThread *this)
 +ves_icall_System_Threading_Thread_GetPriority (MonoThread *this_obj)
  {
        return ThreadPriority_Lowest;
  }
@@@ -1355,23 -1362,6 +1358,23 @@@ mono_thread_current (void
        return *current_thread_ptr;
  }
  
 +/* Return the thread object belonging to INTERNAL in the current domain */
 +static MonoThread *
 +mono_thread_current_for_thread (MonoInternalThread *internal)
 +{
 +      MonoDomain *domain = mono_domain_get ();
 +      MonoThread **current_thread_ptr;
 +
 +      g_assert (internal);
 +      current_thread_ptr = get_current_thread_ptr_for_domain (domain, internal);
 +
 +      if (!*current_thread_ptr) {
 +              g_assert (domain != mono_get_root_domain ());
 +              *current_thread_ptr = new_thread_with_internal (domain, internal);
 +      }
 +      return *current_thread_ptr;
 +}
 +
  MonoInternalThread*
  mono_thread_internal_current (void)
  {
@@@ -1500,10 -1490,10 +1503,10 @@@ gboolean ves_icall_System_Threading_Wai
        g_free(handles);
  
        if(ret==WAIT_FAILED) {
 -              THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Wait failed", __func__, GetCurrentThreadId ()));
 +              THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Wait failed", __func__, mono_native_thread_id_get ()));
                return(FALSE);
        } else if(ret==WAIT_TIMEOUT) {
 -              THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Wait timed out", __func__, GetCurrentThreadId ()));
 +              THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Wait timed out", __func__, mono_native_thread_id_get ()));
                return(FALSE);
        }
        
@@@ -1542,7 -1532,7 +1545,7 @@@ gint32 ves_icall_System_Threading_WaitH
  
        mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
  
 -      THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") returning %d", __func__, GetCurrentThreadId (), ret));
 +      THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") returning %d", __func__, mono_native_thread_id_get (), ret));
  
        /*
         * These need to be here.  See MSDN dos on WaitForMultipleObjects.
@@@ -1564,7 -1554,7 +1567,7 @@@ gboolean ves_icall_System_Threading_Wai
        guint32 ret;
        MonoInternalThread *thread = mono_thread_internal_current ();
  
 -      THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for %p, %d ms", __func__, GetCurrentThreadId (), handle, ms));
 +      THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for %p, %d ms", __func__, mono_native_thread_id_get (), handle, ms));
        
        if(ms== -1) {
                ms=INFINITE;
        mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
        
        if(ret==WAIT_FAILED) {
 -              THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Wait failed", __func__, GetCurrentThreadId ()));
 +              THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Wait failed", __func__, mono_native_thread_id_get ()));
                return(FALSE);
        } else if(ret==WAIT_TIMEOUT) {
 -              THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Wait timed out", __func__, GetCurrentThreadId ()));
 +              THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Wait timed out", __func__, mono_native_thread_id_get ()));
                return(FALSE);
        }
        
@@@ -1919,7 -1909,7 +1922,7 @@@ MonoObject
  ves_icall_System_Threading_Interlocked_CompareExchange_T (MonoObject **location, MonoObject *value, MonoObject *comparand)
  {
        MonoObject *res;
 -      res = InterlockedCompareExchangePointer ((gpointer *)location, value, comparand);
 +      res = (MonoObject *)InterlockedCompareExchangePointer ((volatile gpointer *)location, value, comparand);
        mono_gc_wbarrier_generic_nostore (location);
        return res;
  }
@@@ -1928,7 -1918,7 +1931,7 @@@ MonoObject
  ves_icall_System_Threading_Interlocked_Exchange_T (MonoObject **location, MonoObject *value)
  {
        MonoObject *res;
 -      res = InterlockedExchangePointer ((gpointer *)location, value);
 +      res = (MonoObject *)InterlockedExchangePointer ((volatile gpointer *)location, value);
        mono_gc_wbarrier_generic_nostore (location);
        return res;
  }
@@@ -1977,9 -1967,9 +1980,9 @@@ ves_icall_System_Threading_Thread_Memor
  }
  
  void
 -ves_icall_System_Threading_Thread_ClrState (MonoInternalThread* this, guint32 state)
 +ves_icall_System_Threading_Thread_ClrState (MonoInternalThread* this_obj, guint32 state)
  {
 -      mono_thread_clr_state (thisstate);
 +      mono_thread_clr_state (this_obj, (MonoThreadState)state);
  
        if (state & ThreadState_Background) {
                /* If the thread changes the background mode, the main thread has to
  }
  
  void
 -ves_icall_System_Threading_Thread_SetState (MonoInternalThread* this, guint32 state)
 +ves_icall_System_Threading_Thread_SetState (MonoInternalThread* this_obj, guint32 state)
  {
 -      mono_thread_set_state (thisstate);
 +      mono_thread_set_state (this_obj, (MonoThreadState)state);
        
        if (state & ThreadState_Background) {
                /* If the thread changes the background mode, the main thread has to
  }
  
  guint32
 -ves_icall_System_Threading_Thread_GetState (MonoInternalThread* this)
 +ves_icall_System_Threading_Thread_GetState (MonoInternalThread* this_obj)
  {
        guint32 state;
  
 -      LOCK_THREAD (this);
 +      LOCK_THREAD (this_obj);
        
 -      state = this->state;
 +      state = this_obj->state;
  
 -      UNLOCK_THREAD (this);
 +      UNLOCK_THREAD (this_obj);
        
        return state;
  }
  void ves_icall_System_Threading_Thread_Interrupt_internal (MonoThread *this_obj)
  {
        MonoInternalThread *current;
 -      gboolean throw;
 +      gboolean throw_;
        MonoInternalThread *thread = this_obj->internal_thread;
  
        LOCK_THREAD (thread);
        current = mono_thread_internal_current ();
  
        thread->thread_interrupt_requested = TRUE;
 -      throw = current != thread && (thread->state & ThreadState_WaitSleepJoin);
 +      throw_ = current != thread && (thread->state & ThreadState_WaitSleepJoin);
  
        UNLOCK_THREAD (thread);
        
 -      if (throw) {
 +      if (throw_) {
                abort_thread_internal (thread, TRUE, FALSE);
        }
  }
  void mono_thread_current_check_pending_interrupt ()
  {
        MonoInternalThread *thread = mono_thread_internal_current ();
 -      gboolean throw = FALSE;
 +      gboolean throw_ = FALSE;
  
        LOCK_THREAD (thread);
        
        if (thread->thread_interrupt_requested) {
 -              throw = TRUE;
 +              throw_ = TRUE;
                thread->thread_interrupt_requested = FALSE;
        }
        
        UNLOCK_THREAD (thread);
  
 -      if (throw) {
 +      if (throw_) {
                mono_raise_exception (mono_get_exception_thread_interrupted ());
        }
  }
@@@ -2087,15 -2077,15 +2090,15 @@@ ves_icall_System_Threading_Thread_Abor
        }
        thread->abort_exc = NULL;
  
 -      UNLOCK_THREAD (thread);
 -
 -      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Abort requested for %p (%"G_GSIZE_FORMAT")", __func__, GetCurrentThreadId (), thread, (gsize)thread->tid));
 +      THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Abort requested for %p (%"G_GSIZE_FORMAT")", __func__, mono_native_thread_id_get (), thread, (gsize)thread->tid));
  
        /* During shutdown, we can't wait for other threads */
        if (!shutting_down)
                /* Make sure the thread is awake */
                mono_thread_resume (thread);
 -      
 +
 +      UNLOCK_THREAD (thread);
 +
        abort_thread_internal (thread, TRUE, TRUE);
  }
  
@@@ -2212,12 -2202,14 +2215,12 @@@ ves_icall_System_Threading_Thread_Suspe
        }
  }
  
 +/* LOCKING: LOCK_THREAD(thread) must be held */
  static gboolean
  mono_thread_resume (MonoInternalThread *thread)
  {
 -      LOCK_THREAD (thread);
 -
        if ((thread->state & ThreadState_SuspendRequested) != 0) {
                thread->state &= ~ThreadState_SuspendRequested;
 -              UNLOCK_THREAD (thread);
                return TRUE;
        }
  
                (thread->state & ThreadState_Aborted) != 0 || 
                (thread->state & ThreadState_Stopped) != 0)
        {
 -              UNLOCK_THREAD (thread);
                return FALSE;
        }
  
 -      return resume_thread_internal (thread);
 +      UNLOCK_THREAD (thread);
 +
 +      /* Awake the thread */
 +      if (!mono_thread_info_resume (thread_get_tid (thread)))
 +              return FALSE;
 +
 +      LOCK_THREAD (thread);
 +
 +      thread->state &= ~ThreadState_Suspended;
 +
 +      return TRUE;
  }
  
  void
  ves_icall_System_Threading_Thread_Resume (MonoThread *thread)
  {
 -      if (!thread->internal_thread || !mono_thread_resume (thread->internal_thread)) {
 +      if (!thread->internal_thread) {
                mono_set_pending_exception (mono_get_exception_thread_state ("Thread has not been started, or is dead."));
 -              return;
 +      } else {
 +              LOCK_THREAD (thread->internal_thread);
 +              if (!mono_thread_resume (thread->internal_thread))
 +                      mono_set_pending_exception (mono_get_exception_thread_state ("Thread has not been started, or is dead."));
 +              UNLOCK_THREAD (thread->internal_thread);
        }
  }
  
@@@ -2382,19 -2361,19 +2385,19 @@@ ves_icall_System_Threading_Thread_Volat
  gint8
  ves_icall_System_Threading_Volatile_Read1 (void *ptr)
  {
 -      return InterlockedRead8 (ptr);
 +      return InterlockedRead8 ((volatile gint8 *)ptr);
  }
  
  gint16
  ves_icall_System_Threading_Volatile_Read2 (void *ptr)
  {
 -      return InterlockedRead16 (ptr);
 +      return InterlockedRead16 ((volatile gint16 *)ptr);
  }
  
  gint32
  ves_icall_System_Threading_Volatile_Read4 (void *ptr)
  {
 -      return InterlockedRead (ptr);
 +      return InterlockedRead ((volatile gint32 *)ptr);
  }
  
  gint64
@@@ -2409,13 -2388,13 +2412,13 @@@ ves_icall_System_Threading_Volatile_Rea
                return val;
        }
  #endif
 -      return InterlockedRead64 (ptr);
 +      return InterlockedRead64 ((volatile gint64 *)ptr);
  }
  
  void *
  ves_icall_System_Threading_Volatile_ReadIntPtr (void *ptr)
  {
 -      return InterlockedReadPointer (ptr);
 +      return InterlockedReadPointer ((volatile gpointer *)ptr);
  }
  
  double
@@@ -2433,7 -2412,7 +2436,7 @@@ ves_icall_System_Threading_Volatile_Rea
        }
  #endif
  
 -      u.ival = InterlockedRead64 (ptr);
 +      u.ival = InterlockedRead64 ((volatile gint64 *)ptr);
  
        return u.fval;
  }
@@@ -2443,7 -2422,7 +2446,7 @@@ ves_icall_System_Threading_Volatile_Rea
  {
        IntFloatUnion u;
  
 -      u.ival = InterlockedRead (ptr);
 +      u.ival = InterlockedRead ((volatile gint32 *)ptr);
  
        return u.fval;
  }
  MonoObject*
  ves_icall_System_Threading_Volatile_Read_T (void *ptr)
  {
 -      return InterlockedReadPointer (ptr);
 +      return (MonoObject *)InterlockedReadPointer ((volatile gpointer *)ptr);
  }
  
  void
@@@ -2505,19 -2484,19 +2508,19 @@@ ves_icall_System_Threading_Thread_Volat
  void
  ves_icall_System_Threading_Volatile_Write1 (void *ptr, gint8 value)
  {
 -      InterlockedWrite8 (ptr, value);
 +      InterlockedWrite8 ((volatile gint8 *)ptr, value);
  }
  
  void
  ves_icall_System_Threading_Volatile_Write2 (void *ptr, gint16 value)
  {
 -      InterlockedWrite16 (ptr, value);
 +      InterlockedWrite16 ((volatile gint16 *)ptr, value);
  }
  
  void
  ves_icall_System_Threading_Volatile_Write4 (void *ptr, gint32 value)
  {
 -      InterlockedWrite (ptr, value);
 +      InterlockedWrite ((volatile gint32 *)ptr, value);
  }
  
  void
@@@ -2532,13 -2511,13 +2535,13 @@@ ves_icall_System_Threading_Volatile_Wri
        }
  #endif
  
 -      InterlockedWrite64 (ptr, value);
 +      InterlockedWrite64 ((volatile gint64 *)ptr, value);
  }
  
  void
  ves_icall_System_Threading_Volatile_WriteIntPtr (void *ptr, void *value)
  {
 -      InterlockedWritePointer (ptr, value);
 +      InterlockedWritePointer ((volatile gpointer *)ptr, value);
  }
  
  void
@@@ -2557,7 -2536,7 +2560,7 @@@ ves_icall_System_Threading_Volatile_Wri
  
        u.fval = value;
  
 -      InterlockedWrite64 (ptr, u.ival);
 +      InterlockedWrite64 ((volatile gint64 *)ptr, u.ival);
  }
  
  void
@@@ -2567,7 -2546,7 +2570,7 @@@ ves_icall_System_Threading_Volatile_Wri
  
        u.fval = value;
  
 -      InterlockedWrite (ptr, u.ival);
 +      InterlockedWrite ((volatile gint32 *)ptr, u.ival);
  }
  
  void
@@@ -2576,6 -2555,31 +2579,31 @@@ ves_icall_System_Threading_Volatile_Wri
        mono_gc_wbarrier_generic_store_atomic (ptr, value);
  }
  
+ static void
+ free_context (void *user_data)
+ {
+       ContextStaticData *data = user_data;
+       mono_threads_lock ();
+       /*
+        * There is no guarantee that, by the point this reference queue callback
+        * has been invoked, the GC handle associated with the object will fail to
+        * resolve as one might expect. So if we don't free and remove the GC
+        * handle here, free_context_static_data_helper () could end up resolving
+        * a GC handle to an actually-dead context which would contain a pointer
+        * to an already-freed static data segment, resulting in a crash when
+        * accessing it.
+        */
+       g_hash_table_remove (contexts, GUINT_TO_POINTER (data->gc_handle));
+       mono_threads_unlock ();
+       mono_gchandle_free (data->gc_handle);
+       mono_free_static_data (data->static_data);
+       g_free (data);
+ }
  void
  ves_icall_System_Runtime_Remoting_Contexts_Context_RegisterContext (MonoAppContext *ctx)
  {
        if (!contexts)
                contexts = g_hash_table_new (NULL, NULL);
  
-       context_adjust_static_data (ctx);
+       if (!context_queue)
+               context_queue = mono_gc_reference_queue_new (free_context);
        gpointer gch = GUINT_TO_POINTER (mono_gchandle_new_weakref (&ctx->obj, FALSE));
        g_hash_table_insert (contexts, gch, gch);
  
+       /*
+        * We use this intermediate structure to contain a duplicate pointer to
+        * the static data because we can't rely on being able to resolve the GC
+        * handle in the reference queue callback.
+        */
+       ContextStaticData *data = g_new0 (ContextStaticData, 1);
+       data->gc_handle = GPOINTER_TO_UINT (gch);
+       ctx->data = data;
+       context_adjust_static_data (ctx);
+       mono_gc_reference_queue_add (context_queue, &ctx->obj, data);
        mono_threads_unlock ();
  
        mono_profiler_context_loaded (ctx);
@@@ -2601,9 -2619,7 +2643,7 @@@ ves_icall_System_Runtime_Remoting_Conte
        /*
         * NOTE: Since finalizers are unreliable for the purposes of ensuring
         * cleanup in exceptional circumstances, we don't actually do any
-        * cleanup work here. We instead do this when we iterate the `contexts`
-        * hash table. The only purpose of this finalizer, at the moment, is to
-        * notify the profiler.
+        * cleanup work here. We instead do this via a reference queue.
         */
  
        //g_print ("Releasing context %d in domain %d\n", ctx->context_id, ctx->domain_id);
@@@ -2621,10 -2637,9 +2661,10 @@@ mono_thread_init_tls (void
  void mono_thread_init (MonoThreadStartCB start_cb,
                       MonoThreadAttachCB attach_cb)
  {
 -      mono_mutex_init_recursive(&threads_mutex);
 -      mono_mutex_init_recursive(&interlocked_mutex);
 -      mono_mutex_init_recursive(&joinable_threads_mutex);
 +      mono_coop_mutex_init_recursive (&threads_mutex);
 +
 +      mono_os_mutex_init_recursive(&interlocked_mutex);
 +      mono_os_mutex_init_recursive(&joinable_threads_mutex);
        
        background_change_event = CreateEvent (NULL, TRUE, FALSE, NULL);
        g_assert(background_change_event != NULL);
@@@ -2665,10 -2680,10 +2705,10 @@@ void mono_thread_cleanup (void
         * critical sections can be locked when mono_thread_cleanup is
         * called.
         */
 -      mono_mutex_destroy (&threads_mutex);
 -      mono_mutex_destroy (&interlocked_mutex);
 -      mono_mutex_destroy (&delayed_free_table_mutex);
 -      mono_mutex_destroy (&small_id_mutex);
 +      mono_coop_mutex_destroy (&threads_mutex);
 +      mono_os_mutex_destroy (&interlocked_mutex);
 +      mono_os_mutex_destroy (&delayed_free_table_mutex);
 +      mono_os_mutex_destroy (&small_id_mutex);
        CloseHandle (background_change_event);
  #endif
  
@@@ -2873,18 -2888,17 +2913,18 @@@ static gboolea
  remove_and_abort_threads (gpointer key, gpointer value, gpointer user)
  {
        struct wait_data *wait=(struct wait_data *)user;
 -      gsize self = GetCurrentThreadId ();
 -      MonoInternalThread *thread = value;
 +      MonoNativeThreadId self = mono_native_thread_id_get ();
 +      MonoInternalThread *thread = (MonoInternalThread *)value;
        HANDLE handle;
  
        if (wait->num >= MAXIMUM_WAIT_OBJECTS)
                return FALSE;
  
        /* The finalizer thread is not a background thread */
 -      if (thread->tid != self && (thread->state & ThreadState_Background) != 0 &&
 -              !(thread->flags & MONO_THREAD_FLAG_DONT_MANAGE)) {
 -      
 +      if (!mono_native_thread_id_equals (thread_get_tid (thread), self)
 +           && (thread->state & ThreadState_Background) != 0
 +           && (thread->flags & MONO_THREAD_FLAG_DONT_MANAGE) == 0
 +      ) {
                handle = mono_threads_open_thread_handle (thread->handle, thread_get_tid (thread));
                if (handle == NULL)
                        return FALSE;
                return TRUE;
        }
  
 -      return (thread->tid != self && !mono_gc_is_finalizer_internal_thread (thread)); 
 +      return !mono_native_thread_id_equals (thread_get_tid (thread), self)
 +              && !mono_gc_is_finalizer_internal_thread (thread);
  }
  
  /** 
@@@ -3028,6 -3041,29 +3068,6 @@@ void mono_thread_manage (void
        mono_thread_info_yield ();
  }
  
 -static void terminate_thread (gpointer key, gpointer value, gpointer user)
 -{
 -      MonoInternalThread *thread=(MonoInternalThread *)value;
 -      
 -      if(thread->tid != (gsize)user) {
 -              /*TerminateThread (thread->handle, -1);*/
 -      }
 -}
 -
 -void mono_thread_abort_all_other_threads (void)
 -{
 -      gsize self = GetCurrentThreadId ();
 -
 -      mono_threads_lock ();
 -      THREAD_DEBUG (g_message ("%s: There are %d threads to abort", __func__,
 -                               mono_g_hash_table_size (threads));
 -                    mono_g_hash_table_foreach (threads, print_tids, NULL));
 -
 -      mono_g_hash_table_foreach (threads, terminate_thread, (gpointer)self);
 -      
 -      mono_threads_unlock ();
 -}
 -
  static void
  collect_threads_for_suspend (gpointer key, gpointer value, gpointer user_data)
  {
@@@ -3066,7 -3102,7 +3106,7 @@@ void mono_thread_suspend_all_other_thre
        struct wait_data wait_data;
        struct wait_data *wait = &wait_data;
        int i;
 -      gsize self = GetCurrentThreadId ();
 +      MonoNativeThreadId self = mono_native_thread_id_get ();
        guint32 eventidx = 0;
        gboolean starting, finished;
  
                for (i = 0; i < wait->num; ++i) {
                        MonoInternalThread *thread = wait->threads [i];
  
 -                      if ((thread->tid == self) || mono_gc_is_finalizer_internal_thread (thread) || (thread->flags & MONO_THREAD_FLAG_DONT_MANAGE)) {
 +                      if (mono_native_thread_id_equals (thread_get_tid (thread), self)
 +                           || mono_gc_is_finalizer_internal_thread (thread)
 +                           || (thread->flags & MONO_THREAD_FLAG_DONT_MANAGE)
 +                      ) {
                                //CloseHandle (wait->handles [i]);
                                wait->threads [i] = NULL; /* ignore this thread in next loop */
                                continue;
                                starting = FALSE;
                        mono_threads_unlock ();
                        if (starting)
 -                              Sleep (100);
 +                              mono_thread_info_sleep (100, NULL);
                        else
                                finished = TRUE;
                }
        }
  }
  
 +typedef struct {
 +      MonoInternalThread *thread;
 +      MonoStackFrameInfo *frames;
 +      int nframes, max_frames;
 +      int nthreads, max_threads;
 +      MonoInternalThread **threads;
 +} ThreadDumpUserData;
 +
  static gboolean thread_dump_requested;
  
 -static G_GNUC_UNUSED gboolean
 -print_stack_frame_to_string (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data)
 +/* This needs to be async safe */
 +static gboolean
 +collect_frame (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data)
  {
 -      GString *p = (GString*)data;
 -      MonoMethod *method = NULL;
 -      if (frame->type == FRAME_TYPE_MANAGED)
 -              method = mono_jit_info_get_method (frame->ji);
 +      ThreadDumpUserData *ud = (ThreadDumpUserData *)data;
  
 -      if (method) {
 -              gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, frame->domain);
 -              g_string_append_printf (p, "  %s\n", location);
 -              g_free (location);
 -      } else
 -              g_string_append_printf (p, "  at <unknown> <0x%05x>\n", frame->native_offset);
 +      if (ud->nframes < ud->max_frames) {
 +              memcpy (&ud->frames [ud->nframes], frame, sizeof (MonoStackFrameInfo));
 +              ud->nframes ++;
 +      }
  
        return FALSE;
  }
  
 +/* This needs to be async safe */
  static SuspendThreadResult
 -print_thread_dump (MonoThreadInfo *info, gpointer ud)
 +get_thread_dump (MonoThreadInfo *info, gpointer ud)
 +{
 +      ThreadDumpUserData *user_data = (ThreadDumpUserData *)ud;
 +      MonoInternalThread *thread = user_data->thread;
 +
 +#if 0
 +/* This no longer works with remote unwinding */
 +#ifndef HOST_WIN32
 +      wapi_desc = wapi_current_thread_desc ();
 +      g_string_append_printf (text, " tid=0x%p this=0x%p %s\n", (gpointer)(gsize)thread->tid, thread,  wapi_desc);
 +      free (wapi_desc);
 +#endif
 +#endif
 +
 +      if (thread == mono_thread_internal_current ())
 +              mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (collect_frame, NULL, MONO_UNWIND_SIGNAL_SAFE, ud);
 +      else
 +              mono_get_eh_callbacks ()->mono_walk_stack_with_state (collect_frame, mono_thread_info_get_suspend_state (info), MONO_UNWIND_SIGNAL_SAFE, ud);
 +
 +      return MonoResumeThread;
 +}
 +
 +typedef struct {
 +      int nthreads, max_threads;
 +      MonoInternalThread **threads;
 +} CollectThreadsUserData;
 +
 +static void
 +collect_thread (gpointer key, gpointer value, gpointer user)
 +{
 +      CollectThreadsUserData *ud = (CollectThreadsUserData *)user;
 +      MonoInternalThread *thread = (MonoInternalThread *)value;
 +
 +      if (ud->nthreads < ud->max_threads)
 +              ud->threads [ud->nthreads ++] = thread;
 +}
 +
 +/*
 + * Collect running threads into the THREADS array.
 + * THREADS should be an array allocated on the stack.
 + */
 +static int
 +collect_threads (MonoInternalThread **thread_array, int max_threads)
 +{
 +      CollectThreadsUserData ud;
 +
 +      memset (&ud, 0, sizeof (ud));
 +      /* This array contains refs, but its on the stack, so its ok */
 +      ud.threads = thread_array;
 +      ud.max_threads = max_threads;
 +
 +      mono_threads_lock ();
 +      mono_g_hash_table_foreach (threads, collect_thread, &ud);
 +      mono_threads_unlock ();
 +
 +      return ud.nthreads;
 +}
 +
 +static void
 +dump_thread (MonoInternalThread *thread, ThreadDumpUserData *ud)
  {
 -      MonoInternalThread *thread = ud;
        GString* text = g_string_new (0);
        char *name;
        GError *error = NULL;
 +      int i;
 +
 +      ud->thread = thread;
 +      ud->nframes = 0;
  
 +      /* Collect frames for the thread */
 +      if (thread == mono_thread_internal_current ()) {
 +              get_thread_dump (mono_thread_info_current (), ud);
 +      } else {
 +              mono_thread_info_safe_suspend_and_run (thread_get_tid (thread), FALSE, get_thread_dump, ud);
 +      }
 +
 +      /*
 +       * Do all the non async-safe work outside of get_thread_dump.
 +       */
        if (thread->name) {
                name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
                g_assert (!error);
                g_string_append_printf (text, "\n\"%s\"", name);
                g_free (name);
        }
 -      else if (thread->threadpool_thread)
 +      else if (thread->threadpool_thread) {
                g_string_append (text, "\n\"<threadpool thread>\"");
 -      else
 +      } else {
                g_string_append (text, "\n\"<unnamed thread>\"");
 +      }
  
 -#if 0
 -/* This no longer works with remote unwinding */
 -#ifndef HOST_WIN32
 -      wapi_desc = wapi_current_thread_desc ();
 -      g_string_append_printf (text, " tid=0x%p this=0x%p %s\n", (gpointer)(gsize)thread->tid, thread,  wapi_desc);
 -      free (wapi_desc);
 -#endif
 -#endif
 +      for (i = 0; i < ud->nframes; ++i) {
 +              MonoStackFrameInfo *frame = &ud->frames [i];
 +              MonoMethod *method = NULL;
  
 -      mono_get_eh_callbacks ()->mono_walk_stack_with_state (print_stack_frame_to_string, mono_thread_info_get_suspend_state (info), MONO_UNWIND_SIGNAL_SAFE, text);
 +              if (frame->type == FRAME_TYPE_MANAGED)
 +                      method = mono_jit_info_get_method (frame->ji);
 +
 +              if (method) {
 +                      gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, frame->domain);
 +                      g_string_append_printf (text, "  %s\n", location);
 +                      g_free (location);
 +              } else {
 +                      g_string_append_printf (text, "  at <unknown> <0x%05x>\n", frame->native_offset);
 +              }
 +      }
  
        fprintf (stdout, "%s", text->str);
  
  
        g_string_free (text, TRUE);
        fflush (stdout);
 -      return MonoResumeThread;
 -}
 -
 -static void
 -dump_thread (gpointer key, gpointer value, gpointer user)
 -{
 -      MonoInternalThread *thread = (MonoInternalThread *)value;
 -
 -      if (thread == mono_thread_internal_current ())
 -              return;
 -
 -      /*
 -      FIXME This still can hang if we stop a thread during malloc.
 -      FIXME This can hang if we suspend on a critical method and the GC kicks in. A fix might be to have function
 -      that takes a callback and runs it with the target suspended.
 -      We probably should loop a bit around trying to get it to either managed code
 -      or WSJ state.
 -      */
 -      mono_thread_info_safe_suspend_and_run (thread_get_tid (thread), FALSE, print_thread_dump, thread);
  }
  
  void
  mono_threads_perform_thread_dump (void)
  {
 +      ThreadDumpUserData ud;
 +      MonoInternalThread *thread_array [128];
 +      int tindex, nthreads;
 +
        if (!thread_dump_requested)
                return;
  
        printf ("Full thread dump:\n");
  
 -      /* We take the loader lock and the root domain lock as to increase our odds of not deadlocking if
 -      something needs then in the process.
 -      */
 -      mono_loader_lock ();
 -      mono_domain_lock (mono_get_root_domain ());
 +      /* Make a copy of the threads hash to avoid doing work inside threads_lock () */
 +      nthreads = collect_threads (thread_array, 128);
  
 -      mono_threads_lock ();
 -      mono_g_hash_table_foreach (threads, dump_thread, NULL);
 -      mono_threads_unlock ();
 +      memset (&ud, 0, sizeof (ud));
 +      ud.frames = g_new0 (MonoStackFrameInfo, 256);
 +      ud.max_frames = 256;
 +
 +      for (tindex = 0; tindex < nthreads; ++tindex)
 +              dump_thread (thread_array [tindex], &ud);
  
 -      mono_domain_unlock (mono_get_root_domain ());
 -      mono_loader_unlock ();
 +      g_free (ud.frames);
  
        thread_dump_requested = FALSE;
  }
  
 +/* Obtain the thread dump of all threads */
 +static void
 +mono_threads_get_thread_dump (MonoArray **out_threads, MonoArray **out_stack_frames)
 +{
 +      ThreadDumpUserData ud;
 +      MonoInternalThread *thread_array [128];
 +      MonoDomain *domain = mono_domain_get ();
 +      MonoDebugSourceLocation *location;
 +      int tindex, nthreads;
 +
 +      *out_threads = NULL;
 +      *out_stack_frames = NULL;
 +
 +      /* Make a copy of the threads hash to avoid doing work inside threads_lock () */
 +      nthreads = collect_threads (thread_array, 128);
 +
 +      memset (&ud, 0, sizeof (ud));
 +      ud.frames = g_new0 (MonoStackFrameInfo, 256);
 +      ud.max_frames = 256;
 +
 +      *out_threads = mono_array_new (domain, mono_defaults.thread_class, nthreads);
 +      *out_stack_frames = mono_array_new (domain, mono_defaults.array_class, nthreads);
 +
 +      for (tindex = 0; tindex < nthreads; ++tindex) {
 +              MonoInternalThread *thread = thread_array [tindex];
 +              MonoArray *thread_frames;
 +              int i;
 +
 +              ud.thread = thread;
 +              ud.nframes = 0;
 +
 +              /* Collect frames for the thread */
 +              if (thread == mono_thread_internal_current ()) {
 +                      get_thread_dump (mono_thread_info_current (), &ud);
 +              } else {
 +                      mono_thread_info_safe_suspend_and_run (thread_get_tid (thread), FALSE, get_thread_dump, &ud);
 +              }
 +
 +              mono_array_setref_fast (*out_threads, tindex, mono_thread_current_for_thread (thread));
 +
 +              thread_frames = mono_array_new (domain, mono_defaults.stack_frame_class, ud.nframes);
 +              mono_array_setref_fast (*out_stack_frames, tindex, thread_frames);
 +
 +              for (i = 0; i < ud.nframes; ++i) {
 +                      MonoStackFrameInfo *frame = &ud.frames [i];
 +                      MonoMethod *method = NULL;
 +                      MonoStackFrame *sf = (MonoStackFrame *)mono_object_new (domain, mono_defaults.stack_frame_class);
 +
 +                      sf->native_offset = frame->native_offset;
 +
 +                      if (frame->type == FRAME_TYPE_MANAGED)
 +                              method = mono_jit_info_get_method (frame->ji);
 +
 +                      if (method) {
 +                              sf->method_address = (gsize) frame->ji->code_start;
 +
 +                              MONO_OBJECT_SETREF (sf, method, mono_method_get_object (domain, method, NULL));
 +
 +                              location = mono_debug_lookup_source_location (method, frame->native_offset, domain);
 +                              if (location) {
 +                                      sf->il_offset = location->il_offset;
 +
 +                                      if (location && location->source_file) {
 +                                              MONO_OBJECT_SETREF (sf, filename, mono_string_new (domain, location->source_file));
 +                                              sf->line = location->row;
 +                                              sf->column = location->column;
 +                                      }
 +                                      mono_debug_free_source_location (location);
 +                              } else {
 +                                      sf->il_offset = -1;
 +                              }
 +                      }
 +                      mono_array_setref (thread_frames, i, sf);
 +              }
 +      }
 +
 +      g_free (ud.frames);
 +}
 +
  /**
   * mono_threads_request_thread_dump:
   *
@@@ -3448,7 -3335,7 +3488,7 @@@ ref_stack_new (gint initial_size
  static void
  ref_stack_destroy (gpointer ptr)
  {
 -      RefStack *rs = ptr;
 +      RefStack *rs = (RefStack *)ptr;
  
        if (rs != NULL) {
                g_free (rs->refs);
@@@ -3462,7 -3349,7 +3502,7 @@@ ref_stack_push (RefStack *rs, gpointer 
        g_assert (rs != NULL);
  
        if (rs->bottom >= rs->allocated) {
 -              rs->refs = g_realloc (rs->refs, rs->allocated * 2 * sizeof (gpointer) + 1);
 +              rs->refs = (void **)g_realloc (rs->refs, rs->allocated * 2 * sizeof (gpointer) + 1);
                rs->allocated <<= 1;
                rs->refs [rs->allocated] = NULL;
        }
@@@ -3511,7 -3398,7 +3551,7 @@@ mono_thread_push_appdomain_ref (MonoDom
                SPIN_LOCK (thread->lock_thread_id);
                if (thread->appdomain_refs == NULL)
                        thread->appdomain_refs = ref_stack_new (16);
 -              ref_stack_push (thread->appdomain_refs, domain);
 +              ref_stack_push ((RefStack *)thread->appdomain_refs, domain);
                SPIN_UNLOCK (thread->lock_thread_id);
        }
  }
@@@ -3524,7 -3411,7 +3564,7 @@@ mono_thread_pop_appdomain_ref (void
        if (thread) {
                /* printf ("POP REF: %"G_GSIZE_FORMAT" -> %s.\n", (gsize)thread->tid, ((MonoDomain*)(thread->appdomain_refs->data))->friendly_name); */
                SPIN_LOCK (thread->lock_thread_id);
 -              ref_stack_pop (thread->appdomain_refs);
 +              ref_stack_pop ((RefStack *)thread->appdomain_refs);
                SPIN_UNLOCK (thread->lock_thread_id);
        }
  }
@@@ -3534,7 -3421,7 +3574,7 @@@ mono_thread_internal_has_appdomain_ref 
  {
        gboolean res;
        SPIN_LOCK (thread->lock_thread_id);
 -      res = ref_stack_find (thread->appdomain_refs, domain);
 +      res = ref_stack_find ((RefStack *)thread->appdomain_refs, domain);
        SPIN_UNLOCK (thread->lock_thread_id);
        return res;
  }
@@@ -3705,10 -3592,10 +3745,10 @@@ static MonoBitSet *context_reference_bi
  static void
  mark_slots (void *addr, MonoBitSet **bitmaps, MonoGCMarkFunc mark_func, void *gc_data)
  {
 -      gpointer *static_data = addr;
 +      gpointer *static_data = (gpointer *)addr;
  
        for (int i = 0; i < NUM_STATIC_DATA_IDX; ++i) {
 -              void **ptr = static_data [i];
 +              void **ptr = (void **)static_data [i];
  
                if (!ptr)
                        continue;
@@@ -3758,7 -3645,7 +3798,7 @@@ mono_alloc_static_data (gpointer **stat
                                ctx_desc = mono_gc_make_root_descr_user (mark_ctx_slots);
                }
  
 -              static_data = mono_gc_alloc_fixed (static_data_size [0], threadlocal ? tls_desc : ctx_desc,
 +              static_data = (void **)mono_gc_alloc_fixed (static_data_size [0], threadlocal ? tls_desc : ctx_desc,
                        threadlocal ? MONO_ROOT_SOURCE_THREAD_STATIC : MONO_ROOT_SOURCE_CONTEXT_STATIC,
                        threadlocal ? "managed thread-static variables" : "managed context-static variables");
                *static_data_ptr = static_data;
@@@ -3869,6 -3756,7 +3909,7 @@@ context_adjust_static_data (MonoAppCont
        if (context_static_info.offset || context_static_info.idx > 0) {
                guint32 offset = MAKE_SPECIAL_STATIC_OFFSET (context_static_info.idx, context_static_info.offset, 0);
                mono_alloc_static_data (&ctx->static_data, offset, FALSE);
+               ctx->data->static_data = ctx->static_data;
        }
  }
  
  static void 
  alloc_thread_static_data_helper (gpointer key, gpointer value, gpointer user)
  {
 -      MonoInternalThread *thread = value;
 +      MonoInternalThread *thread = (MonoInternalThread *)value;
        guint32 offset = GPOINTER_TO_UINT (user);
  
        mono_alloc_static_data (&(thread->static_data), offset, TRUE);
  /*
   * LOCKING: requires that threads_mutex is held
   */
- static gboolean
+ static void
  alloc_context_static_data_helper (gpointer key, gpointer value, gpointer user)
  {
-       uint32_t gch = GPOINTER_TO_INT (key);
-       MonoAppContext *ctx = (MonoAppContext *) mono_gchandle_get_target (gch);
+       MonoAppContext *ctx = (MonoAppContext *) mono_gchandle_get_target (GPOINTER_TO_INT (key));
  
-       if (!ctx) {
-               mono_gchandle_free (gch);
-               return TRUE; // Remove this key/value pair
-       }
+       if (!ctx)
+               return;
  
        guint32 offset = GPOINTER_TO_UINT (user);
        mono_alloc_static_data (&ctx->static_data, offset, FALSE);
-       return FALSE; // Don't remove it
+       ctx->data->static_data = ctx->static_data;
  }
  
  static StaticDataFreeList*
@@@ -3993,7 -3877,7 +4030,7 @@@ mono_alloc_special_static_data (guint3
                        mono_g_hash_table_foreach (threads, alloc_thread_static_data_helper, GUINT_TO_POINTER (offset));
        } else {
                if (contexts != NULL)
-                       g_hash_table_foreach_remove (contexts, alloc_context_static_data_helper, GUINT_TO_POINTER (offset));
+                       g_hash_table_foreach (contexts, alloc_context_static_data_helper, GUINT_TO_POINTER (offset));
  
                ACCESS_SPECIAL_STATIC_OFFSET (offset, type) = SPECIAL_STATIC_OFFSET_TYPE_CONTEXT;
        }
@@@ -4032,8 -3916,8 +4069,8 @@@ typedef struct 
  static void 
  free_thread_static_data_helper (gpointer key, gpointer value, gpointer user)
  {
 -      MonoInternalThread *thread = value;
 -      OffsetSize *data = user;
 +      MonoInternalThread *thread = (MonoInternalThread *)value;
 +      OffsetSize *data = (OffsetSize *)user;
        int idx = ACCESS_SPECIAL_STATIC_OFFSET (data->offset, index);
        int off = ACCESS_SPECIAL_STATIC_OFFSET (data->offset, offset);
        char *ptr;
  /*
   * LOCKING: requires that threads_mutex is held
   */
- static gboolean
+ static void
  free_context_static_data_helper (gpointer key, gpointer value, gpointer user)
  {
-       uint32_t gch = GPOINTER_TO_INT (key);
-       MonoAppContext *ctx = (MonoAppContext *) mono_gchandle_get_target (gch);
+       MonoAppContext *ctx = (MonoAppContext *) mono_gchandle_get_target (GPOINTER_TO_INT (key));
  
-       if (!ctx) {
-               mono_gchandle_free (gch);
-               return TRUE; // Remove this key/value pair
-       }
+       if (!ctx)
+               return;
  
 -      OffsetSize *data = user;
 +      OffsetSize *data = (OffsetSize *)user;
        int idx = ACCESS_SPECIAL_STATIC_OFFSET (data->offset, index);
        int off = ACCESS_SPECIAL_STATIC_OFFSET (data->offset, offset);
        char *ptr;
  
        if (!ctx->static_data || !ctx->static_data [idx])
-               return FALSE; // Don't remove this key/value pair
+               return;
  
        ptr = ((char*) ctx->static_data [idx]) + off;
        mono_gc_bzero_atomic (ptr, data->size);
-       return FALSE; // Don't remove this key/value pair
  }
  
  static void
@@@ -4098,7 -3977,7 +4130,7 @@@ do_free_special_slot (guint32 offset, g
                        mono_g_hash_table_foreach (threads, free_thread_static_data_helper, &data);
        } else {
                if (contexts != NULL)
-                       g_hash_table_foreach_remove (contexts, free_context_static_data_helper, &data);
+                       g_hash_table_foreach (contexts, free_context_static_data_helper, &data);
        }
  
        if (!mono_runtime_is_shutting_down ()) {
  static void
  do_free_special (gpointer key, gpointer value, gpointer data)
  {
 -      MonoClassField *field = key;
 +      MonoClassField *field = (MonoClassField *)key;
        guint32 offset = GPOINTER_TO_UINT (value);
        gint32 align;
        guint32 size;
@@@ -4524,7 -4403,7 +4556,7 @@@ mono_jit_info_match (MonoJitInfo *ji, g
  static gboolean
  last_managed (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data)
  {
 -      MonoJitInfo **dest = data;
 +      MonoJitInfo **dest = (MonoJitInfo **)data;
        *dest = frame->ji;
        return TRUE;
  }
@@@ -4548,7 -4427,7 +4580,7 @@@ typedef struct 
  static SuspendThreadResult
  abort_thread_critical (MonoThreadInfo *info, gpointer ud)
  {
 -      AbortThreadData *data = ud;
 +      AbortThreadData *data = (AbortThreadData *)ud;
        MonoInternalThread *thread = data->thread;
        MonoJitInfo *ji = NULL;
        gboolean protected_wrapper;
@@@ -4628,7 -4507,7 +4660,7 @@@ typedef struct
  static SuspendThreadResult
  suspend_thread_critical (MonoThreadInfo *info, gpointer ud)
  {
 -      SuspendThreadData *data = ud;
 +      SuspendThreadData *data = (SuspendThreadData *)ud;
        MonoInternalThread *thread = data->thread;
        MonoJitInfo *ji = NULL;
        gboolean protected_wrapper;
                if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 0)
                        InterlockedIncrement (&thread_interruption_requested);
                if (data->interrupt)
 -                      data->interrupt_token = mono_thread_info_prepare_interrupt (thread->thread_info);
 +                      data->interrupt_token = mono_thread_info_prepare_interrupt ((MonoThreadInfo *)thread->thread_info);
                
                if (mono_thread_notify_pending_exc_fn && !running_managed)
                        /* The JIT will notify the thread about the interruption */
@@@ -4689,6 -4568,20 +4721,6 @@@ self_suspend_internal (MonoInternalThre
        mono_thread_info_end_self_suspend ();
  }
  
 -/*This is called with @thread synch_cs held and it must release it*/
 -static gboolean
 -resume_thread_internal (MonoInternalThread *thread)
 -{
 -      UNLOCK_THREAD (thread);
 -      /* Awake the thread */
 -      if (!mono_thread_info_resume (thread_get_tid (thread)))
 -              return FALSE;
 -      LOCK_THREAD (thread);
 -      thread->state &= ~ThreadState_Suspended;
 -      UNLOCK_THREAD (thread);
 -      return TRUE;
 -}
 -
  
  /*
   * mono_thread_is_foreign:
  mono_bool
  mono_thread_is_foreign (MonoThread *thread)
  {
 -      MonoThreadInfo *info = thread->internal_thread->thread_info;
 +      MonoThreadInfo *info = (MonoThreadInfo *)thread->internal_thread->thread_info;
        return info->runtime_thread == FALSE;
  }
  
@@@ -4843,9 -4736,3 +4875,9 @@@ mono_thread_internal_unhandled_exceptio
                }
        }
  }
 +
 +void
 +ves_icall_System_Threading_Thread_GetStackTraces (MonoArray **out_threads, MonoArray **out_stack_traces)
 +{
 +      mono_threads_get_thread_dump (out_threads, out_stack_traces);
 +}