Does gettimeofday() on macOS use a system call?

前端 未结 2 1290
执笔经年
执笔经年 2021-02-09 13:19

I expect that gettimeofday() will call a system call to do the work of actually getting the time. However, running the following program

#include &l         


        
相关标签:
2条回答
  • 2021-02-09 13:28

    The use of dtrace instead of dtruss will clear your doubt. gettimeofday() is itself a system call. You can see this system call getting called if you run dtrace script.

    You can use following dtrace script "dtrace1.d"

    syscall:::entry
    / execname == "foo" / 
    {
    }
    

    (foo is the name of your executable)

    to run above dtrace use: dtrace -s dtrace1.d

    and then execute your program to see all system call used by your program

    0 讨论(0)
  • 2021-02-09 13:29

    As TheDarkKnight pointed out, there is a gettimeofday system call. However, the userspace gettimeofday function often does not call the corresponding system call, but rather __commpage_gettimeofday, which tries to read the time from a special part of the process' address space called the commpage. Only if this call fails does the gettimeofday system call get used as a fallback. This reduces the cost of most calls to gettimeofday from that of an ordinary system call to just a memory read.

    The book Mac OSX Internals: A Systems Approach describes the commpage. Briefly, it is a special area of kernel memory that is mapped into the last eight pages of the address space of every process. Among other things, it contains time values that are "updated asynchronously from the kernel and read atomically from user space, leading to occasional failures in reading".

    To see how often the gettimeofday() system call is called by the userspace function, I wrote a test program that called gettimeofday() 100 million times in a tight loop:

    #include <sys/time.h>
    int main(int argc, char const *argv[])
    {
        const int NUM_TRIALS = 100000000;
        struct timeval tv;
        for (int i = 0; i < NUM_TRIALS; i++) {
            gettimeofday(&tv, NULL);
        }
        return 0;
    }
    

    Running this under dtruss -d on my machine showed that this triggered between 10-20 calls to the gettimeofday() system calls (0.00001%-0.00002% of all the userspace calls).


    For those interested, the relevant lines in the source code for the userspace gettimeofday() function (for macOS 10.11 - El Capitan) are

    if (__commpage_gettimeofday(tp)) {      /* first try commpage */
        if (__gettimeofday(tp, NULL) < 0) { /* if it fails, use syscall */
            return (-1);
        }
    }
    

    The function __commpage_gettimeofday combines the timestamp read from the commpage and a reading of the time stamp counter register to calculate the time since epoch in seconds and microseconds. (The rdstc instruction is inside _mach_absolute_time.)

    0 讨论(0)
提交回复
热议问题