Merge pull request #4621 from alexanderkyte/strdup_env
[mono.git] / mono / metadata / boehm-gc.c
index d3153d29967deb995f5d80da007197e6f7575475..8adf077e6b1956fca0f4f3accd195b8b72394126 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * boehm-gc.c: GC implementation using either the installed or included Boehm GC.
+/**
+ * \file
+ * GC implementation using either the installed or included Boehm GC.
  *
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2011 Novell, Inc (http://www.novell.com)
@@ -24,6 +25,7 @@
 #include <mono/metadata/runtime.h>
 #include <mono/metadata/handle.h>
 #include <mono/metadata/sgen-toggleref.h>
+#include <mono/metadata/w32handle.h>
 #include <mono/utils/atomic.h>
 #include <mono/utils/mono-logger-internals.h>
 #include <mono/utils/mono-memory-model.h>
@@ -33,6 +35,7 @@
 #include <mono/utils/gc_wrapper.h>
 #include <mono/utils/mono-os-mutex.h>
 #include <mono/utils/mono-counters.h>
+#include <mono/utils/mono-compiler.h>
 
 #if HAVE_BOEHM_GC
 
@@ -58,6 +61,8 @@ boehm_thread_register (MonoThreadInfo* info, void *baseptr);
 static void
 boehm_thread_unregister (MonoThreadInfo *p);
 static void
+boehm_thread_detach (MonoThreadInfo *p);
+static void
 register_test_toggleref_callback (void);
 
 #define BOEHM_GC_BIT_FINALIZER_AWARE 1
@@ -97,6 +102,9 @@ mono_gc_warning (char *msg, GC_word arg)
        mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_GC, msg, (unsigned long)arg);
 }
 
+static void on_gc_notification (GC_EventType event);
+static void on_gc_heap_resize (size_t new_size);
+
 void
 mono_gc_base_init (void)
 {
@@ -109,6 +117,10 @@ mono_gc_base_init (void)
 
        mono_counters_init ();
 
+#ifndef HOST_WIN32
+       mono_w32handle_init ();
+#endif
+
        /*
         * Handle the case when we are called from a thread different from the main thread,
         * confusing libgc.
@@ -187,6 +199,7 @@ mono_gc_base_init (void)
                                        log_finalizers = 1;
                                }
                        }
+                       g_free (env);
                }
        }
 
@@ -230,12 +243,14 @@ mono_gc_base_init (void)
                                */
                        }
                }
+               g_free (env);
                g_strfreev (opts);
        }
 
        memset (&cb, 0, sizeof (cb));
        cb.thread_register = boehm_thread_register;
        cb.thread_unregister = boehm_thread_unregister;
+       cb.thread_detach = boehm_thread_detach;
        cb.mono_method_is_critical = (gboolean (*)(void *))mono_runtime_is_critical_method;
 
        mono_threads_init (&cb, sizeof (MonoThreadInfo));
@@ -244,10 +259,8 @@ mono_gc_base_init (void)
 
        mono_thread_info_attach (&dummy);
 
-       mono_gc_enable_events ();
-
-       MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_NORMAL].entries, MONO_ROOT_SOURCE_GC_HANDLE, "gc handles table");
-       MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_PINNED].entries, MONO_ROOT_SOURCE_GC_HANDLE, "gc handles table");
+       GC_set_on_collection_event (on_gc_notification);
+       GC_on_heap_resize = on_gc_heap_resize;
 
        gc_initialized = TRUE;
 }
@@ -260,15 +273,15 @@ mono_gc_base_cleanup (void)
 
 /**
  * mono_gc_collect:
- * @generation: GC generation identifier
+ * \param generation GC generation identifier
  *
  * Perform a garbage collection for the given generation, higher numbers
  * mean usually older objects. Collecting a high-numbered generation
  * implies collecting also the lower-numbered generations.
- * The maximum value for @generation can be retrieved with a call to
- * mono_gc_max_generation(), so this function is usually called as:
+ * The maximum value for \p generation can be retrieved with a call to
+ * \c mono_gc_max_generation, so this function is usually called as:
  *
- *     mono_gc_collect (mono_gc_max_generation ());
+ * <code>mono_gc_collect (mono_gc_max_generation ());</code>
  */
 void
 mono_gc_collect (int generation)
