5 // Copyright (c) 2011 Apple Inc.
10 #include <mach/mach_time.h>
11 #include <sys/sysctl.h>
15 #include "LinearMath/btAlignedAllocator.h"
25 int gReportNanoseconds = 0;
29 uint64_t ReadTicks( void )
33 double TicksToCycles( uint64_t delta )
38 double TicksToSeconds( uint64_t delta )
43 void *GuardCalloc( size_t count, size_t size, size_t *objectStride )
47 return (void*) btAlignedAlloc(count * size,16);
49 void GuardFree( void *buf )
59 uint64_t ReadTicks( void )
61 return mach_absolute_time();
64 double TicksToCycles( uint64_t delta )
66 static long double conversion = 0.0L;
67 if( 0.0L == conversion )
69 // attempt to get conversion to nanoseconds
70 mach_timebase_info_data_t info;
71 int err = mach_timebase_info( &info );
73 return __builtin_nanf("");
74 conversion = (long double) info.numer / info.denom;
76 // attempt to get conversion to cycles
77 if( 0 == gReportNanoseconds )
79 uint64_t frequency = 0;
80 size_t freq_size = sizeof( frequency );
81 err = sysctlbyname( "hw.cpufrequency_max", &frequency, &freq_size, NULL, 0 );
82 if( err || 0 == frequency )
83 vlog( "Failed to get max cpu frequency. Reporting times as nanoseconds.\n" );
86 conversion *= 1e-9L /* sec / ns */ * frequency /* cycles / sec */;
87 vlog( "Reporting times as cycles. (%2.2f MHz)\n", 1e-6 * frequency );
91 vlog( "Reporting times as nanoseconds.\n" );
94 return (double) (delta * conversion);
97 double TicksToSeconds( uint64_t delta )
99 static long double conversion = 0.0L;
100 if( 0.0L == conversion )
102 // attempt to get conversion to nanoseconds
103 mach_timebase_info_data_t info;
104 int err = mach_timebase_info( &info );
106 return __builtin_nanf("");
107 conversion = info.numer / (1e9L * info.denom);
110 return (double) (delta * conversion);
116 #pragma mark GuardCalloc
118 #define kPageSize 4096
121 typedef struct BufInfo
129 static int GuardMarkBuffer( void *buffer, int flag );
131 void *GuardCalloc( size_t count, size_t size, size_t *objectStride )
136 // Round size up to a multiple of a page size
137 size_t stride = (size + kPageSize - 1) & -kPageSize;
139 //Calculate total size of the allocation
140 size_t totalSize = count * (stride + kPageSize) + kPageSize;
143 char *buf = (char*)mmap( NULL,
145 PROT_READ | PROT_WRITE,
146 MAP_ANON | MAP_SHARED,
148 if( MAP_FAILED == buf )
150 vlog( "mmap failed: %d\n", errno );
154 // Find the first byte of user data
155 char *result = buf + kPageSize;
157 // Record what we did for posterity
158 BufInfo *bptr = (BufInfo*) result - 1;
161 bptr->stride = stride;
162 bptr->totalSize = totalSize;
164 // Place the first guard page. Masks our record above.
165 if( mprotect(buf, kPageSize, PROT_NONE) )
167 munmap( buf, totalSize);
168 vlog( "mprotect -1 failed: %d\n", errno );
172 // Place the rest of the guard pages
175 for( i = 0; i < count; i++ )
178 if( mprotect(p, kPageSize, PROT_NONE) )
180 munmap( buf, totalSize);
181 vlog( "mprotect %lu failed: %d\n", i, errno );
187 // record the stride from object to object
189 *objectStride = stride + kPageSize;
191 // return pointer to first object
196 void GuardFree( void *buf )
198 if( mprotect((char*)buf - kPageSize, kPageSize, PROT_READ) )
200 vlog( "Unable to read buf info. GuardFree failed! %p (%d)\n", buf, errno );
204 BufInfo *bptr = (BufInfo*) buf - 1;
206 if( munmap( bptr->head, bptr->totalSize ) )
207 vlog( "Unable to unmap data. GuardFree failed! %p (%d)\n", buf, errno );
210 int GuardMarkReadOnly( void *buf )
212 return GuardMarkBuffer(buf, PROT_READ);
215 int GuardMarkReadWrite( void *buf)
217 return GuardMarkBuffer(buf, PROT_READ | PROT_WRITE);
220 int GuardMarkWriteOnly( void *buf)
222 return GuardMarkBuffer(buf, PROT_WRITE);
225 static int GuardMarkBuffer( void *buf, int flag )
227 if( mprotect((char*)buf - kPageSize, kPageSize, PROT_READ) )
229 vlog( "Unable to read buf info. GuardMarkBuffer %d failed! %p (%d)\n", flag, buf, errno );
233 BufInfo *bptr = (BufInfo*) buf - 1;
235 size_t count = bptr->count;
236 size_t stride = bptr->stride;
239 for( i = 0; i < count; i++ )
241 if( mprotect(buf, stride, flag) )
243 vlog( "Unable to protect segment %ld. GuardMarkBuffer %d failed! %p (%d)\n", i, flag, buf, errno );
246 bptr += stride + kPageSize;
249 if( mprotect((char*)buf - kPageSize, kPageSize, PROT_NONE) )
251 vlog( "Unable to protect leading guard page. GuardMarkBuffer %d failed! %p (%d)\n", flag, buf, errno );
259 uint32_t random_number32(void)
261 return ((uint32_t) rand() << 16) ^ rand();
265 uint64_t random_number64(void)
267 return ((uint64_t) rand() << 48) ^
268 ((uint64_t) rand() << 32) ^
269 ((uint64_t) rand() << 16) ^