summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarel Gardas <karel.gardas@centrum.cz>2015-02-14 22:46:47 +0100
committerKarel Gardas <karel.gardas@centrum.cz>2015-02-23 10:27:37 +0100
commitb2be772a97f6e7fe9f1d1c28108949f81a13158b (patch)
tree86ab34834027222796365549d46a5e818eea4a4b
parent1f60d635cee1ff3db72e0129f9035b147f52c9c4 (diff)
downloadhaskell-b2be772a97f6e7fe9f1d1c28108949f81a13158b.tar.gz
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
-rw-r--r--includes/rts/storage/TSO.h3
-rw-r--r--rts/Schedule.c6
-rw-r--r--rts/Threads.c6
-rw-r--r--rts/sm/Storage.c10
4 files changed, 17 insertions, 8 deletions
diff --git a/includes/rts/storage/TSO.h b/includes/rts/storage/TSO.h
index 06056fe716..744ab2b519 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 f25b37288d..957aa4b9cb 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 90efd9ce4e..99f2be7304 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 f02c00591c..50926b70b3 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;