Apple contribution for OSX SSE and iOS NEON optimizations unit tests, thanks to Jordan Hubbard, Ian Ollmann and Hristo Hristov.
For OSX: cd build ./premake_osx xcode4 for iOS: cd build ./ios_build.sh ./ios_run.sh Also integrated the branches/StackAllocation to make it easier to multi-thread collision detection in the near future. It avoids changing the btCollisionObject while performing collision detection. As this is a large patch, some stuff might be temporarily broken, I'll keep an eye out on issues.
This commit is contained in:
272
Test/Source/Utils.cpp
Normal file
272
Test/Source/Utils.cpp
Normal file
@@ -0,0 +1,272 @@
|
||||
//
|
||||
// File.c
|
||||
// BulletTest
|
||||
//
|
||||
// Copyright (c) 2011 Apple Inc.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef __APPLE__
|
||||
#include <mach/mach_time.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include "LinearMath/btAlignedAllocator.h"
|
||||
|
||||
#endif //__APPLE__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
#pragma mark Timing
|
||||
|
||||
int gReportNanoseconds = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <intrin.h>
|
||||
uint64_t ReadTicks( void )
|
||||
{
|
||||
return __rdtsc();
|
||||
}
|
||||
double TicksToCycles( uint64_t delta )
|
||||
{
|
||||
return double(delta);
|
||||
}
|
||||
|
||||
double TicksToSeconds( uint64_t delta )
|
||||
{
|
||||
return double(delta);
|
||||
}
|
||||
|
||||
void *GuardCalloc( size_t count, size_t size, size_t *objectStride )
|
||||
{
|
||||
if (objectStride)
|
||||
*objectStride = size;
|
||||
return (void*) btAlignedAlloc(count * size,16);
|
||||
}
|
||||
void GuardFree( void *buf )
|
||||
{
|
||||
btAlignedFree(buf);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
uint64_t ReadTicks( void )
|
||||
{
|
||||
return mach_absolute_time();
|
||||
}
|
||||
|
||||
double TicksToCycles( uint64_t delta )
|
||||
{
|
||||
static long double conversion = 0.0L;
|
||||
if( 0.0L == conversion )
|
||||
{
|
||||
// attempt to get conversion to nanoseconds
|
||||
mach_timebase_info_data_t info;
|
||||
int err = mach_timebase_info( &info );
|
||||
if( err )
|
||||
return __builtin_nanf("");
|
||||
conversion = (long double) info.numer / info.denom;
|
||||
|
||||
// attempt to get conversion to cycles
|
||||
if( 0 == gReportNanoseconds )
|
||||
{
|
||||
uint64_t frequency = 0;
|
||||
size_t freq_size = sizeof( frequency );
|
||||
err = sysctlbyname( "hw.cpufrequency_max", &frequency, &freq_size, NULL, 0 );
|
||||
if( err || 0 == frequency )
|
||||
vlog( "Failed to get max cpu frequency. Reporting times as nanoseconds.\n" );
|
||||
else
|
||||
{
|
||||
conversion *= 1e-9L /* sec / ns */ * frequency /* cycles / sec */;
|
||||
vlog( "Reporting times as cycles. (%2.2f MHz)\n", 1e-6 * frequency );
|
||||
}
|
||||
}
|
||||
else
|
||||
vlog( "Reporting times as nanoseconds.\n" );
|
||||
}
|
||||
|
||||
return (double) (delta * conversion);
|
||||
}
|
||||
|
||||
double TicksToSeconds( uint64_t delta )
|
||||
{
|
||||
static long double conversion = 0.0L;
|
||||
if( 0.0L == conversion )
|
||||
{
|
||||
// attempt to get conversion to nanoseconds
|
||||
mach_timebase_info_data_t info;
|
||||
int err = mach_timebase_info( &info );
|
||||
if( err )
|
||||
return __builtin_nanf("");
|
||||
conversion = info.numer / (1e9L * info.denom);
|
||||
}
|
||||
|
||||
return (double) (delta * conversion);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark GuardCalloc
|
||||
|
||||
#define kPageSize 4096
|
||||
|
||||
|
||||
typedef struct BufInfo
|
||||
{
|
||||
void *head;
|
||||
size_t count;
|
||||
size_t stride;
|
||||
size_t totalSize;
|
||||
}BufInfo;
|
||||
|
||||
static int GuardMarkBuffer( void *buffer, int flag );
|
||||
|
||||
void *GuardCalloc( size_t count, size_t size, size_t *objectStride )
|
||||
{
|
||||
if( objectStride )
|
||||
*objectStride = 0;
|
||||
|
||||
// Round size up to a multiple of a page size
|
||||
size_t stride = (size + kPageSize - 1) & -kPageSize;
|
||||
|
||||
//Calculate total size of the allocation
|
||||
size_t totalSize = count * (stride + kPageSize) + kPageSize;
|
||||
|
||||
// Allocate
|
||||
char *buf = (char*)mmap( NULL,
|
||||
totalSize,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_ANON | MAP_SHARED,
|
||||
0, 0 );
|
||||
if( MAP_FAILED == buf )
|
||||
{
|
||||
vlog( "mmap failed: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Find the first byte of user data
|
||||
char *result = buf + kPageSize;
|
||||
|
||||
// Record what we did for posterity
|
||||
BufInfo *bptr = (BufInfo*) result - 1;
|
||||
bptr->head = buf;
|
||||
bptr->count = count;
|
||||
bptr->stride = stride;
|
||||
bptr->totalSize = totalSize;
|
||||
|
||||
// Place the first guard page. Masks our record above.
|
||||
if( mprotect(buf, kPageSize, PROT_NONE) )
|
||||
{
|
||||
munmap( buf, totalSize);
|
||||
vlog( "mprotect -1 failed: %d\n", errno );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Place the rest of the guard pages
|
||||
size_t i;
|
||||
char *p = result;
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
p += stride;
|
||||
if( mprotect(p, kPageSize, PROT_NONE) )
|
||||
{
|
||||
munmap( buf, totalSize);
|
||||
vlog( "mprotect %lu failed: %d\n", i, errno );
|
||||
return NULL;
|
||||
}
|
||||
p += kPageSize;
|
||||
}
|
||||
|
||||
// record the stride from object to object
|
||||
if( objectStride )
|
||||
*objectStride = stride + kPageSize;
|
||||
|
||||
// return pointer to first object
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void GuardFree( void *buf )
|
||||
{
|
||||
if( mprotect((char*)buf - kPageSize, kPageSize, PROT_READ) )
|
||||
{
|
||||
vlog( "Unable to read buf info. GuardFree failed! %p (%d)\n", buf, errno );
|
||||
return;
|
||||
}
|
||||
|
||||
BufInfo *bptr = (BufInfo*) buf - 1;
|
||||
|
||||
if( munmap( bptr->head, bptr->totalSize ) )
|
||||
vlog( "Unable to unmap data. GuardFree failed! %p (%d)\n", buf, errno );
|
||||
}
|
||||
|
||||
int GuardMarkReadOnly( void *buf )
|
||||
{
|
||||
return GuardMarkBuffer(buf, PROT_READ);
|
||||
}
|
||||
|
||||
int GuardMarkReadWrite( void *buf)
|
||||
{
|
||||
return GuardMarkBuffer(buf, PROT_READ | PROT_WRITE);
|
||||
}
|
||||
|
||||
int GuardMarkWriteOnly( void *buf)
|
||||
{
|
||||
return GuardMarkBuffer(buf, PROT_WRITE);
|
||||
}
|
||||
|
||||
static int GuardMarkBuffer( void *buf, int flag )
|
||||
{
|
||||
if( mprotect((char*)buf - kPageSize, kPageSize, PROT_READ) )
|
||||
{
|
||||
vlog( "Unable to read buf info. GuardMarkBuffer %d failed! %p (%d)\n", flag, buf, errno );
|
||||
return errno;
|
||||
}
|
||||
|
||||
BufInfo *bptr = (BufInfo*) buf - 1;
|
||||
|
||||
size_t count = bptr->count;
|
||||
size_t stride = bptr->stride;
|
||||
|
||||
size_t i;
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
if( mprotect(buf, stride, flag) )
|
||||
{
|
||||
vlog( "Unable to protect segment %ld. GuardMarkBuffer %d failed! %p (%d)\n", i, flag, buf, errno );
|
||||
return errno;
|
||||
}
|
||||
bptr += stride + kPageSize;
|
||||
}
|
||||
|
||||
if( mprotect((char*)buf - kPageSize, kPageSize, PROT_NONE) )
|
||||
{
|
||||
vlog( "Unable to protect leading guard page. GuardMarkBuffer %d failed! %p (%d)\n", flag, buf, errno );
|
||||
return errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t random_number32(void)
|
||||
{
|
||||
return ((uint32_t) rand() << 16) ^ rand();
|
||||
}
|
||||
|
||||
|
||||
uint64_t random_number64(void)
|
||||
{
|
||||
return ((uint64_t) rand() << 48) ^
|
||||
((uint64_t) rand() << 32) ^
|
||||
((uint64_t) rand() << 16) ^
|
||||
rand();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user