This cl adds an API for getting an aligned pointer from a pointer to memory. Also adds a short-hand for creating scoped pointers of aligned memory.
BUG=N/A Review URL: https://webrtc-codereview.appspot.com/849006 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2851 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@@ -11,15 +11,37 @@
|
|||||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
||||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
||||||
|
|
||||||
|
// The functions declared here
|
||||||
|
// 1) Allocates block of aligned memory.
|
||||||
|
// 2) Re-calculates a pointer such that it is aligned to a higher or equal
|
||||||
|
// address.
|
||||||
|
// Note: alignment must be a power of two. The alignment is in bytes.
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
namespace webrtc
|
#include "system_wrappers/interface/scoped_ptr.h"
|
||||||
{
|
|
||||||
void* AlignedMalloc(
|
namespace webrtc {
|
||||||
size_t size,
|
|
||||||
size_t alignment);
|
// Returns a pointer to the first boundry of |alignment| bytes following the
|
||||||
void AlignedFree(
|
// address of |ptr|.
|
||||||
void* memBlock);
|
// Note that there is no guarantee that the memory in question is available.
|
||||||
}
|
// |ptr| has no requirements other than it can't be NULL.
|
||||||
|
void* GetRightAlign(const void* ptr, size_t alignment);
|
||||||
|
|
||||||
|
// Allocates memory of |size| bytes aligned on an |alignment| boundry.
|
||||||
|
// The return value is a pointer to the memory. Note that the memory must
|
||||||
|
// be de-allocated using AlignedFree.
|
||||||
|
void* AlignedMalloc(size_t size, size_t alignment);
|
||||||
|
// De-allocates memory created using the AlignedMalloc() API.
|
||||||
|
void AlignedFree(void* memBlock);
|
||||||
|
|
||||||
|
// Scoped pointer to AlignedMalloc-memory.
|
||||||
|
template<typename T>
|
||||||
|
struct Allocator {
|
||||||
|
typedef scoped_ptr_malloc<T, AlignedFree> scoped_ptr_aligned;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ALIGNED_MALLOC_H_
|
||||||
|
|||||||
@@ -45,15 +45,43 @@ struct AlignedMemory
|
|||||||
void* memoryPointer;
|
void* memoryPointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
void* AlignedMalloc(size_t size, size_t alignment)
|
uintptr_t GetRightAlign(uintptr_t startPos, size_t alignment)
|
||||||
{
|
{
|
||||||
if(alignment == 0)
|
// The pointer should be aligned with |alignment| bytes. The - 1 guarantees
|
||||||
|
// that it is aligned towards the closest higher (right) address.
|
||||||
|
return (startPos + 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* ptr, size_t alignment)
|
||||||
|
{
|
||||||
|
if (!ptr)
|
||||||
{
|
{
|
||||||
// Don't allow alignment 0 since it's undefined.
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// Make sure that the alignment is an integer power of two or fail.
|
if (!ValidAlignment(alignment))
|
||||||
if(alignment & (alignment - 1))
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
uintptr_t startPos = reinterpret_cast<uintptr_t> (ptr);
|
||||||
|
return reinterpret_cast<void*> (GetRightAlign(startPos, alignment));
|
||||||
|
}
|
||||||
|
|
||||||
|
void* AlignedMalloc(size_t size, size_t alignment)
|
||||||
|
{
|
||||||
|
if (size == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!ValidAlignment(alignment))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -80,19 +108,14 @@ void* AlignedMalloc(size_t size, size_t alignment)
|
|||||||
// in the same memory block.
|
// in the same memory block.
|
||||||
uintptr_t alignStartPos = (uintptr_t)returnValue->memoryPointer;
|
uintptr_t alignStartPos = (uintptr_t)returnValue->memoryPointer;
|
||||||
alignStartPos += sizeof(uintptr_t);
|
alignStartPos += sizeof(uintptr_t);
|
||||||
|
uintptr_t alignedPos = GetRightAlign(alignStartPos, alignment);
|
||||||
// The buffer should be aligned with 'alignment' bytes. The - 1 guarantees
|
returnValue->alignedBuffer = reinterpret_cast<void*> (alignedPos);
|
||||||
// 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
|
// Store the address to the AlignedMemory struct in the header so that a
|
||||||
// it's possible to reclaim all memory.
|
// it's possible to reclaim all memory.
|
||||||
uintptr_t headerPos = alignedPos;
|
uintptr_t headerPos = alignedPos;
|
||||||
headerPos -= sizeof(uintptr_t);
|
headerPos -= sizeof(uintptr_t);
|
||||||
void* headerPtr = (void*) headerPos;
|
void* headerPtr = reinterpret_cast<void*> (headerPos);
|
||||||
uintptr_t headerValue = (uintptr_t)returnValue;
|
uintptr_t headerValue = (uintptr_t)returnValue;
|
||||||
memcpy(headerPtr,&headerValue,sizeof(uintptr_t));
|
memcpy(headerPtr,&headerValue,sizeof(uintptr_t));
|
||||||
|
|
||||||
@@ -118,4 +141,4 @@ void AlignedFree(void* memBlock)
|
|||||||
}
|
}
|
||||||
delete deleteMemory;
|
delete deleteMemory;
|
||||||
}
|
}
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
77
src/system_wrappers/source/aligned_malloc_unittest.cc
Normal file
77
src/system_wrappers/source/aligned_malloc_unittest.cc
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 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 "system_wrappers/interface/aligned_malloc.h"
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "typedefs.h" // NOLINT
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
// Returns true if |size| and |alignment| are valid combinations.
|
||||||
|
bool CorrectUsage(size_t size, size_t alignment) {
|
||||||
|
webrtc::Allocator<char>::scoped_ptr_aligned scoped(
|
||||||
|
static_cast<char*> (webrtc::AlignedMalloc(size, alignment)));
|
||||||
|
if (scoped.get() == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const uintptr_t scoped_address = reinterpret_cast<uintptr_t> (scoped.get());
|
||||||
|
return 0u == scoped_address % alignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AlignedMalloc, GetRightAlign) {
|
||||||
|
const size_t size = 100;
|
||||||
|
const size_t alignment = 32;
|
||||||
|
const size_t left_missalignment = 8;
|
||||||
|
webrtc::Allocator<char>::scoped_ptr_aligned scoped(
|
||||||
|
static_cast<char*> (webrtc::AlignedMalloc(size, alignment)));
|
||||||
|
EXPECT_TRUE(scoped.get() != NULL);
|
||||||
|
const uintptr_t aligned_address = reinterpret_cast<uintptr_t> (scoped.get());
|
||||||
|
const uintptr_t missaligned_address = aligned_address - left_missalignment;
|
||||||
|
const void* missaligned_ptr = reinterpret_cast<void*> (missaligned_address);
|
||||||
|
const void* realignedPtr = webrtc::GetRightAlign(
|
||||||
|
missaligned_ptr, alignment);
|
||||||
|
EXPECT_EQ(scoped.get(), realignedPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AlignedMalloc, IncorrectSize) {
|
||||||
|
const size_t incorrect_size = 0;
|
||||||
|
const size_t alignment = 64;
|
||||||
|
EXPECT_FALSE(CorrectUsage(incorrect_size, alignment));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AlignedMalloc, IncorrectAlignment) {
|
||||||
|
const size_t size = 100;
|
||||||
|
const size_t incorrect_alignment = 63;
|
||||||
|
EXPECT_FALSE(CorrectUsage(size, incorrect_alignment));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AlignedMalloc, AlignTo2Bytes) {
|
||||||
|
size_t size = 100;
|
||||||
|
size_t alignment = 2;
|
||||||
|
EXPECT_TRUE(CorrectUsage(size, alignment));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AlignedMalloc, AlignTo32Bytes) {
|
||||||
|
size_t size = 100;
|
||||||
|
size_t alignment = 32;
|
||||||
|
EXPECT_TRUE(CorrectUsage(size, alignment));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AlignedMalloc, AlignTo128Bytes) {
|
||||||
|
size_t size = 100;
|
||||||
|
size_t alignment = 128;
|
||||||
|
EXPECT_TRUE(CorrectUsage(size, alignment));
|
||||||
|
}
|
||||||
@@ -202,6 +202,7 @@
|
|||||||
'<(webrtc_root)/test/test.gyp:test_support_main',
|
'<(webrtc_root)/test/test.gyp:test_support_main',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
|
'aligned_malloc_unittest.cc',
|
||||||
'condition_variable_unittest.cc',
|
'condition_variable_unittest.cc',
|
||||||
'cpu_wrapper_unittest.cc',
|
'cpu_wrapper_unittest.cc',
|
||||||
'cpu_measurement_harness.h',
|
'cpu_measurement_harness.h',
|
||||||
|
|||||||
Reference in New Issue
Block a user