| /* |
| * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "aligned_malloc.h" |
| |
| #include <assert.h> |
| #include <memory.h> |
| |
| #ifdef ANDROID |
| #include <stdlib.h> |
| #endif |
| |
| #if WEBRTC_MAC |
| #include <malloc/malloc.h> |
| #else |
| #include <malloc.h> |
| #endif |
| |
| #if _WIN32 |
| #include <windows.h> |
| #else |
| #include <stdint.h> |
| #endif |
| |
| #include "typedefs.h" |
| |
| // Ok reference on memory alignment: |
| // http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me |
| |
| namespace webrtc |
| { |
| // TODO (hellner) better to create just one memory block and |
| // interpret the first sizeof(AlignedMemory) bytes as |
| // an AlignedMemory struct. |
| struct AlignedMemory |
| { |
| void* alignedBuffer; |
| void* memoryPointer; |
| }; |
| |
| void* AlignedMalloc(size_t size, size_t alignment) |
| { |
| if(alignment == 0) |
| { |
| // Don't allow alignment 0 since it's undefined. |
| return NULL; |
| } |
| // Make sure that the alignment is an integer power of two or fail. |
| if(alignment & (alignment - 1)) |
| { |
| return NULL; |
| } |
| |
| AlignedMemory* returnValue = new AlignedMemory(); |
| if(returnValue == NULL) |
| { |
| return NULL; |
| } |
| |
| // The memory is aligned towards the lowest address that so only |
| // alignment - 1 bytes needs to be allocated. |
| // A pointer to AlignedMemory must be stored so that it can be retreived for |
| // deletion, ergo the sizeof(uintptr_t). |
| returnValue->memoryPointer = malloc(size + sizeof(uintptr_t) + |
| alignment - 1); |
| if(returnValue->memoryPointer == NULL) |
| { |
| delete returnValue; |
| return NULL; |
| } |
| |
| // Alligning after the sizeof(header) bytes will leave room for the header |
| // in the same memory block. |
| uintptr_t alignStartPos = (uintptr_t)returnValue->memoryPointer; |
| alignStartPos += sizeof(uintptr_t); |
| |
| // The buffer should be aligned with 'alignment' bytes. The - 1 guarantees |
| // that we align towards the lowest address. |
| uintptr_t alignedPos = (alignStartPos + alignment - 1) & ~(alignment - 1); |
| |
| // alignedPos is the address sought for. |
| returnValue->alignedBuffer = (void*)alignedPos; |
| |
| // Store the address to the AlignedMemory struct in the header so that a |
| // it's possible to reclaim all memory. |
| uintptr_t headerPos = alignedPos; |
| headerPos -= sizeof(uintptr_t); |
| void* headerPtr = (void*) headerPos; |
| uintptr_t headerValue = (uintptr_t)returnValue; |
| memcpy(headerPtr,&headerValue,sizeof(uintptr_t)); |
| |
| return returnValue->alignedBuffer; |
| } |
| |
| void AlignedFree(void* memBlock) |
| { |
| if(memBlock == NULL) |
| { |
| return; |
| } |
| uintptr_t alignedPos = (uintptr_t)memBlock; |
| uintptr_t headerPos = alignedPos - sizeof(uintptr_t); |
| |
| // Read out the address of the AlignedMemory struct from the header. |
| uintptr_t* headerPtr = (uintptr_t*)headerPos; |
| AlignedMemory* deleteMemory = (AlignedMemory*) *headerPtr; |
| |
| if(deleteMemory->memoryPointer != NULL) |
| { |
| free(deleteMemory->memoryPointer); |
| } |
| delete deleteMemory; |
| } |
| } // namespace webrtc |