[Git][ghc/ghc][wip/T22264] 7 commits: testsuite: Only run T22795* in the normal way

Ben Gamari (@bgamari) gitlab at gitlab.haskell.org
Wed Mar 8 03:41:11 UTC 2023



Ben Gamari pushed to branch wip/T22264 at Glasgow Haskell Compiler / GHC


Commits:
6f93d1ab by Ben Gamari at 2023-03-07T20:23:29-05:00
testsuite: Only run T22795* in the normal way

It doesn't make sense to run these in multiple ways as they merely test
whether `-threaded`/`-single-threaded` flags.

- - - - -
6a698354 by Ben Gamari at 2023-03-07T21:07:32-05:00
rts: Rename clear_segment(_free_blocks)?

To reflect the fact that these are to do with the nonmoving collector,
now since they are exposed no longer static.

- - - - -
2ab96142 by Ben Gamari at 2023-03-07T22:13:19-05:00
rts: Fix incorrect STATIC_INLINE

This should be INLINE_HEADER lest we get unused declaration warnings.

- - - - -
e76488f3 by Ben Gamari at 2023-03-07T22:13:19-05:00
rts: Capture GC configuration in a struct

The number of distinct arguments passed to GarbageCollect was getting a
bit out of hand.

- - - - -
69863e58 by Ben Gamari at 2023-03-07T22:13:19-05:00
nonmoving: Non-concurrent collection

- - - - -
09bc4845 by Ben Gamari at 2023-03-07T22:33:46-05:00
testsuite: Mark ffi023 as broken due to #23089

- - - - -
6cb91e16 by Ben Gamari at 2023-03-07T22:40:39-05:00
testsuite: Skip T7160 in the nonmoving way

Finalization order is different under the nonmoving collector.

- - - - -


13 changed files:

- rts/Schedule.c
- rts/include/rts/storage/GC.h
- rts/sm/GC.c
- rts/sm/GC.h
- rts/sm/NonMoving.c
- rts/sm/NonMoving.h
- rts/sm/NonMovingMark.c
- rts/sm/NonMovingSweep.c
- rts/sm/Storage.c
- rts/sm/Storage.h
- testsuite/tests/ffi/should_run/all.T
- testsuite/tests/ffi/should_run/ffi023_c.c
- testsuite/tests/rts/all.T


Changes:

=====================================
rts/Schedule.c
=====================================
@@ -157,7 +157,10 @@ static bool scheduleHandleThreadFinished( Capability *cap, Task *task,
                                           StgTSO *t );
 static bool scheduleNeedHeapProfile(bool ready_to_gc);
 static void scheduleDoGC( Capability **pcap, Task *task,
-                          bool force_major, bool is_overflow_gc, bool deadlock_detect );
+                          bool force_major,
+                          bool is_overflow_gc,
+                          bool deadlock_detect,
+                          bool nonconcurrent );
 
 static void deleteThread (StgTSO *tso);
 static void deleteAllThreads (void);
@@ -259,7 +262,7 @@ schedule (Capability *initialCapability, Task *task)
     case SCHED_INTERRUPTING:
         debugTrace(DEBUG_sched, "SCHED_INTERRUPTING");
         /* scheduleDoGC() deletes all the threads */
-        scheduleDoGC(&cap,task,true,false,false);
+        scheduleDoGC(&cap,task,true,false,false,false);
 
         // after scheduleDoGC(), we must be shutting down.  Either some
         // other Capability did the final GC, or we did it above,
@@ -572,7 +575,7 @@ run_thread:
     }
 
     if (ready_to_gc || scheduleNeedHeapProfile(ready_to_gc)) {
-      scheduleDoGC(&cap,task,false,ready_to_gc,false);
+      scheduleDoGC(&cap,task,false,ready_to_gc,false,false);
     }
   } /* end of while() */
 }
@@ -966,7 +969,7 @@ scheduleDetectDeadlock (Capability **pcap, Task *task)
         // they are unreachable and will therefore be sent an
         // exception.  Any threads thus released will be immediately
         // runnable.
