X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fboehm-gc.c;h=bbebb14a1d3b9a937e2e974717e44855d5b98ee0;hb=b9e97c9957ceb5a04ab1a43da3074646b196e946;hp=b858650c874c5b213684f311f8802926f9a93ca6;hpb=04a90dcbb0e1ceea50731553f24800edef85e1fa;p=mono.git diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index b858650c874..bbebb14a1d3 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,8 @@ #include #include #include +#include +#include #if HAVE_BOEHM_GC @@ -48,9 +51,17 @@ void *pthread_get_stackaddr_np(pthread_t); #define MIN_BOEHM_MAX_HEAP_SIZE (MIN_BOEHM_MAX_HEAP_SIZE_IN_MB << 20) static gboolean gc_initialized = FALSE; +static mono_mutex_t mono_gc_lock; static void* boehm_thread_register (MonoThreadInfo* info, void *baseptr); +static void +boehm_thread_unregister (MonoThreadInfo *p); +static void +register_test_toggleref_callback (void); + +#define BOEHM_GC_BIT_FINALIZER_AWARE 1 +static MonoGCFinalizerCallbacks fin_callbacks; static void mono_gc_warning (char *msg, GC_word arg) @@ -63,10 +74,13 @@ mono_gc_base_init (void) { MonoThreadInfoCallbacks cb; const char *env; + int dummy; if (gc_initialized) return; + mono_counters_init (); + /* * Handle the case when we are called from a thread different from the main thread, * confusing libgc. @@ -153,7 +167,7 @@ mono_gc_base_init (void) for (ptr = opts; *ptr; ++ptr) { char *opt = *ptr; if (g_str_has_prefix (opt, "max-heap-size=")) { - glong max_heap; + size_t max_heap; opt = strchr (opt, '=') + 1; if (*opt && mono_gc_parse_environment_string_extract_number (opt, &max_heap)) { @@ -167,6 +181,9 @@ mono_gc_base_init (void) exit (1); } continue; + } else if (g_str_has_prefix (opt, "toggleref-test")) { + register_test_toggleref_callback (); + continue; } else { /* Could be a parameter for sgen */ /* @@ -181,12 +198,17 @@ mono_gc_base_init (void) memset (&cb, 0, sizeof (cb)); cb.thread_register = boehm_thread_register; + cb.thread_unregister = boehm_thread_unregister; cb.mono_method_is_critical = (gpointer)mono_runtime_is_critical_method; #ifndef HOST_WIN32 + cb.thread_exit = mono_gc_pthread_exit; cb.mono_gc_pthread_create = (gpointer)mono_gc_pthread_create; #endif mono_threads_init (&cb, sizeof (MonoThreadInfo)); + mono_mutex_init (&mono_gc_lock); + + mono_thread_info_attach (&dummy); mono_gc_enable_events (); gc_initialized = TRUE; @@ -352,6 +374,17 @@ boehm_thread_register (MonoThreadInfo* info, void *baseptr) #endif } +static void +boehm_thread_unregister (MonoThreadInfo *p) +{ + MonoNativeThreadId tid; + + tid = mono_thread_info_get_tid (p); + + if (p->runtime_thread) + mono_threads_add_joinable_thread ((gpointer)tid); +} + gboolean mono_object_is_alive (MonoObject* o) { @@ -425,7 +458,7 @@ on_gc_notification (GCEventType event) mono_perfcounters->gc_gen0size = heap_size; } #endif - gc_stats.major_gc_time_usecs += (mono_100ns_ticks () - gc_start_time) / 10; + gc_stats.major_gc_time += mono_100ns_ticks () - gc_start_time; mono_trace_message (MONO_TRACE_GC, "gc took %d usecs", (mono_100ns_ticks () - gc_start_time) / 10); break; } @@ -616,7 +649,7 @@ mono_gc_wbarrier_set_arrayref (MonoArray *arr, gpointer slot_ptr, MonoObject* va void mono_gc_wbarrier_arrayref_copy (gpointer dest_ptr, gpointer src_ptr, int count) { - mono_gc_memmove (dest_ptr, src_ptr, count * sizeof (gpointer)); + mono_gc_memmove_aligned (dest_ptr, src_ptr, count * sizeof (gpointer)); } void @@ -639,14 +672,14 @@ mono_gc_wbarrier_generic_nostore (gpointer ptr) void mono_gc_wbarrier_value_copy (gpointer dest, gpointer src, int count, MonoClass *klass) { - mono_gc_memmove (dest, src, count * mono_class_value_size (klass, NULL)); + mono_gc_memmove_atomic (dest, src, count * mono_class_value_size (klass, NULL)); } void mono_gc_wbarrier_object_copy (MonoObject* obj, MonoObject *src) { /* do not copy the sync state */ - mono_gc_memmove ((char*)obj + sizeof (MonoObject), (char*)src + sizeof (MonoObject), + mono_gc_memmove_aligned ((char*)obj + sizeof (MonoObject), (char*)src + sizeof (MonoObject), mono_object_class (obj)->instance_size - sizeof (MonoObject)); } @@ -665,6 +698,16 @@ mono_gc_get_suspend_signal (void) #endif } +int +mono_gc_get_restart_signal (void) +{ +#ifdef USE_INCLUDED_GC + return GC_get_restart_signal (); +#else + return -1; +#endif +} + #if defined(USE_INCLUDED_LIBGC) && defined(USE_COMPILER_TLS) && defined(__linux__) && (defined(__i386__) || defined(__x86_64__)) extern __thread MONO_TLS_FAST void* GC_thread_tls; #include "metadata-internals.h" @@ -713,7 +756,7 @@ create_allocator (int atype, int tls_key) bytes_var = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg); if (atype == ATYPE_STRING) { /* a string alloator method takes the args: (vtable, len) */ - /* bytes = (sizeof (MonoString) + ((len + 1) * 2)); */ + /* bytes = (offsetof (MonoString, chars) + ((len + 1) * 2)); */ mono_mb_emit_ldarg (mb, 1); mono_mb_emit_icon (mb, 1); mono_mb_emit_byte (mb, MONO_CEE_ADD); @@ -976,11 +1019,20 @@ mono_gc_get_managed_allocator_by_type (int atype) mono_tls_key_set_offset (TLS_KEY_BOEHM_GC_THREAD, offset); - mono_loader_lock (); res = alloc_method_cache [atype]; - if (!res) - res = alloc_method_cache [atype] = create_allocator (atype, TLS_KEY_BOEHM_GC_THREAD); - mono_loader_unlock (); + if (res) + return res; + + res = create_allocator (atype, TLS_KEY_BOEHM_GC_THREAD); + mono_mutex_lock (&mono_gc_lock); + if (alloc_method_cache [atype]) { + mono_free_method (res); + res = alloc_method_cache [atype]; + } else { + mono_memory_barrier (); + alloc_method_cache [atype] = res; + } + mono_mutex_unlock (&mono_gc_lock); return res; } @@ -1128,7 +1180,7 @@ mono_gc_conservatively_scan_area (void *start, void *end) } void * -mono_gc_scan_object (void *obj) +mono_gc_scan_object (void *obj, void *gc_data) { g_assert_not_reached (); return NULL; @@ -1196,6 +1248,7 @@ void mono_gc_pthread_exit (void *retval) { pthread_exit (retval); + g_assert_not_reached (); } #endif @@ -1214,6 +1267,10 @@ BOOL APIENTRY mono_gc_dllmain (HMODULE module_handle, DWORD reason, LPVOID reser guint mono_gc_get_vtable_bits (MonoClass *class) { + if (fin_callbacks.is_class_finalization_aware) { + if (fin_callbacks.is_class_finalization_aware (class)) + return BOEHM_GC_BIT_FINALIZER_AWARE; + } return 0; } @@ -1237,6 +1294,18 @@ mono_gc_get_los_limit (void) return G_MAXINT; } +void +mono_gc_set_string_length (MonoString *str, gint32 new_length) +{ + mono_unichar2 *new_end = str->chars + new_length; + + /* zero the discarded string. This null-delimits the string and allows + * the space to be reclaimed by SGen. */ + + memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2)); + str->length = new_length; +} + gboolean mono_gc_user_markers_supported (void) { @@ -1255,5 +1324,67 @@ mono_gc_set_allow_synchronous_major (gboolean flag) { return flag; } +/* Toggleref support */ + +void +mono_gc_toggleref_add (MonoObject *object, mono_bool strong_ref) +{ + GC_toggleref_add ((GC_PTR)object, (int)strong_ref); +} + +void +mono_gc_toggleref_register_callback (MonoToggleRefStatus (*proccess_toggleref) (MonoObject *obj)) +{ + GC_toggleref_register_callback ((int (*) (GC_PTR obj)) proccess_toggleref); +} + +/* Test support code */ + +static MonoToggleRefStatus +test_toggleref_callback (MonoObject *obj) +{ + static MonoClassField *mono_toggleref_test_field; + int status = MONO_TOGGLE_REF_DROP; + + if (!mono_toggleref_test_field) { + mono_toggleref_test_field = mono_class_get_field_from_name (mono_object_get_class (obj), "__test"); + g_assert (mono_toggleref_test_field); + } + + mono_field_get_value (obj, mono_toggleref_test_field, &status); + printf ("toggleref-cb obj %d\n", status); + return status; +} + +static void +register_test_toggleref_callback (void) +{ + mono_gc_toggleref_register_callback (test_toggleref_callback); +} + +static gboolean +is_finalization_aware (MonoObject *obj) +{ + MonoVTable *vt = obj->vtable; + return (vt->gc_bits & BOEHM_GC_BIT_FINALIZER_AWARE) == BOEHM_GC_BIT_FINALIZER_AWARE; +} + +static void +fin_notifier (MonoObject *obj) +{ + if (is_finalization_aware (obj)) + fin_callbacks.object_queued_for_finalization (obj); +} + +void +mono_gc_register_finalizer_callbacks (MonoGCFinalizerCallbacks *callbacks) +{ + if (callbacks->version != MONO_GC_FINALIZER_EXTENSION_VERSION) + g_error ("Invalid finalizer callback version. Expected %d but got %d\n", MONO_GC_FINALIZER_EXTENSION_VERSION, callbacks->version); + + fin_callbacks = *callbacks; + + GC_set_finalizer_notify_proc ((void (*) (GC_PTR))fin_notifier); +} #endif /* no Boehm GC */