#include <OS.h>
#include "AreaUtils.h"
#include "DebugSupport.h"
#include "Misc.h"
#ifndef USE_STANDARD_FUNCTIONS
#define USE_STANDARD_FUNCTIONS 0
#endif
static
status_t
area_info_for(void *address, area_info *info)
{
status_t error = B_OK;
if (address) {
area_id area = area_for(address);
if (area >= 0)
error = get_area_info(area, info);
else
error = area;
} else
error = B_BAD_VALUE;
return error;
}
void *
AreaUtils::calloc(size_t nmemb, size_t size)
{
return AreaUtils::malloc(nmemb * size);
}
void
AreaUtils::free(void *ptr)
{
#if USE_STANDARD_FUNCTIONS
return ::free(ptr);
#else
if (ptr) {
area_info info;
if (area_info_for(ptr, &info) == B_OK) {
if (ptr == info.address) {
delete_area(info.area);
} else {
INFORM("WARNING: AreaUtils::free(%p): area begin is %p."
"Ignored.\n", ptr, info.address);
}
}
}
#endif
}
void *
AreaUtils::malloc(size_t size)
{
#if USE_STANDARD_FUNCTIONS
return ::malloc(size);
#else
void *address = NULL;
if (size > 0) {
size = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE * B_PAGE_SIZE;
#if USER
area_id area = create_area("AreaUtils::malloc", &address,
B_ANY_ADDRESS, size, B_NO_LOCK,
B_WRITE_AREA | B_READ_AREA);
#else
area_id area = create_area("AreaUtils::malloc", &address,
B_ANY_KERNEL_ADDRESS, size, B_FULL_LOCK,
B_READ_AREA | B_WRITE_AREA);
#endif
if (area < 0)
address = NULL;
}
return address;
#endif
}
void *
AreaUtils::realloc(void * ptr, size_t size)
{
#if USE_STANDARD_FUNCTIONS
return ::realloc(ptr, size);
#else
void *newAddress = NULL;
if (size == 0) {
AreaUtils::free(ptr);
} else if (ptr) {
area_info info;
if (area_info_for(ptr, &info) == B_OK) {
if (ptr == info.address) {
size = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE * B_PAGE_SIZE;
if (size == info.size) {
newAddress = ptr;
} else if (resize_area(info.area, size) == B_OK) {
newAddress = ptr;
} else {
newAddress = AreaUtils::malloc(size);
if (newAddress) {
memcpy(newAddress, ptr, min(size, info.size));
delete_area(info.area);
}
}
} else {
INFORM("WARNING: AreaUtils::realloc(%p): area begin is %p."
"Ignored.\n", ptr, info.address);
}
}
}
return newAddress;
#endif
}