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:
henrike@webrtc.org
2012-09-29 03:49:36 +00:00
parent 2a476e9c95
commit cd9adf7ae3
4 changed files with 145 additions and 22 deletions

View File

@@ -11,15 +11,37 @@
#ifndef 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>
namespace webrtc
{
void* AlignedMalloc(
size_t size,
size_t alignment);
void AlignedFree(
void* memBlock);
}
#include "system_wrappers/interface/scoped_ptr.h"
namespace webrtc {
// Returns a pointer to the first boundry of |alignment| bytes following the
// address of |ptr|.
// 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_

View File

@@ -45,15 +45,43 @@ struct AlignedMemory
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;
}
// Make sure that the alignment is an integer power of two or fail.
if(alignment & (alignment - 1))
if (!ValidAlignment(alignment))
{
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;
}
@@ -80,19 +108,14 @@ void* AlignedMalloc(size_t size, size_t alignment)
// 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;
uintptr_t alignedPos = GetRightAlign(alignStartPos, alignment);
returnValue->alignedBuffer = reinterpret_cast<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;
void* headerPtr = reinterpret_cast<void*> (headerPos);
uintptr_t headerValue = (uintptr_t)returnValue;
memcpy(headerPtr,&headerValue,sizeof(uintptr_t));
@@ -118,4 +141,4 @@ void AlignedFree(void* memBlock)
}
delete deleteMemory;
}
} // namespace webrtc
} // namespace webrtc

View 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));
}

View File

@@ -202,6 +202,7 @@
'<(webrtc_root)/test/test.gyp:test_support_main',
],
'sources': [
'aligned_malloc_unittest.cc',
'condition_variable_unittest.cc',
'cpu_wrapper_unittest.cc',
'cpu_measurement_harness.h',