-        scheduleDoGC (pcap, task, true/*force major GC*/, false /* Whether it is an overflow GC */, true/*deadlock detection*/);
+        scheduleDoGC (pcap, task, true/*force major GC*/, false /* Whether it is an overflow GC */, true/*deadlock detection*/, false/*nonconcurrent*/);
         cap = *pcap;
         // when force_major == true. scheduleDoGC sets
         // recent_activity to ACTIVITY_DONE_GC and turns off the timer
@@ -1015,7 +1018,7 @@ scheduleProcessInbox (Capability **pcap USED_IF_THREADS)
     while (!emptyInbox(cap)) {
         // Executing messages might use heap, so we should check for GC.
         if (doYouWantToGC(cap)) {
-            scheduleDoGC(pcap, cap->running_task, false, false, false);
+            scheduleDoGC(pcap, cap->running_task, false, false, false, false);
             cap = *pcap;
         }
 
@@ -1583,7 +1586,10 @@ void releaseAllCapabilities(uint32_t n, Capability *keep_cap, Task *task)
 // behind deadlock_detect argument.
 static void
 scheduleDoGC (Capability **pcap, Task *task USED_IF_THREADS,
-              bool force_major, bool is_overflow_gc, bool deadlock_detect)
+              bool force_major,
+              bool is_overflow_gc,
+              bool deadlock_detect,
+              bool nonconcurrent)
 {
     Capability *cap = *pcap;
     bool heap_census;
@@ -1873,14 +1879,23 @@ delete_threads_and_gc:
     // Do any remaining idle GC work from the previous GC
     doIdleGCWork(cap, true /* all of it */);
 
+    struct GcConfig config = {
+        .collect_gen = collect_gen,
+        .do_heap_census = heap_census,
+        .overflow_gc = is_overflow_gc,
+        .deadlock_detect = deadlock_detect,
+        .nonconcurrent = nonconcurrent
+    };
+
 #if defined(THREADED_RTS)
     // reset pending_sync *before* GC, so that when the GC threads
     // emerge they don't immediately re-enter the GC.
     RELAXED_STORE(&pending_sync, 0);
     signalCondition(&sync_finished_cond);
-    GarbageCollect(collect_gen, heap_census, is_overflow_gc, deadlock_detect, gc_type, cap, idle_cap);
+    config.parallel = gc_type == SYNC_GC_PAR;
+    GarbageCollect(config, cap, idle_cap);
 #else
-    GarbageCollect(collect_gen, heap_census, is_overflow_gc, deadlock_detect, 0, cap, NULL);
+    GarbageCollect(config, cap, NULL);
 #endif
 
     // If we're shutting down, don't leave any idle GC work to do.
@@ -2770,7 +2785,7 @@ exitScheduler (bool wait_foreign USED_IF_THREADS)
         nonmovingStop();
         Capability *cap = task->cap;
         waitForCapability(&cap,task);
-        scheduleDoGC(&cap,task,true,false,false);
+        scheduleDoGC(&cap,task,true,false,false,true);
         ASSERT(task->incall->tso == NULL);
         releaseCapability(cap);
     }
@@ -2815,7 +2830,7 @@ freeScheduler( void )
    -------------------------------------------------------------------------- */
 
 static void
-performGC_(bool force_major)
+performGC_(bool force_major, bool nonconcurrent)
 {
     Task *task;
     Capability *cap = NULL;
@@ -2828,7 +2843,7 @@ performGC_(bool force_major)
     // TODO: do we need to traceTask*() here?
 
     waitForCapability(&cap,task);
-    scheduleDoGC(&cap,task,force_major,false,false);
+    scheduleDoGC(&cap,task,force_major,false,false,nonconcurrent);
     releaseCapability(cap);
     exitMyTask();
 }
@@ -2836,13 +2851,19 @@ performGC_(bool force_major)
 void
 performGC(void)
 {
-    performGC_(false);
+    performGC_(false, false);
 }
 
 void
 performMajorGC(void)
 {
-    performGC_(true);
+    performGC_(true, false);
+}
+
+void
+performBlockingMajorGC(void)
+{
+    performGC_(true, true);
 }
 
 /* ---------------------------------------------------------------------------


=====================================
rts/include/rts/storage/GC.h
=====================================
@@ -215,6 +215,7 @@ extern W_ large_alloc_lim;
 
 void performGC(void);
 void performMajorGC(void);
+void performBlockingMajorGC(void);
 
 /* -----------------------------------------------------------------------------
    The CAF table - used to let us revert CAFs in GHCi


=====================================
rts/sm/GC.c
=====================================
@@ -278,11 +278,7 @@ addMutListScavStats(const MutListScavStats *src,
    -------------------------------------------------------------------------- */
 
 void
