1// AreaUtils.cpp 2// 3// Copyright (c) 2003, Ingo Weinhold (bonefish@cs.tu-berlin.de) 4// 5// Permission is hereby granted, free of charge, to any person obtaining a 6// copy of this software and associated documentation files (the "Software"), 7// to deal in the Software without restriction, including without limitation 8// the rights to use, copy, modify, merge, publish, distribute, sublicense, 9// and/or sell copies of the Software, and to permit persons to whom the 10// Software is furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21// DEALINGS IN THE SOFTWARE. 22// 23// Except as contained in this notice, the name of a copyright holder shall 24// not be used in advertising or otherwise to promote the sale, use or other 25// dealings in this Software without prior written authorization of the 26// copyright holder. 27 28#include <OS.h> 29 30#include "AreaUtils.h" 31#include "Debug.h" 32#include "Misc.h" 33 34#ifndef USE_STANDARD_FUNCTIONS 35#define USE_STANDARD_FUNCTIONS 0 36#endif 37 38 39// area_info_for 40static 41status_t 42area_info_for(void *address, area_info *info) 43{ 44 status_t error = B_OK; 45 if (address) { 46 // get the area ID for the ptr 47 area_id area = area_for(address); 48 // check if supplied pointer points to the beginning of the area 49 if (area >= 0) 50 error = get_area_info(area, info); 51 else 52 error = area; 53 } else 54 error = B_BAD_VALUE; 55 return error; 56} 57 58// calloc 59void * 60AreaUtils::calloc(size_t nmemb, size_t size) 61{ 62//PRINT(("AreaUtils::calloc(%lu, %lu)\n", nmemb, size)); 63 return AreaUtils::malloc(nmemb * size); 64} 65 66// free 67void 68AreaUtils::free(void *ptr) 69{ 70//PRINT(("AreaUtils::free(%p)\n", ptr)); 71#if USE_STANDARD_FUNCTIONS 72 return ::free(ptr); 73#else 74 if (ptr) { 75 // get the area for the pointer 76 area_info info; 77 if (area_info_for(ptr, &info) == B_OK) { 78 if (ptr == info.address) { 79 // everything is fine, delete the area 80 delete_area(info.area); 81 } else { 82 INFORM(("WARNING: AreaUtils::free(%p): area begin is %p." 83 "Ignored.\n", ptr, info.address)); 84 } 85 } 86 } 87#endif 88} 89 90// malloc 91void * 92AreaUtils::malloc(size_t size) 93{ 94//PRINT(("AreaUtils::malloc(%lu)\n", size)); 95#if USE_STANDARD_FUNCTIONS 96 return ::malloc(size); 97#else 98 void *address = NULL; 99 if (size > 0) { 100 // round to multiple of page size 101 size = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE * B_PAGE_SIZE; 102 // create an area 103#if USER 104 area_id area = create_area("AreaUtils::malloc", &address, 105 B_ANY_ADDRESS, size, B_NO_LOCK, 106 B_WRITE_AREA | B_READ_AREA); 107#else 108 area_id area = create_area("AreaUtils::malloc", &address, 109 B_ANY_KERNEL_ADDRESS, size, B_FULL_LOCK, 110 B_READ_AREA | B_WRITE_AREA); 111#endif 112 if (area < 0) 113 address = NULL; 114 } 115 return address; 116#endif 117} 118 119// realloc 120void * 121AreaUtils::realloc(void * ptr, size_t size) 122{ 123//PRINT(("AreaUtils::realloc(%p, %lu)\n", ptr, size)) 124#if USE_STANDARD_FUNCTIONS 125 return ::realloc(ptr, size); 126#else 127 void *newAddress = NULL; 128 if (size == 0) { 129 AreaUtils::free(ptr); 130 } else if (ptr) { 131 // get the area for the pointer 132 area_info info; 133 if (area_info_for(ptr, &info) == B_OK) { 134 if (ptr == info.address) { 135 // round to multiple of page size 136 size = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE * B_PAGE_SIZE; 137 if (size == info.size) { 138 // nothing to do 139 newAddress = ptr; 140 } else if (resize_area(info.area, size) == B_OK) { 141 // resizing the area went fine 142 newAddress = ptr; 143 } else { 144 // resizing the area failed: we need to allocate a new one 145 newAddress = AreaUtils::malloc(size); 146 if (newAddress) { 147 memcpy(newAddress, ptr, min(size, info.size)); 148 delete_area(info.area); 149 } 150 } 151 } else { 152 INFORM(("WARNING: AreaUtils::realloc(%p): area begin is %p." 153 "Ignored.\n", ptr, info.address)); 154 } 155 } 156 } 157 return newAddress; 158#endif 159} 160 161