2014-05-07 15:54:08 +00:00
|
|
|
//
|
|
|
|
// 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"
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
#endif //__APPLE__
|
2014-05-07 15:54:08 +00:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "Utils.h"
|
|
|
|
|
|
|
|
#pragma mark Timing
|
|
|
|
|
|
|
|
int gReportNanoseconds = 0;
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include <intrin.h>
|
2018-09-23 21:17:31 +00:00
|
|
|
uint64_t ReadTicks(void)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
return __rdtsc();
|
2014-05-07 15:54:08 +00:00
|
|
|
}
|
2018-09-23 21:17:31 +00:00
|
|
|
double TicksToCycles(uint64_t delta)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
|
|
|
return double(delta);
|
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
double TicksToSeconds(uint64_t delta)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
|
|
|
return double(delta);
|
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
void *GuardCalloc(size_t count, size_t size, size_t *objectStride)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
|
|
|
if (objectStride)
|
|
|
|
*objectStride = size;
|
2018-09-23 21:17:31 +00:00
|
|
|
return (void *)btAlignedAlloc(count * size, 16);
|
2014-05-07 15:54:08 +00:00
|
|
|
}
|
2018-09-23 21:17:31 +00:00
|
|
|
void GuardFree(void *buf)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
|
|
|
btAlignedFree(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
uint64_t ReadTicks(void)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
return mach_absolute_time();
|
2014-05-07 15:54:08 +00:00
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
double TicksToCycles(uint64_t delta)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
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);
|
2014-05-07 15:54:08 +00:00
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
double TicksToSeconds(uint64_t delta)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
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);
|
2014-05-07 15:54:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
#pragma mark GuardCalloc
|
|
|
|
|
|
|
|
#define kPageSize 4096
|
|
|
|
|
|
|
|
typedef struct BufInfo
|
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
void *head;
|
|
|
|
size_t count;
|
|
|
|
size_t stride;
|
|
|
|
size_t totalSize;
|
|
|
|
} BufInfo;
|
2014-05-07 15:54:08 +00:00
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
static int GuardMarkBuffer(void *buffer, int flag);
|
2014-05-07 15:54:08 +00:00
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
void *GuardCalloc(size_t count, size_t size, size_t *objectStride)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
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;
|
2014-05-07 15:54:08 +00:00
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
// return pointer to first object
|
|
|
|
return result;
|
|
|
|
}
|
2014-05-07 15:54:08 +00:00
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
void GuardFree(void *buf)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
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);
|
2014-05-07 15:54:08 +00:00
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
int GuardMarkReadOnly(void *buf)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
return GuardMarkBuffer(buf, PROT_READ);
|
2014-05-07 15:54:08 +00:00
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
int GuardMarkReadWrite(void *buf)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
return GuardMarkBuffer(buf, PROT_READ | PROT_WRITE);
|
2014-05-07 15:54:08 +00:00
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
int GuardMarkWriteOnly(void *buf)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
return GuardMarkBuffer(buf, PROT_WRITE);
|
2014-05-07 15:54:08 +00:00
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
static int GuardMarkBuffer(void *buf, int flag)
|
2014-05-07 15:54:08 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
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;
|
2014-05-07 15:54:08 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
uint32_t random_number32(void)
|
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
return ((uint32_t)rand() << 16) ^ rand();
|
2014-05-07 15:54:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t random_number64(void)
|
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
return ((uint64_t)rand() << 48) ^
|
|
|
|
((uint64_t)rand() << 32) ^
|
|
|
|
((uint64_t)rand() << 16) ^
|
|
|
|
rand();
|
2014-05-07 15:54:08 +00:00
|
|
|
}
|