blob: 62257533e35af0327ef328768cbba130e36ceaf8 [file] [log] [blame]
niklase@google.comf0779a22011-05-30 11:39:38 +00001/*
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
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