@@ -296,12 +309,12 @@ mono_gc_max_generation (void)
 
 /**
  * mono_gc_get_generation:
- * @object: a managed object
+ * \param object a managed object
  *
- * Get the garbage collector's generation that @object belongs to.
+ * Get the garbage collector's generation that \p object belongs to.
  * Use this has a hint only.
  *
- * Returns: a garbage collector generation number
+ * \returns a garbage collector generation number
  */
 int
 mono_gc_get_generation  (MonoObject *object)
@@ -311,12 +324,12 @@ mono_gc_get_generation  (MonoObject *object)
 
 /**
  * mono_gc_collection_count:
- * @generation: a GC generation number
+ * \param generation a GC generation number
  *
  * Get how many times a garbage collection has been performed
- * for the given @generation number.
+ * for the given \p generation number.
  *
- * Returns: the number of garbage collections
+ * \returns the number of garbage collections
  */
 int
 mono_gc_collection_count (int generation)
@@ -326,13 +339,13 @@ mono_gc_collection_count (int generation)
 
 /**
  * mono_gc_add_memory_pressure:
- * @value: amount of bytes
+ * \param value amount of bytes
  *
  * Adjust the garbage collector's view of how many bytes of memory
  * are indirectly referenced by managed objects (for example unmanaged
  * memory holding image or other binary data).
  * This is a hint only to the garbage collector algorithm.
- * Note that negative amounts of @value will decrease the memory
+ * Note that negative amounts of value will decrease the memory
  * pressure.
  */
 void
@@ -406,6 +419,13 @@ boehm_thread_unregister (MonoThreadInfo *p)
                mono_threads_add_joinable_thread ((gpointer)tid);
 }
 
+static void
+boehm_thread_detach (MonoThreadInfo *p)
+{
+       if (mono_thread_internal_current_is_attached ())
+               mono_thread_detach_internal (mono_thread_internal_current ());
+}
+
 gboolean
 mono_object_is_alive (MonoObject* o)
 {
@@ -509,21 +529,6 @@ on_gc_heap_resize (size_t new_size)
        mono_profiler_gc_heap_resize (new_size);
 }
 
-void
-mono_gc_enable_events (void)
-{
-       GC_set_on_collection_event (on_gc_notification);
-       GC_on_heap_resize = on_gc_heap_resize;
-}
-
-static gboolean alloc_events = FALSE;
-
-void
-mono_gc_enable_alloc_events (void)
-{
-       alloc_events = TRUE;
-}
-
 int
 mono_gc_register_root (char *start, size_t size, void *descr, MonoGCRootSource source, const char *msg)
 {
@@ -533,6 +538,12 @@ mono_gc_register_root (char *start, size_t size, void *descr, MonoGCRootSource s
        return TRUE;
 }
 
+int
+mono_gc_register_root_wbarrier (char *start, size_t size, MonoGCDescriptor descr, MonoGCRootSource source, const char *msg)
+{
+       return mono_gc_register_root (start, size, descr, source, msg);
+}
+
 void
 mono_gc_deregister_root (char* addr)
 {
@@ -609,6 +620,12 @@ mono_gc_make_descr_from_bitmap (gsize *bitmap, int numbits)
                return (gpointer)GC_make_descriptor ((GC_bitmap)bitmap, numbits);
 }
 
+void*
+mono_gc_make_vector_descr (void)
+{
+       return NULL;
+}
+
 void*
 mono_gc_make_root_descr_all_refs (int numbits)
 {
@@ -618,25 +635,13 @@ mono_gc_make_root_descr_all_refs (int numbits)
 void*
 mono_gc_alloc_fixed (size_t size, void *descr, MonoGCRootSource source, const char *msg)
 {
-       /* To help track down typed allocation bugs */
-       /*
-       static int count;
-       count ++;
-       if (count == atoi (g_getenv ("COUNT2")))
-               printf ("HIT!\n");
-       if (count > atoi (g_getenv ("COUNT2")))
-               return GC_MALLOC (size);
-       */
-
-       if (descr)
-               return GC_MALLOC_EXPLICITLY_TYPED (size, (GC_descr)descr);
-       else
-               return GC_MALLOC (size);
+       return GC_MALLOC_UNCOLLECTABLE (size);
 }
 
 void
 mono_gc_free_fixed (void* addr)
 {
+       GC_FREE (addr);
 }
 
 void *
@@ -665,7 +670,7 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
                obj->vtable = vtable;
        }
 
-       if (G_UNLIKELY (alloc_events))
+       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
                mono_profiler_allocation (obj);
 
        return obj;
@@ -699,7 +704,7 @@ mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length)
 
        obj->max_length = max_length;
 
