summaryrefslogtreecommitdiff
path: root/rts/sm/Storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'rts/sm/Storage.c')
-rw-r--r--rts/sm/Storage.c76
1 files changed, 58 insertions, 18 deletions
diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c
index 7174425e04..e4a6984c40 100644
--- a/rts/sm/Storage.c
+++ b/rts/sm/Storage.c
@@ -532,6 +532,7 @@ assignNurseriesToCapabilities (nat from, nat to)
for (i = from; i < to; i++) {
capabilities[i]->r.rCurrentNursery = nurseries[i].blocks;
+ newNurseryBlock(nurseries[i].blocks);
capabilities[i]->r.rCurrentAlloc = NULL;
}
}
@@ -551,17 +552,16 @@ allocNurseries (nat from, nat to)
}
void
-clearNursery (Capability *cap)
+clearNursery (Capability *cap USED_IF_DEBUG)
{
+#ifdef DEBUG
bdescr *bd;
-
for (bd = nurseries[cap->no].blocks; bd; bd = bd->link) {
- cap->total_allocated += (W_)(bd->free - bd->start);
- bd->free = bd->start;
ASSERT(bd->gen_no == 0);
ASSERT(bd->gen == g0);
- IF_DEBUG(sanity,memset(bd->start, 0xaa, BLOCK_SIZE));
+ IF_DEBUG(sanity, memset(bd->start, 0xaa, BLOCK_SIZE));
}
+#endif
}
void
@@ -734,14 +734,16 @@ StgPtr allocate (Capability *cap, W_ n)
bd = cap->r.rCurrentAlloc;
if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) {
+ if (bd) finishedNurseryBlock(cap,bd);
+
// The CurrentAlloc block is full, we need to find another
// one. First, we try taking the next block from the
// nursery:
bd = cap->r.rCurrentNursery->link;
- if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) {
- // The nursery is empty, or the next block is already
- // full: allocate a fresh block (we can't fail here).
+ if (bd == NULL) {
+ // The nursery is empty: allocate a fresh block (we can't
+ // fail here).
ACQUIRE_SM_LOCK;
bd = allocBlock();
cap->r.rNursery->n_blocks++;
@@ -752,6 +754,7 @@ StgPtr allocate (Capability *cap, W_ n)
// pretty quickly now, because MAYBE_GC() will
// notice that CurrentNursery->link is NULL.
} else {
+ newNurseryBlock(bd);
// we have a block in the nursery: take it and put
// it at the *front* of the nursery list, and use it
// to allocate() from.
@@ -846,9 +849,9 @@ allocatePinned (Capability *cap, W_ n)
// next GC cycle these objects will be moved to
// g0->large_objects.
if (bd != NULL) {
- dbl_link_onto(bd, &cap->pinned_object_blocks);
// add it to the allocation stats when the block is full
- cap->total_allocated += bd->free - bd->start;
+ finishedNurseryBlock(cap, bd);
+ dbl_link_onto(bd, &cap->pinned_object_blocks);
}
// We need to find another block. We could just allocate one,
@@ -861,7 +864,7 @@ allocatePinned (Capability *cap, W_ n)
// an *empty* block, because we're about to mark it as
// BF_PINNED | BF_LARGE.
bd = cap->r.rCurrentNursery->link;
- if (bd == NULL || bd->free != bd->start) { // must be empty!
+ if (bd == NULL) { // must be empty!
// The nursery is empty, or the next block is non-empty:
// allocate a fresh block (we can't fail here).
@@ -878,6 +881,7 @@ allocatePinned (Capability *cap, W_ n)
RELEASE_SM_LOCK;
initBdescr(bd, g0, g0);
} else {
+ newNurseryBlock(bd);
// we have a block in the nursery: steal it
cap->r.rCurrentNursery->link = bd->link;
if (bd->link != NULL) {
@@ -1001,21 +1005,57 @@ dirty_MVAR(StgRegTable *reg, StgClosure *p)
* -------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
- * updateNurseriesStats()
+ * [Note allocation accounting]
*
- * Update the per-cap total_allocated numbers with an approximation of
- * the amount of memory used in each cap's nursery.
+ * - When cap->r.rCurrentNusery moves to a new block in the nursery,
+ * we add the size of the used portion of the previous block to
+ * cap->total_allocated. (see finishedNurseryBlock())
+ *
+ * - When we start a GC, the allocated portion of CurrentNursery and
+ * CurrentAlloc are added to cap->total_allocated. (see
+ * updateNurseriesStats())
*
- * Since this update is also performed by clearNurseries() then we only
- * need this function for the final stats when the RTS is shutting down.
* -------------------------------------------------------------------------- */
-void updateNurseriesStats (void)
+//
+// Calculate the total allocated memory since the start of the
+// program. Also emits events reporting the per-cap allocation
+// totals.
+//
+StgWord
+calcTotalAllocated (void)
+{
+ W_ tot_alloc = 0;
+ W_ n;
+
+ for (n = 0; n < n_capabilities; n++) {
+ tot_alloc += capabilities[n]->total_allocated;
+
+ traceEventHeapAllocated(capabilities[n],
+ CAPSET_HEAP_DEFAULT,
+ capabilities[n]->total_allocated * sizeof(W_));
+ }
+
+ return tot_alloc;
+}
+
+//
+// Update the per-cap total_allocated numbers with an approximation of
+// the amount of memory used in each cap's nursery.
+//
+void
+updateNurseriesStats (void)
{
nat i;
+ bdescr *bd;
for (i = 0; i < n_capabilities; i++) {
- capabilities[i]->total_allocated += countOccupied(nurseries[i].blocks);
+ // The current nursery block and the current allocate block have not
+ // yet been accounted for in cap->total_allocated, so we add them here.
+ bd = capabilities[i]->r.rCurrentNursery;
+ if (bd) finishedNurseryBlock(capabilities[i], bd);
+ bd = capabilities[i]->r.rCurrentAlloc;
+ if (bd) finishedNurseryBlock(capabilities[i], bd);
}
}