Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Test / Source / Utils.cpp
1 //
2 //  File.c
3 //  BulletTest
4 //
5 //  Copyright (c) 2011 Apple Inc.
6 //
7
8 #include <stdio.h>
9 #ifdef __APPLE__
10 #include <mach/mach_time.h>
11 #include <sys/sysctl.h>
12 #include <sys/mman.h>
13 #include <errno.h>
14 #else
15 #include "LinearMath/btAlignedAllocator.h"
16
17 #endif //__APPLE__
18
19 #include <stdlib.h>
20
21 #include "Utils.h"
22
23 #pragma mark Timing
24
25 int gReportNanoseconds = 0;
26
27 #ifdef _WIN32
28 #include <intrin.h>
29 uint64_t ReadTicks( void )
30 {
31          return __rdtsc();
32 }
33 double  TicksToCycles( uint64_t delta )
34 {
35         return double(delta);
36 }
37
38 double  TicksToSeconds( uint64_t delta )
39 {
40         return double(delta);
41 }
42
43 void *GuardCalloc( size_t count, size_t size, size_t *objectStride )
44 {
45         if (objectStride)
46                 *objectStride = size;
47         return (void*) btAlignedAlloc(count * size,16);
48 }
49 void GuardFree( void *buf )
50 {
51         btAlignedFree(buf);
52 }
53
54 #endif
55
56
57 #ifdef __APPLE__
58
59 uint64_t ReadTicks( void )
60 {
61     return mach_absolute_time();
62 }
63
64 double  TicksToCycles( uint64_t delta )
65 {
66     static long double conversion = 0.0L;
67     if( 0.0L == conversion )
68     {
69         // attempt to get conversion to nanoseconds
70         mach_timebase_info_data_t info;
71         int err = mach_timebase_info( &info );
72         if( err )
73             return __builtin_nanf("");
74         conversion = (long double) info.numer / info.denom;
75         
76         // attempt to get conversion to cycles
77         if( 0 == gReportNanoseconds )
78         {
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" );
84             else
85             {
86                 conversion *= 1e-9L /* sec / ns */  * frequency /* cycles / sec */;
87                 vlog( "Reporting times as cycles. (%2.2f MHz)\n", 1e-6 * frequency );
88             }
89         }
90         else
91             vlog( "Reporting times as nanoseconds.\n" );
92     }
93     
94     return (double) (delta * conversion);
95 }
96
97 double  TicksToSeconds( uint64_t delta )
98 {
99     static long double conversion = 0.0L;
100     if( 0.0L == conversion )
101     {
102         // attempt to get conversion to nanoseconds
103         mach_timebase_info_data_t info;
104         int err = mach_timebase_info( &info );
105         if( err )
106             return __builtin_nanf("");
107         conversion = info.numer / (1e9L * info.denom);
108     }
109     
110     return (double) (delta * conversion);
111 }
112
113
114
115 #pragma mark -
116 #pragma mark GuardCalloc
117
118 #define kPageSize 4096
119
120
121 typedef struct BufInfo
122 {
123     void    *head;
124     size_t  count;
125     size_t  stride;
126     size_t  totalSize;
127 }BufInfo;
128
129 static int GuardMarkBuffer( void *buffer, int flag );
130
131 void *GuardCalloc( size_t count, size_t size, size_t *objectStride )
132 {
133     if( objectStride )
134         *objectStride = 0;
135     
136     // Round size up to a multiple of a page size
137     size_t stride = (size + kPageSize - 1) & -kPageSize;
138     
139     //Calculate total size of the allocation
140     size_t totalSize = count * (stride + kPageSize) + kPageSize;
141
142     // Allocate
143     char *buf = (char*)mmap( NULL, 
144                      totalSize, 
145                      PROT_READ | PROT_WRITE, 
146                      MAP_ANON | MAP_SHARED,
147                      0, 0 );
148     if( MAP_FAILED == buf )
149     {
150         vlog( "mmap failed: %d\n", errno );
151         return NULL;
152     }
153
154     // Find the first byte of user data
155     char *result = buf + kPageSize;
156
157     // Record what we did for posterity
158     BufInfo *bptr = (BufInfo*) result - 1;
159     bptr->head = buf;
160     bptr->count = count;
161     bptr->stride = stride;
162     bptr->totalSize = totalSize;
163     
164     // Place the first guard page. Masks our record above.
165     if( mprotect(buf, kPageSize, PROT_NONE) )
166     {
167         munmap( buf, totalSize);
168         vlog( "mprotect -1 failed: %d\n", errno );
169         return NULL;
170     }
171     
172     // Place the rest of the guard pages
173     size_t i;
174     char *p = result;
175     for( i = 0; i < count; i++ )
176     {
177         p += stride;
178         if( mprotect(p, kPageSize, PROT_NONE) )
179         {
180             munmap( buf, totalSize);
181             vlog( "mprotect %lu failed: %d\n", i, errno );
182             return NULL;
183         }
184         p += kPageSize;
185     }
186     
187     // record the stride from object to object
188     if( objectStride )
189         *objectStride = stride + kPageSize;
190     
191     // return pointer to first object
192     return result;
193 }
194
195
196 void GuardFree( void *buf )
197 {
198     if( mprotect((char*)buf - kPageSize, kPageSize, PROT_READ) )
199     {
200         vlog( "Unable to read buf info. GuardFree failed! %p  (%d)\n", buf, errno );
201         return;
202     }
203     
204     BufInfo *bptr = (BufInfo*) buf - 1;
205     
206     if( munmap( bptr->head, bptr->totalSize ) )
207         vlog( "Unable to unmap data. GuardFree failed! %p (%d)\n", buf, errno );
208 }
209
210 int GuardMarkReadOnly( void *buf )
211 {
212     return GuardMarkBuffer(buf, PROT_READ);
213 }
214
215 int GuardMarkReadWrite( void *buf)
216 {
217     return GuardMarkBuffer(buf, PROT_READ | PROT_WRITE);
218 }
219
220 int GuardMarkWriteOnly( void *buf)
221 {
222     return GuardMarkBuffer(buf, PROT_WRITE);
223 }
224
225 static int GuardMarkBuffer( void *buf, int flag )
226 {
227     if( mprotect((char*)buf - kPageSize, kPageSize, PROT_READ) )
228     {
229         vlog( "Unable to read buf info. GuardMarkBuffer %d failed! %p  (%d)\n", flag, buf, errno );
230         return errno;
231     }
232     
233     BufInfo *bptr = (BufInfo*) buf - 1;
234     
235     size_t count = bptr->count;
236     size_t stride = bptr->stride;
237     
238     size_t i;
239     for( i = 0; i < count; i++ )
240     {
241         if( mprotect(buf, stride, flag) )
242         {
243             vlog( "Unable to protect segment %ld. GuardMarkBuffer %d failed! %p  (%d)\n", i, flag, buf, errno );
244             return errno;
245         }
246         bptr += stride + kPageSize;
247     }
248         
249     if( mprotect((char*)buf - kPageSize, kPageSize, PROT_NONE) )
250     {
251         vlog( "Unable to protect leading guard page. GuardMarkBuffer %d failed! %p  (%d)\n", flag, buf, errno );
252         return errno;
253     }
254     
255     return 0;
256 }
257 #endif
258
259 uint32_t random_number32(void)
260 {
261     return ((uint32_t) rand() << 16) ^ rand();
262 }
263
264
265 uint64_t random_number64(void)
266 {
267     return ((uint64_t) rand() << 48) ^
268             ((uint64_t) rand() << 32) ^
269             ((uint64_t) rand() << 16) ^
270             rand();
271 }
272