From ab5aad587de8e3d9dde539982ae728b33e5bca50 Mon Sep 17 00:00:00 2001
From: Simon Marlow <marlowsd@gmail.com>
Date: Mon, 6 Jun 2011 04:52:27 +0100
Subject: [PATCH] fix an interaction between the new pinned_object_block policy
 and globalisation.

---
 rts/sm/Globalise.c | 15 ++++++++++++++-
 rts/sm/Storage.c   | 12 ++++++++----
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/rts/sm/Globalise.c b/rts/sm/Globalise.c
index ff9db7b19819..831d45e80b50 100644
--- a/rts/sm/Globalise.c
+++ b/rts/sm/Globalise.c
@@ -217,7 +217,20 @@ globalise_large (StgPtr p)
 
     ACQUIRE_SPIN_LOCK(&gen->sync);
 
-    // remove from large_object list 
+    // the object we need to globalise might be in the
+    // pinned_object_block, which is still being allocated into.  In
+    // that case, we just mark the pinned_object_block with the global
+    // generation, and allocatePinned() will attach the block to the
+    // correct gen->large_objects list when it is full.
+    if (bd == gct->cap->pinned_object_block) {
+        new_gen = &all_generations[global_gen_ix];
+        initBdescr(bd, new_gen, new_gen->to);
+
+        RELEASE_SPIN_LOCK(&gen->sync);
+        return;
+    }
+
+    // remove from large_object list
     if (bd->u.back) {
         bd->u.back->link = bd->link;
     } else { // first object in the list 
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c
index 3a8c0fa84a27..eaffdc6dd99f 100644
--- a/rts/sm/Storage.c
+++ b/rts/sm/Storage.c
@@ -778,16 +778,20 @@ allocatePinned (Capability *cap, lnat n)
         // the next GC the BF_EVACUATED flag will be cleared, and the
         // block will be promoted as usual (if anything in it is
         // live).
-        ACQUIRE_SM_LOCK;
-        gen = cap->r.rG0; // use our local G0
         if (bd != NULL) {
+            gen = bd->gen;
+            // attach it to the correct generation - the block might
+            // have been globalised by now (see globalise_large()).
+            if (gen->no != 0) { ACQUIRE_SPIN_LOCK(&gen->sync); }
             dbl_link_onto(bd, &gen->large_objects);
             gen->n_large_blocks++;
-            g0->n_new_large_words += bd->free - bd->start;
+            gen->n_new_large_words += bd->free - bd->start;
+            if (gen->no != 0) { RELEASE_SPIN_LOCK(&gen->sync); }
         }
+        ACQUIRE_SM_LOCK;
         cap->pinned_object_block = bd = allocBlock();
         RELEASE_SM_LOCK;
-        initBdescr(bd, gen, gen);
+        initBdescr(bd, cap->r.rG0, cap->r.rG0);  // use our local G0
         bd->flags  = BF_PINNED | BF_LARGE | BF_EVACUATED;
         bd->free   = bd->start;
     }
-- 
GitLab