Changeset 25059 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Nov 27, 2009 6:17:44 PM (15 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/alloc/heapoffset.cpp
r25055 r25059 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - A SimpleHeap.3 * IPRT - An Offset Based Heap. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2006-200 7Sun Microsystems, Inc.7 * Copyright (C) 2006-2009 Sun Microsystems, Inc. 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 51 51 *******************************************************************************/ 52 52 /** Pointer to the heap anchor block. */ 53 typedef struct RTHEAP SIMPLEINTERNAL *PRTHEAPSIMPLEINTERNAL;53 typedef struct RTHEAPOFFSETINTERNAL *PRTHEAPOFFSETINTERNAL; 54 54 /** Pointer to a heap block. */ 55 typedef struct RTHEAP SIMPLEBLOCK *PRTHEAPSIMPLEBLOCK;55 typedef struct RTHEAPOFFSETBLOCK *PRTHEAPOFFSETBLOCK; 56 56 /** Pointer to a free heap block. */ 57 typedef struct RTHEAPSIMPLEFREE *PRTHEAPSIMPLEFREE; 58 59 /** 60 * Structure describing a simple heap block. 57 typedef struct RTHEAPOFFSETFREE *PRTHEAPOFFSETFREE; 58 59 /** 60 * Structure describing a block in an offset based heap. 61 * 61 62 * If this block is allocated, it is followed by the user data. 62 * If this block is free, see RTHEAP SIMPLEFREE.63 */ 64 typedef struct RTHEAP SIMPLEBLOCK63 * If this block is free, see RTHEAPOFFSETFREE. 64 */ 65 typedef struct RTHEAPOFFSETBLOCK 65 66 { 66 67 /** The next block in the global block list. */ 67 PRTHEAPSIMPLEBLOCK pNext;68 uint32_t /*PRTHEAPOFFSETBLOCK*/ offNext; 68 69 /** The previous block in the global block list. */ 69 PRTHEAPSIMPLEBLOCK pPrev;70 /** Pointer to the heapanchor block. */71 PRTHEAPSIMPLEINTERNAL pHeap;70 uint32_t /*PRTHEAPOFFSETBLOCK*/ offPrev; 71 /** Offset into the heap of this block. Used to locate the anchor block. */ 72 uint32_t /*PRTHEAPOFFSETINTERNAL*/ offSelf; 72 73 /** Flags + magic. */ 73 uint ptr_tfFlags;74 } RTHEAP SIMPLEBLOCK;75 AssertCompileSizeAlignment(RTHEAP SIMPLEBLOCK, 16);74 uint32_t fFlags; 75 } RTHEAPOFFSETBLOCK; 76 AssertCompileSizeAlignment(RTHEAPOFFSETBLOCK, 16); 76 77 77 78 /** The block is free if this flag is set. When cleared it's allocated. */ 78 #define RTHEAP SIMPLEBLOCK_FLAGS_FREE ((uintptr_t)RT_BIT(0))79 #define RTHEAPOFFSETBLOCK_FLAGS_FREE (RT_BIT_32(0)) 79 80 /** The magic value. */ 80 #define RTHEAP SIMPLEBLOCK_FLAGS_MAGIC ((uintptr_t)0xabcdef00)81 /** The mask that needs to be applied to RTHEAP SIMPLEBLOCK::fFlags to obtain the magic value. */82 #define RTHEAP SIMPLEBLOCK_FLAGS_MAGIC_MASK (~(uintptr_t)RT_BIT(0))81 #define RTHEAPOFFSETBLOCK_FLAGS_MAGIC (UINT32_C(0xabcdef00)) 82 /** The mask that needs to be applied to RTHEAPOFFSETBLOCK::fFlags to obtain the magic value. */ 83 #define RTHEAPOFFSETBLOCK_FLAGS_MAGIC_MASK (~RT_BIT_32(0)) 83 84 84 85 /** 85 86 * Checks if the specified block is valid or not. 86 87 * @returns boolean answer. 87 * @param pBlock Pointer to a RTHEAP SIMPLEBLOCK structure.88 */ 89 #define RTHEAP SIMPLEBLOCK_IS_VALID(pBlock) \90 ( ((pBlock)->fFlags & RTHEAP SIMPLEBLOCK_FLAGS_MAGIC_MASK) == RTHEAPSIMPLEBLOCK_FLAGS_MAGIC )88 * @param pBlock Pointer to a RTHEAPOFFSETBLOCK structure. 89 */ 90 #define RTHEAPOFFSETBLOCK_IS_VALID(pBlock) \ 91 ( ((pBlock)->fFlags & RTHEAPOFFSETBLOCK_FLAGS_MAGIC_MASK) == RTHEAPOFFSETBLOCK_FLAGS_MAGIC ) 91 92 92 93 /** 93 94 * Checks if the specified block is valid and in use. 94 95 * @returns boolean answer. 95 * @param pBlock Pointer to a RTHEAP SIMPLEBLOCK structure.96 */ 97 #define RTHEAP SIMPLEBLOCK_IS_VALID_USED(pBlock) \98 ( ((pBlock)->fFlags & (RTHEAP SIMPLEBLOCK_FLAGS_MAGIC_MASK | RTHEAPSIMPLEBLOCK_FLAGS_FREE)) \99 == RTHEAP SIMPLEBLOCK_FLAGS_MAGIC )96 * @param pBlock Pointer to a RTHEAPOFFSETBLOCK structure. 97 */ 98 #define RTHEAPOFFSETBLOCK_IS_VALID_USED(pBlock) \ 99 ( ((pBlock)->fFlags & (RTHEAPOFFSETBLOCK_FLAGS_MAGIC_MASK | RTHEAPOFFSETBLOCK_FLAGS_FREE)) \ 100 == RTHEAPOFFSETBLOCK_FLAGS_MAGIC ) 100 101 101 102 /** 102 103 * Checks if the specified block is valid and free. 103 104 * @returns boolean answer. 104 * @param pBlock Pointer to a RTHEAP SIMPLEBLOCK structure.105 */ 106 #define RTHEAP SIMPLEBLOCK_IS_VALID_FREE(pBlock) \107 ( ((pBlock)->fFlags & (RTHEAP SIMPLEBLOCK_FLAGS_MAGIC_MASK | RTHEAPSIMPLEBLOCK_FLAGS_FREE)) \108 == (RTHEAP SIMPLEBLOCK_FLAGS_MAGIC | RTHEAPSIMPLEBLOCK_FLAGS_FREE) )105 * @param pBlock Pointer to a RTHEAPOFFSETBLOCK structure. 106 */ 107 #define RTHEAPOFFSETBLOCK_IS_VALID_FREE(pBlock) \ 108 ( ((pBlock)->fFlags & (RTHEAPOFFSETBLOCK_FLAGS_MAGIC_MASK | RTHEAPOFFSETBLOCK_FLAGS_FREE)) \ 109 == (RTHEAPOFFSETBLOCK_FLAGS_MAGIC | RTHEAPOFFSETBLOCK_FLAGS_FREE) ) 109 110 110 111 /** 111 112 * Checks if the specified block is free or not. 112 113 * @returns boolean answer. 113 * @param pBlock Pointer to a valid RTHEAP SIMPLEBLOCK structure.114 */ 115 #define RTHEAP SIMPLEBLOCK_IS_FREE(pBlock) (!!((pBlock)->fFlags & RTHEAPSIMPLEBLOCK_FLAGS_FREE))114 * @param pBlock Pointer to a valid RTHEAPOFFSETBLOCK structure. 115 */ 116 #define RTHEAPOFFSETBLOCK_IS_FREE(pBlock) (!!((pBlock)->fFlags & RTHEAPOFFSETBLOCK_FLAGS_FREE)) 116 117 117 118 /** 118 119 * A free heap block. 119 * This is an extended version of RTHEAP SIMPLEBLOCK that takes the unused120 * This is an extended version of RTHEAPOFFSETBLOCK that takes the unused 120 121 * user data to store free list pointers and a cached size value. 121 122 */ 122 typedef struct RTHEAP SIMPLEFREE123 typedef struct RTHEAPOFFSETFREE 123 124 { 124 125 /** Core stuff. */ 125 RTHEAP SIMPLEBLOCKCore;126 RTHEAPOFFSETBLOCK Core; 126 127 /** Pointer to the next free block. */ 127 PRTHEAPSIMPLEFREE pNext;128 uint32_t /*PRTHEAPOFFSETFREE*/ offNext; 128 129 /** Pointer to the previous free block. */ 129 PRTHEAPSIMPLEFREE pPrev; 130 /** The size of the block (excluding the RTHEAPSIMPLEBLOCK part). */ 131 size_t cb; 132 /** An alignment filler to make it a multiple of (sizeof(void *) * 2). */ 133 size_t Alignment; 134 } RTHEAPSIMPLEFREE; 130 uint32_t /*PRTHEAPOFFSETFREE*/ offPrev; 131 /** The size of the block (excluding the RTHEAPOFFSETBLOCK part). */ 132 uint32_t cb; 133 /** An alignment filler to make it a multiple of 16 bytes. */ 134 uint32_t Alignment; 135 } RTHEAPOFFSETFREE; 136 AssertCompileSizeAlignment(RTHEAPOFFSETFREE, 16); 135 137 136 138 137 139 /** 138 140 * The heap anchor block. 139 * This structure is placed at the head of the memory block specified to RTHeap SimpleInit(),140 * which means that the first RTHEAP SIMPLEBLOCK appears immediately after this structure.141 */ 142 typedef struct RTHEAP SIMPLEINTERNAL143 { 144 /** The typical magic (RTHEAP SIMPLE_MAGIC). */145 size_t uMagic;141 * This structure is placed at the head of the memory block specified to RTHeapOffsetInit(), 142 * which means that the first RTHEAPOFFSETBLOCK appears immediately after this structure. 143 */ 144 typedef struct RTHEAPOFFSETINTERNAL 145 { 146 /** The typical magic (RTHEAPOFFSET_MAGIC). */ 147 uint32_t u32Magic; 146 148 /** The heap size. (This structure is included!) */ 147 size_t cbHeap; 148 /** Pointer to the end of the heap. */ 149 void *pvEnd; 149 uint32_t cbHeap; 150 150 /** The amount of free memory in the heap. */ 151 size_tcbFree;151 uint32_t cbFree; 152 152 /** Free head pointer. */ 153 PRTHEAPSIMPLEFREE pFreeHead;153 uint32_t /*PRTHEAPOFFSETFREE*/ offFreeHead; 154 154 /** Free tail pointer. */ 155 PRTHEAPSIMPLEFREE pFreeTail;155 uint32_t /*PRTHEAPOFFSETFREE*/ offFreeTail; 156 156 /** Make the size of this structure is a multiple of 32. */ 157 size_t auAlignment[2];158 } RTHEAP SIMPLEINTERNAL;159 AssertCompileSizeAlignment(RTHEAP SIMPLEINTERNAL, 32);157 uint32_t au32Alignment[3]; 158 } RTHEAPOFFSETINTERNAL; 159 AssertCompileSizeAlignment(RTHEAPOFFSETINTERNAL, 32); 160 160 161 161 162 162 /** The minimum allocation size. */ 163 #define RTHEAP SIMPLE_MIN_BLOCK (sizeof(RTHEAPSIMPLEBLOCK))164 AssertCompile(RTHEAP SIMPLE_MIN_BLOCK >= sizeof(RTHEAPSIMPLEBLOCK));165 AssertCompile(RTHEAP SIMPLE_MIN_BLOCK >= sizeof(RTHEAPSIMPLEFREE) - sizeof(RTHEAPSIMPLEBLOCK));163 #define RTHEAPOFFSET_MIN_BLOCK (sizeof(RTHEAPOFFSETBLOCK)) 164 AssertCompile(RTHEAPOFFSET_MIN_BLOCK >= sizeof(RTHEAPOFFSETBLOCK)); 165 AssertCompile(RTHEAPOFFSET_MIN_BLOCK >= sizeof(RTHEAPOFFSETFREE) - sizeof(RTHEAPOFFSETBLOCK)); 166 166 167 167 /** The minimum and default alignment. */ 168 #define RTHEAP SIMPLE_ALIGNMENT (sizeof(RTHEAPSIMPLEBLOCK))168 #define RTHEAPOFFSET_ALIGNMENT (sizeof(RTHEAPOFFSETBLOCK)) 169 169 170 170 … … 173 173 *******************************************************************************/ 174 174 #ifdef RT_STRICT 175 # define RTHEAPSIMPLE_STRICT 1 176 #endif 177 178 #define ASSERT_L(a, b) AssertMsg((uintptr_t)(a) < (uintptr_t)(b), ("a=%p b=%p\n", (uintptr_t)(a), (uintptr_t)(b))) 179 #define ASSERT_LE(a, b) AssertMsg((uintptr_t)(a) <= (uintptr_t)(b), ("a=%p b=%p\n", (uintptr_t)(a), (uintptr_t)(b))) 180 #define ASSERT_G(a, b) AssertMsg((uintptr_t)(a) > (uintptr_t)(b), ("a=%p b=%p\n", (uintptr_t)(a), (uintptr_t)(b))) 181 #define ASSERT_GE(a, b) AssertMsg((uintptr_t)(a) >= (uintptr_t)(b), ("a=%p b=%p\n", (uintptr_t)(a), (uintptr_t)(b))) 182 #define ASSERT_ALIGN(a) AssertMsg(!((uintptr_t)(a) & (RTHEAPSIMPLE_ALIGNMENT - 1)), ("a=%p\n", (uintptr_t)(a))) 175 # define RTHEAPOFFSET_STRICT 1 176 #endif 177 178 /** 179 * Converts RTHEAPOFFSETBLOCK::offSelf into a heap anchor block pointer. 180 * 181 * @returns Pointer of given type. 182 * @param pBlock The block to find the heap anchor block for. 183 */ 184 #define RTHEAPOFF_GET_ANCHOR(pBlock) ( (PRTHEAPOFFSETINTERNAL)((uint8_t *)(pBlock) - (pBlock)->offSelf ) ) 185 186 187 /** 188 * Converts an offset to a pointer. 189 * 190 * All offsets are relative to the heap to make life simple. 191 * 192 * @returns Pointer of given type. 193 * @param pHeapInt Pointer to the heap anchor block. 194 * @param off The offset to convert. 195 * @param type The desired type. 196 */ 197 #ifdef RTHEAPOFFSET_STRICT 198 # define RTHEAPOFF_TO_PTR(pHeapInt, off, type) ( (type)rtHeapOffCheckedOffToPtr(pHeapInt, off) ) 199 #else 200 # define RTHEAPOFF_TO_PTR(pHeapInt, off, type) ( (type)((off) ? (uint8_t *)(pHeapInt) + (off) : NULL) ) 201 #endif 202 203 /** 204 * Converts a pointer to an offset. 205 * 206 * All offsets are relative to the heap to make life simple. 207 * 208 * @returns Offset into the heap. 209 * @param pHeapInt Pointer to the heap anchor block. 210 * @param ptr The pointer to convert. 211 */ 212 #ifdef RTHEAPOFFSET_STRICT 213 # define RTHEAPOFF_TO_OFF(pHeapInt, ptr) rtHeapOffCheckedPtrToOff(pHeapInt, ptr) 214 #else 215 # define RTHEAPOFF_TO_OFF(pHeapInt, ptr) ( (uint32_t)((ptr) ? (uintptr_t)(ptr) - (uintptr_t)(pHeapInt) : UINT32_C(0)) ) 216 #endif 217 218 #define ASSERT_L(a, b) AssertMsg((a) < (b), ("a=%08x b=%08x\n", (a), (b))) 219 #define ASSERT_LE(a, b) AssertMsg((a) <= (b), ("a=%08x b=%08x\n", (a), (b))) 220 #define ASSERT_G(a, b) AssertMsg((a) > (b), ("a=%08x b=%08x\n", (a), (b))) 221 #define ASSERT_GE(a, b) AssertMsg((a) >= (b), ("a=%08x b=%08x\n", (a), (b))) 222 #define ASSERT_ALIGN(a) AssertMsg(!((uintptr_t)(a) & (RTHEAPOFFSET_ALIGNMENT - 1)), ("a=%p\n", (uintptr_t)(a))) 183 223 184 224 #define ASSERT_PREV(pHeapInt, pBlock) \ 185 do { ASSERT_ALIGN((pBlock)-> pPrev); \186 if ((pBlock)-> pPrev) \225 do { ASSERT_ALIGN((pBlock)->offPrev); \ 226 if ((pBlock)->offPrev) \ 187 227 { \ 188 ASSERT_L((pBlock)-> pPrev, (pBlock)); \189 ASSERT_GE((pBlock)-> pPrev, (pHeapInt) + 1); \228 ASSERT_L((pBlock)->offPrev, RTHEAPOFF_TO_OFF(pHeapInt, pBlock)); \ 229 ASSERT_GE((pBlock)->offPrev, sizeof(RTHEAPOFFSETINTERNAL)); \ 190 230 } \ 191 231 else \ 192 Assert((pBlock) == (PRTHEAP SIMPLEBLOCK)((pHeapInt) + 1)); \232 Assert((pBlock) == (PRTHEAPOFFSETBLOCK)((pHeapInt) + 1)); \ 193 233 } while (0) 194 234 195 235 #define ASSERT_NEXT(pHeap, pBlock) \ 196 do { ASSERT_ALIGN((pBlock)-> pNext); \197 if ((pBlock)-> pNext) \236 do { ASSERT_ALIGN((pBlock)->offNext); \ 237 if ((pBlock)->offNext) \ 198 238 { \ 199 ASSERT_L((pBlock)-> pNext, (pHeapInt)->pvEnd); \200 ASSERT_G((pBlock)-> pNext, (pBlock)); \239 ASSERT_L((pBlock)->offNext, (pHeapInt)->cbHeap); \ 240 ASSERT_G((pBlock)->offNext, RTHEAPOFF_TO_OFF(pHeapInt, pBlock)); \ 201 241 } \ 202 242 } while (0) 203 243 204 244 #define ASSERT_BLOCK(pHeapInt, pBlock) \ 205 do { AssertMsg(RTHEAP SIMPLEBLOCK_IS_VALID(pBlock), ("%#x\n", (pBlock)->fFlags)); \206 AssertMsg( (pBlock)->pHeap == (pHeapInt), ("%p != %p\n", (pBlock)->pHeap, (pHeapInt))); \207 ASSERT_GE( (pBlock), (pHeapInt) + 1); \208 ASSERT_L( (pBlock), (pHeapInt)->pvEnd); \245 do { AssertMsg(RTHEAPOFFSETBLOCK_IS_VALID(pBlock), ("%#x\n", (pBlock)->fFlags)); \ 246 AssertMsg(RTHEAPOFF_GET_ANCHOR(pBlock) == (pHeapInt), ("%p != %p\n", RTHEAPOFF_GET_ANCHOR(pBlock), (pHeapInt))); \ 247 ASSERT_GE(RTHEAPOFF_TO_OFF(pHeapInt, pBlock), sizeof(RTHEAPOFFSETINTERNAL)); \ 248 ASSERT_L( RTHEAPOFF_TO_OFF(pHeapInt, pBlock), (pHeapInt)->cbHeap); \ 209 249 ASSERT_NEXT(pHeapInt, pBlock); \ 210 250 ASSERT_PREV(pHeapInt, pBlock); \ … … 212 252 213 253 #define ASSERT_BLOCK_USED(pHeapInt, pBlock) \ 214 do { AssertMsg(RTHEAP SIMPLEBLOCK_IS_VALID_USED((pBlock)), ("%#x\n", (pBlock)->fFlags)); \215 AssertMsg( (pBlock)->pHeap == (pHeapInt), ("%p != %p\n", (pBlock)->pHeap, (pHeapInt))); \216 ASSERT_GE( (pBlock), (pHeapInt) + 1); \217 ASSERT_L( (pBlock), (pHeapInt)->pvEnd); \254 do { AssertMsg(RTHEAPOFFSETBLOCK_IS_VALID_USED((pBlock)), ("%#x\n", (pBlock)->fFlags)); \ 255 AssertMsg(RTHEAPOFF_GET_ANCHOR(pBlock) == (pHeapInt), ("%p != %p\n", RTHEAPOFF_GET_ANCHOR(pBlock), (pHeapInt))); \ 256 ASSERT_GE(RTHEAPOFF_TO_OFF(pHeapInt, pBlock), sizeof(RTHEAPOFFSETINTERNAL)); \ 257 ASSERT_L( RTHEAPOFF_TO_OFF(pHeapInt, pBlock), (pHeapInt)->cbHeap); \ 218 258 ASSERT_NEXT(pHeapInt, pBlock); \ 219 259 ASSERT_PREV(pHeapInt, pBlock); \ … … 221 261 222 262 #define ASSERT_FREE_PREV(pHeapInt, pBlock) \ 223 do { ASSERT_ALIGN((pBlock)-> pPrev); \224 if ((pBlock)-> pPrev) \263 do { ASSERT_ALIGN((pBlock)->offPrev); \ 264 if ((pBlock)->offPrev) \ 225 265 { \ 226 ASSERT_GE((pBlock)-> pPrev, (pHeapInt)->pFreeHead); \227 ASSERT_L((pBlock)-> pPrev, (pBlock)); \228 ASSERT_LE((pBlock)-> pPrev, (pBlock)->Core.pPrev); \266 ASSERT_GE((pBlock)->offPrev, (pHeapInt)->offFreeHead); \ 267 ASSERT_L((pBlock)->offPrev, RTHEAPOFF_TO_OFF(pHeapInt, pBlock)); \ 268 ASSERT_LE((pBlock)->offPrev, (pBlock)->Core.offPrev); \ 229 269 } \ 230 270 else \ 231 Assert((pBlock) == (pHeapInt)->pFreeHead); \271 Assert((pBlock) == RTHEAPOFF_TO_PTR(pHeapInt, (pHeapInt)->offFreeHead, PRTHEAPOFFSETFREE) ); \ 232 272 } while (0) 233 273 234 274 #define ASSERT_FREE_NEXT(pHeapInt, pBlock) \ 235 do { ASSERT_ALIGN((pBlock)-> pNext); \236 if ((pBlock)-> pNext) \275 do { ASSERT_ALIGN((pBlock)->offNext); \ 276 if ((pBlock)->offNext) \ 237 277 { \ 238 ASSERT_LE((pBlock)-> pNext, (pHeapInt)->pFreeTail); \239 ASSERT_G((pBlock)-> pNext, (pBlock)); \240 ASSERT_GE((pBlock)-> pNext, (pBlock)->Core.pNext); \278 ASSERT_LE((pBlock)->offNext, (pHeapInt)->offFreeTail); \ 279 ASSERT_G((pBlock)->offNext, RTHEAPOFF_TO_OFF(pHeapInt, pBlock)); \ 280 ASSERT_GE((pBlock)->offNext, (pBlock)->Core.offNext); \ 241 281 } \ 242 282 else \ 243 Assert((pBlock) == (pHeapInt)->pFreeTail); \283 Assert((pBlock) == RTHEAPOFF_TO_PTR(pHeapInt, (pHeapInt)->offFreeTail, PRTHEAPOFFSETFREE)); \ 244 284 } while (0) 245 285 246 #ifdef RTHEAP SIMPLE_STRICT286 #ifdef RTHEAPOFFSET_STRICT 247 287 # define ASSERT_FREE_CB(pHeapInt, pBlock) \ 248 do { size_t cbCalc = ((pBlock)->Core. pNext ? (uintptr_t)(pBlock)->Core.pNext : (uintptr_t)(pHeapInt)->pvEnd) \249 - (uintptr_t)(pBlock) - sizeof(RTHEAPSIMPLEBLOCK); \288 do { size_t cbCalc = ((pBlock)->Core.offNext ? (pBlock)->Core.offNext : (pHeapInt)->cbHeap) \ 289 - RTHEAPOFF_TO_OFF((pHeapInt), (pBlock)) - sizeof(RTHEAPOFFSETBLOCK); \ 250 290 AssertMsg((pBlock)->cb == cbCalc, ("cb=%#zx cbCalc=%#zx\n", (pBlock)->cb, cbCalc)); \ 251 291 } while (0) … … 257 297 #define ASSERT_BLOCK_FREE(pHeapInt, pBlock) \ 258 298 do { ASSERT_BLOCK(pHeapInt, &(pBlock)->Core); \ 259 Assert(RTHEAP SIMPLEBLOCK_IS_VALID_FREE(&(pBlock)->Core)); \260 ASSERT_GE( (pBlock), (pHeapInt)->pFreeHead); \261 ASSERT_LE( (pBlock), (pHeapInt)->pFreeTail); \299 Assert(RTHEAPOFFSETBLOCK_IS_VALID_FREE(&(pBlock)->Core)); \ 300 ASSERT_GE(RTHEAPOFF_TO_OFF(pHeapInt, pBlock), (pHeapInt)->offFreeHead); \ 301 ASSERT_LE(RTHEAPOFF_TO_OFF(pHeapInt, pBlock), (pHeapInt)->offFreeTail); \ 262 302 ASSERT_FREE_NEXT(pHeapInt, pBlock); \ 263 303 ASSERT_FREE_PREV(pHeapInt, pBlock); \ … … 268 308 #define ASSERT_ANCHOR(pHeapInt) \ 269 309 do { AssertPtr(pHeapInt);\ 270 Assert((pHeapInt)->u Magic == RTHEAPSIMPLE_MAGIC); \310 Assert((pHeapInt)->u32Magic == RTHEAPOFFSET_MAGIC); \ 271 311 } while (0) 272 312 … … 275 315 * Internal Functions * 276 316 *******************************************************************************/ 277 #ifdef RTHEAPSIMPLE_STRICT 278 static void rtHeapSimpleAssertAll(PRTHEAPSIMPLEINTERNAL pHeapInt); 279 #endif 280 static PRTHEAPSIMPLEBLOCK rtHeapSimpleAllocBlock(PRTHEAPSIMPLEINTERNAL pHeapInt, size_t cb, size_t uAlignment); 281 static void rtHeapSimpleFreeBlock(PRTHEAPSIMPLEINTERNAL pHeapInt, PRTHEAPSIMPLEBLOCK pBlock); 282 283 284 RTDECL(int) RTHeapSimpleInit(PRTHEAPSIMPLE phHeap, void *pvMemory, size_t cbMemory) 285 { 286 PRTHEAPSIMPLEINTERNAL pHeapInt; 287 PRTHEAPSIMPLEFREE pFree; 317 #ifdef RTHEAPOFFSET_STRICT 318 static void rtHeapOffsetAssertAll(PRTHEAPOFFSETINTERNAL pHeapInt); 319 #endif 320 static PRTHEAPOFFSETBLOCK rtHeapOffsetAllocBlock(PRTHEAPOFFSETINTERNAL pHeapInt, size_t cb, size_t uAlignment); 321 static void rtHeapOffsetFreeBlock(PRTHEAPOFFSETINTERNAL pHeapInt, PRTHEAPOFFSETBLOCK pBlock); 322 323 #ifdef RTHEAPOFFSET_STRICT 324 325 /** Checked version of RTHEAPOFF_TO_PTR. */ 326 DECLINLINE(void *) rtHeapOffCheckedOffToPtr(PRTHEAPOFFSETINTERNAL pHeapInt, uint32_t off) 327 { 328 if (!off) 329 return NULL; 330 AssertMsg(off < pHeapInt->cbHeap, ("%#x %#x\n", off, pHeapInt->cbHeap)); 331 AssertMsg(off >= sizeof(*pHeapInt), ("%#x %#x\n", off, sizeof(*pHeapInt))); 332 return (uint8_t *)pHeapInt + off; 333 } 334 335 /** Checked version of RTHEAPOFF_TO_OFF. */ 336 DECLINLINE(uint32_t) rtHeapOffCheckedPtrToOff(PRTHEAPOFFSETINTERNAL pHeapInt, void *pv) 337 { 338 if (!pv) 339 return 0; 340 uintptr_t off = (uintptr_t)pv - (uintptr_t)pHeapInt; 341 AssertMsg(off < pHeapInt->cbHeap, ("%#x %#x\n", off, pHeapInt->cbHeap)); 342 AssertMsg(off >= sizeof(*pHeapInt), ("%#x %#x\n", off, sizeof(*pHeapInt))); 343 return (uint32_t)off; 344 } 345 346 #endif /* RTHEAPOFFSET_STRICT */ 347 348 349 350 RTDECL(int) RTHeapOffsetInit(PRTHEAPOFFSET phHeap, void *pvMemory, size_t cbMemory) 351 { 352 PRTHEAPOFFSETINTERNAL pHeapInt; 353 PRTHEAPOFFSETFREE pFree; 288 354 unsigned i; 289 355 … … 299 365 * enforce 32 byte alignment of it. Also align the heap size correctly. 300 366 */ 301 pHeapInt = (PRTHEAP SIMPLEINTERNAL)pvMemory;367 pHeapInt = (PRTHEAPOFFSETINTERNAL)pvMemory; 302 368 if ((uintptr_t)pvMemory & 31) 303 369 { 304 370 const uintptr_t off = 32 - ((uintptr_t)pvMemory & 31); 305 371 cbMemory -= off; 306 pHeapInt = (PRTHEAP SIMPLEINTERNAL)((uintptr_t)pvMemory + off);307 } 308 cbMemory &= ~(RTHEAP SIMPLE_ALIGNMENT - 1);372 pHeapInt = (PRTHEAPOFFSETINTERNAL)((uintptr_t)pvMemory + off); 373 } 374 cbMemory &= ~(RTHEAPOFFSET_ALIGNMENT - 1); 309 375 310 376 311 377 /* Init the heap anchor block. */ 312 pHeapInt->uMagic = RTHEAPSIMPLE_MAGIC; 313 pHeapInt->pvEnd = (uint8_t *)pHeapInt + cbMemory; 378 pHeapInt->u32Magic = RTHEAPOFFSET_MAGIC; 314 379 pHeapInt->cbHeap = cbMemory; 315 380 pHeapInt->cbFree = cbMemory 316 - sizeof(RTHEAP SIMPLEBLOCK)317 - sizeof(RTHEAP SIMPLEINTERNAL);318 pHeapInt-> pFreeTail = pHeapInt->pFreeHead = (PRTHEAPSIMPLEFREE)(pHeapInt + 1);319 for (i = 0; i < RT_ELEMENTS(pHeapInt->au Alignment); i++)320 pHeapInt->au Alignment[i] = ~(size_t)0;381 - sizeof(RTHEAPOFFSETBLOCK) 382 - sizeof(RTHEAPOFFSETINTERNAL); 383 pHeapInt->offFreeTail = pHeapInt->offFreeHead = sizeof(*pHeapInt); 384 for (i = 0; i < RT_ELEMENTS(pHeapInt->au32Alignment); i++) 385 pHeapInt->au32Alignment[i] = UINT32_MAX; 321 386 322 387 /* Init the single free block. */ 323 pFree = pHeapInt->pFreeHead;324 pFree->Core. pNext = NULL;325 pFree->Core. pPrev = NULL;326 pFree->Core. pHeap = pHeapInt;327 pFree->Core.fFlags = RTHEAP SIMPLEBLOCK_FLAGS_MAGIC | RTHEAPSIMPLEBLOCK_FLAGS_FREE;328 pFree-> pNext = NULL;329 pFree-> pPrev = NULL;388 pFree = RTHEAPOFF_TO_PTR(pHeapInt, pHeapInt->offFreeHead, PRTHEAPOFFSETFREE); 389 pFree->Core.offNext = 0; 390 pFree->Core.offPrev = 0; 391 pFree->Core.offSelf = pHeapInt->offFreeHead; 392 pFree->Core.fFlags = RTHEAPOFFSETBLOCK_FLAGS_MAGIC | RTHEAPOFFSETBLOCK_FLAGS_FREE; 393 pFree->offNext = 0; 394 pFree->offPrev = 0; 330 395 pFree->cb = pHeapInt->cbFree; 331 396 332 397 *phHeap = pHeapInt; 333 398 334 #ifdef RTHEAP SIMPLE_STRICT335 rtHeap SimpleAssertAll(pHeapInt);399 #ifdef RTHEAPOFFSET_STRICT 400 rtHeapOffsetAssertAll(pHeapInt); 336 401 #endif 337 402 return VINF_SUCCESS; 338 403 } 339 RT_EXPORT_SYMBOL(RTHeapSimpleInit); 340 341 342 RTDECL(int) RTHeapSimpleRelocate(RTHEAPSIMPLE hHeap, uintptr_t offDelta) 343 { 344 PRTHEAPSIMPLEINTERNAL pHeapInt = hHeap; 345 PRTHEAPSIMPLEFREE pCur; 346 347 /* 348 * Validate input. 349 */ 350 AssertPtrReturn(pHeapInt, VERR_INVALID_HANDLE); 351 AssertReturn(pHeapInt->uMagic == RTHEAPSIMPLE_MAGIC, VERR_INVALID_HANDLE); 352 AssertMsgReturn((uintptr_t)pHeapInt - (uintptr_t)pHeapInt->pvEnd + pHeapInt->cbHeap == offDelta, 353 ("offDelta=%p, expected=%p\n", offDelta, (uintptr_t)pHeapInt->pvEnd - pHeapInt->cbHeap - (uintptr_t)pHeapInt), 354 VERR_INVALID_PARAMETER); 355 356 /* 357 * Relocate the heap anchor block. 358 */ 359 #define RELOCATE_IT(var, type, offDelta) do { if (RT_UNLIKELY((var) != NULL)) { (var) = (type)((uintptr_t)(var) + offDelta); } } while (0) 360 RELOCATE_IT(pHeapInt->pvEnd, void *, offDelta); 361 RELOCATE_IT(pHeapInt->pFreeHead, PRTHEAPSIMPLEFREE, offDelta); 362 RELOCATE_IT(pHeapInt->pFreeTail, PRTHEAPSIMPLEFREE, offDelta); 363 364 /* 365 * Walk the heap blocks. 366 */ 367 for (pCur = (PRTHEAPSIMPLEFREE)(pHeapInt + 1); 368 pCur && (uintptr_t)pCur < (uintptr_t)pHeapInt->pvEnd; 369 pCur = (PRTHEAPSIMPLEFREE)pCur->Core.pNext) 370 { 371 RELOCATE_IT(pCur->Core.pNext, PRTHEAPSIMPLEBLOCK, offDelta); 372 RELOCATE_IT(pCur->Core.pPrev, PRTHEAPSIMPLEBLOCK, offDelta); 373 RELOCATE_IT(pCur->Core.pHeap, PRTHEAPSIMPLEINTERNAL, offDelta); 374 if (RTHEAPSIMPLEBLOCK_IS_FREE(&pCur->Core)) 375 { 376 RELOCATE_IT(pCur->pNext, PRTHEAPSIMPLEFREE, offDelta); 377 RELOCATE_IT(pCur->pPrev, PRTHEAPSIMPLEFREE, offDelta); 378 } 379 } 380 #undef RELOCATE_IT 381 382 #ifdef RTHEAPSIMPLE_STRICT 383 /* 384 * Give it a once over before we return. 385 */ 386 rtHeapSimpleAssertAll(pHeapInt); 387 #endif 388 return VINF_SUCCESS; 389 } 390 RT_EXPORT_SYMBOL(RTHeapSimpleRelocate); 391 392 393 RTDECL(void *) RTHeapSimpleAlloc(RTHEAPSIMPLE hHeap, size_t cb, size_t cbAlignment) 394 { 395 PRTHEAPSIMPLEINTERNAL pHeapInt = hHeap; 396 PRTHEAPSIMPLEBLOCK pBlock; 404 RT_EXPORT_SYMBOL(RTHeapOffsetInit); 405 406 407 RTDECL(void *) RTHeapOffsetAlloc(RTHEAPOFFSET hHeap, size_t cb, size_t cbAlignment) 408 { 409 PRTHEAPOFFSETINTERNAL pHeapInt = hHeap; 410 PRTHEAPOFFSETBLOCK pBlock; 397 411 398 412 /* … … 400 414 */ 401 415 AssertPtrReturn(pHeapInt, NULL); 402 if (cb < RTHEAP SIMPLE_MIN_BLOCK)403 cb = RTHEAP SIMPLE_MIN_BLOCK;416 if (cb < RTHEAPOFFSET_MIN_BLOCK) 417 cb = RTHEAPOFFSET_MIN_BLOCK; 404 418 else 405 cb = RT_ALIGN_Z(cb, RTHEAP SIMPLE_ALIGNMENT);419 cb = RT_ALIGN_Z(cb, RTHEAPOFFSET_ALIGNMENT); 406 420 if (!cbAlignment) 407 cbAlignment = RTHEAP SIMPLE_ALIGNMENT;421 cbAlignment = RTHEAPOFFSET_ALIGNMENT; 408 422 else 409 423 { 410 424 Assert(!(cbAlignment & (cbAlignment - 1))); 411 425 Assert((cbAlignment & ~(cbAlignment - 1)) == cbAlignment); 412 if (cbAlignment < RTHEAP SIMPLE_ALIGNMENT)413 cbAlignment = RTHEAP SIMPLE_ALIGNMENT;426 if (cbAlignment < RTHEAPOFFSET_ALIGNMENT) 427 cbAlignment = RTHEAPOFFSET_ALIGNMENT; 414 428 } 415 429 … … 417 431 * Do the allocation. 418 432 */ 419 pBlock = rtHeap SimpleAllocBlock(pHeapInt, cb, cbAlignment);433 pBlock = rtHeapOffsetAllocBlock(pHeapInt, cb, cbAlignment); 420 434 if (RT_LIKELY(pBlock)) 421 435 { … … 425 439 return NULL; 426 440 } 427 RT_EXPORT_SYMBOL(RTHeap SimpleAlloc);428 429 430 RTDECL(void *) RTHeap SimpleAllocZ(RTHEAPSIMPLEhHeap, size_t cb, size_t cbAlignment)431 { 432 PRTHEAP SIMPLEINTERNAL pHeapInt = hHeap;433 PRTHEAP SIMPLEBLOCK pBlock;441 RT_EXPORT_SYMBOL(RTHeapOffsetAlloc); 442 443 444 RTDECL(void *) RTHeapOffsetAllocZ(RTHEAPOFFSET hHeap, size_t cb, size_t cbAlignment) 445 { 446 PRTHEAPOFFSETINTERNAL pHeapInt = hHeap; 447 PRTHEAPOFFSETBLOCK pBlock; 434 448 435 449 /* … … 437 451 */ 438 452 AssertPtrReturn(pHeapInt, NULL); 439 if (cb < RTHEAP SIMPLE_MIN_BLOCK)440 cb = RTHEAP SIMPLE_MIN_BLOCK;453 if (cb < RTHEAPOFFSET_MIN_BLOCK) 454 cb = RTHEAPOFFSET_MIN_BLOCK; 441 455 else 442 cb = RT_ALIGN_Z(cb, RTHEAP SIMPLE_ALIGNMENT);456 cb = RT_ALIGN_Z(cb, RTHEAPOFFSET_ALIGNMENT); 443 457 if (!cbAlignment) 444 cbAlignment = RTHEAP SIMPLE_ALIGNMENT;458 cbAlignment = RTHEAPOFFSET_ALIGNMENT; 445 459 else 446 460 { 447 461 Assert(!(cbAlignment & (cbAlignment - 1))); 448 462 Assert((cbAlignment & ~(cbAlignment - 1)) == cbAlignment); 449 if (cbAlignment < RTHEAP SIMPLE_ALIGNMENT)450 cbAlignment = RTHEAP SIMPLE_ALIGNMENT;463 if (cbAlignment < RTHEAPOFFSET_ALIGNMENT) 464 cbAlignment = RTHEAPOFFSET_ALIGNMENT; 451 465 } 452 466 … … 454 468 * Do the allocation. 455 469 */ 456 pBlock = rtHeap SimpleAllocBlock(pHeapInt, cb, cbAlignment);470 pBlock = rtHeapOffsetAllocBlock(pHeapInt, cb, cbAlignment); 457 471 if (RT_LIKELY(pBlock)) 458 472 { … … 463 477 return NULL; 464 478 } 465 RT_EXPORT_SYMBOL(RTHeap SimpleAllocZ);479 RT_EXPORT_SYMBOL(RTHeapOffsetAllocZ); 466 480 467 481 … … 478 492 * @param uAlignment The alignment specifications for the allocated block. 479 493 */ 480 static PRTHEAPSIMPLEBLOCK rtHeapSimpleAllocBlock(PRTHEAPSIMPLEINTERNAL pHeapInt, size_t cb, size_t uAlignment) 481 { 482 PRTHEAPSIMPLEBLOCK pRet = NULL; 483 PRTHEAPSIMPLEFREE pFree; 484 485 #ifdef RTHEAPSIMPLE_STRICT 486 rtHeapSimpleAssertAll(pHeapInt); 494 static PRTHEAPOFFSETBLOCK rtHeapOffsetAllocBlock(PRTHEAPOFFSETINTERNAL pHeapInt, size_t cb, size_t uAlignment) 495 { 496 PRTHEAPOFFSETBLOCK pRet = NULL; 497 PRTHEAPOFFSETFREE pFree; 498 499 AssertReturn((pHeapInt)->u32Magic == RTHEAPOFFSET_MAGIC, NULL); 500 #ifdef RTHEAPOFFSET_STRICT 501 rtHeapOffsetAssertAll(pHeapInt); 487 502 #endif 488 503 … … 490 505 * Search for a fitting block from the lower end of the heap. 491 506 */ 492 for (pFree = pHeapInt->pFreeHead;507 for (pFree = RTHEAPOFF_TO_PTR(pHeapInt, pHeapInt->offFreeHead, PRTHEAPOFFSETFREE); 493 508 pFree; 494 pFree = pFree->pNext)509 pFree = RTHEAPOFF_TO_PTR(pHeapInt, pFree->offNext, PRTHEAPOFFSETFREE)) 495 510 { 496 511 uintptr_t offAlign; … … 505 520 if (offAlign) 506 521 { 507 RTHEAP SIMPLEFREE Free;508 PRTHEAP SIMPLEBLOCK pPrev;522 RTHEAPOFFSETFREE Free; 523 PRTHEAPOFFSETBLOCK pPrev; 509 524 510 525 offAlign = uAlignment - offAlign; … … 516 531 */ 517 532 Free = *pFree; 518 pFree = (PRTHEAP SIMPLEFREE)((uintptr_t)pFree + offAlign);533 pFree = (PRTHEAPOFFSETFREE)((uintptr_t)pFree + offAlign); 519 534 520 535 /* … … 527 542 * for that.) 528 543 */ 529 pPrev = Free.Core.pPrev;544 pPrev = RTHEAPOFF_TO_PTR(pHeapInt, Free.Core.offPrev, PRTHEAPOFFSETBLOCK); 530 545 if (pPrev) 531 546 { 532 AssertMsg(!RTHEAP SIMPLEBLOCK_IS_FREE(pPrev), ("Impossible!\n"));533 pPrev-> pNext = &pFree->Core;547 AssertMsg(!RTHEAPOFFSETBLOCK_IS_FREE(pPrev), ("Impossible!\n")); 548 pPrev->offNext = RTHEAPOFF_TO_OFF(pHeapInt, pFree); 534 549 } 535 550 else 536 551 { 537 pPrev = (PRTHEAP SIMPLEBLOCK)(pHeapInt + 1);552 pPrev = (PRTHEAPOFFSETBLOCK)(pHeapInt + 1); 538 553 Assert(pPrev == &pFree->Core); 539 pPrev-> pPrev = NULL;540 pPrev-> pNext = &pFree->Core;541 pPrev-> pHeap = pHeapInt;542 pPrev->fFlags = RTHEAP SIMPLEBLOCK_FLAGS_MAGIC;554 pPrev->offPrev = 0; 555 pPrev->offNext = RTHEAPOFF_TO_OFF(pHeapInt, pFree); 556 pPrev->offSelf = RTHEAPOFF_TO_OFF(pHeapInt, pPrev); 557 pPrev->fFlags = RTHEAPOFFSETBLOCK_FLAGS_MAGIC; 543 558 } 544 559 pHeapInt->cbFree -= offAlign; … … 548 563 */ 549 564 *pFree = Free; 565 pFree->Core.offSelf = RTHEAPOFF_TO_OFF(pHeapInt, pFree); 550 566 551 567 /* the core */ 552 if (pFree->Core. pNext)553 pFree->Core.pNext->pPrev = &pFree->Core;554 pFree->Core. pPrev = pPrev;568 if (pFree->Core.offNext) 569 RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETBLOCK)->offPrev = pFree->Core.offSelf; 570 pFree->Core.offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pPrev); 555 571 556 572 /* the free part */ 557 573 pFree->cb -= offAlign; 558 if (pFree-> pNext)559 pFree->pNext->pPrev = pFree;574 if (pFree->offNext) 575 RTHEAPOFF_TO_PTR(pHeapInt, pFree->offNext, PRTHEAPOFFSETFREE)->offPrev = pFree->Core.offSelf; 560 576 else 561 pHeapInt-> pFreeTail = pFree;562 if (pFree-> pPrev)563 pFree->pPrev->pNext = pFree;577 pHeapInt->offFreeTail = pFree->Core.offSelf; 578 if (pFree->offPrev) 579 RTHEAPOFF_TO_PTR(pHeapInt, pFree->offPrev, PRTHEAPOFFSETFREE)->offNext = pFree->Core.offSelf; 564 580 else 565 pHeapInt-> pFreeHead = pFree;581 pHeapInt->offFreeHead = pFree->Core.offSelf; 566 582 ASSERT_BLOCK_FREE(pHeapInt, pFree); 567 583 ASSERT_BLOCK_USED(pHeapInt, pPrev); … … 571 587 * Split off a new FREE block? 572 588 */ 573 if (pFree->cb >= cb + RT_ALIGN_Z(sizeof(RTHEAP SIMPLEFREE), RTHEAPSIMPLE_ALIGNMENT))589 if (pFree->cb >= cb + RT_ALIGN_Z(sizeof(RTHEAPOFFSETFREE), RTHEAPOFFSET_ALIGNMENT)) 574 590 { 575 591 /* 576 592 * Move the FREE block up to make room for the new USED block. 577 593 */ 578 PRTHEAP SIMPLEFREE pNew = (PRTHEAPSIMPLEFREE)((uintptr_t)&pFree->Core + cb + sizeof(RTHEAPSIMPLEBLOCK));579 580 pNew->Core. pNext = pFree->Core.pNext;581 if (pFree->Core.pNext)582 pFree->Core.pNext->pPrev = &pNew->Core;583 pNew->Core.pPrev = &pFree->Core;584 pNew->Core. pHeap = pHeapInt;585 pNew->Core.fFlags = RTHEAP SIMPLEBLOCK_FLAGS_MAGIC | RTHEAPSIMPLEBLOCK_FLAGS_FREE;586 587 pNew-> pNext = pFree->pNext;588 if (pNew-> pNext)589 pNew->pNext->pPrev = pNew;594 PRTHEAPOFFSETFREE pNew = (PRTHEAPOFFSETFREE)((uintptr_t)&pFree->Core + cb + sizeof(RTHEAPOFFSETBLOCK)); 595 596 pNew->Core.offSelf = RTHEAPOFF_TO_OFF(pHeapInt, pNew); 597 pNew->Core.offNext = pFree->Core.offNext; 598 if (pFree->Core.offNext) 599 RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETBLOCK)->offPrev = pNew->Core.offSelf; 600 pNew->Core.offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree); 601 pNew->Core.fFlags = RTHEAPOFFSETBLOCK_FLAGS_MAGIC | RTHEAPOFFSETBLOCK_FLAGS_FREE; 602 603 pNew->offNext = pFree->offNext; 604 if (pNew->offNext) 605 RTHEAPOFF_TO_PTR(pHeapInt, pNew->offNext, PRTHEAPOFFSETFREE)->offPrev = pNew->Core.offSelf; 590 606 else 591 pHeapInt-> pFreeTail = pNew;592 pNew-> pPrev = pFree->pPrev;593 if (pNew-> pPrev)594 pNew->pPrev->pNext = pNew;607 pHeapInt->offFreeTail = pNew->Core.offSelf; 608 pNew->offPrev = pFree->offPrev; 609 if (pNew->offPrev) 610 RTHEAPOFF_TO_PTR(pHeapInt, pNew->offPrev, PRTHEAPOFFSETFREE)->offNext = pNew->Core.offSelf; 595 611 else 596 pHeapInt-> pFreeHead = pNew;597 pNew->cb = (pNew->Core. pNext ? (uintptr_t)pNew->Core.pNext : (uintptr_t)pHeapInt->pvEnd) \598 - (uintptr_t)pNew - sizeof(RTHEAPSIMPLEBLOCK);612 pHeapInt->offFreeHead = pNew->Core.offSelf; 613 pNew->cb = (pNew->Core.offNext ? pNew->Core.offNext : pHeapInt->cbHeap) \ 614 - pNew->Core.offSelf - sizeof(RTHEAPOFFSETBLOCK); 599 615 ASSERT_BLOCK_FREE(pHeapInt, pNew); 600 616 … … 602 618 * Update the old FREE node making it a USED node. 603 619 */ 604 pFree->Core.fFlags &= ~RTHEAP SIMPLEBLOCK_FLAGS_FREE;605 pFree->Core. pNext = &pNew->Core;620 pFree->Core.fFlags &= ~RTHEAPOFFSETBLOCK_FLAGS_FREE; 621 pFree->Core.offNext = pNew->Core.offSelf; 606 622 pHeapInt->cbFree -= pFree->cb; 607 623 pHeapInt->cbFree += pNew->cb; … … 614 630 * Link it out of the free list. 615 631 */ 616 if (pFree-> pNext)617 pFree->pNext->pPrev = pFree->pPrev;632 if (pFree->offNext) 633 RTHEAPOFF_TO_PTR(pHeapInt, pFree->offNext, PRTHEAPOFFSETFREE)->offPrev = pFree->offPrev; 618 634 else 619 pHeapInt-> pFreeTail = pFree->pPrev;620 if (pFree-> pPrev)621 pFree->pPrev->pNext = pFree->pNext;635 pHeapInt->offFreeTail = pFree->offPrev; 636 if (pFree->offPrev) 637 RTHEAPOFF_TO_PTR(pHeapInt, pFree->offPrev, PRTHEAPOFFSETFREE)->offNext = pFree->offNext; 622 638 else 623 pHeapInt-> pFreeHead = pFree->pNext;639 pHeapInt->offFreeHead = pFree->offNext; 624 640 625 641 /* … … 627 643 */ 628 644 pHeapInt->cbFree -= pFree->cb; 629 pFree->Core.fFlags &= ~RTHEAP SIMPLEBLOCK_FLAGS_FREE;645 pFree->Core.fFlags &= ~RTHEAPOFFSETBLOCK_FLAGS_FREE; 630 646 pRet = &pFree->Core; 631 647 ASSERT_BLOCK_USED(pHeapInt, pRet); … … 634 650 } 635 651 636 #ifdef RTHEAP SIMPLE_STRICT637 rtHeap SimpleAssertAll(pHeapInt);652 #ifdef RTHEAPOFFSET_STRICT 653 rtHeapOffsetAssertAll(pHeapInt); 638 654 #endif 639 655 return pRet; … … 641 657 642 658 643 RTDECL(void) RTHeap SimpleFree(RTHEAPSIMPLEhHeap, void *pv)644 { 645 PRTHEAP SIMPLEINTERNAL pHeapInt;646 PRTHEAP SIMPLEBLOCK pBlock;659 RTDECL(void) RTHeapOffsetFree(RTHEAPOFFSET hHeap, void *pv) 660 { 661 PRTHEAPOFFSETINTERNAL pHeapInt; 662 PRTHEAPOFFSETBLOCK pBlock; 647 663 648 664 /* … … 652 668 return; 653 669 AssertPtr(pv); 654 Assert(RT_ALIGN_P(pv, RTHEAP SIMPLE_ALIGNMENT) == pv);670 Assert(RT_ALIGN_P(pv, RTHEAPOFFSET_ALIGNMENT) == pv); 655 671 656 672 /* 657 673 * Get the block and heap. If in strict mode, validate these. 658 674 */ 659 pBlock = (PRTHEAP SIMPLEBLOCK)pv - 1;660 pHeapInt = pBlock->pHeap;675 pBlock = (PRTHEAPOFFSETBLOCK)pv - 1; 676 pHeapInt = RTHEAPOFF_GET_ANCHOR(pBlock); 661 677 ASSERT_BLOCK_USED(pHeapInt, pBlock); 662 678 ASSERT_ANCHOR(pHeapInt); 663 Assert(pHeapInt == (PRTHEAP SIMPLEINTERNAL)hHeap || !hHeap);664 665 #ifdef RTHEAP SIMPLE_FREE_POISON679 Assert(pHeapInt == (PRTHEAPOFFSETINTERNAL)hHeap || !hHeap); 680 681 #ifdef RTHEAPOFFSET_FREE_POISON 666 682 /* 667 683 * Poison the block. 668 684 */ 669 685 const size_t cbBlock = (pBlock->pNext ? (uintptr_t)pBlock->pNext : (uintptr_t)pHeapInt->pvEnd) 670 - (uintptr_t)pBlock - sizeof(RTHEAP SIMPLEBLOCK);671 memset(pBlock + 1, RTHEAP SIMPLE_FREE_POISON, cbBlock);686 - (uintptr_t)pBlock - sizeof(RTHEAPOFFSETBLOCK); 687 memset(pBlock + 1, RTHEAPOFFSET_FREE_POISON, cbBlock); 672 688 #endif 673 689 … … 675 691 * Call worker which does the actual job. 676 692 */ 677 rtHeap SimpleFreeBlock(pHeapInt, pBlock);678 } 679 RT_EXPORT_SYMBOL(RTHeap SimpleFree);693 rtHeapOffsetFreeBlock(pHeapInt, pBlock); 694 } 695 RT_EXPORT_SYMBOL(RTHeapOffsetFree); 680 696 681 697 … … 686 702 * @param pBlock The memory block to free. 687 703 */ 688 static void rtHeap SimpleFreeBlock(PRTHEAPSIMPLEINTERNAL pHeapInt, PRTHEAPSIMPLEBLOCK pBlock)689 { 690 PRTHEAP SIMPLEFREE pFree = (PRTHEAPSIMPLEFREE)pBlock;691 PRTHEAP SIMPLEFREE pLeft;692 PRTHEAP SIMPLEFREE pRight;693 694 #ifdef RTHEAP SIMPLE_STRICT695 rtHeap SimpleAssertAll(pHeapInt);704 static void rtHeapOffsetFreeBlock(PRTHEAPOFFSETINTERNAL pHeapInt, PRTHEAPOFFSETBLOCK pBlock) 705 { 706 PRTHEAPOFFSETFREE pFree = (PRTHEAPOFFSETFREE)pBlock; 707 PRTHEAPOFFSETFREE pLeft; 708 PRTHEAPOFFSETFREE pRight; 709 710 #ifdef RTHEAPOFFSET_STRICT 711 rtHeapOffsetAssertAll(pHeapInt); 696 712 #endif 697 713 … … 702 718 pLeft = NULL; 703 719 pRight = NULL; 704 if (pHeapInt-> pFreeTail)705 { 706 pRight = (PRTHEAPSIMPLEFREE)pFree->Core.pNext;707 while (pRight && !RTHEAP SIMPLEBLOCK_IS_FREE(&pRight->Core))720 if (pHeapInt->offFreeTail) 721 { 722 pRight = RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETFREE); 723 while (pRight && !RTHEAPOFFSETBLOCK_IS_FREE(&pRight->Core)) 708 724 { 709 725 ASSERT_BLOCK(pHeapInt, &pRight->Core); 710 pRight = (PRTHEAPSIMPLEFREE)pRight->Core.pNext;726 pRight = RTHEAPOFF_TO_PTR(pHeapInt, pRight->Core.offNext, PRTHEAPOFFSETFREE); 711 727 } 712 728 if (!pRight) 713 pLeft = pHeapInt->pFreeTail;729 pLeft = RTHEAPOFF_TO_PTR(pHeapInt, pHeapInt->offFreeTail, PRTHEAPOFFSETFREE); 714 730 else 715 731 { 716 732 ASSERT_BLOCK_FREE(pHeapInt, pRight); 717 pLeft = pRight->pPrev;733 pLeft = RTHEAPOFF_TO_PTR(pHeapInt, pRight->offPrev, PRTHEAPOFFSETFREE); 718 734 } 719 735 if (pLeft) … … 721 737 } 722 738 AssertMsgReturnVoid(pLeft != pFree, ("Freed twice! pv=%p (pBlock=%p)\n", pBlock + 1, pBlock)); 723 ASSERT_L( pLeft, pFree);739 ASSERT_L(RTHEAPOFF_TO_OFF(pHeapInt, pLeft), RTHEAPOFF_TO_OFF(pHeapInt, pFree)); 724 740 Assert(!pRight || (uintptr_t)pRight > (uintptr_t)pFree); 725 Assert(!pLeft || pLeft->pNext== pRight);741 Assert(!pLeft || RTHEAPOFF_TO_PTR(pHeapInt, pLeft->offNext, PRTHEAPOFFSETFREE) == pRight); 726 742 727 743 /* … … 730 746 if (!pLeft) 731 747 { 732 Assert(pRight == pHeapInt->pFreeHead);733 pFree->Core.fFlags |= RTHEAP SIMPLEBLOCK_FLAGS_FREE;734 pFree-> pPrev = NULL;735 pFree-> pNext = pRight;748 Assert(pRight == RTHEAPOFF_TO_PTR(pHeapInt, pHeapInt->offFreeHead, PRTHEAPOFFSETFREE)); 749 pFree->Core.fFlags |= RTHEAPOFFSETBLOCK_FLAGS_FREE; 750 pFree->offPrev = 0; 751 pFree->offNext = RTHEAPOFF_TO_OFF(pHeapInt, pRight); 736 752 if (pRight) 737 pRight-> pPrev = pFree;753 pRight->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree); 738 754 else 739 pHeapInt-> pFreeTail = pFree;740 pHeapInt-> pFreeHead = pFree;755 pHeapInt->offFreeTail = RTHEAPOFF_TO_OFF(pHeapInt, pFree); 756 pHeapInt->offFreeHead = RTHEAPOFF_TO_OFF(pHeapInt, pFree); 741 757 } 742 758 else … … 745 761 * Can we merge with left hand free block? 746 762 */ 747 if (pLeft->Core. pNext == &pFree->Core)763 if (pLeft->Core.offNext == RTHEAPOFF_TO_OFF(pHeapInt, pFree)) 748 764 { 749 pLeft->Core. pNext = pFree->Core.pNext;750 if (pFree->Core. pNext)751 pFree->Core.pNext->pPrev = &pLeft->Core;765 pLeft->Core.offNext = pFree->Core.offNext; 766 if (pFree->Core.offNext) 767 RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETBLOCK)->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pLeft); 752 768 pHeapInt->cbFree -= pLeft->cb; 753 769 pFree = pLeft; … … 758 774 else 759 775 { 760 pFree->Core.fFlags |= RTHEAP SIMPLEBLOCK_FLAGS_FREE;761 pFree-> pNext = pRight;762 pFree-> pPrev = pLeft;763 pLeft-> pNext = pFree;776 pFree->Core.fFlags |= RTHEAPOFFSETBLOCK_FLAGS_FREE; 777 pFree->offNext = RTHEAPOFF_TO_OFF(pHeapInt, pRight); 778 pFree->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pLeft); 779 pLeft->offNext = RTHEAPOFF_TO_OFF(pHeapInt, pFree); 764 780 if (pRight) 765 pRight-> pPrev = pFree;781 pRight->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree); 766 782 else 767 pHeapInt-> pFreeTail = pFree;783 pHeapInt->offFreeTail = RTHEAPOFF_TO_OFF(pHeapInt, pFree); 768 784 } 769 785 } … … 773 789 */ 774 790 if ( pRight 775 && pRight->Core. pPrev == &pFree->Core)791 && pRight->Core.offPrev == RTHEAPOFF_TO_OFF(pHeapInt, pFree)) 776 792 { 777 793 /* core */ 778 pFree->Core. pNext = pRight->Core.pNext;779 if (pRight->Core. pNext)780 pRight->Core.pNext->pPrev = &pFree->Core;794 pFree->Core.offNext = pRight->Core.offNext; 795 if (pRight->Core.offNext) 796 RTHEAPOFF_TO_PTR(pHeapInt, pRight->Core.offNext, PRTHEAPOFFSETBLOCK)->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree); 781 797 782 798 /* free */ 783 pFree-> pNext = pRight->pNext;784 if (pRight-> pNext)785 pRight->pNext->pPrev = pFree;799 pFree->offNext = pRight->offNext; 800 if (pRight->offNext) 801 RTHEAPOFF_TO_PTR(pHeapInt, pRight->offNext, PRTHEAPOFFSETFREE)->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree); 786 802 else 787 pHeapInt-> pFreeTail = pFree;803 pHeapInt->offFreeTail = RTHEAPOFF_TO_OFF(pHeapInt, pFree); 788 804 pHeapInt->cbFree -= pRight->cb; 789 805 } … … 792 808 * Calculate the size and update free stats. 793 809 */ 794 pFree->cb = (pFree->Core. pNext ? (uintptr_t)pFree->Core.pNext : (uintptr_t)pHeapInt->pvEnd)795 - (uintptr_t)pFree - sizeof(RTHEAPSIMPLEBLOCK);810 pFree->cb = (pFree->Core.offNext ? pFree->Core.offNext : pHeapInt->cbHeap) 811 - RTHEAPOFF_TO_OFF(pHeapInt, pFree) - sizeof(RTHEAPOFFSETBLOCK); 796 812 pHeapInt->cbFree += pFree->cb; 797 813 ASSERT_BLOCK_FREE(pHeapInt, pFree); 798 814 799 #ifdef RTHEAP SIMPLE_STRICT800 rtHeap SimpleAssertAll(pHeapInt);801 #endif 802 } 803 804 805 #ifdef RTHEAP SIMPLE_STRICT815 #ifdef RTHEAPOFFSET_STRICT 816 rtHeapOffsetAssertAll(pHeapInt); 817 #endif 818 } 819 820 821 #ifdef RTHEAPOFFSET_STRICT 806 822 /** 807 823 * Internal consistency check (relying on assertions). 808 824 * @param pHeapInt 809 825 */ 810 static void rtHeap SimpleAssertAll(PRTHEAPSIMPLEINTERNAL pHeapInt)811 { 812 PRTHEAP SIMPLEFREE pPrev = NULL;813 PRTHEAP SIMPLEFREE pPrevFree = NULL;814 PRTHEAP SIMPLEFREE pBlock;815 for (pBlock = (PRTHEAP SIMPLEFREE)(pHeapInt + 1);826 static void rtHeapOffsetAssertAll(PRTHEAPOFFSETINTERNAL pHeapInt) 827 { 828 PRTHEAPOFFSETFREE pPrev = NULL; 829 PRTHEAPOFFSETFREE pPrevFree = NULL; 830 PRTHEAPOFFSETFREE pBlock; 831 for (pBlock = (PRTHEAPOFFSETFREE)(pHeapInt + 1); 816 832 pBlock; 817 pBlock = (PRTHEAPSIMPLEFREE)pBlock->Core.pNext)818 { 819 if (RTHEAP SIMPLEBLOCK_IS_FREE(&pBlock->Core))833 pBlock = RTHEAPOFF_TO_PTR(pHeapInt, pBlock->Core.offNext, PRTHEAPOFFSETFREE)) 834 { 835 if (RTHEAPOFFSETBLOCK_IS_FREE(&pBlock->Core)) 820 836 { 821 837 ASSERT_BLOCK_FREE(pHeapInt, pBlock); 822 Assert(pBlock-> pPrev == pPrevFree);823 Assert(pPrevFree || pHeapInt-> pFreeHead == pBlock);838 Assert(pBlock->offPrev == RTHEAPOFF_TO_OFF(pHeapInt, pPrevFree)); 839 Assert(pPrevFree || pHeapInt->offFreeHead == RTHEAPOFF_TO_OFF(pHeapInt, pBlock)); 824 840 pPrevFree = pBlock; 825 841 } 826 842 else 827 843 ASSERT_BLOCK_USED(pHeapInt, &pBlock->Core); 828 Assert(!pPrev || pPrev == (PRTHEAPSIMPLEFREE)pBlock->Core.pPrev);844 Assert(!pPrev || RTHEAPOFF_TO_OFF(pHeapInt, pPrev) == pBlock->Core.offPrev); 829 845 pPrev = pBlock; 830 846 } 831 Assert(pHeapInt-> pFreeTail == pPrevFree);832 } 833 #endif 834 835 836 RTDECL(size_t) RTHeap SimpleSize(RTHEAPSIMPLEhHeap, void *pv)837 { 838 PRTHEAP SIMPLEINTERNAL pHeapInt;839 PRTHEAP SIMPLEBLOCK pBlock;847 Assert(pHeapInt->offFreeTail == RTHEAPOFF_TO_OFF(pHeapInt, pPrevFree)); 848 } 849 #endif 850 851 852 RTDECL(size_t) RTHeapOffsetSize(RTHEAPOFFSET hHeap, void *pv) 853 { 854 PRTHEAPOFFSETINTERNAL pHeapInt; 855 PRTHEAPOFFSETBLOCK pBlock; 840 856 size_t cbBlock; 841 857 … … 846 862 return 0; 847 863 AssertPtrReturn(pv, 0); 848 AssertReturn(RT_ALIGN_P(pv, RTHEAP SIMPLE_ALIGNMENT) == pv, 0);864 AssertReturn(RT_ALIGN_P(pv, RTHEAPOFFSET_ALIGNMENT) == pv, 0); 849 865 850 866 /* 851 867 * Get the block and heap. If in strict mode, validate these. 852 868 */ 853 pBlock = (PRTHEAP SIMPLEBLOCK)pv - 1;854 pHeapInt = pBlock->pHeap;869 pBlock = (PRTHEAPOFFSETBLOCK)pv - 1; 870 pHeapInt = RTHEAPOFF_GET_ANCHOR(pBlock); 855 871 ASSERT_BLOCK_USED(pHeapInt, pBlock); 856 872 ASSERT_ANCHOR(pHeapInt); 857 Assert(pHeapInt == (PRTHEAP SIMPLEINTERNAL)hHeap || !hHeap);873 Assert(pHeapInt == (PRTHEAPOFFSETINTERNAL)hHeap || !hHeap); 858 874 859 875 /* 860 876 * Calculate the block size. 861 877 */ 862 cbBlock = (pBlock-> pNext ? (uintptr_t)pBlock->pNext : (uintptr_t)pHeapInt->pvEnd)863 - (uintptr_t)pBlock- sizeof(RTHEAPSIMPLEBLOCK);878 cbBlock = (pBlock->offNext ? pBlock->offNext : pHeapInt->cbHeap) 879 - RTHEAPOFF_TO_OFF(pHeapInt, pBlock) - sizeof(RTHEAPOFFSETBLOCK); 864 880 return cbBlock; 865 881 } 866 RT_EXPORT_SYMBOL(RTHeap SimpleSize);867 868 869 RTDECL(size_t) RTHeap SimpleGetHeapSize(RTHEAPSIMPLEhHeap)870 { 871 PRTHEAP SIMPLEINTERNAL pHeapInt;872 873 if (hHeap == NIL_RTHEAP SIMPLE)882 RT_EXPORT_SYMBOL(RTHeapOffsetSize); 883 884 885 RTDECL(size_t) RTHeapOffsetGetHeapSize(RTHEAPOFFSET hHeap) 886 { 887 PRTHEAPOFFSETINTERNAL pHeapInt; 888 889 if (hHeap == NIL_RTHEAPOFFSET) 874 890 return 0; 875 891 … … 879 895 return pHeapInt->cbHeap; 880 896 } 881 RT_EXPORT_SYMBOL(RTHeap SimpleGetHeapSize);882 883 884 RTDECL(size_t) RTHeap SimpleGetFreeSize(RTHEAPSIMPLEhHeap)885 { 886 PRTHEAP SIMPLEINTERNAL pHeapInt;887 888 if (hHeap == NIL_RTHEAP SIMPLE)897 RT_EXPORT_SYMBOL(RTHeapOffsetGetHeapSize); 898 899 900 RTDECL(size_t) RTHeapOffsetGetFreeSize(RTHEAPOFFSET hHeap) 901 { 902 PRTHEAPOFFSETINTERNAL pHeapInt; 903 904 if (hHeap == NIL_RTHEAPOFFSET) 889 905 return 0; 890 906 … … 894 910 return pHeapInt->cbFree; 895 911 } 896 RT_EXPORT_SYMBOL(RTHeap SimpleGetFreeSize);897 898 899 RTDECL(void) RTHeap SimpleDump(RTHEAPSIMPLE hHeap, PFNRTHEAPSIMPLEPRINTF pfnPrintf)900 { 901 PRTHEAP SIMPLEINTERNAL pHeapInt = (PRTHEAPSIMPLEINTERNAL)hHeap;902 PRTHEAP SIMPLEFREE pBlock;903 904 pfnPrintf("**** Dumping Heap %p - cbHeap=% zx cbFree=%zx ****\n",912 RT_EXPORT_SYMBOL(RTHeapOffsetGetFreeSize); 913 914 915 RTDECL(void) RTHeapOffsetDump(RTHEAPOFFSET hHeap, PFNRTHEAPOFFSETPRINTF pfnPrintf) 916 { 917 PRTHEAPOFFSETINTERNAL pHeapInt = (PRTHEAPOFFSETINTERNAL)hHeap; 918 PRTHEAPOFFSETFREE pBlock; 919 920 pfnPrintf("**** Dumping Heap %p - cbHeap=%x cbFree=%x ****\n", 905 921 hHeap, pHeapInt->cbHeap, pHeapInt->cbFree); 906 922 907 for (pBlock = (PRTHEAP SIMPLEFREE)(pHeapInt + 1);923 for (pBlock = (PRTHEAPOFFSETFREE)(pHeapInt + 1); 908 924 pBlock; 909 pBlock = (PRTHEAPSIMPLEFREE)pBlock->Core.pNext)910 { 911 size_t cb = (pBlock-> pNext ? (uintptr_t)pBlock->Core.pNext : (uintptr_t)pHeapInt->pvEnd)912 - (uintptr_t)pBlock - sizeof(RTHEAPSIMPLEBLOCK);913 if (RTHEAP SIMPLEBLOCK_IS_FREE(&pBlock->Core))914 pfnPrintf("%p %06x FREE pNext=%p pPrev=%p fFlags=%#x cb=%#06x : cb=%#06x pNext=%p pPrev=%p\n",915 pBlock, (uintptr_t)pBlock - (uintptr_t)(pHeapInt + 1), pBlock->Core.pNext, pBlock->Core.pPrev, pBlock->Core.fFlags, cb,916 pBlock->cb, pBlock-> pNext, pBlock->pPrev);925 pBlock = RTHEAPOFF_TO_PTR(pHeapInt, pBlock->Core.offNext, PRTHEAPOFFSETFREE)) 926 { 927 size_t cb = (pBlock->offNext ? pBlock->Core.offNext : pHeapInt->cbHeap) 928 - RTHEAPOFF_TO_OFF(pHeapInt, pBlock) - sizeof(RTHEAPOFFSETBLOCK); 929 if (RTHEAPOFFSETBLOCK_IS_FREE(&pBlock->Core)) 930 pfnPrintf("%p %06x FREE offNext=%06x offPrev=%06x fFlags=%#x cb=%#06x : cb=%#06x offNext=%06x offPrev=%06x\n", 931 pBlock, pBlock->Core.offSelf, pBlock->Core.offNext, pBlock->Core.offPrev, pBlock->Core.fFlags, cb, 932 pBlock->cb, pBlock->offNext, pBlock->offPrev); 917 933 else 918 pfnPrintf("%p %06x USED pNext=%p pPrev=%pfFlags=%#x cb=%#06x\n",919 pBlock, (uintptr_t)pBlock - (uintptr_t)(pHeapInt + 1), pBlock->Core.pNext, pBlock->Core.pPrev, pBlock->Core.fFlags, cb);934 pfnPrintf("%p %06x USED offNext=%06x offPrev=%06x fFlags=%#x cb=%#06x\n", 935 pBlock, pBlock->Core.offSelf, pBlock->Core.offNext, pBlock->Core.offPrev, pBlock->Core.fFlags, cb); 920 936 } 921 937 pfnPrintf("**** Done dumping Heap %p ****\n", hHeap); 922 938 } 923 RT_EXPORT_SYMBOL(RTHeap SimpleDump);924 939 RT_EXPORT_SYMBOL(RTHeapOffsetDump); 940
Note:
See TracChangeset
for help on using the changeset viewer.