version 1.18, 2013/11/08 00:39:15 |
version 1.19, 2014/01/04 17:50:55 |
|
|
|
|
#include <errno.h> |
#include <errno.h> |
#include <stdarg.h> |
#include <stdarg.h> |
|
#include <stddef.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
|
|
static int |
static int |
mm_compare(struct mm_share *a, struct mm_share *b) |
mm_compare(struct mm_share *a, struct mm_share *b) |
{ |
{ |
long diff = (char *)a->address - (char *)b->address; |
ptrdiff_t diff = (char *)a->address - (char *)b->address; |
|
|
if (diff == 0) |
if (diff == 0) |
return (0); |
return (0); |
|
|
|
|
tmp2 = RB_INSERT(mmtree, head, tmp); |
tmp2 = RB_INSERT(mmtree, head, tmp); |
if (tmp2 != NULL) |
if (tmp2 != NULL) |
fatal("mm_make_entry(%p): double address %p->%p(%lu)", |
fatal("mm_make_entry(%p): double address %p->%p(%zu)", |
mm, tmp2, address, (u_long)size); |
mm, tmp2, address, size); |
|
|
return (tmp); |
return (tmp); |
} |
} |
|
|
mm->mmalloc = mmalloc; |
mm->mmalloc = mmalloc; |
|
|
address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED, |
address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED, |
-1, (off_t)0); |
-1, 0); |
if (address == MAP_FAILED) |
if (address == MAP_FAILED) |
fatal("mmap(%lu): %s", (u_long)size, strerror(errno)); |
fatal("mmap(%zu): %s", size, strerror(errno)); |
|
|
mm->address = address; |
mm->address = address; |
mm->size = size; |
mm->size = size; |
|
|
mm_freelist(mm->mmalloc, &mm->rb_allocated); |
mm_freelist(mm->mmalloc, &mm->rb_allocated); |
|
|
if (munmap(mm->address, mm->size) == -1) |
if (munmap(mm->address, mm->size) == -1) |
fatal("munmap(%p, %lu): %s", mm->address, (u_long)mm->size, |
fatal("munmap(%p, %zu): %s", mm->address, mm->size, |
strerror(errno)); |
strerror(errno)); |
if (mm->mmalloc == NULL) |
if (mm->mmalloc == NULL) |
free(mm); |
free(mm); |
|
|
|
|
address = mm_malloc(mm, size); |
address = mm_malloc(mm, size); |
if (address == NULL) |
if (address == NULL) |
fatal("%s: mm_malloc(%lu)", __func__, (u_long)size); |
fatal("%s: mm_malloc(%zu)", __func__, size); |
memset(address, 0, size); |
memset(address, 0, size); |
return (address); |
return (address); |
} |
} |
|
|
|
|
/* Does not change order in RB tree */ |
/* Does not change order in RB tree */ |
mms->size -= size; |
mms->size -= size; |
mms->address = (u_char *)mms->address + size; |
mms->address = (char *)mms->address + size; |
|
|
if (mms->size == 0) { |
if (mms->size == 0) { |
RB_REMOVE(mmtree, &mm->rb_free, mms); |
RB_REMOVE(mmtree, &mm->rb_free, mms); |
|
|
|
|
/* Check if range does not overlap */ |
/* Check if range does not overlap */ |
if (prev != NULL && MM_ADDRESS_END(prev) > address) |
if (prev != NULL && MM_ADDRESS_END(prev) > address) |
fatal("mm_free: memory corruption: %p(%lu) > %p", |
fatal("mm_free: memory corruption: %p(%zu) > %p", |
prev->address, (u_long)prev->size, address); |
prev->address, prev->size, address); |
|
|
/* See if we can merge backwards */ |
/* See if we can merge backwards */ |
if (prev != NULL && MM_ADDRESS_END(prev) == address) { |
if (prev != NULL && MM_ADDRESS_END(prev) == address) { |
|
|
return; |
return; |
|
|
if (MM_ADDRESS_END(prev) > mms->address) |
if (MM_ADDRESS_END(prev) > mms->address) |
fatal("mm_free: memory corruption: %p < %p(%lu)", |
fatal("mm_free: memory corruption: %p < %p(%zu)", |
mms->address, prev->address, (u_long)prev->size); |
mms->address, prev->address, prev->size); |
if (MM_ADDRESS_END(prev) != mms->address) |
if (MM_ADDRESS_END(prev) != mms->address) |
return; |
return; |
|
|
|
|
void |
void |
mm_memvalid(struct mm_master *mm, void *address, size_t size) |
mm_memvalid(struct mm_master *mm, void *address, size_t size) |
{ |
{ |
void *end = (u_char *)address + size; |
void *end = (char *)address + size; |
|
|
if (address < mm->address) |
if (address < mm->address) |
fatal("mm_memvalid: address too small: %p", address); |
fatal("mm_memvalid: address too small: %p", address); |
if (end < address) |
if (end < address) |
fatal("mm_memvalid: end < address: %p < %p", end, address); |
fatal("mm_memvalid: end < address: %p < %p", end, address); |
if (end > (void *)((u_char *)mm->address + mm->size)) |
if (end > MM_ADDRESS_END(mm)) |
fatal("mm_memvalid: address too large: %p", address); |
fatal("mm_memvalid: address too large: %p", address); |
} |
} |