[sgen] Implement work context for thread pool threads
[mono.git] / mono / sgen / sgen-simple-nursery.c
index 4234559e9e8cec8ced5617f60fe64e9e9e862c38..5d39368402b133d4e6c0a0bd2adcc22ad611c2af 100644 (file)
@@ -19,7 +19,9 @@
 #include "mono/sgen/sgen-protocol.h"
 #include "mono/sgen/sgen-layout-stats.h"
 #include "mono/sgen/sgen-client.h"
+#include "mono/sgen/sgen-workers.h"
 #include "mono/utils/mono-memory-model.h"
+#include "mono/utils/mono-proclib.h"
 
 static inline GCObject*
 alloc_for_promotion (GCVTable vtable, GCObject *obj, size_t objsize, gboolean has_references)
@@ -28,6 +30,19 @@ alloc_for_promotion (GCVTable vtable, GCObject *obj, size_t objsize, gboolean ha
        return major_collector.alloc_object (vtable, objsize, has_references);
 }
 
+static inline GCObject*
+alloc_for_promotion_par (GCVTable vtable, GCObject *obj, size_t objsize, gboolean has_references)
+{
+       /*
+        * FIXME
+        * Note that the stat is not precise. total_promoted_size incrementing is not atomic and
+        * even in that case, the same object might be promoted simultaneously by different workers
+        * leading to one of the allocated major object to be discarded.
+        */
+       total_promoted_size += objsize;
+       return major_collector.alloc_object_par (vtable, objsize, has_references);
+}
+
 static SgenFragment*
 build_fragments_get_exclude_head (void)
 {
@@ -57,7 +72,14 @@ clear_fragments (void)
 static void
 init_nursery (SgenFragmentAllocator *allocator, char *start, char *end)
 {
-       sgen_fragment_allocator_add (allocator, start, end);
+       char *nursery_limit = sgen_nursery_start + sgen_nursery_size;
+
+       if (start < nursery_limit && end > nursery_limit) {
+               sgen_fragment_allocator_add (allocator, start, nursery_limit);
+               sgen_fragment_allocator_add (allocator, nursery_limit, end);
+       } else {
+               sgen_fragment_allocator_add (allocator, start, end);
+       }
 }
 
 
@@ -65,6 +87,7 @@ init_nursery (SgenFragmentAllocator *allocator, char *start, char *end)
 
 #define collector_pin_object(obj, queue) sgen_pin_object (obj, queue);
 #define COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION alloc_for_promotion
+#define COLLECTOR_PARALLEL_ALLOC_FOR_PROMOTION alloc_for_promotion_par
 
 #define COPY_OR_MARK_PARALLEL
 #include "sgen-copy-object.h"
@@ -109,10 +132,14 @@ fill_serial_with_concurrent_major_ops (SgenObjectOperations *ops)
 void
 sgen_simple_nursery_init (SgenMinorCollector *collector, gboolean parallel)
 {
+       if (mono_cpu_count () <= 1)
+               parallel = FALSE;
+
        collector->is_split = FALSE;
        collector->is_parallel = parallel;
 
        collector->alloc_for_promotion = alloc_for_promotion;
+       collector->alloc_for_promotion_par = alloc_for_promotion_par;
 
        collector->prepare_to_space = prepare_to_space;
        collector->clear_fragments = clear_fragments;
@@ -124,6 +151,13 @@ sgen_simple_nursery_init (SgenMinorCollector *collector, gboolean parallel)
        fill_serial_ops (&collector->serial_ops);
        fill_serial_with_concurrent_major_ops (&collector->serial_ops_with_concurrent_major);
        fill_parallel_ops (&collector->parallel_ops);
+
+       /*
+        * The nursery worker context is created first so it will have priority over
+        * concurrent mark and concurrent sweep.
+        */
+       if (parallel)
+               sgen_workers_create_context (GENERATION_NURSERY, mono_cpu_count ());
 }