Reactos
at master 95 lines 3.1 kB view raw
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. 17static long long source_frequency; 18static 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. 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(). 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. 74extern "C" clock_t __cdecl clock() 75{ 76 if (start_count == -1) 77 return -1; 78 79 LARGE_INTEGER current_count; 80 if (!QueryPerformanceCounter(&current_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}