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