bullet3/test/Bullet2/Source/Utils.cpp

266 lines
5.2 KiB
C++
Raw Normal View History

//
// 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();
}