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