[zone] Fix z_split_block and Z_Realloc

z_split_block missed updating the back pointer in the block after the
split block, and Z_Realloc missed setting the sentinel.
This commit is contained in:
Bill Currie 2023-12-21 02:13:40 +09:00
parent 18c0ea3657
commit 82428ffb9d

View file

@ -140,6 +140,7 @@ z_split_block (memblock_t *block, size_t size)
.prev = block, .prev = block,
.id = ZONEID, .id = ZONEID,
}; };
split->next->prev = split;
block->next = split; block->next = split;
block->block_size = size; block->block_size = size;
return split; return split;
@ -160,6 +161,12 @@ z_merge_blocks (memzone_t *zone, memblock_t *a, memblock_t *b)
return a; return a;
} }
static void
z_set_sentinal (memblock_t *block)
{
*(int *) ((byte *) block + block->block_size - 4) = ZONEID;
}
static void static void
z_deadbeef (memblock_t *block) z_deadbeef (memblock_t *block)
{ {
@ -241,6 +248,10 @@ Z_Free (memzone_t *zone, void *ptr)
{ {
memblock_t *block, *other; memblock_t *block, *other;
if (developer & SYS_zone) {
Z_CheckHeap (zone);
}
if (!ptr) { if (!ptr) {
if (zone->error) { if (zone->error) {
zone->error (zone->data, "Z_Free: NULL pointer"); zone->error (zone->data, "Z_Free: NULL pointer");
@ -279,6 +290,9 @@ Z_Free (memzone_t *zone, void *ptr)
// merge the next free block onto the end // merge the next free block onto the end
z_merge_blocks (zone, block, other); z_merge_blocks (zone, block, other);
} }
if (developer & SYS_zone) {
Z_CheckHeap (zone);
}
} }
VISIBLE void * VISIBLE void *
@ -306,7 +320,7 @@ Z_TagMalloc (memzone_t *zone, size_t size, int tag)
memblock_t *start, *rover, *base; memblock_t *start, *rover, *base;
if (developer & SYS_zone) { if (developer & SYS_zone) {
Z_CheckHeap (zone); // DEBUG Z_CheckHeap (zone);
} }
if (!tag) { if (!tag) {
@ -347,7 +361,11 @@ Z_TagMalloc (memzone_t *zone, size_t size, int tag)
zone->used += base->block_size; zone->used += base->block_size;
// marker for memory trash testing // marker for memory trash testing
*(int *) ((byte *) base + base->block_size - 4) = ZONEID; z_set_sentinal (base);
if (developer & SYS_zone) {
Z_CheckHeap (zone);
}
return (void *) (base + 1); return (void *) (base + 1);
} }
@ -358,8 +376,9 @@ Z_Realloc (memzone_t *zone, void *ptr, size_t size)
if (!ptr) if (!ptr)
return Z_Malloc (zone, size); return Z_Malloc (zone, size);
if (developer & SYS_zone) if (developer & SYS_zone) {
Z_CheckHeap (zone); // DEBUG Z_CheckHeap (zone);
}
auto block = z_ptr_block (zone, ptr); auto block = z_ptr_block (zone, ptr);
if (block->tag == 0) { if (block->tag == 0) {
@ -383,12 +402,14 @@ Z_Realloc (memzone_t *zone, void *ptr, size_t size)
} }
} }
block->size = size; block->size = size;
z_set_sentinal (block);
} else { } else {
auto other = block->next; auto other = block->next;
if (!other->tag && block->block_size + other->block_size >= new_size) { if (!other->tag && block->block_size + other->block_size >= new_size) {
z_split_block (other, new_size - block->block_size); z_split_block (other, new_size - block->block_size);
z_merge_blocks (zone, block, other); z_merge_blocks (zone, block, other);
block->size = size; block->size = size;
z_set_sentinal (block);
} else { } else {
ptr = Z_TagMalloc (zone, size, 1); ptr = Z_TagMalloc (zone, size, 1);
} }
@ -400,6 +421,9 @@ Z_Realloc (memzone_t *zone, void *ptr, size_t size)
} }
Sys_Error ("Z_Realloc: failed on allocation of %zd bytes", size); Sys_Error ("Z_Realloc: failed on allocation of %zd bytes", size);
} }
if (developer & SYS_zone) {
Z_CheckHeap (zone);
}
if (ptr != old_ptr) { if (ptr != old_ptr) {
memmove (ptr, old_ptr, min (old_size, size)); memmove (ptr, old_ptr, min (old_size, size));