| 25 | #ifdef __APPLE__ |
| 26 | |
| 27 | #pragma weak clock_gettime |
| 28 | |
| 29 | #include <sys/time.h> |
| 30 | #include <sys/resource.h> |
| 31 | #include <mach/mach.h> |
| 32 | #include <mach/clock.h> |
| 33 | #include <mach/mach_time.h> |
| 34 | #include <errno.h> |
| 35 | #include <unistd.h> |
| 36 | #include <sched.h> |
| 37 | |
| 38 | typedef enum { |
| 39 | CLOCK_REALTIME, |
| 40 | CLOCK_MONOTONIC, |
| 41 | CLOCK_PROCESS_CPUTIME_ID, |
| 42 | CLOCK_THREAD_CPUTIME_ID |
| 43 | } clockid_t; |
| 44 | |
| 45 | static mach_timebase_info_data_t __clock_gettime_inf; |
| 46 | |
| 47 | static int clock_gettime(clockid_t clk_id, struct timespec *tp) { |
| 48 | kern_return_t ret; |
| 49 | clock_serv_t clk; |
| 50 | clock_id_t clk_serv_id; |
| 51 | mach_timespec_t tm; |
| 52 | |
| 53 | uint64_t start, end, delta, nano; |
| 54 | |
| 55 | task_basic_info_data_t tinfo; |
| 56 | task_thread_times_info_data_t ttinfo; |
| 57 | mach_msg_type_number_t tflag; |
| 58 | |
| 59 | int retval = -1; |
| 60 | switch (clk_id) { |
| 61 | case CLOCK_REALTIME: |
| 62 | case CLOCK_MONOTONIC: |
| 63 | clk_serv_id = clk_id == CLOCK_REALTIME ? CALENDAR_CLOCK : SYSTEM_CLOCK; |
| 64 | if (KERN_SUCCESS == (ret = host_get_clock_service(mach_host_self(), clk_serv_id, &clk))) { |
| 65 | if (KERN_SUCCESS == (ret = clock_get_time(clk, &tm))) { |
| 66 | tp->tv_sec = tm.tv_sec; |
| 67 | tp->tv_nsec = tm.tv_nsec; |
| 68 | retval = 0; |
| 69 | } |
| 70 | } |
| 71 | if (KERN_SUCCESS != ret) { |
| 72 | errno = EINVAL; |
| 73 | retval = -1; |
| 74 | } |
| 75 | break; |
| 76 | case CLOCK_PROCESS_CPUTIME_ID: |
| 77 | case CLOCK_THREAD_CPUTIME_ID: |
| 78 | start = mach_absolute_time(); |
| 79 | if (clk_id == CLOCK_PROCESS_CPUTIME_ID) { |
| 80 | getpid(); |
| 81 | } else { |
| 82 | sched_yield(); |
| 83 | } |
| 84 | end = mach_absolute_time(); |
| 85 | delta = end - start; |
| 86 | if (0 == __clock_gettime_inf.denom) { |
| 87 | mach_timebase_info(&__clock_gettime_inf); |
| 88 | } |
| 89 | nano = delta * __clock_gettime_inf.numer / __clock_gettime_inf.denom; |
| 90 | tp->tv_sec = nano * 1e-9; |
| 91 | tp->tv_nsec = nano - (tp->tv_sec * 1e9); |
| 92 | retval = 0; |
| 93 | break; |
| 94 | default: |
| 95 | errno = EINVAL; |
| 96 | retval = -1; |
| 97 | } |
| 98 | return retval; |
| 99 | } |
| 100 | |
| 101 | #endif // __APPLE__ |
| 102 | |