1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 11c6d6fed3c0a82bb7a09095381b974e8e5eebcb35pbos@webrtc.org#include "webrtc/system_wrappers/interface/aligned_malloc.h" 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <memory.h> 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <stdlib.h> 15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#if _WIN32 17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <windows.h> 18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#else 19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <stdint.h> 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 22c6d6fed3c0a82bb7a09095381b974e8e5eebcb35pbos@webrtc.org#include "webrtc/typedefs.h" 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Reference on memory alignment: 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc { 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orguintptr_t GetRightAlign(uintptr_t start_pos, size_t alignment) { 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The pointer should be aligned with |alignment| bytes. The - 1 guarantees 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // that it is aligned towards the closest higher (right) address. 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (start_pos + alignment - 1) & ~(alignment - 1); 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Alignment must be an integer power of two. 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool ValidAlignment(size_t alignment) { 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!alignment) { 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return (alignment & (alignment - 1)) == 0; 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid* GetRightAlign(const void* pointer, size_t alignment) { 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!pointer) { 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return NULL; 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!ValidAlignment(alignment)) { 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return NULL; 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uintptr_t start_pos = reinterpret_cast<uintptr_t>(pointer); 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return reinterpret_cast<void*>(GetRightAlign(start_pos, alignment)); 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid* AlignedMalloc(size_t size, size_t alignment) { 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (size == 0) { 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return NULL; 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!ValidAlignment(alignment)) { 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return NULL; 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The memory is aligned towards the lowest address that so only 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // alignment - 1 bytes needs to be allocated. 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // A pointer to the start of the memory must be stored so that it can be 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // retreived for deletion, ergo the sizeof(uintptr_t). 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org void* memory_pointer = malloc(size + sizeof(uintptr_t) + alignment - 1); 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (memory_pointer == NULL) { 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return NULL; 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Aligning after the sizeof(uintptr_t) bytes will leave room for the header 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // in the same memory block. 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uintptr_t align_start_pos = reinterpret_cast<uintptr_t>(memory_pointer); 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org align_start_pos += sizeof(uintptr_t); 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uintptr_t aligned_pos = GetRightAlign(align_start_pos, alignment); 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org void* aligned_pointer = reinterpret_cast<void*>(aligned_pos); 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Store the address to the beginning of the memory just before the aligned 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // memory. 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uintptr_t header_pos = aligned_pos - sizeof(uintptr_t); 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org void* header_pointer = reinterpret_cast<void*>(header_pos); 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uintptr_t memory_start = reinterpret_cast<uintptr_t>(memory_pointer); 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(header_pointer, &memory_start, sizeof(uintptr_t)); 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return aligned_pointer; 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AlignedFree(void* mem_block) { 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (mem_block == NULL) { 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return; 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uintptr_t aligned_pos = reinterpret_cast<uintptr_t>(mem_block); 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uintptr_t header_pos = aligned_pos - sizeof(uintptr_t); 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Read out the address of the AlignedMemory struct from the header. 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uintptr_t memory_start_pos = *reinterpret_cast<uintptr_t*>(header_pos); 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org void* memory_start = reinterpret_cast<void*>(memory_start_pos); 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org free(memory_start); 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} // namespace webrtc 101