summaryrefslogtreecommitdiff
path: root/webrtc/rtc_base/memory/aligned_malloc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webrtc/rtc_base/memory/aligned_malloc.cc')
-rw-r--r--webrtc/rtc_base/memory/aligned_malloc.cc98
1 files changed, 98 insertions, 0 deletions
diff --git a/webrtc/rtc_base/memory/aligned_malloc.cc b/webrtc/rtc_base/memory/aligned_malloc.cc
new file mode 100644
index 0000000..b00fab2
--- /dev/null
+++ b/webrtc/rtc_base/memory/aligned_malloc.cc
@@ -0,0 +1,98 @@
+/*
+ * 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 "rtc_base/memory/aligned_malloc.h"
+
+#include <stdlib.h> // for free, malloc
+#include <string.h> // for memcpy
+
+#include "rtc_base/checks.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <stdint.h>
+#endif
+
+// Reference on memory alignment:
+// http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me
+namespace webrtc {
+
+uintptr_t GetRightAlign(uintptr_t start_pos, size_t alignment) {
+ // The pointer should be aligned with |alignment| bytes. The - 1 guarantees
+ // that it is aligned towards the closest higher (right) address.
+ return (start_pos + alignment - 1) & ~(alignment - 1);
+}
+
+// Alignment must be an integer power of two.
+bool ValidAlignment(size_t alignment) {
+ if (!alignment) {
+ return false;
+ }
+ return (alignment & (alignment - 1)) == 0;
+}
+
+void* GetRightAlign(const void* pointer, size_t alignment) {
+ if (!pointer) {
+ return NULL;
+ }
+ if (!ValidAlignment(alignment)) {
+ return NULL;
+ }
+ uintptr_t start_pos = reinterpret_cast<uintptr_t>(pointer);
+ return reinterpret_cast<void*>(GetRightAlign(start_pos, alignment));
+}
+
+void* AlignedMalloc(size_t size, size_t alignment) {
+ if (size == 0) {
+ return NULL;
+ }
+ if (!ValidAlignment(alignment)) {
+ return NULL;
+ }
+
+ // The memory is aligned towards the lowest address that so only
+ // alignment - 1 bytes needs to be allocated.
+ // A pointer to the start of the memory must be stored so that it can be
+ // retreived for deletion, ergo the sizeof(uintptr_t).
+ void* memory_pointer = malloc(size + sizeof(uintptr_t) + alignment - 1);
+ RTC_CHECK(memory_pointer) << "Couldn't allocate memory in AlignedMalloc";
+
+ // Aligning after the sizeof(uintptr_t) bytes will leave room for the header
+ // in the same memory block.
+ uintptr_t align_start_pos = reinterpret_cast<uintptr_t>(memory_pointer);
+ align_start_pos += sizeof(uintptr_t);
+ uintptr_t aligned_pos = GetRightAlign(align_start_pos, alignment);
+ void* aligned_pointer = reinterpret_cast<void*>(aligned_pos);
+
+ // Store the address to the beginning of the memory just before the aligned
+ // memory.
+ uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
+ void* header_pointer = reinterpret_cast<void*>(header_pos);
+ uintptr_t memory_start = reinterpret_cast<uintptr_t>(memory_pointer);
+ memcpy(header_pointer, &memory_start, sizeof(uintptr_t));
+
+ return aligned_pointer;
+}
+
+void AlignedFree(void* mem_block) {
+ if (mem_block == NULL) {
+ return;
+ }
+ uintptr_t aligned_pos = reinterpret_cast<uintptr_t>(mem_block);
+ uintptr_t header_pos = aligned_pos - sizeof(uintptr_t);
+
+ // Read out the address of the AlignedMemory struct from the header.
+ uintptr_t memory_start_pos = *reinterpret_cast<uintptr_t*>(header_pos);
+ void* memory_start = reinterpret_cast<void*>(memory_start_pos);
+ free(memory_start);
+}
+
+} // namespace webrtc