-GarbageCollect (uint32_t collect_gen,
-                const bool do_heap_census,
-                const bool is_overflow_gc,
-                const bool deadlock_detect,
-                uint32_t gc_type USED_IF_THREADS,
+GarbageCollect (struct GcConfig config,
                 Capability *cap,
                 bool idle_cap[])
 {
@@ -298,7 +294,7 @@ GarbageCollect (uint32_t collect_gen,
   // The time we should report our heap census as occurring at, if necessary.
   Time mut_time = 0;
 
-  if (do_heap_census) {
+  if (config.do_heap_census) {
       RTSStats stats;
       getRTSStats(&stats);
       mut_time = stats.mutator_cpu_ns;
@@ -307,6 +303,8 @@ GarbageCollect (uint32_t collect_gen,
   // necessary if we stole a callee-saves register for gct:
 #if defined(THREADED_RTS)
   saved_gct = gct;
+#else
+  ASSERT(!config.parallel);
 #endif
 
 #if defined(PROFILING)
@@ -349,11 +347,11 @@ GarbageCollect (uint32_t collect_gen,
 
   /* Figure out which generation to collect
    */
-  N = collect_gen;
+  N = config.collect_gen;
   major_gc = (N == RtsFlags.GcFlags.generations-1);
 
   /* See Note [Deadlock detection under the nonmoving collector]. */
-  deadlock_detect_gc = deadlock_detect;
+  deadlock_detect_gc = config.deadlock_detect;
 
 #if defined(THREADED_RTS)
   if (major_gc && RtsFlags.GcFlags.useNonmoving && RELAXED_LOAD(&concurrent_coll_running)) {
@@ -362,7 +360,7 @@ GarbageCollect (uint32_t collect_gen,
        * TODO: Catch heap-size runaway.
        */
       N--;
-      collect_gen--;
+      config.collect_gen--;
       major_gc = false;
   }
 #endif
@@ -397,7 +395,7 @@ GarbageCollect (uint32_t collect_gen,
    * we set n_gc_threads, work_stealing, n_gc_idle_threads, gc_running_threads
    * here
   */
-  if (gc_type == SYNC_GC_PAR) {
+  if (config.parallel) {
       n_gc_threads = getNumCapabilities();
       n_gc_idle_threads = 0;
       for (uint32_t i = 0; i < getNumCapabilities(); ++i) {
@@ -858,6 +856,8 @@ GarbageCollect (uint32_t collect_gen,
   // oldest_gen->scavenged_large_objects back to oldest_gen->large_objects.
   ASSERT(oldest_gen->scavenged_large_objects == NULL);
   if (RtsFlags.GcFlags.useNonmoving && major_gc) {
+      bool concurrent = false;
+
       // All threads in non-moving heap should be found to be alive, because
       // threads in the non-moving generation's list should live in the
       // non-moving heap, and we consider non-moving objects alive during
@@ -871,18 +871,21 @@ GarbageCollect (uint32_t collect_gen,
       // old_weak_ptr_list should be empty.
       ASSERT(oldest_gen->old_weak_ptr_list == NULL);
 
+#if defined(THREADED_RTS)
+      concurrent = !config.nonconcurrent;
+#else
+      // In the non-threaded runtime this is the only time we push to the
+      // upd_rem_set
+      nonmovingAddUpdRemSetBlocks(&gct->cap->upd_rem_set);
+#endif
+
       // dead_weak_ptr_list contains weak pointers with dead keys. Those need to
       // be kept alive because we'll use them in finalizeSchedulers(). Similarly
       // resurrected_threads are also going to be used in resurrectedThreads()
       // so we need to mark those too.
       // Note that in sequential case these lists will be appended with more
       // weaks and threads found to be dead in mark.
-#if !defined(THREADED_RTS)
-      // In the non-threaded runtime this is the only time we push to the
-      // upd_rem_set
-      nonmovingAddUpdRemSetBlocks(&gct->cap->upd_rem_set);
-#endif
-      nonmovingCollect(&dead_weak_ptr_list, &resurrected_threads);
+      nonmovingCollect(&dead_weak_ptr_list, &resurrected_threads, concurrent);
   }
 
   // Update the max size of older generations after a major GC:
@@ -963,7 +966,7 @@ GarbageCollect (uint32_t collect_gen,
   // resurrectThreads(), for the same reason as checkSanity above:
   // resurrectThreads() will overwrite some closures and leave slop
   // behind.
-  if (do_heap_census) {
+  if (config.do_heap_census) {
       debugTrace(DEBUG_sched, "performing heap census");
       RELEASE_SM_LOCK;
       heapCensus(mut_time);
@@ -1014,7 +1017,7 @@ GarbageCollect (uint32_t collect_gen,
 #endif
 
       // Reset the counter if the major GC was caused by a heap overflow
-      consec_idle_gcs = is_overflow_gc ? 0 : consec_idle_gcs + 1;
+      consec_idle_gcs = config.overflow_gc ? 0 : consec_idle_gcs + 1;
 
       // See Note [Scaling retained memory]
       double scaled_factor =


=====================================
rts/sm/GC.h
=====================================
@@ -17,11 +17,23 @@
 
 #include "BeginPrivate.h"
 
-void GarbageCollect (uint32_t collect_gen,
-                     bool do_heap_census,
-                     bool is_overflow_gc,
-                     bool deadlock_detect,
-                     uint32_t gc_type,
+struct GcConfig {
+    // which generation are we requesting be collected?
+    uint32_t collect_gen;
+    // is a heap census requested?
+    bool do_heap_census;
+    // is this GC triggered by a heap overflow?
+    bool overflow_gc;
+    // is this GC triggered by a deadlock?
+    bool deadlock_detect;
+    // should we force non-concurrent collection if the non-moving collector is
+    // being used?
+    bool nonconcurrent;
+    // should we use parallel scavenging?
+    bool parallel;
+};
+
+void GarbageCollect (struct GcConfig config,
                      Capability *cap,
                      bool idle_cap[]);
 


=====================================
rts/sm/NonMoving.c
=====================================
@@ -548,7 +548,7 @@ MarkBudget sync_phase_marking_budget = 200000;
 #if defined(THREADED_RTS)
 static void* nonmovingConcurrentMark(void *mark_queue);
 #endif
-static void nonmovingMark_(MarkQueue *mark_queue, StgWeak **dead_weaks, StgTSO **resurrected_threads);
+static void nonmovingMark_(MarkQueue *mark_queue, StgWeak **dead_weaks, StgTSO **resurrected_threads, bool concurrent);
 
 // Add a segment to the free list.
 void nonmovingPushFreeSegment(struct NonmovingSegment *seg)
@@ -712,7 +712,7 @@ static void nonmovingPrepareMark(void)
 #endif
 }
 
-void nonmovingCollect(StgWeak **dead_weaks, StgTSO **resurrected_threads)
+void nonmovingCollect(StgWeak **dead_weaks, StgTSO **resurrected_threads, bool concurrent STG_UNUSED)
 {
 #if defined(THREADED_RTS)
     // We can't start a new collection until the old one has finished
@@ -799,7 +799,7 @@ void nonmovingCollect(StgWeak **dead_weaks, StgTSO **resurrected_threads)
     }
     trace(TRACE_nonmoving_gc, "Finished nonmoving GC preparation");
 
-    // We are now safe to start concurrent marking
+    // We are now safe to start (possibly concurrent) marking
 
     // Note that in concurrent mark we can't use dead_weaks and
     // resurrected_threads from the preparation to add new weaks and threads as
@@ -807,13 +807,17 @@ void nonmovingCollect(StgWeak **dead_weaks, StgTSO **resurrected_threads)
     // those lists to mark function in sequential case. In concurrent case we
     // allocate fresh lists.
 
-#if defined(THREADED_RTS)
     // If we're interrupting or shutting down, do not let this capability go and
     // run a STW collection. Reason: we won't be able to acquire this capability
     // again for the sync if we let it go, because it'll immediately start doing
     // a major GC, because that's what we do when exiting scheduler (see
     // exitScheduler()).
-    if (getSchedState() == SCHED_RUNNING) {
+    if (getSchedState() != SCHED_RUNNING) {
+        concurrent = false;
+    }
+
+#if defined(THREADED_RTS)
+    if (concurrent) {
         RELAXED_STORE(&concurrent_coll_running, true);
         nonmoving_write_barrier_enabled = true;
         debugTrace(DEBUG_nonmoving_gc, "Starting concurrent mark thread");
@@ -823,14 +827,19 @@ void nonmovingCollect(StgWeak **dead_weaks, StgTSO **resurrected_threads)
             barf("nonmovingCollect: failed to spawn mark thread: %s", strerror(errno));
         }
         RELAXED_STORE(&mark_thread, thread);
+        return;
     } else {
-        nonmovingConcurrentMark(mark_queue);
+        RELEASE_SM_LOCK;
     }
-#else
+#endif
+
     // Use the weak and thread lists from the preparation for any new weaks and
     // threads found to be dead in mark.
-    nonmovingMark_(mark_queue, dead_weaks, resurrected_threads);
-#endif
+    nonmovingMark_(mark_queue, dead_weaks, resurrected_threads, false);
+
+    if (!concurrent) {
+        ACQUIRE_SM_LOCK;
+    }
 }
 
 /* Mark queue, threads, and weak pointers until no more weaks have been
@@ -862,7 +871,7 @@ static void* nonmovingConcurrentMark(void *data)
     MarkQueue *mark_queue = (MarkQueue*)data;
     StgWeak *dead_weaks = NULL;
     StgTSO *resurrected_threads = (StgTSO*)&stg_END_TSO_QUEUE_closure;
-    nonmovingMark_(mark_queue, &dead_weaks, &resurrected_threads);
+    nonmovingMark_(mark_queue, &dead_weaks, &resurrected_threads, true);
     return NULL;
 }
 
@@ -876,8 +885,11 @@ static void appendWeakList( StgWeak **w1, StgWeak *w2 )
 }
 #endif
 
-static void nonmovingMark_(MarkQueue *mark_queue, StgWeak **dead_weaks, StgTSO **resurrected_threads)
+static void nonmovingMark_(MarkQueue *mark_queue, StgWeak **dead_weaks, StgTSO **resurrected_threads, bool concurrent)
 {
+#if !defined(THREADED_RTS)
+    ASSERT(!concurrent);
+#endif
     ACQUIRE_LOCK(&nonmoving_collection_mutex);
     debugTrace(DEBUG_nonmoving_gc, "Starting mark...");
     stat_startNonmovingGc();
@@ -920,38 +932,41 @@ concurrent_marking:
     }
 
 #if defined(THREADED_RTS)
-    Task *task = newBoundTask();
-
-    // If at this point if we've decided to exit then just return
-    if (getSchedState() > SCHED_RUNNING) {
-        // Note that we break our invariants here and leave segments in
-        // nonmovingHeap.sweep_list, don't free nonmoving_large_objects etc.
-        // However because we won't be running sweep in the final GC this
-        // is OK.
-        //
-        // However, we must move any weak pointers remaining on
-        // nonmoving_old_weak_ptr_list back to nonmoving_weak_ptr_list
-        // such that their C finalizers can be run by hs_exit_.
-        appendWeakList(&nonmoving_weak_ptr_list, nonmoving_old_weak_ptr_list);
-        goto finish;
-    }
-
-    // We're still running, request a sync
-    nonmovingBeginFlush(task);
-
-    bool all_caps_syncd;
-    MarkBudget sync_marking_budget = sync_phase_marking_budget;
-    do {
-        all_caps_syncd = nonmovingWaitForFlush();
-        if (nonmovingMarkThreadsWeaks(&sync_marking_budget, mark_queue) == false) {
-            // We ran out of budget for marking. Abort sync.
-            // See Note [Sync phase marking budget].
-            traceConcSyncEnd();
-            stat_endNonmovingGcSync();
-            releaseAllCapabilities(n_capabilities, NULL, task);
-            goto concurrent_marking;
+    Task *task = NULL;
+    if (concurrent) {
+        task = newBoundTask();
+
+        // If at this point if we've decided to exit then just return
+        if (getSchedState() > SCHED_RUNNING) {
+            // Note that we break our invariants here and leave segments in
+            // nonmovingHeap.sweep_list, don't free nonmoving_large_objects etc.
+            // However because we won't be running sweep in the final GC this
+            // is OK.
+            //
+            // However, we must move any weak pointers remaining on
+            // nonmoving_old_weak_ptr_list back to nonmoving_weak_ptr_list
+            // such that their C finalizers can be run by hs_exit_.
+            appendWeakList(&nonmoving_weak_ptr_list, nonmoving_old_weak_ptr_list);
+            goto finish;
         }
-    } while (!all_caps_syncd);
+
+        // We're still running, request a sync
+        nonmovingBeginFlush(task);
+
+        bool all_caps_syncd;
+        MarkBudget sync_marking_budget = sync_phase_marking_budget;
+        do {
+            all_caps_syncd = nonmovingWaitForFlush();
+            if (nonmovingMarkThreadsWeaks(&sync_marking_budget, mark_queue) == false) {
+                // We ran out of budget for marking. Abort sync.
+                // See Note [Sync phase marking budget].
+                traceConcSyncEnd();
+                stat_endNonmovingGcSync();
+                releaseAllCapabilities(n_capabilities, NULL, task);
+                goto concurrent_marking;
+            }
+        } while (!all_caps_syncd);
+    }
 #endif
 
     nonmovingResurrectThreads(mark_queue, resurrected_threads);
@@ -981,15 +996,15 @@ concurrent_marking:
 
 
     // Schedule finalizers and resurrect threads
-#if defined(THREADED_RTS)
-    // Just pick a random capability. Not sure if this is a good idea -- we use
-    // only one capability for all finalizers.
-    scheduleFinalizers(getCapability(0), *dead_weaks);
-    // Note that this mutates heap and causes running write barriers.
-    // See Note [Unintentional marking in resurrectThreads] in NonMovingMark.c
-    // for how we deal with this.
-    resurrectThreads(*resurrected_threads);
-#endif
+    if (concurrent) {
+        // Just pick a random capability. Not sure if this is a good idea -- we use
+        // only one capability for all finalizers.
+        scheduleFinalizers(getCapability(0), *dead_weaks);
+        // Note that this mutates heap and causes running write barriers.
+        // See Note [Unintentional marking in resurrectThreads] in NonMovingMark.c
+        // for how we deal with this.
+        resurrectThreads(*resurrected_threads);
+    }
 
 #if defined(DEBUG)
     // Zap CAFs that we will sweep
@@ -1019,15 +1034,19 @@ concurrent_marking:
     // Prune spark lists
     // See Note [Spark management under the nonmoving collector].
 #if defined(THREADED_RTS)
-    for (uint32_t n = 0; n < getNumCapabilities(); n++) {
-        pruneSparkQueue(true, getCapability(n));
+    if (concurrent) {
+        for (uint32_t n = 0; n < getNumCapabilities(); n++) {
+            pruneSparkQueue(true, getCapability(n));
+        }
     }
-#endif
 
     // Everything has been marked; allow the mutators to proceed
-#if defined(THREADED_RTS) && !defined(NONCONCURRENT_SWEEP)
-    nonmoving_write_barrier_enabled = false;
-    nonmovingFinishFlush(task);
+#if !defined(NONCONCURRENT_SWEEP)
+    if (concurrent) {
+        nonmoving_write_barrier_enabled = false;
+        nonmovingFinishFlush(task);
+    }
+#endif
 #endif
 
     current_mark_queue = NULL;
@@ -1064,24 +1083,28 @@ concurrent_marking:
         nonmovingTraceAllocatorCensus();
 #endif
 
-#if defined(THREADED_RTS) && defined(NONCONCURRENT_SWEEP)
+#if defined(NONCONCURRENT_SWEEP)
 #if defined(DEBUG)
     checkNonmovingHeap(&nonmovingHeap);
     checkSanity(true, true);
 #endif
-    nonmoving_write_barrier_enabled = false;
-    nonmovingFinishFlush(task);
+    if (concurrent) {
+        nonmoving_write_barrier_enabled = false;
+        nonmovingFinishFlush(task);
+    }
 #endif
 
     // TODO: Remainder of things done by GarbageCollect (update stats)
 
 #if defined(THREADED_RTS)
 finish:
-    exitMyTask();
+    if (concurrent) {
+        exitMyTask();
 
-    // We are done...
-    RELAXED_STORE(&mark_thread, 0);
-    stat_endNonmovingGc();
+        // We are done...
+        RELAXED_STORE(&mark_thread, 0);
+        stat_endNonmovingGc();
+    }
 
     // Signal that the concurrent collection is finished, allowing the next
     // non-moving collection to proceed


=====================================
rts/sm/NonMoving.h
=====================================
@@ -149,7 +149,8 @@ void nonmovingExit(void);
 //   directly, but in a pause.
 //
 void nonmovingCollect(StgWeak **dead_weaks,
-                       StgTSO **resurrected_threads);
+                      StgTSO **resurrected_threads,
+                      bool concurrent);
 
 void nonmovingPushFreeSegment(struct NonmovingSegment *seg);
 
@@ -361,9 +362,9 @@ void print_thread_list(StgTSO* tso);
 
 #endif
 
-RTS_PRIVATE void clear_segment(struct NonmovingSegment*);
+RTS_PRIVATE void nonmovingClearSegment(struct NonmovingSegment*);
 
-RTS_PRIVATE void clear_segment_free_blocks(struct NonmovingSegment*);
+RTS_PRIVATE void nonmovingClearSegmentFreeBlocks(struct NonmovingSegment*);
 
 #include "EndPrivate.h"
 


=====================================
rts/sm/NonMovingMark.c
=====================================
@@ -27,8 +27,10 @@
 #include "sm/Storage.h"
 #include "CNF.h"
 
+#if defined(THREADED_RTS)
 static void nonmovingResetUpdRemSetQueue (MarkQueue *rset);
 static void nonmovingResetUpdRemSet (UpdRemSet *rset);
+#endif
 static bool check_in_nonmoving_heap(StgClosure *p);
 static void mark_closure (MarkQueue *queue, const StgClosure *p, StgClosure **origin);
 static void trace_tso (MarkQueue *queue, StgTSO *tso);
@@ -955,6 +957,7 @@ void nonmovingInitUpdRemSet (UpdRemSet *rset)
     rset->queue.is_upd_rem_set = true;
 }
 
+#if defined(THREADED_RTS)
 static void nonmovingResetUpdRemSetQueue (MarkQueue *rset)
 {
     // UpdRemSets always have one block for the mark queue. This assertion is to
@@ -968,6 +971,7 @@ void nonmovingResetUpdRemSet (UpdRemSet *rset)
 {
     nonmovingResetUpdRemSetQueue(&rset->queue);
 }
+#endif
 
 void freeMarkQueue (MarkQueue *queue)
 {


=====================================
rts/sm/NonMovingSweep.c
=====================================
@@ -110,14 +110,14 @@ void nonmovingGcCafs()
 #endif
 
 void
-clear_segment(struct NonmovingSegment* seg)
+nonmovingClearSegment(struct NonmovingSegment* seg)
 {
     size_t end = ((size_t)seg) + NONMOVING_SEGMENT_SIZE;
     memset(&seg->bitmap, 0, end - (size_t)&seg->bitmap);
 }
 
 void
-clear_segment_free_blocks(struct NonmovingSegment* seg)
+nonmovingClearSegmentFreeBlocks(struct NonmovingSegment* seg)
 {
     unsigned int block_size = nonmovingSegmentBlockSize(seg);
     for (unsigned int p_idx = 0; p_idx < nonmovingSegmentBlockCount(seg); ++p_idx) {
@@ -142,11 +142,11 @@ GNUC_ATTR_HOT void nonmovingSweep(void)
 
         switch (ret) {
         case SEGMENT_FREE:
-            IF_DEBUG(sanity, clear_segment(seg));
+            IF_DEBUG(sanity, nonmovingClearSegment(seg));
             nonmovingPushFreeSegment(seg);
             break;
         case SEGMENT_PARTIAL:
-            IF_DEBUG(sanity, clear_segment_free_blocks(seg));
+            IF_DEBUG(sanity, nonmovingClearSegmentFreeBlocks(seg));
             nonmovingPushActiveSegment(seg);
             break;
         case SEGMENT_FILLED:


=====================================
rts/sm/Storage.c
=====================================
@@ -1942,19 +1942,19 @@ void rts_clearMemory(void) {
     if (RtsFlags.GcFlags.useNonmoving)
     {
         for (struct NonmovingSegment *seg = nonmovingHeap.free; seg; seg = seg->link) {
-            clear_segment(seg);
+            nonmovingClearSegment(seg);
         }
 
         for (int i = 0; i < NONMOVING_ALLOCA_CNT; ++i) {
             struct NonmovingAllocator *alloc = &nonmovingHeap.allocators[i];
 
             for (struct NonmovingSegment *seg = alloc->active; seg; seg = seg->link) {
-                clear_segment_free_blocks(seg);
+                nonmovingClearSegmentFreeBlocks(seg);
             }
 
             for (unsigned int j = 0; j < getNumCapabilities(); ++j) {
                 Capability *cap = getCapability(j);
-                clear_segment_free_blocks(cap->current_segments[i]);
+                nonmovingClearSegmentFreeBlocks(cap->current_segments[i]);
             }
         }
     }


=====================================
rts/sm/Storage.h
=====================================
@@ -215,7 +215,7 @@ extern StgIndStatic * dyn_caf_list;
 extern StgIndStatic * debug_caf_list;
 extern StgIndStatic * revertible_caf_list;
 
-STATIC_INLINE void clear_blocks(bdescr *bd) {
+INLINE_HEADER void clear_blocks(bdescr *bd) {
    memset(bd->start, 0, BLOCK_SIZE * bd->blocks);
 }
 


=====================================
testsuite/tests/ffi/should_run/all.T
=====================================
@@ -191,6 +191,7 @@ test('T8083', [omit_ways(['ghci']), req_c], compile_and_run, ['T8083_c.c'])
 test('T9274', [omit_ways(['ghci'])], compile_and_run, [''])
 
 test('ffi023', [ omit_ways(['ghci']),
+                expect_broken_for(23089, ['threaded2', 'nonmoving_thr', 'nonmoving_thr_sanity', 'nonmoving_thr_ghc']),
                 extra_run_opts('1000 4'),
                 js_broken(22363),
                 pre_cmd('$MAKE -s --no-print-directory ffi023_setup') ],


=====================================
testsuite/tests/ffi/should_run/ffi023_c.c
=====================================
@@ -4,7 +4,7 @@
 
 HsInt out (HsInt x)
 {
-    performMajorGC();
+    performBlockingMajorGC();
     rts_clearMemory();
     return incall(x);
 }


=====================================
testsuite/tests/rts/all.T
=====================================
@@ -261,8 +261,8 @@ test('T6006', [ omit_ways(prof_ways + ['ghci']),
 test('T7037', req_c, makefile_test, ['T7037'])
 
 test('T7087', exit_code(1), compile_and_run, [''])
-test('T7160', [ # finalization order is too nondeterministic in the concurrent GC
-                omit_ways(['nonmoving_thr', 'nonmoving_thr_ghc', 'nonmoving_thr_sanity'])
+test('T7160', [ # finalization order is different in the nonmoving
+                omit_ways(['nonmoving', 'nonmoving_thr', 'nonmoving_thr_ghc', 'nonmoving_thr_sanity'])
               , js_broken(22261)
               ], compile_and_run, [''])
 
@@ -570,6 +570,6 @@ test('decodeMyStack_emptyListForMissingFlag',
   ], compile_and_run, [''])
 
 # Skip for JS platform as the JS RTS is always single threaded
-test('T22795a', [js_skip], compile_and_run, ['-threaded'])
-test('T22795b', [js_skip], compile_and_run, ['-single-threaded'])
-test('T22795c', [js_skip], compile_and_run, ['-threaded -single-threaded'])
+test('T22795a', [only_ways(['normal']), js_skip], compile_and_run, ['-threaded'])
+test('T22795b', [only_ways(['normal']), js_skip], compile_and_run, ['-single-threaded'])
+test('T22795c', [only_ways(['normal']), js_skip], compile_and_run, ['-threaded -single-threaded'])



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/cfc68b5c9ee9000010ccb2b7f1d346542df3b79f...6cb91e16d661f9ef755c5fc399cf90b82368b43b

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/cfc68b5c9ee9000010ccb2b7f1d346542df3b79f...6cb91e16d661f9ef755c5fc399cf90b82368b43b
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20230307/c4b3b361/attachment-0001.html>


More information about the ghc-commits mailing list