Merge pull request #2274 from esdrubal/udpclientreceive
[mono.git] / mono / sgen / sgen-gc.h
index 103a7fe5d9ffddf00da9a06cb2cf9bd41684293b..9e022e12ba902d4bac866957dc71ccbfe3c4c1e3 100644 (file)
@@ -39,10 +39,12 @@ typedef struct _SgenThreadInfo SgenThreadInfo;
 #include <stdint.h>
 #include "mono/utils/mono-compiler.h"
 #include "mono/utils/atomic.h"
-#include "mono/utils/mono-mutex.h"
+#include "mono/utils/mono-os-mutex.h"
+#include "mono/utils/mono-coop-mutex.h"
 #include "mono/sgen/sgen-conf.h"
 #include "mono/sgen/sgen-hash-table.h"
 #include "mono/sgen/sgen-protocol.h"
+#include "mono/sgen/gc-internal-agnostic.h"
 
 /* The method used to clear the nursery */
 /* Clearing at nursery collections is the safest, but has bad interactions with caches.
@@ -88,23 +90,14 @@ struct _GCMemSection {
 #define LOCK_DECLARE(name) mono_mutex_t name
 /* if changing LOCK_INIT to something that isn't idempotent, look at
    its use in mono_gc_base_init in sgen-gc.c */
-#define LOCK_INIT(name)        mono_mutex_init (&(name))
-#define LOCK_GC do {                                           \
-               MONO_TRY_BLOCKING       \
-               mono_mutex_lock (&gc_mutex);                    \
-               MONO_FINISH_TRY_BLOCKING        \
-       } while (0)
+#define LOCK_INIT(name)        mono_os_mutex_init (&(name))
+#define LOCK_GC do { sgen_gc_lock (); } while (0)
 #define UNLOCK_GC do { sgen_gc_unlock (); } while (0)
 
-extern LOCK_DECLARE (sgen_interruption_mutex);
-
-#define LOCK_INTERRUPTION do { \
-       MONO_TRY_BLOCKING       \
-       mono_mutex_lock (&sgen_interruption_mutex);     \
-       MONO_FINISH_TRY_BLOCKING        \
-} while (0)
+extern MonoCoopMutex sgen_interruption_mutex;
 
-#define UNLOCK_INTERRUPTION mono_mutex_unlock (&sgen_interruption_mutex)
+#define LOCK_INTERRUPTION mono_coop_mutex_lock (&sgen_interruption_mutex)
+#define UNLOCK_INTERRUPTION mono_coop_mutex_unlock (&sgen_interruption_mutex)
 
 /* FIXME: Use InterlockedAdd & InterlockedAdd64 to reduce the CAS cost. */
 #define SGEN_CAS       InterlockedCompareExchange
@@ -172,14 +165,6 @@ sgen_aligned_addr_hash (gconstpointer ptr)
        return GPOINTER_TO_UINT (ptr) >> 3;
 }
 
-/*
- * The link pointer is hidden by negating each bit.  We use the lowest
- * bit of the link (before negation) to store whether it needs
- * resurrection tracking.
- */
-#define HIDE_POINTER(p,t)      ((gpointer)(~((size_t)(p)|((t)?1:0))))
-#define REVEAL_POINTER(p)      ((gpointer)((~(size_t)(p))&~3L))
-
 #define SGEN_PTR_IN_NURSERY(p,bits,start,end)  (((mword)(p) & ~((1 << (bits)) - 1)) == (mword)(start))
 
 #ifdef USER_CONFIG
@@ -252,8 +237,8 @@ sgen_get_nursery_end (void)
 #define SGEN_POINTER_UNTAG_VTABLE(p)           SGEN_POINTER_UNTAG_ALL((p))
 
 /* returns NULL if not forwarded, or the forwarded address */
-#define SGEN_VTABLE_IS_FORWARDED(vtable) (SGEN_POINTER_IS_TAGGED_FORWARDED ((vtable)) ? SGEN_POINTER_UNTAG_VTABLE ((vtable)) : NULL)
-#define SGEN_OBJECT_IS_FORWARDED(obj) (SGEN_VTABLE_IS_FORWARDED (((mword*)(obj))[0]))
+#define SGEN_VTABLE_IS_FORWARDED(vtable) ((GCVTable *)(SGEN_POINTER_IS_TAGGED_FORWARDED ((vtable)) ? SGEN_POINTER_UNTAG_VTABLE ((vtable)) : NULL))
+#define SGEN_OBJECT_IS_FORWARDED(obj) ((GCObject *)SGEN_VTABLE_IS_FORWARDED (((mword*)(obj))[0]))
 
 #define SGEN_VTABLE_IS_PINNED(vtable) SGEN_POINTER_IS_TAGGED_PINNED ((vtable))
 #define SGEN_OBJECT_IS_PINNED(obj) (SGEN_VTABLE_IS_PINNED (((mword*)(obj))[0]))
