#include "PosixSource.h"
#include "Rts.h"
-#include "RtsFlags.h"
+
+#include "Storage.h"
#include "RtsUtils.h"
#include "BlockAlloc.h"
-#include "MBlock.h"
-#include "Storage.h"
#include <string.h>
{
// we take our chunk off the end here.
nat best_mblocks = BLOCKS_TO_MBLOCKS(best->blocks);
- bd = FIRST_BDESCR(MBLOCK_ROUND_DOWN(best) +
+ bd = FIRST_BDESCR((StgWord8*)MBLOCK_ROUND_DOWN(best) +
(best_mblocks-mblocks)*MBLOCK_SIZE);
best->blocks = MBLOCK_GROUP_BLOCKS(best_mblocks - mblocks);
ln = log_2_ceil(n);
- while (free_list[ln] == NULL && ln < MAX_FREE_LIST) {
+ while (ln < MAX_FREE_LIST && free_list[ln] == NULL) {
ln++;
}
q = p->link;
if (q != NULL &&
MBLOCK_ROUND_DOWN(q) ==
- MBLOCK_ROUND_DOWN(p) + BLOCKS_TO_MBLOCKS(p->blocks) * MBLOCK_SIZE) {
+ (StgWord8*)MBLOCK_ROUND_DOWN(p) +
+ BLOCKS_TO_MBLOCKS(p->blocks) * MBLOCK_SIZE) {
// can coalesce
p->blocks = MBLOCK_GROUP_BLOCKS(BLOCKS_TO_MBLOCKS(p->blocks) +
BLOCKS_TO_MBLOCKS(q->blocks));
RELEASE_SM_LOCK;
}
+// splitBlockGroup(bd,B) splits bd in two. Afterward, bd will have B
+// blocks, and a new block descriptor pointing to the remainder is
+// returned.
bdescr *
splitBlockGroup (bdescr *bd, nat blocks)
{
}
if (bd->blocks > BLOCKS_PER_MBLOCK) {
- nat mblocks;
+ nat low_mblocks, high_mblocks;
void *new_mblock;
if ((blocks - BLOCKS_PER_MBLOCK) % (MBLOCK_SIZE / BLOCK_SIZE) != 0) {
barf("splitLargeBlock: not a multiple of a megablock");
}
- mblocks = 1 + (blocks - BLOCKS_PER_MBLOCK) / (MBLOCK_SIZE / BLOCK_SIZE);
- new_mblock = (void *) ((P_)MBLOCK_ROUND_DOWN(bd) + mblocks * MBLOCK_SIZE_W);
+ low_mblocks = 1 + (blocks - BLOCKS_PER_MBLOCK) / (MBLOCK_SIZE / BLOCK_SIZE);
+ high_mblocks = (bd->blocks - blocks) / (MBLOCK_SIZE / BLOCK_SIZE);
+
+ new_mblock = (void *) ((P_)MBLOCK_ROUND_DOWN(bd) + low_mblocks * MBLOCK_SIZE_W);
initMBlock(new_mblock);
new_bd = FIRST_BDESCR(new_mblock);
- new_bd->blocks = MBLOCK_GROUP_BLOCKS(mblocks);
+ new_bd->blocks = MBLOCK_GROUP_BLOCKS(high_mblocks);
+
+ ASSERT(blocks + new_bd->blocks ==
+ bd->blocks + BLOCKS_PER_MBLOCK - MBLOCK_SIZE/BLOCK_SIZE);
}
else
{
static void
initMBlock(void *mblock)
{
- bdescr *bd;
- void *block;
-
- /* the first few Bdescr's in a block are unused, so we don't want to
- * put them all on the free list.
- */
- block = FIRST_BLOCK(mblock);
- bd = FIRST_BDESCR(mblock);
-
- /* Initialise the start field of each block descriptor
- */
- for (; block <= LAST_BLOCK(mblock); bd += 1, block += BLOCK_SIZE) {
- bd->start = block;
- }
+ bdescr *bd;
+ StgWord8 *block;
+
+ /* the first few Bdescr's in a block are unused, so we don't want to
+ * put them all on the free list.
+ */
+ block = FIRST_BLOCK(mblock);
+ bd = FIRST_BDESCR(mblock);
+
+ /* Initialise the start field of each block descriptor
+ */
+ for (; block <= (StgWord8*)LAST_BLOCK(mblock); bd += 1,
+ block += BLOCK_SIZE) {
+ bd->start = (void*)block;
+ }
}
/* -----------------------------------------------------------------------------
if (bd->link != NULL)
{
ASSERT (MBLOCK_ROUND_DOWN(bd->link) !=
- MBLOCK_ROUND_DOWN(bd) +
+ (StgWord8*)MBLOCK_ROUND_DOWN(bd) +
BLOCKS_TO_MBLOCKS(bd->blocks) * MBLOCK_SIZE);
}
}
}
return total_blocks;
}
+
+void
+markBlocks (bdescr *bd)
+{
+ for (; bd != NULL; bd = bd->link) {
+ bd->flags |= BF_KNOWN;
+ }
+}
+
+void
+reportUnmarkedBlocks (void)
+{
+ void *mblock;
+ bdescr *bd;
+
+ debugBelch("Unreachable blocks:\n");
+ for (mblock = getFirstMBlock(); mblock != NULL;
+ mblock = getNextMBlock(mblock)) {
+ for (bd = FIRST_BDESCR(mblock); bd <= LAST_BDESCR(mblock); ) {
+ if (!(bd->flags & BF_KNOWN) && bd->free != (P_)-1) {
+ debugBelch(" %p\n",bd);
+ }
+ if (bd->blocks >= BLOCKS_PER_MBLOCK) {
+ mblock = (StgWord8*)mblock +
+ (BLOCKS_TO_MBLOCKS(bd->blocks) - 1) * MBLOCK_SIZE;
+ break;
+ } else {
+ bd += bd->blocks;
+ }
+ }
+ }
+}
+
#endif