1 // 2 // clock.cpp 3 // 4 // Copyright (c) Microsoft Corporation. All rights reserved. 5 // 6 // The clock() function, which calculates the amount of elapsed time since the 7 // process started execution. 8 // 9 #include <corecrt_internal_time.h> 10 #include <sys/timeb.h> 11 #include <sys/types.h> 12 13 14 15 // The source frequency of the performance counter and the counter value at 16 // process startup, in the source frequency. 17 static long long source_frequency; 18 static long long start_count; 19 20 21 22 // Scales a 64-bit counter from the QueryPerformanceCounter frequency to the 23 // clock() frequency defined by CLOCKS_PER_SEC. This is the same algorithm as 24 // is used internally by QueryPerformanceCounter to deal with frequency changes. scale_count(long long count)25static long long scale_count(long long count) 26 { 27 // Convert the count to seconds and multiply this by the destination frequency: 28 long long scaled_count = (count / source_frequency) * CLOCKS_PER_SEC; 29 30 // To reduce error introduced by scaling using integer division, separately 31 // handle the remainder from the above division by multiplying the left-over 32 // counter by the destination frequency, then diviting by the input frequency: 33 count %= source_frequency; 34 35 scaled_count += (count * CLOCKS_PER_SEC) / source_frequency; 36 37 return scaled_count; 38 } 39 40 41 42 // This function initializes the global start_count variable when the CRT is 43 // initialized. This initializer always runs in the CRT DLL; it only runs in 44 // the static CRT if this object file is linked into the module, which will only 45 // happen if some user code calls clock(). __acrt_initialize_clock()46extern "C" int __cdecl __acrt_initialize_clock() 47 { 48 LARGE_INTEGER local_frequency; 49 LARGE_INTEGER local_start_count; 50 if (!QueryPerformanceFrequency(&local_frequency) || 51 !QueryPerformanceCounter(&local_start_count) || 52 local_frequency.QuadPart == 0) 53 { 54 source_frequency = -1; 55 start_count = -1; 56 return 0; 57 } 58 59 source_frequency = local_frequency.QuadPart; 60 start_count = local_start_count.QuadPart; 61 62 return 0; 63 } 64 65 _CRT_LINKER_FORCE_INCLUDE(__acrt_clock_initializer); 66 67 // Calculates and returns the amount of elapsed time since the process started 68 // execution. During CRT initialization, the 'start_count' global variable is 69 // initialized to the current tick count; subsequent calls to clock() get the 70 // new tick count and subtract the 'start_count' from it. 71 // 72 // The return value is the number of CLK_TCKs that have elapsed (milliseconds). 73 // On failure, -1 is returned. clock()74extern "C" clock_t __cdecl clock() 75 { 76 if (start_count == -1) 77 return -1; 78 79 LARGE_INTEGER current_count; 80 if (!QueryPerformanceCounter(¤t_count)) 81 return -1; 82 83 long long const result = current_count.QuadPart - start_count; 84 if (result < 0) 85 return -1; 86 87 long long const scaled_result = scale_count(result); 88 89 // Per C11 7.27.2.1 ("The clock function")/3, "If the processor time used... 90 // cannot be represented, the function returns the value (clock_t)(-1)." 91 if (scaled_result > LONG_MAX) 92 return -1; 93 94 return static_cast<clock_t>(scaled_result); 95 } 96