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 WEBRTC_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 37namespace 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. 42struct AlignedMemory 43{ 44 void* alignedBuffer; 45 void* memoryPointer; 46}; 47 48void* 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 102void 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