1 /* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "aligned_malloc.h" 12 13 #include <assert.h> 14 #include <memory.h> 15 16 #ifdef ANDROID 17 #include <stdlib.h> 18 #endif 19 20 #if WEBRTC_MAC 21 #include <malloc/malloc.h> 22 #else 23 #include <malloc.h> 24 #endif 25 26 #if _WIN32 27 #include <windows.h> 28 #else 29 #include <stdint.h> 30 #endif 31 32 #include "typedefs.h" 33 34 // Ok reference on memory alignment: 35 // http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me 36 37 namespace webrtc 38 { 39 // TODO (hellner) better to create just one memory block and 40 // interpret the first sizeof(AlignedMemory) bytes as 41 // an AlignedMemory struct. 42 struct AlignedMemory 43 { 44 void* alignedBuffer; 45 void* memoryPointer; 46 }; 47 48 void* AlignedMalloc(size_t size, size_t alignment) 49 { 50 if(alignment == 0) 51 { 52 // Don't allow alignment 0 since it's undefined. 53 return NULL; 54 } 55 // Make sure that the alignment is an integer power of two or fail. 56 if(alignment & (alignment - 1)) 57 { 58 return NULL; 59 } 60 61 AlignedMemory* returnValue = new AlignedMemory(); 62 if(returnValue == NULL) 63 { 64 return NULL; 65 } 66 67 // The memory is aligned towards the lowest address that so only 68 // alignment - 1 bytes needs to be allocated. 69 // A pointer to AlignedMemory must be stored so that it can be retreived for 70 // deletion, ergo the sizeof(uintptr_t). 71 returnValue->memoryPointer = malloc(size + sizeof(uintptr_t) + 72 alignment - 1); 73 if(returnValue->memoryPointer == NULL) 74 { 75 delete returnValue; 76 return NULL; 77 } 78 79 // Alligning after the sizeof(header) bytes will leave room for the header 80 // in the same memory block. 81 uintptr_t alignStartPos = (uintptr_t)returnValue->memoryPointer; 82 alignStartPos += sizeof(uintptr_t); 83 84 // The buffer should be aligned with 'alignment' bytes. The - 1 guarantees 85 // that we align towards the lowest address. 86 uintptr_t alignedPos = (alignStartPos + alignment - 1) & ~(alignment - 1); 87 88 // alignedPos is the address sought for. 89 returnValue->alignedBuffer = (void*)alignedPos; 90 91 // Store the address to the AlignedMemory struct in the header so that a 92 // it's possible to reclaim all memory. 93 uintptr_t headerPos = alignedPos; 94 headerPos -= sizeof(uintptr_t); 95 void* headerPtr = (void*) headerPos; 96 uintptr_t headerValue = (uintptr_t)returnValue; 97 memcpy(headerPtr,&headerValue,sizeof(uintptr_t)); 98 99 return returnValue->alignedBuffer; 100 } 101 102 void AlignedFree(void* memBlock) 103 { 104 if(memBlock == NULL) 105 { 106 return; 107 } 108 uintptr_t alignedPos = (uintptr_t)memBlock; 109 uintptr_t headerPos = alignedPos - sizeof(uintptr_t); 110 111 // Read out the address of the AlignedMemory struct from the header. 112 uintptr_t* headerPtr = (uintptr_t*)headerPos; 113 AlignedMemory* deleteMemory = (AlignedMemory*) *headerPtr; 114 115 if(deleteMemory->memoryPointer != NULL) 116 { 117 free(deleteMemory->memoryPointer); 118 } 119 delete deleteMemory; 120 } 121 } // namespace webrtc 122