X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fdomain.c;h=447e860164654c913ca0d35a916a283a97728594;hb=5611946a3057c0c646256aa5b23e7040b8fc2cd4;hp=e73d81ae5908690fc3e7f9c593b0f32cab63cbaf;hpb=dace44d806ce5e447a52997540921a33e9900d84;p=mono.git diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c index e73d81ae590..447e8601646 100644 --- a/mono/metadata/domain.c +++ b/mono/metadata/domain.c @@ -17,12 +17,15 @@ #include +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -40,7 +43,7 @@ #include #include -/* #define DEBUG_DOMAIN_UNLOAD */ +//#define DEBUG_DOMAIN_UNLOAD 1 /* we need to use both the Tls* functions and __thread because * some archs may generate faster jit code with one meachanism @@ -56,17 +59,25 @@ MONO_FAST_TLS_DECLARE(tls_appdomain); #define GET_APPDOMAIN() ((MonoDomain*)MONO_FAST_TLS_GET(tls_appdomain)) #define SET_APPDOMAIN(x) do { \ + MonoThreadInfo *info; \ MONO_FAST_TLS_SET (tls_appdomain,x); \ mono_native_tls_set_value (appdomain_thread_id, x); \ mono_gc_set_current_thread_appdomain (x); \ + info = mono_thread_info_current (); \ + if (info) \ + mono_thread_info_tls_set (info, TLS_KEY_DOMAIN, (x)); \ } while (FALSE) #else /* !MONO_HAVE_FAST_TLS */ #define GET_APPDOMAIN() ((MonoDomain *)mono_native_tls_get_value (appdomain_thread_id)) #define SET_APPDOMAIN(x) do { \ + MonoThreadInfo *info; \ mono_native_tls_set_value (appdomain_thread_id, x); \ mono_gc_set_current_thread_appdomain (x); \ + info = mono_thread_info_current (); \ + if (info) \ + mono_thread_info_tls_set (info, TLS_KEY_DOMAIN, (x)); \ } while (FALSE) #endif @@ -114,6 +125,7 @@ static const MonoRuntimeInfo supported_runtimes[] = { {"v4.0.30319","4.5", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } }, {"v4.0.30128","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } }, {"v4.0.20506","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } }, + {"mobile", "2.1", { {2,0,5,0}, {10,0,0,0}, {2,0,5,0}, {2,0,5,0} } }, {"moonlight", "2.1", { {2,0,5,0}, { 9,0,0,0}, {3,5,0,0}, {3,0,0,0} } }, }; @@ -371,6 +383,9 @@ jit_info_table_find (MonoJitInfoTable *table, MonoThreadHazardPointers *hp, gint * * If TRY_AOT is FALSE, avoid loading information for missing methods from AOT images, which is currently not async safe. * In this case, only those AOT methods will be found whose jit info is already loaded. + * ASYNC SAFETY: When called in an async context (mono_thread_info_is_async_context ()), this is async safe. + * In this case, the returned MonoJitInfo might not have metadata information, in particular, + * mono_jit_info_get_method () could fail. */ MonoJitInfo* mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_aot) @@ -882,6 +897,7 @@ mono_jit_info_get_code_size (MonoJitInfo* ji) MonoMethod* mono_jit_info_get_method (MonoJitInfo* ji) { + g_assert (!ji->async); return ji->d.method; } @@ -1000,6 +1016,95 @@ mono_jit_info_get_cas_info (MonoJitInfo *ji) } } +#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1)) +#define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1))) + +static LockFreeMempool* +lock_free_mempool_new (void) +{ + return g_new0 (LockFreeMempool, 1); +} + +static void +lock_free_mempool_free (LockFreeMempool *mp) +{ + LockFreeMempoolChunk *chunk, *next; + + chunk = mp->chunks; + while (chunk) { + next = chunk->prev; + mono_vfree (chunk, mono_pagesize ()); + chunk = next; + } + g_free (mp); +} + +/* + * This is async safe + */ +static LockFreeMempoolChunk* +lock_free_mempool_chunk_new (LockFreeMempool *mp, int len) +{ + LockFreeMempoolChunk *chunk, *prev; + int size; + + size = mono_pagesize (); + while (size - sizeof (LockFreeMempoolChunk) < len) + size += mono_pagesize (); + chunk = mono_valloc (0, size, MONO_MMAP_READ|MONO_MMAP_WRITE); + g_assert (chunk); + chunk->mem = ALIGN_PTR_TO ((char*)chunk + sizeof (LockFreeMempoolChunk), 16); + chunk->size = ((char*)chunk + size) - (char*)chunk->mem; + chunk->pos = 0; + + /* Add to list of chunks lock-free */ + while (TRUE) { + prev = mp->chunks; + if (InterlockedCompareExchangePointer ((volatile gpointer*)&mp->chunks, chunk, prev) == prev) + break; + } + chunk->prev = prev; + + return chunk; +} + +/* + * This is async safe + */ +static gpointer +lock_free_mempool_alloc0 (LockFreeMempool *mp, guint size) +{ + LockFreeMempoolChunk *chunk; + gpointer res; + int oldpos; + + // FIXME: Free the allocator + + size = ALIGN_TO (size, 8); + chunk = mp->current; + if (!chunk) { + chunk = lock_free_mempool_chunk_new (mp, size); + mono_memory_barrier (); + /* Publish */ + mp->current = chunk; + } + + /* The code below is lock-free, 'chunk' is shared state */ + oldpos = InterlockedExchangeAdd (&chunk->pos, size); + if (oldpos + size > chunk->size) { + chunk = lock_free_mempool_chunk_new (mp, size); + g_assert (chunk->pos + size <= chunk->size); + res = chunk->mem; + chunk->pos += size; + mono_memory_barrier (); + mp->current = chunk; + } else { + res = (char*)chunk->mem + oldpos; + } + + return res; +} + void mono_install_create_domain_hook (MonoCreateDomainFunc func) { @@ -1172,6 +1277,7 @@ mono_domain_create (void) domain->mp = mono_mempool_new (); domain->code_mp = mono_code_manager_new (); + domain->lock_free_mp = lock_free_mempool_new (); domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC); domain->domain_assemblies = NULL; domain->assembly_bindings = NULL; @@ -1871,6 +1977,13 @@ mono_domain_free (MonoDomain *domain, gboolean force) mono_reflection_cleanup_domain (domain); + /* This must be done before type_hash is freed */ + if (domain->class_vtable_array) { + int i; + for (i = 0; i < domain->class_vtable_array->len; ++i) + unregister_vtable_reflection_type (g_ptr_array_index (domain->class_vtable_array, i)); + } + if (domain->type_hash) { mono_g_hash_table_destroy (domain->type_hash); domain->type_hash = NULL; @@ -1880,12 +1993,6 @@ mono_domain_free (MonoDomain *domain, gboolean force) domain->type_init_exception_hash = NULL; } - if (domain->class_vtable_array) { - int i; - for (i = 0; i < domain->class_vtable_array->len; ++i) - unregister_vtable_reflection_type (g_ptr_array_index (domain->class_vtable_array, i)); - } - for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { MonoAssembly *ass = tmp->data; mono_assembly_release_gc_roots (ass); @@ -1993,6 +2100,8 @@ mono_domain_free (MonoDomain *domain, gboolean force) mono_code_manager_destroy (domain->code_mp); domain->code_mp = NULL; #endif + lock_free_mempool_free (domain->lock_free_mp); + domain->lock_free_mp = NULL; g_hash_table_destroy (domain->finalizable_objects_hash); domain->finalizable_objects_hash = NULL; @@ -2100,6 +2209,12 @@ mono_domain_alloc0 (MonoDomain *domain, guint size) return res; } +gpointer +mono_domain_alloc0_lock_free (MonoDomain *domain, guint size) +{ + return lock_free_mempool_alloc0 (domain->lock_free_mp, size); +} + /* * mono_domain_code_reserve: * @@ -2243,7 +2358,7 @@ mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointe if (next >= size) { /* 'data' is allocated by alloc_fixed */ gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), MONO_GC_ROOT_DESCR_FOR_FIXED (size * 2)); - mono_gc_memmove (new_array, domain->static_data_array, sizeof (gpointer) * size); + mono_gc_memmove_aligned (new_array, domain->static_data_array, sizeof (gpointer) * size); size *= 2; new_array [1] = GINT_TO_POINTER (size); mono_gc_free_fixed (domain->static_data_array);