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