Search code examples
c++cmacosposixreal-time

CLOCK_THREAD_CPUTIME_ID On MacOSX


I have a function that I'm porting from Linux to MacOSX that makes use of clock_gettime with CLOCK_THREAD_CPUTIME_ID to measure the time spent on the process. I found this code on the internet that would give me the equivalent to CLOCK_REALTIME:

#ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
    clock_serv_t cclock;
    mach_timespec_t ts;
    host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
    clock_get_time(cclock, &ts);
    mach_port_deallocate(mach_task_self(), cclock);
#else
    timespec ts;
    clock_gettime(CLOCK_REALTIME, ts);
#endif

But I can't seem to figure out an easy way to get the clock_gettime(CLOCK_THREAD_CPUTIME_ID, ts); Anyone knows a good solution for this?


Solution

  • Recently I've been porting some of the pcsx2 project to Darwin/OSX, and I needed something similar to CLOCK_THREAD_CPUTIME_ID as well. This is what I came up with:

    #include <stdint.h>
    
    #include <mach/mach_init.h>
    #include <mach/thread_act.h>
    #include <mach/mach_port.h>
    
    typedef uint64_t u64;
    
    // gets the CPU time used by the current thread (both system and user), in
    // microseconds, returns 0 on failure
    static u64 getthreadtime(thread_port_t thread) {
        mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
        thread_basic_info_data_t info;
    
        int kr = thread_info(thread, THREAD_BASIC_INFO, (thread_info_t) &info, &count);
        if (kr != KERN_SUCCESS) {
            return 0;
        }
    
        // add system and user time
        return (u64) info.user_time.seconds * (u64) 1e6 +
            (u64) info.user_time.microseconds +
            (u64) info.system_time.seconds * (u64) 1e6 +
            (u64) info.system_time.microseconds;
    }
    
    // Returns the CPU time the calling thread has used (system + user) in
    // units of 100 nanoseconds. The weird units are to mirror the Windows
    // counterpart in WinThreads.cpp, which uses the GetThreadTimes() API.  On
    // OSX/Darwin, this is only accurate up until 1ms (and possibly less), so
    // not very good.
    u64 Threading::GetThreadCpuTime() {
        thread_port_t thread = mach_thread_self();
        u64 us = getthreadtime(thread);
        mach_port_deallocate(mach_task_self(), thread);
        return us * 10ULL;
    }