[commit: ghc] master: fix bus errors on SPARC caused by unalignment access to alloc_limit (fixes #10043) (b2be772)

git at git.haskell.org git at git.haskell.org
Mon Feb 23 09:25:50 UTC 2015


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/b2be772a97f6e7fe9f1d1c28108949f81a13158b/ghc

>---------------------------------------------------------------

commit b2be772a97f6e7fe9f1d1c28108949f81a13158b
Author: Karel Gardas <karel.gardas at centrum.cz>
Date:   Sat Feb 14 22:46:47 2015 +0100

    fix bus errors on SPARC caused by unalignment access to alloc_limit (fixes #10043)
    
    Reviewers: austin, simonmar
    
    Subscribers: thomie
    
    Differential Revision: https://phabricator.haskell.org/D657


>---------------------------------------------------------------

b2be772a97f6e7fe9f1d1c28108949f81a13158b
 includes/rts/storage/TSO.h |  3 +++
 rts/Schedule.c             |  6 +++---
 rts/Threads.c              |  6 +++---
 rts/sm/Storage.c           | 10 ++++++++--
 4 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/includes/rts/storage/TSO.h b/includes/rts/storage/TSO.h
index 06056fe..744ab2b 100644
--- a/includes/rts/storage/TSO.h
+++ b/includes/rts/storage/TSO.h
@@ -155,6 +155,9 @@ typedef struct StgTSO_ {
      * This is an integer, because we might update it in a place where
      * it isn't convenient to raise the exception, so we want it to
      * stay negative until we get around to checking it.
+     *
+     * Use only PK_Int64/ASSIGN_Int64 macros to get/set the value of alloc_limit
+     * in C code otherwise you will cause alignment issues on SPARC
      */
     StgInt64  alloc_limit;     /* in bytes */
 
diff --git a/rts/Schedule.c b/rts/Schedule.c
index f25b372..957aa4b 100644
--- a/rts/Schedule.c
+++ b/rts/Schedule.c
@@ -1086,15 +1086,15 @@ schedulePostRunThread (Capability *cap, StgTSO *t)
     // If the current thread's allocation limit has run out, send it
     // the AllocationLimitExceeded exception.
 
-    if (t->alloc_limit < 0 && (t->flags & TSO_ALLOC_LIMIT)) {
+    if (PK_Int64((W_*)&(t->alloc_limit)) < 0 && (t->flags & TSO_ALLOC_LIMIT)) {
         // Use a throwToSelf rather than a throwToSingleThreaded, because
         // it correctly handles the case where the thread is currently
         // inside mask.  Also the thread might be blocked (e.g. on an
         // MVar), and throwToSingleThreaded doesn't unblock it
         // correctly in that case.
         throwToSelf(cap, t, allocationLimitExceeded_closure);
-        t->alloc_limit = (StgInt64)RtsFlags.GcFlags.allocLimitGrace
-            * BLOCK_SIZE;
+        ASSIGN_Int64((W_*)&(t->alloc_limit),
+                     (StgInt64)RtsFlags.GcFlags.allocLimitGrace * BLOCK_SIZE);
     }
 
   /* some statistics gathering in the parallel case */
diff --git a/rts/Threads.c b/rts/Threads.c
index 90efd9c..99f2be7 100644
--- a/rts/Threads.c
+++ b/rts/Threads.c
@@ -110,7 +110,7 @@ createThread(Capability *cap, W_ size)
     tso->stackobj       = stack;
     tso->tot_stack_size = stack->stack_size;
 
-    tso->alloc_limit = 0;
+    ASSIGN_Int64((W_*)&(tso->alloc_limit), 0);
 
     tso->trec = NO_TREC;
 
@@ -173,12 +173,12 @@ HsInt64 rts_getThreadAllocationCounter(StgPtr tso)
 {
     // NB. doesn't take into account allocation in the current nursery
     // block, so it might be off by up to 4k.
-    return ((StgTSO *)tso)->alloc_limit;
+    return PK_Int64((W_*)&(((StgTSO *)tso)->alloc_limit));
 }
 
 void rts_setThreadAllocationCounter(StgPtr tso, HsInt64 i)
 {
-    ((StgTSO *)tso)->alloc_limit = i;
+    ASSIGN_Int64((W_*)&(((StgTSO *)tso)->alloc_limit), i);
 }
 
 void rts_enableThreadAllocationLimit(StgPtr tso)
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c
index f02c005..50926b7 100644
--- a/rts/sm/Storage.c
+++ b/rts/sm/Storage.c
@@ -746,7 +746,10 @@ StgPtr allocate (Capability *cap, W_ n)
     TICK_ALLOC_HEAP_NOCTR(WDS(n));
     CCS_ALLOC(cap->r.rCCCS,n);
     if (cap->r.rCurrentTSO != NULL) {
-        cap->r.rCurrentTSO->alloc_limit -= n*sizeof(W_);
+        // cap->r.rCurrentTSO->alloc_limit -= n*sizeof(W_)
+        ASSIGN_Int64((W_*)&(cap->r.rCurrentTSO->alloc_limit),
+                     (PK_Int64((W_*)&(cap->r.rCurrentTSO->alloc_limit))
+                      - n*sizeof(W_)));
     }
 
     if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
@@ -897,7 +900,10 @@ allocatePinned (Capability *cap, W_ n)
     TICK_ALLOC_HEAP_NOCTR(WDS(n));
     CCS_ALLOC(cap->r.rCCCS,n);
     if (cap->r.rCurrentTSO != NULL) {
-        cap->r.rCurrentTSO->alloc_limit -= n*sizeof(W_);
+        // cap->r.rCurrentTSO->alloc_limit -= n*sizeof(W_);
+        ASSIGN_Int64((W_*)&(cap->r.rCurrentTSO->alloc_limit),
+                     (PK_Int64((W_*)&(cap->r.rCurrentTSO->alloc_limit))
+                      - n*sizeof(W_)));
     }
 
     bd = cap->pinned_object_block;



More information about the ghc-commits mailing list