Fork me on GitHub
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mach_gettime.h
Go to the documentation of this file.
1 #ifndef MACH_GETTIME_H
2 #define MACH_GETTIME_H
3 
4 #include <sys/types.h>
5 #include <sys/_types/_timespec.h>
6 #include <mach/mach.h>
7 #include <mach/clock.h>
8 #include <mach/mach_time.h>
9 
10 /* The opengroup spec isn't clear on the mapping from REALTIME to CALENDAR
11  being appropriate or not.
12  http://pubs.opengroup.org/onlinepubs/009695299/basedefs/time.h.html */
13 
14 // XXX only supports a single timer
15 #define TIMER_ABSTIME -1
16 #define CLOCK_REALTIME CALENDAR_CLOCK
17 #define CLOCK_MONOTONIC SYSTEM_CLOCK
18 
19 typedef int clockid_t;
20 
21 /* the mach kernel uses struct mach_timespec, so struct timespec
22  is loaded from <sys/_types/_timespec.h> for compatability */
23 // struct timespec { time_t tv_sec; long tv_nsec; };
24 
25 int clock_gettime(clockid_t clk_id, struct timespec *tp);
26 
27 #include <mach/mach_time.h>
28 
29 #define MT_NANO (+1.0E-9)
30 #define MT_GIGA UINT64_C(1000000000)
31 
32 // TODO create a list of timers,
33 static double mt_timebase = 0.0;
34 static uint64_t mt_timestart = 0;
35 
36 // TODO be more careful in a multithreaded environement
37 int clock_gettime(clockid_t clk_id, struct timespec *tp)
38 {
39  kern_return_t retval = KERN_SUCCESS;
40  if( clk_id == TIMER_ABSTIME)
41  {
42  if (!mt_timestart) { // only one timer, initilized on the first call to the TIMER
43  mach_timebase_info_data_t tb = { 0 };
44  mach_timebase_info(&tb);
45  mt_timebase = tb.numer;
46  mt_timebase /= tb.denom;
47  mt_timestart = mach_absolute_time();
48  }
49 
50  double diff = (mach_absolute_time() - mt_timestart) * mt_timebase;
51  tp->tv_sec = diff * MT_NANO;
52  tp->tv_nsec = diff - (tp->tv_sec * MT_GIGA);
53  }
54  else // other clk_ids are mapped to the coresponding mach clock_service
55  {
56  clock_serv_t cclock;
57  mach_timespec_t mts;
58 
59  host_get_clock_service(mach_host_self(), clk_id, &cclock);
60  retval = clock_get_time(cclock, &mts);
61  mach_port_deallocate(mach_task_self(), cclock);
62 
63  tp->tv_sec = mts.tv_sec;
64  tp->tv_nsec = mts.tv_nsec;
65  }
66 
67  return retval;
68 }
69 #endif