blob: e8be1c8076ad120c3f71169aa4dee40e5a82097b [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Portable interface to the CPU cycle counter
3 *
Paul Bakker530927b2015-02-13 14:24:10 +01004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
Manuel Pégourié-Gonnarde12abf92015-01-28 17:13:45 +00006 * This file is part of mbed TLS (https://polarssl.org)
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00007 *
Paul Bakker5121ce52009-01-03 21:22:43 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
Paul Bakker40e46942009-01-03 21:51:57 +000023#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000024
Paul Bakker40e46942009-01-03 21:51:57 +000025#if defined(POLARSSL_TIMING_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000026
Paul Bakker40e46942009-01-03 21:51:57 +000027#include "polarssl/timing.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000028
Paul Bakkerff60ee62010-03-16 21:09:09 +000029#if defined(_WIN32)
Paul Bakker5121ce52009-01-03 21:22:43 +000030
31#include <windows.h>
32#include <winbase.h>
33
34struct _hr_time
35{
36 LARGE_INTEGER start;
37};
38
39#else
40
41#include <unistd.h>
42#include <sys/types.h>
43#include <sys/time.h>
44#include <signal.h>
45#include <time.h>
46
47struct _hr_time
48{
49 struct timeval start;
50};
51
52#endif
53
Paul Bakkerbb0139c2012-10-31 09:53:08 +000054#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
Paul Bakker34a90562009-04-19 21:17:09 +000055 (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
Paul Bakker5121ce52009-01-03 21:22:43 +000056
Paul Bakkerbb0139c2012-10-31 09:53:08 +000057#define POLARSSL_HAVE_HARDCLOCK
58
Paul Bakker5121ce52009-01-03 21:22:43 +000059unsigned long hardclock( void )
60{
61 unsigned long tsc;
62 __asm rdtsc
63 __asm mov [tsc], eax
64 return( tsc );
65}
Paul Bakkerbb0139c2012-10-31 09:53:08 +000066#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000067
Manuel Pégourié-Gonnard7e828842015-04-10 17:34:32 +020068/* some versions of mingw-64 have 32-bit longs even on x84_64 */
Paul Bakkerbb0139c2012-10-31 09:53:08 +000069#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
Manuel Pégourié-Gonnard7e828842015-04-10 17:34:32 +020070 defined(__GNUC__) && ( defined(__i386__) || ( \
71 ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) )
Paul Bakkerbb0139c2012-10-31 09:53:08 +000072
73#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +000074
75unsigned long hardclock( void )
76{
Paul Bakkerca410102011-10-19 14:27:36 +000077 unsigned long lo, hi;
78 asm( "rdtsc" : "=a" (lo), "=d" (hi) );
79 return( lo );
Paul Bakker5121ce52009-01-03 21:22:43 +000080}
Paul Bakkerbb0139c2012-10-31 09:53:08 +000081#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000082
Paul Bakkerbb0139c2012-10-31 09:53:08 +000083#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
84 defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__))
85
86#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +000087
88unsigned long hardclock( void )
89{
90 unsigned long lo, hi;
91 asm( "rdtsc" : "=a" (lo), "=d" (hi) );
92 return( lo | (hi << 32) );
93}
Paul Bakkerbb0139c2012-10-31 09:53:08 +000094#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000095
Paul Bakkerbb0139c2012-10-31 09:53:08 +000096#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
97 defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
98
99#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +0000100
101unsigned long hardclock( void )
102{
103 unsigned long tbl, tbu0, tbu1;
104
105 do
106 {
107 asm( "mftbu %0" : "=r" (tbu0) );
108 asm( "mftb %0" : "=r" (tbl ) );
109 asm( "mftbu %0" : "=r" (tbu1) );
110 }
111 while( tbu0 != tbu1 );
112
113 return( tbl );
114}
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000115#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000116
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000117#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
118 defined(__GNUC__) && defined(__sparc64__)
119
120#if defined(__OpenBSD__)
121#warning OpenBSD does not allow access to tick register using software version instead
Paul Bakker5121ce52009-01-03 21:22:43 +0000122#else
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000123#define POLARSSL_HAVE_HARDCLOCK
124
125unsigned long hardclock( void )
126{
127 unsigned long tick;
128 asm( "rdpr %%tick, %0;" : "=&r" (tick) );
129 return( tick );
130}
131#endif
132#endif
133
134#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
135 defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__)
136
137#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +0000138
139unsigned long hardclock( void )
140{
141 unsigned long tick;
142 asm( ".byte 0x83, 0x41, 0x00, 0x00" );
143 asm( "mov %%g1, %0" : "=r" (tick) );
144 return( tick );
145}
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000146#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000147
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000148#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
149 defined(__GNUC__) && defined(__alpha__)
150
151#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +0000152
153unsigned long hardclock( void )
154{
155 unsigned long cc;
156 asm( "rpcc %0" : "=r" (cc) );
157 return( cc & 0xFFFFFFFF );
158}
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000159#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000160
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000161#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
162 defined(__GNUC__) && defined(__ia64__)
163
164#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +0000165
166unsigned long hardclock( void )
167{
168 unsigned long itc;
169 asm( "mov %0 = ar.itc" : "=r" (itc) );
170 return( itc );
171}
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000172#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000173
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000174#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(_MSC_VER)
175
176#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker2eee9022011-04-24 15:28:55 +0000177
178unsigned long hardclock( void )
179{
180 LARGE_INTEGER offset;
181
182 QueryPerformanceCounter( &offset );
183
184 return (unsigned long)( offset.QuadPart );
185}
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000186#endif
Paul Bakker2eee9022011-04-24 15:28:55 +0000187
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000188#if !defined(POLARSSL_HAVE_HARDCLOCK)
189
190#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +0000191
192static int hardclock_init = 0;
193static struct timeval tv_init;
194
195unsigned long hardclock( void )
196{
197 struct timeval tv_cur;
198
199 if( hardclock_init == 0 )
200 {
201 gettimeofday( &tv_init, NULL );
202 hardclock_init = 1;
203 }
204
205 gettimeofday( &tv_cur, NULL );
206 return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000
207 + ( tv_cur.tv_usec - tv_init.tv_usec ) );
208}
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000209#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000210
Paul Bakker2eee9022011-04-24 15:28:55 +0000211volatile int alarmed = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000212
Paul Bakkerff60ee62010-03-16 21:09:09 +0000213#if defined(_WIN32)
Paul Bakker5121ce52009-01-03 21:22:43 +0000214
215unsigned long get_timer( struct hr_time *val, int reset )
216{
217 unsigned long delta;
218 LARGE_INTEGER offset, hfreq;
219 struct _hr_time *t = (struct _hr_time *) val;
220
221 QueryPerformanceCounter( &offset );
222 QueryPerformanceFrequency( &hfreq );
223
224 delta = (unsigned long)( ( 1000 *
225 ( offset.QuadPart - t->start.QuadPart ) ) /
226 hfreq.QuadPart );
227
228 if( reset )
229 QueryPerformanceCounter( &t->start );
230
231 return( delta );
232}
233
Manuel Pégourié-Gonnarda9553a82015-04-10 17:30:46 +0200234/* It's OK to use a global because alarm() is supposed to be global anyway */
235static DWORD alarmMs;
236
237static DWORD WINAPI TimerProc( LPVOID TimerContext )
238{
239 ((void) TimerContext);
240 Sleep( alarmMs );
241 alarmed = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000242 return( TRUE );
243}
244
245void set_alarm( int seconds )
Manuel Pégourié-Gonnarda9553a82015-04-10 17:30:46 +0200246{
Paul Bakker5121ce52009-01-03 21:22:43 +0000247 DWORD ThreadId;
248
Manuel Pégourié-Gonnarda9553a82015-04-10 17:30:46 +0200249 alarmed = 0;
250 alarmMs = seconds * 1000;
251 CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000252}
253
254void m_sleep( int milliseconds )
255{
256 Sleep( milliseconds );
257}
258
259#else
260
261unsigned long get_timer( struct hr_time *val, int reset )
262{
263 unsigned long delta;
264 struct timeval offset;
265 struct _hr_time *t = (struct _hr_time *) val;
266
267 gettimeofday( &offset, NULL );
268
Paul Bakker5121ce52009-01-03 21:22:43 +0000269 if( reset )
270 {
271 t->start.tv_sec = offset.tv_sec;
272 t->start.tv_usec = offset.tv_usec;
Alfred Klompd6d5ef22014-07-14 22:32:21 +0200273 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000274 }
275
Alfred Klompd6d5ef22014-07-14 22:32:21 +0200276 delta = ( offset.tv_sec - t->start.tv_sec ) * 1000
277 + ( offset.tv_usec - t->start.tv_usec ) / 1000;
278
Paul Bakker5121ce52009-01-03 21:22:43 +0000279 return( delta );
280}
281
Paul Bakker49d75672012-09-26 15:22:07 +0000282#if defined(INTEGRITY)
283void m_sleep( int milliseconds )
284{
285 usleep( milliseconds * 1000 );
286}
287
288#else
289
Paul Bakker5121ce52009-01-03 21:22:43 +0000290static void sighandler( int signum )
291{
292 alarmed = 1;
293 signal( signum, sighandler );
294}
295
296void set_alarm( int seconds )
297{
298 alarmed = 0;
299 signal( SIGALRM, sighandler );
300 alarm( seconds );
301}
302
303void m_sleep( int milliseconds )
304{
305 struct timeval tv;
306
307 tv.tv_sec = milliseconds / 1000;
308 tv.tv_usec = milliseconds * 1000;
309
310 select( 0, NULL, NULL, NULL, &tv );
311}
Paul Bakker49d75672012-09-26 15:22:07 +0000312#endif /* INTEGRITY */
Paul Bakker5121ce52009-01-03 21:22:43 +0000313
314#endif
315
316#endif