• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
37 namespace 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.
42 struct AlignedMemory
43 {
44   void* alignedBuffer;
45   void* memoryPointer;
46 };
47 
AlignedMalloc(size_t size,size_t alignment)48 void* 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 
AlignedFree(void * memBlock)102 void 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