[COMPLIB] Add support for retrieveing high resolution counter tick
[mirror/winof/.git] / core / complib / user / cl_timer.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 \r
33 \r
34 #include "complib/cl_timer.h"\r
35 \r
36 \r
37 static void CALLBACK\r
38 __timer_callback( \r
39         IN cl_timer_t* const p_timer,\r
40         IN BOOLEAN timer_signalled )\r
41 {\r
42         /* timer_signalled is always TRUE, and has no value. */\r
43         CL_ASSERT( timer_signalled );\r
44         UNUSED_PARAM( timer_signalled );\r
45 \r
46         p_timer->timeout_time = 0;\r
47         p_timer->thread_id = GetCurrentThreadId();\r
48 \r
49         (p_timer->pfn_callback)( (void*)p_timer->context );\r
50 \r
51         p_timer->thread_id = 0;\r
52 }\r
53 \r
54 \r
55 void\r
56 cl_timer_construct(\r
57         IN      cl_timer_t* const       p_timer )\r
58 {\r
59         p_timer->h_timer = NULL;\r
60         p_timer->timeout_time = 0;\r
61         p_timer->thread_id = 0;\r
62 }\r
63 \r
64 \r
65 \r
66 cl_status_t\r
67 cl_timer_init( \r
68         IN      cl_timer_t* const               p_timer,\r
69         IN      cl_pfn_timer_callback_t pfn_callback,\r
70         IN      const void* const               context )\r
71 {\r
72         CL_ASSERT( p_timer );\r
73         CL_ASSERT( pfn_callback );\r
74 \r
75         cl_timer_construct( p_timer );\r
76 \r
77         p_timer->pfn_callback = pfn_callback;\r
78         p_timer->context = context;\r
79         return( CL_SUCCESS );\r
80 }\r
81 \r
82 \r
83 void\r
84 cl_timer_destroy(\r
85         IN      cl_timer_t* const       p_timer )\r
86 {\r
87         CL_ASSERT( p_timer );\r
88         \r
89         cl_timer_stop( p_timer );\r
90 }\r
91 \r
92 \r
93 cl_status_t \r
94 cl_timer_start(\r
95         IN      cl_timer_t* const       p_timer,\r
96         IN      const uint32_t          time_ms )\r
97 {\r
98         CL_ASSERT( p_timer );\r
99 \r
100         cl_timer_stop( p_timer );\r
101 \r
102         p_timer->timeout_time = cl_get_time_stamp() + (((uint64_t)time_ms) * 1000);\r
103 \r
104         if( !CreateTimerQueueTimer( &p_timer->h_timer, NULL, __timer_callback,\r
105                 p_timer, time_ms, 0, WT_EXECUTEINIOTHREAD ) )\r
106         {\r
107                 return( CL_ERROR );\r
108         }\r
109         \r
110         return( CL_SUCCESS );\r
111 }\r
112 \r
113 \r
114 cl_status_t \r
115 cl_timer_trim(\r
116         IN      cl_timer_t* const       p_timer,\r
117         IN      const uint32_t          time_ms )\r
118 {\r
119         uint64_t                timeout_time;\r
120 \r
121         CL_ASSERT( p_timer );\r
122         CL_ASSERT( p_timer->pfn_callback );\r
123 \r
124         /* Calculate the timeout time in the timer object. */\r
125         timeout_time = cl_get_time_stamp() + (((uint64_t)time_ms) * 1000);\r
126 \r
127         /* Only pull in the timeout time. */\r
128         if( p_timer->timeout_time && p_timer->timeout_time < timeout_time )\r
129                 return( CL_SUCCESS );\r
130 \r
131         return cl_timer_start( p_timer, time_ms );\r
132 }\r
133 \r
134 \r
135 void\r
136 cl_timer_stop(\r
137         IN      cl_timer_t* const       p_timer )\r
138 {\r
139         CL_ASSERT( p_timer );\r
140 \r
141         if( p_timer->h_timer && p_timer->thread_id != GetCurrentThreadId() )\r
142         {\r
143                 /* Make sure we block until the timer is cancelled. */\r
144                 DeleteTimerQueueTimer( NULL, p_timer->h_timer, INVALID_HANDLE_VALUE );\r
145                 p_timer->h_timer = NULL;\r
146         }\r
147         p_timer->timeout_time = 0;\r
148 }\r
149 \r
150 \r
151 #define SEC_TO_MICRO            1000000ULL      // s to ┬Ás conversion\r
152 \r
153 uint64_t\r
154 cl_get_time_stamp( void )\r
155 {\r
156         LARGE_INTEGER   tick_count, frequency;\r
157 \r
158         if( !QueryPerformanceFrequency( &frequency ) )\r
159                 return( 0 );\r
160 \r
161         if( !QueryPerformanceCounter( &tick_count ) )\r
162                 return( 0 );\r
163 \r
164         return( tick_count.QuadPart / (frequency.QuadPart / SEC_TO_MICRO) );\r
165 }\r
166 \r
167 uint32_t\r
168 cl_get_time_stamp_sec( void )\r
169 {\r
170         return( (uint32_t)(cl_get_time_stamp() / SEC_TO_MICRO) );\r
171 }\r
172 \r
173 \r
174 uint64_t\r
175 cl_get_tick_count( void )\r
176 {\r
177         LARGE_INTEGER   tick_count;\r
178 \r
179         if( !QueryPerformanceCounter( &tick_count ) )\r
180                 return( 0 );\r
181 \r
182         return tick_count.QuadPart;\r
183 }\r
184 \r
185 \r
186 uint64_t\r
187 cl_get_frequency( void )\r
188 {\r
189         LARGE_INTEGER   frequency;\r
190 \r
191         if( !QueryPerformanceFrequency( &frequency ) )\r
192                 return( 0 );\r
193 \r
194         return frequency.QuadPart;\r
195 }\r