@@ -279,7 +264,7 @@ sgen_get_nursery_end (void)
  * Since we set bits in the vtable, use the macro to load it from the pointer to
  * an object that is potentially pinned.
  */
-#define SGEN_LOAD_VTABLE(obj)          ((GCVTable)(SGEN_POINTER_UNTAG_ALL (SGEN_LOAD_VTABLE_UNCHECKED ((obj)))))
+#define SGEN_LOAD_VTABLE(obj)          ((GCVTable)(SGEN_POINTER_UNTAG_ALL (SGEN_LOAD_VTABLE_UNCHECKED ((GCObject *)(obj)))))
 
 /*
 List of what each bit on of the vtable gc bits means. 
@@ -373,6 +358,8 @@ typedef struct _RootRecord RootRecord;
 struct _RootRecord {
        char *end_root;
        SgenDescriptor root_desc;
+       int source;
+       const char *msg;
 };
 
 enum {
@@ -384,7 +371,7 @@ enum {
 
 extern SgenHashTable roots_hash [ROOT_TYPE_NUM];
 
-int sgen_register_root (char *start, size_t size, SgenDescriptor descr, int root_type);
+int sgen_register_root (char *start, size_t size, SgenDescriptor descr, int root_type, int source, const char *msg);
 void sgen_deregister_root (char* addr);
 
 typedef void (*IterateObjectCallbackFunc) (GCObject*, size_t, void*);
@@ -416,11 +403,14 @@ gboolean sgen_is_worker_thread (MonoNativeThreadId thread);
 typedef void (*CopyOrMarkObjectFunc) (GCObject**, SgenGrayQueue*);
 typedef void (*ScanObjectFunc) (GCObject *obj, SgenDescriptor desc, SgenGrayQueue*);
 typedef void (*ScanVTypeFunc) (GCObject *full_object, char *start, SgenDescriptor desc, SgenGrayQueue* BINARY_PROTOCOL_ARG (size_t size));
+typedef gboolean (*DrainGrayStackFunc) (SgenGrayQueue *queue);
 
 typedef struct {
        CopyOrMarkObjectFunc copy_or_mark_object;
        ScanObjectFunc scan_object;
        ScanVTypeFunc scan_vtype;
+       /* Drain stack optimized for the above functions */
+       DrainGrayStackFunc drain_gray_stack;
        /*FIXME add allocation function? */
 } SgenObjectOperations;
 
@@ -451,7 +441,7 @@ void sgen_pin_stats_register_global_remset (GCObject *obj);
 void sgen_pin_stats_print_class_stats (void);
 
 void sgen_sort_addresses (void **array, size_t size);
-void sgen_add_to_global_remset (gpointer ptr, gpointer obj);
+void sgen_add_to_global_remset (gpointer ptr, GCObject *obj);
 
 int sgen_get_current_collection_generation (void);
 gboolean sgen_collection_is_concurrent (void);
