Utils.cpp 6.1 KB

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