-       if (G_UNLIKELY (alloc_events))
+       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
                mono_profiler_allocation (&obj->obj);
 
        return obj;
@@ -736,7 +741,7 @@ mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uint
        if (bounds_size)
                obj->bounds = (MonoArrayBounds *) ((char *) obj + size - bounds_size);
 
-       if (G_UNLIKELY (alloc_events))
+       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
                mono_profiler_allocation (&obj->obj);
 
        return obj;
@@ -754,7 +759,7 @@ mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len)
        obj->length = len;
        obj->chars [len] = 0;
 
-       if (G_UNLIKELY (alloc_events))
+       if (G_UNLIKELY (mono_profiler_events & MONO_PROFILE_ALLOCATIONS))
                mono_profiler_allocation (&obj->object);
 
        return obj;
@@ -863,7 +868,7 @@ mono_gc_get_restart_signal (void)
 }
 
 #if defined(USE_COMPILER_TLS) && defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
-extern __thread MONO_TLS_FAST void* GC_thread_tls;
+extern __thread void* GC_thread_tls;
 #include "metadata-internals.h"
 
 static int
@@ -896,6 +901,8 @@ create_allocator (int atype, int tls_key, gboolean slowpath)
        const char *name = NULL;
        WrapperInfo *info;
 
+       g_assert_not_reached ();
+
        if (atype == ATYPE_FREEPTR) {
                name = slowpath ? "SlowAllocPtrfree" : "AllocPtrfree";
        } else if (atype == ATYPE_FREEPTR_FOR_BOX) {
@@ -1112,7 +1119,7 @@ create_allocator (int atype, int tls_key, gboolean slowpath)
 static MonoMethod* alloc_method_cache [ATYPE_NUM];
 static MonoMethod* slowpath_alloc_method_cache [ATYPE_NUM];
 
-static G_GNUC_UNUSED gboolean
+gboolean
 mono_gc_is_critical_method (MonoMethod *method)
 {
        int i;
@@ -1137,13 +1144,14 @@ mono_gc_is_critical_method (MonoMethod *method)
 MonoMethod*
 mono_gc_get_managed_allocator (MonoClass *klass, gboolean for_box, gboolean known_instance_size)
 {
-       int offset = -1;
        int atype;
-       MONO_THREAD_VAR_OFFSET (GC_thread_tls, offset);
 
-       /*g_print ("thread tls: %d\n", offset);*/
-       if (offset == -1)
-               return NULL;
+       /*
+        * Tls implementation changed, we jump to tls native getters/setters.
+        * Is boehm managed allocator ok with this ? Do we even care ?
+        */
+       return NULL;
+
        if (!SMALL_ENOUGH (klass->instance_size))
                return NULL;
        if (mono_class_has_finalizer (klass) || mono_class_is_marshalbyref (klass))
@@ -1191,19 +1199,17 @@ mono_gc_get_managed_array_allocator (MonoClass *klass)
 MonoMethod*
 mono_gc_get_managed_allocator_by_type (int atype, ManagedAllocatorVariant variant)
 {
-       int offset = -1;
        MonoMethod *res;
        gboolean slowpath = variant != MANAGED_ALLOCATOR_REGULAR;
        MonoMethod **cache = slowpath ? slowpath_alloc_method_cache : alloc_method_cache;
-       MONO_THREAD_VAR_OFFSET (GC_thread_tls, offset);
 
-       mono_tls_key_set_offset (TLS_KEY_BOEHM_GC_THREAD, offset);
+       return NULL;
 
        res = cache [atype];
        if (res)
                return res;
 
-       res = create_allocator (atype, TLS_KEY_BOEHM_GC_THREAD, slowpath);
+       res = create_allocator (atype, -1, slowpath);
        mono_os_mutex_lock (&mono_gc_lock);
        if (cache [atype]) {
                mono_free_method (res);
@@ -1231,7 +1237,7 @@ mono_gc_get_write_barrier (void)
 
 #else
 
-static G_GNUC_UNUSED gboolean
+gboolean
 mono_gc_is_critical_method (MonoMethod *method)
 {
        return FALSE;
@@ -1316,7 +1322,7 @@ mono_gc_is_moving (void)
 gboolean
 mono_gc_is_disabled (void)
 {
-       if (GC_dont_gc || g_getenv ("GC_DONT_GC"))
+       if (GC_dont_gc || g_hasenv ("GC_DONT_GC"))
                return TRUE;
        else
                return FALSE;
@@ -1349,11 +1355,6 @@ mono_gc_get_nursery (int *shift_bits, size_t *size)
        return NULL;
 }
 
-void
-mono_gc_set_current_thread_appdomain (MonoDomain *domain)
-{
-}
-
 gboolean
 mono_gc_precise_stack_mark_enabled (void)
 {
@@ -1366,6 +1367,16 @@ mono_gc_get_logfile (void)
        return NULL;
 }
 
+void
+mono_gc_params_set (const char* options)
+{
+}
+
+void
+mono_gc_debug_set (const char* options)
+{
+}
+
 void
 mono_gc_conservatively_scan_area (void *start, void *end)
 {
@@ -1697,19 +1708,19 @@ alloc_handle (HandleData *handles, MonoObject *obj, gboolean track)
 
 /**
  * mono_gchandle_new:
- * @obj: managed object to get a handle for
- * @pinned: whether the object should be pinned
+ * \param obj managed object to get a handle for
+ * \param pinned whether the object should be pinned
  *
  * This returns a handle that wraps the object, this is used to keep a
  * reference to a managed object from the unmanaged world and preventing the
  * object from being disposed.
  * 
- * If @pinned is false the address of the object can not be obtained, if it is
+ * If \p pinned is false the address of the object can not be obtained, if it is
  * true the address of the object can be obtained.  This will also pin the
  * object so it will not be possible by a moving garbage collector to move the
  * object. 
  * 
- * Returns: a handle that can be used to access the object from
+ * \returns a handle that can be used to access the object from
  * unmanaged code.
  */
 guint32
@@ -1720,23 +1731,23 @@ mono_gchandle_new (MonoObject *obj, gboolean pinned)
 
 /**
  * mono_gchandle_new_weakref:
- * @obj: managed object to get a handle for
- * @track_resurrection: Determines how long to track the object, if this is set to TRUE, the object is tracked after finalization, if FALSE, the object is only tracked up until the point of finalization.
+ * \param obj managed object to get a handle for
+ * \param track_resurrection Determines how long to track the object, if this is set to TRUE, the object is tracked after finalization, if FALSE, the object is only tracked up until the point of finalization.
  *
  * This returns a weak handle that wraps the object, this is used to
  * keep a reference to a managed object from the unmanaged world.
- * Unlike the mono_gchandle_new the object can be reclaimed by the
+ * Unlike the \c mono_gchandle_new the object can be reclaimed by the
  * garbage collector.  In this case the value of the GCHandle will be
  * set to zero.
  * 
- * If @track_resurrection is TRUE the object will be tracked through
+ * If \p track_resurrection is TRUE the object will be tracked through
  * finalization and if the object is resurrected during the execution
  * of the finalizer, then the returned weakref will continue to hold
- * a reference to the object.   If @track_resurrection is FALSE, then
+ * a reference to the object.   If \p track_resurrection is FALSE, then
  * the weak reference's target will become NULL as soon as the object
  * is passed on to the finalizer.
  * 
- * Returns: a handle that can be used to access the object from
+ * \returns a handle that can be used to access the object from
  * unmanaged code.
  */
 guint32
@@ -1747,12 +1758,12 @@ mono_gchandle_new_weakref (MonoObject *obj, gboolean track_resurrection)
 
 /**
  * mono_gchandle_get_target:
- * @gchandle: a GCHandle's handle.
+ * \param gchandle a GCHandle's handle.
  *
- * The handle was previously created by calling `mono_gchandle_new` or
- * `mono_gchandle_new_weakref`.
+ * The handle was previously created by calling \c mono_gchandle_new or
+ * \c mono_gchandle_new_weakref.
  *
- * Returns: A pointer to the `MonoObject*` represented by the handle or
+ * \returns A pointer to the \c MonoObject* represented by the handle or
  * NULL for a collected object if using a weakref handle.
  */
 MonoObject*
@@ -1817,13 +1828,13 @@ mono_gc_is_null (void)
 
 /**
  * mono_gchandle_is_in_domain:
- * @gchandle: a GCHandle's handle.
- * @domain: An application domain.
+ * \param gchandle a GCHandle's handle.
+ * \param domain An application domain.
  *
- * Use this function to determine if the @gchandle points to an
- * object allocated in the specified @domain.
+ * Use this function to determine if the \p gchandle points to an
+ * object allocated in the specified \p domain.
  *
- * Returns: TRUE if the object wrapped by the @gchandle belongs to the specific @domain.
+ * \returns TRUE if the object wrapped by the \p gchandle belongs to the specific \p domain.
  */
 gboolean
 mono_gchandle_is_in_domain (guint32 gchandle, MonoDomain *domain)
@@ -1857,9 +1868,9 @@ mono_gchandle_is_in_domain (guint32 gchandle, MonoDomain *domain)
 
 /**
  * mono_gchandle_free:
- * @gchandle: a GCHandle's handle.
+ * \param gchandle a GCHandle's handle.
  *
- * Frees the @gchandle handle.  If there are no outstanding
+ * Frees the \p gchandle handle.  If there are no outstanding
  * references, the garbage collector can reclaim the memory of the
  * object wrapped. 
  */
@@ -1894,7 +1905,7 @@ mono_gchandle_free (guint32 gchandle)
 
 /**
  * mono_gchandle_free_domain:
- * @domain: domain that is unloading
+ * \param domain domain that is unloading
  *
  * Function used internally to cleanup any GC handle for objects belonging
  * to the specified domain during appdomain unload.
@@ -1929,8 +1940,6 @@ mono_gchandle_free_domain (MonoDomain *domain)
 
 }
 #else
-       #ifdef _MSC_VER
-               // Quiet Visual Studio linker warning, LNK4221, in cases when this source file intentional ends up empty.
-               void __mono_win32_boehm_gc_quiet_lnk4221(void) {}
-       #endif
+
+MONO_EMPTY_SOURCE_FILE (boehm_gc);
 #endif /* no Boehm GC */