@@ -609,13 +599,6 @@ struct _SgenMajorCollector {
        gboolean supports_cardtable;
        gboolean sweeps_lazily;
 
-       /*
-        * This is set to TRUE by the sweep if the next major
-        * collection should be synchronous (for evacuation).  For
-        * non-concurrent collectors, this should be NULL.
-        */
-       gboolean *want_synchronous_collection;
-
        void* (*alloc_heap) (mword nursery_size, mword nursery_align, int nursery_bits);
        gboolean (*is_object_live) (GCObject *obj);
        GCObject* (*alloc_small_pinned_obj) (GCVTable vtable, size_t size, gboolean has_references);
@@ -623,7 +606,6 @@ struct _SgenMajorCollector {
 
        SgenObjectOperations major_ops_serial;
        SgenObjectOperations major_ops_concurrent_start;
-       SgenObjectOperations major_ops_concurrent;
        SgenObjectOperations major_ops_concurrent_finish;
 
        GCObject* (*alloc_object) (GCVTable vtable, size_t size, gboolean has_references);
@@ -653,7 +635,6 @@ struct _SgenMajorCollector {
        void (*finish_nursery_collection) (void);
        void (*start_major_collection) (void);
        void (*finish_major_collection) (ScannedObjectCounts *counts);
-       gboolean (*drain_gray_stack) (ScanCopyContext ctx);
        gboolean (*ptr_is_in_non_pinned_space) (char *ptr, char **start);
        gboolean (*ptr_is_from_pinned_alloc) (char *ptr);
        void (*report_pinned_memory_usage) (void);
@@ -784,7 +765,7 @@ void sgen_collect_bridge_objects (int generation, ScanCopyContext ctx);
 
 typedef gboolean (*SgenObjectPredicateFunc) (GCObject *obj, void *user_data);
 
-void sgen_null_links_if (SgenObjectPredicateFunc predicate, void *data, int generation);
+void sgen_null_links_if (SgenObjectPredicateFunc predicate, void *data, int generation, gboolean track);
 
 gboolean sgen_gc_is_object_ready_for_finalization (GCObject *object);
 void sgen_gc_lock (void);
@@ -794,7 +775,7 @@ void sgen_queue_finalization_entry (GCObject *obj);
 const char* sgen_generation_name (int generation);
 
 void sgen_finalize_in_range (int generation, ScanCopyContext ctx);
-void sgen_null_link_in_range (int generation, gboolean before_finalization, ScanCopyContext ctx);
+void sgen_null_link_in_range (int generation, ScanCopyContext ctx, gboolean track);
 void sgen_process_fin_stage_entries (void);
 gboolean sgen_have_pending_finalizers (void);
 void sgen_object_register_for_finalization (GCObject *obj, void *user_data);
@@ -802,12 +783,11 @@ void sgen_object_register_for_finalization (GCObject *obj, void *user_data);
 int sgen_gather_finalizers_if (SgenObjectPredicateFunc predicate, void *user_data, GCObject **out_array, int out_size);
 void sgen_remove_finalizers_if (SgenObjectPredicateFunc predicate, void *user_data, int generation);
 
-void sgen_process_dislink_stage_entries (void);
 void sgen_register_disappearing_link (GCObject *obj, void **link, gboolean track, gboolean in_gc);
 
 GCObject* sgen_weak_link_get (void **link_addr);
 
-gboolean sgen_drain_gray_stack (int max_objs, ScanCopyContext ctx);
+gboolean sgen_drain_gray_stack (ScanCopyContext ctx);
 
 enum {
        SPACE_NURSERY,
@@ -946,6 +926,19 @@ sgen_is_object_alive_for_current_gen (GCObject *object)
 
 int sgen_gc_invoke_finalizers (void);
 
+/* GC handles */
+
+void sgen_init_gchandles (void);
+
+void sgen_null_links_if (SgenObjectPredicateFunc predicate, void *data, int generation, gboolean track);
+
+typedef gpointer (*SgenGCHandleIterateCallback) (gpointer hidden, GCHandleType handle_type, int max_generation, gpointer user);
+
+void sgen_gchandle_iterate (GCHandleType handle_type, int max_generation, SgenGCHandleIterateCallback callback, gpointer user);
+void sgen_gchandle_set_target (guint32 gchandle, GCObject *obj);
+void sgen_mark_normal_gc_handles (void *addr, SgenUserMarkFunc mark_func, void *gc_data);
+gpointer sgen_gchandle_get_metadata (guint32 gchandle);
+
 /* Other globals */
 
 extern GCMemSection *nursery_section;
@@ -958,7 +951,7 @@ extern guint32 tlab_size;
 extern NurseryClearPolicy nursery_clear_policy;
 extern gboolean sgen_try_free_some_memory;
 
-extern LOCK_DECLARE (gc_mutex);
+extern MonoCoopMutex gc_mutex;
 
 /* Nursery helpers. */
 
@@ -1010,23 +1003,6 @@ void sgen_debug_dump_heap (const char *type, int num, const char *reason);
 void sgen_debug_verify_nursery (gboolean do_dump_nursery_content);
 void sgen_debug_check_nursery_is_clean (void);
 
-/* Write barrier support */
-
-/*
- * This causes the compile to extend the liveness of 'v' till the call to dummy_use
- */
-static inline void
-sgen_dummy_use (gpointer v) {
-#if defined(__GNUC__)
-       __asm__ volatile ("" : "=r"(v) : "r"(v));
-#elif defined(_MSC_VER)
-       static volatile gpointer ptr;
-       ptr = v;
-#else
-#error "Implement sgen_dummy_use for your compiler"
-#endif
-}
-
 /* Environment variable parsing */
 
 #define MONO_GC_PARAMS_NAME    "MONO_GC_PARAMS"
@@ -1073,6 +1049,22 @@ gboolean nursery_canaries_enabled (void);
                                                g_warning ("CORRUPT CANARY:\naddr->%p\ntype->%s\nexcepted->'%s'\nfound->'%s'\n", (char*) addr, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE ((addr))), CANARY_STRING, canary_copy); \
                                } }
 
+/*
+ * This causes the compile to extend the liveness of 'v' till the call to dummy_use
+ */
+static inline void
+sgen_dummy_use (gpointer v)
+{
+#if defined(__GNUC__)
+       __asm__ volatile ("" : "=r"(v) : "r"(v));
+#elif defined(_MSC_VER)
+       static volatile gpointer ptr;
+       ptr = v;
+#else
+#error "Implement sgen_dummy_use for your compiler"
+#endif
+}
+
 #endif /* HAVE_SGEN_GC */
 
 #endif /* __MONO_SGENGC_H__ */