1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com> 
   4 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   5 // at your option, any later version. See the LICENSE.txt file for the text of 
   7 //----------------------------------------------------------------------------- 
   8 // utilities requiring Posix library functions 
   9 //----------------------------------------------------------------------------- 
  12 #define _POSIX_C_SOURCE 199309L                 // need nanosleep() 
  17 #include "util_posix.h" 
  26 static void nsleep(uint64_t n
) { 
  27         struct timespec timeout
; 
  28         timeout
.tv_sec 
= n
/1000000000; 
  29         timeout
.tv_nsec 
= n%1000000000
; 
  30         while (nanosleep(&timeout
, &timeout
) && errno 
== EINTR
); 
  33 void msleep(uint32_t n
) { 
  34         nsleep(1000000 * (uint64_t)n
); 
  40         #define CLOCK_MONOTONIC (1) 
  41         #define CLOCK_REALTIME (2) 
  44         #include <mach/clock.h> 
  45         #include <mach/mach.h> 
  46         #include <mach/mach_time.h> 
  48         /* clock_gettime is not implemented on OSX prior to 10.12 */ 
  49         int _civet_clock_gettime(int clk_id
, struct timespec 
*t
); 
  51         int _civet_clock_gettime(int clk_id
, struct timespec 
*t
) 
  53                 memset(t
, 0, sizeof(*t
)); 
  54                 if (clk_id 
== CLOCK_REALTIME
) { 
  56                         int rv 
= gettimeofday(&now
, NULL
); 
  60                         t
->tv_sec 
= now
.tv_sec
; 
  61                         t
->tv_nsec 
= now
.tv_usec 
* 1000; 
  64                 } else if (clk_id 
== CLOCK_MONOTONIC
) { 
  65                         static uint64_t clock_start_time 
= 0; 
  66                         static mach_timebase_info_data_t timebase_info 
= {0, 0}; 
  68                         uint64_t now 
= mach_absolute_time(); 
  70                         if (clock_start_time 
== 0) { 
  71                                 mach_timebase_info(&timebase_info
); 
  72                                 clock_start_time 
= now
; 
  75                         now 
= (uint64_t)((double)(now 
- clock_start_time
) 
  76                                          * (double)timebase_info
.numer
 
  77                                          / (double)timebase_info
.denom
); 
  79                         t
->tv_sec 
= now 
/ 1000000000; 
  80                         t
->tv_nsec 
= now 
% 1000000000; 
  83                 return -1; // EINVAL - Clock ID is unknown 
  86         /* if clock_gettime is declared, then __CLOCK_AVAILABILITY will be defined */ 
  87         #ifdef __CLOCK_AVAILABILITY 
  88                 /* If we compiled with Mac OSX 10.12 or later, then clock_gettime will be declared 
  89                  * but it may be NULL at runtime. So we need to check before using it. */ 
  90                 int _civet_safe_clock_gettime(int clk_id
, struct timespec 
*t
); 
  92                 int _civet_safe_clock_gettime(int clk_id
, struct timespec 
*t
) { 
  94                                 return clock_gettime(clk_id
, t
); 
  96                         return _civet_clock_gettime(clk_id
, t
); 
  98                 #define clock_gettime _civet_safe_clock_gettime 
 100                 #define clock_gettime _civet_clock_gettime 
 106 // a milliseconds timer for performance measurement 
 109         #include <sys/types.h> 
 111         // WORKAROUND FOR MinGW (some versions - use if normal code does not compile) 
 112         // It has no _ftime_s and needs explicit inclusion of timeb.h 
 113         #include <sys/timeb.h> 
 116         return 1000 * t
.time 
+ t
.millitm
; 
 118 // NORMAL CODE (use _ftime_s) 
 120         //if (_ftime_s(&t)) { 
 123         //      return 1000 * t.time + t.millitm; 
 127         clock_gettime(CLOCK_MONOTONIC
, &t
); 
 128         return (t
.tv_sec 
* 1000 + t
.tv_nsec 
/ 1000000);