1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2019-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #pragma once
10 
11 #include "types.h"
12 
13 #if defined _WIN32
14 #   include <wtypes.h>
15 #   include <winbase.h>
16 #   include <intrin.h>
17 #else
18 #   include <time.h>
19 #   include <x86intrin.h>
20 #   ifndef NSEC_PER_SEC
21 #       define NSEC_PER_SEC 1000000000L
22 #   endif
23 #endif
24 
25 namespace iSTD
26 {
27 /*****************************************************************************\
28 Inline Function:
29     Pause
30 
31 Description:
32     executes __asm pause
33 \*****************************************************************************/
Pause(void)34 __forceinline void Pause( void )
35 {
36     _mm_pause();
37 }
38 
39 #if defined _WIN32
40 /*****************************************************************************\
41 Inline Function:
42     GetTimestampCounter
43 
44 Description:
45     Returns the number of CPU clock cycles since the last reset.
46 \*****************************************************************************/
GetTimestampCounter(void)47 __forceinline QWORD GetTimestampCounter( void )
48 {
49     #ifdef ISTDLIB_UMD
50     {
51         QWORD count = 0;
52         ::QueryPerformanceCounter( (LARGE_INTEGER*)&count );
53         return count;
54     }
55     #else // !ISTDLIB_UMD
56     {
57         #ifdef _WIN64
58         {
59             return __rdtsc();
60         }
61         #else // !_WIN64
62         {
63             __asm rdtsc;
64         }
65         #endif // _WIN64
66     }
67     #endif // ISTDLIB_UMD
68 }
69 
70 /*****************************************************************************\
71 Inline Function:
72     GetTimestampFrequency
73 
74 Description:
75     Returns the frequency of the CPU clock cycles
76 \*****************************************************************************/
GetTimestampFrequency(void)77 __forceinline QWORD GetTimestampFrequency( void )
78 {
79     #ifdef ISTDLIB_UMD
80     {
81         QWORD frequency = 0;
82         ::QueryPerformanceFrequency( (LARGE_INTEGER*)&frequency );
83         return frequency;
84     }
85     #else // !ISTDLIB_UMD
86     {
87         // Note: Use the following for Conroe 2.4GHz
88         // return 2394050000;
89 
90         return 0;
91     }
92     #endif // ISTDLIB_UMD
93 }
94 
95 /*****************************************************************************\
96 Inline Function:
97     Wait
98 
99 Description:
100     Waits for some number of milliseconds to complete
101 \*****************************************************************************/
Wait(const DWORD milliseconds)102 __forceinline void Wait( const DWORD milliseconds )
103 {
104     const QWORD clocksPerSecond = GetTimestampFrequency();
105     const QWORD clocksPerMilliSecond = ( clocksPerSecond > 1000 ) ? clocksPerSecond / 1000 : 1;
106     const QWORD clocks = milliseconds * clocksPerMilliSecond;
107 
108     const QWORD start = GetTimestampCounter();
109     while( clocks < ( GetTimestampCounter() - start ) )
110     {
111         Pause();
112     };
113 }
114 
115 #else
116 
117 /*****************************************************************************\
118 Inline Function:
119     GetTimestampCounter
120 
121 Description:
122     Returns the value of high resolution performance counter
123 \*****************************************************************************/
GetTimestampCounter(void)124 __forceinline QWORD GetTimestampCounter( void )
125 {
126     struct timespec time;
127     clock_gettime(CLOCK_MONOTONIC, &time);
128     return (QWORD)time.tv_nsec +
129            (QWORD)time.tv_sec * (QWORD)NSEC_PER_SEC;
130 
131 }
132 
133 /*****************************************************************************\
134 Inline Function:
135     GetTimestampFrequency
136 
137 Description:
138     Returns the frequency of high resolution performance counter.
139     On Linux/Android we use timer with nsec accuracy
140 \*****************************************************************************/
GetTimestampFrequency(void)141 __forceinline QWORD GetTimestampFrequency( void )
142 {
143     return NSEC_PER_SEC;
144 }
145 
146 #endif
147 
148 } // iSTD
149