* Use 0xdeadbeef as an indicator to only conditionally walk the freelist.

This is not safe when already freed memory is overwritten. But since we also
  store the next pointer of the freelist in there, overwriting would break the
  freelist and cause a crash in that case. This gives a drastic performance
  boost when freelists grow during use and especially when opening and closing
  a lot of programs.
* Optimize filling the freed element with 0xdeadbeef by writing 4 bytes at a
  time instead of using single byte writes. Works as all our bins have an
  element size that is a multiple of four. Put a panic in there just in case
  this assumption isn't met for some reason.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23879 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2008-02-05 20:21:44 +00:00
parent f54626a7ae
commit 0d83dc06e3

View File

@ -497,6 +497,11 @@ memalign(size_t alignment, size_t size)
address = bins[bin_index].free_list;
bins[bin_index].free_list = (void *)(*(unsigned int *)bins[bin_index].free_list);
bins[bin_index].free_count--;
#if PARANOID_KFREE
// Ensure that the 0xdeadbeef is cleared so we do not walk this
// freelist if the user does not clear/use these bytes.
((uint32 *)address)[1] = 0;
#endif
} else {
if (bins[bin_index].raw_count == 0) {
bins[bin_index].raw_list = raw_alloc(bins[bin_index].grow_size, bin_index);
@ -599,19 +604,6 @@ free(void *address)
if (bin->element_size <= B_PAGE_SIZE && (addr_t)address % bin->element_size != 0)
panic("kfree: passed invalid pointer %p! Supposed to be in bin for esize 0x%lx\n", address, bin->element_size);
#if PARANOID_KFREE
// mark the free space as freed
{
uint32 deadbeef = 0xdeadbeef;
uint8 *dead = (uint8 *)address;
uint32 i;
// the first 4 bytes are overwritten with the next free list pointer later
for (i = 4; i < bin->element_size; i++)
dead[i] = ((uint8 *)&deadbeef)[i % 4];
}
#endif
for (i = 0; i < bin->element_size / B_PAGE_SIZE; i++) {
if (page[i].bin_index != page[0].bin_index)
panic("free(): not all pages in allocation match bin_index\n");
@ -619,14 +611,28 @@ free(void *address)
}
#if PARANOID_KFREE
// walk the free list on this bin to make sure this address doesn't exist already
{
if (((uint32 *)address)[1] == 0xdeadbeef) {
// This block looks like it was freed already, walk the free list
// on this bin to make sure this address doesn't exist.
unsigned int *temp;
for (temp = bin->free_list; temp != NULL; temp = (unsigned int *)*temp) {
if (temp == (unsigned int *)address)
panic("free(): address %p already exists in bin free list\n", address);
}
}
// mark the free space as freed
{
uint32 i;
uint32 *dead = (uint32 *)address;
if (bin->element_size % 4 != 0)
panic("free(): didn't expect a bin element size that is not a multiple of 4\n");
// the first 4 bytes are overwritten with the next free list pointer later
for (i = 1; i < bin->element_size / 4; i++)
dead[i] = 0xdeadbeef;
}
#endif
*(unsigned int *)address = (unsigned int)bin->free_list;