blob: 1ba02fec1d5cdab7d0cb81941986151304426051 [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
Paul Bakkerbb0139c2012-10-31 09:53:08 +000068#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
69 defined(__GNUC__) && defined(__i386__)
70
71#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +000072
73unsigned long hardclock( void )
74{
Paul Bakkerca410102011-10-19 14:27:36 +000075 unsigned long lo, hi;
76 asm( "rdtsc" : "=a" (lo), "=d" (hi) );
77 return( lo );
Paul Bakker5121ce52009-01-03 21:22:43 +000078}
Paul Bakkerbb0139c2012-10-31 09:53:08 +000079#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000080
Paul Bakkerbb0139c2012-10-31 09:53:08 +000081#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
82 defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__))
83
84#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +000085
86unsigned long hardclock( void )
87{
88 unsigned long lo, hi;
89 asm( "rdtsc" : "=a" (lo), "=d" (hi) );
90 return( lo | (hi << 32) );
91}
Paul Bakkerbb0139c2012-10-31 09:53:08 +000092#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000093
Paul Bakkerbb0139c2012-10-31 09:53:08 +000094#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
95 defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
96
97#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +000098
99unsigned long hardclock( void )
100{
101 unsigned long tbl, tbu0, tbu1;
102
103 do
104 {
105 asm( "mftbu %0" : "=r" (tbu0) );
106 asm( "mftb %0" : "=r" (tbl ) );
107 asm( "mftbu %0" : "=r" (tbu1) );
108 }
109 while( tbu0 != tbu1 );
110
111 return( tbl );
112}
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000113#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000114
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000115#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
116 defined(__GNUC__) && defined(__sparc64__)
117
118#if defined(__OpenBSD__)
119#warning OpenBSD does not allow access to tick register using software version instead
Paul Bakker5121ce52009-01-03 21:22:43 +0000120#else
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000121#define POLARSSL_HAVE_HARDCLOCK
122
123unsigned long hardclock( void )
124{
125 unsigned long tick;
126 asm( "rdpr %%tick, %0;" : "=&r" (tick) );
127 return( tick );
128}
129#endif
130#endif
131
132#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
133 defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__)
134
135#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +0000136
137unsigned long hardclock( void )
138{
139 unsigned long tick;
140 asm( ".byte 0x83, 0x41, 0x00, 0x00" );
141 asm( "mov %%g1, %0" : "=r" (tick) );
142 return( tick );
143}
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000144#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000145
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000146#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
147 defined(__GNUC__) && defined(__alpha__)
148
149#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +0000150
151unsigned long hardclock( void )
152{
153 unsigned long cc;
154 asm( "rpcc %0" : "=r" (cc) );
155 return( cc & 0xFFFFFFFF );
156}
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000157#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000158
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000159#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
160 defined(__GNUC__) && defined(__ia64__)
161
162#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +0000163
164unsigned long hardclock( void )
165{
166 unsigned long itc;
167 asm( "mov %0 = ar.itc" : "=r" (itc) );
168 return( itc );
169}
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000170#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000171
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000172#if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(_MSC_VER)
173
174#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker2eee9022011-04-24 15:28:55 +0000175
176unsigned long hardclock( void )
177{
178 LARGE_INTEGER offset;
179
180 QueryPerformanceCounter( &offset );
181
182 return (unsigned long)( offset.QuadPart );
183}
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000184#endif
Paul Bakker2eee9022011-04-24 15:28:55 +0000185
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000186#if !defined(POLARSSL_HAVE_HARDCLOCK)
187
188#define POLARSSL_HAVE_HARDCLOCK
Paul Bakker5121ce52009-01-03 21:22:43 +0000189
190static int hardclock_init = 0;
191static struct timeval tv_init;
192
193unsigned long hardclock( void )
194{
195 struct timeval tv_cur;
196
197 if( hardclock_init == 0 )
198 {
199 gettimeofday( &tv_init, NULL );
200 hardclock_init = 1;
201 }
202
203 gettimeofday( &tv_cur, NULL );
204 return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000
205 + ( tv_cur.tv_usec - tv_init.tv_usec ) );
206}
Paul Bakkerbb0139c2012-10-31 09:53:08 +0000207#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000208
Paul Bakker2eee9022011-04-24 15:28:55 +0000209volatile int alarmed = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000210
Paul Bakkerff60ee62010-03-16 21:09:09 +0000211#if defined(_WIN32)
Paul Bakker5121ce52009-01-03 21:22:43 +0000212
213unsigned long get_timer( struct hr_time *val, int reset )
214{
215 unsigned long delta;
216 LARGE_INTEGER offset, hfreq;
217 struct _hr_time *t = (struct _hr_time *) val;
218
219 QueryPerformanceCounter( &offset );
220 QueryPerformanceFrequency( &hfreq );
221
222 delta = (unsigned long)( ( 1000 *
223 ( offset.QuadPart - t->start.QuadPart ) ) /
224 hfreq.QuadPart );
225
226 if( reset )
227 QueryPerformanceCounter( &t->start );
228
229 return( delta );
230}
231
Manuel Pégourié-Gonnarda9553a82015-04-10 17:30:46 +0200232/* It's OK to use a global because alarm() is supposed to be global anyway */
233static DWORD alarmMs;
234
235static DWORD WINAPI TimerProc( LPVOID TimerContext )
236{
237 ((void) TimerContext);
238 Sleep( alarmMs );
239 alarmed = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000240 return( TRUE );
241}
242
243void set_alarm( int seconds )
Manuel Pégourié-Gonnarda9553a82015-04-10 17:30:46 +0200244{
Paul Bakker5121ce52009-01-03 21:22:43 +0000245 DWORD ThreadId;
246
Manuel Pégourié-Gonnarda9553a82015-04-10 17:30:46 +0200247 alarmed = 0;
248 alarmMs = seconds * 1000;
249 CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000250}
251
252void m_sleep( int milliseconds )
253{
254 Sleep( milliseconds );
255}
256
257#else
258
259unsigned long get_timer( struct hr_time *val, int reset )
260{
261 unsigned long delta;
262 struct timeval offset;
263 struct _hr_time *t = (struct _hr_time *) val;
264
265 gettimeofday( &offset, NULL );
266
Paul Bakker5121ce52009-01-03 21:22:43 +0000267 if( reset )
268 {
269 t->start.tv_sec = offset.tv_sec;
270 t->start.tv_usec = offset.tv_usec;
Alfred Klompd6d5ef22014-07-14 22:32:21 +0200271 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000272 }
273
Alfred Klompd6d5ef22014-07-14 22:32:21 +0200274 delta = ( offset.tv_sec - t->start.tv_sec ) * 1000
275 + ( offset.tv_usec - t->start.tv_usec ) / 1000;
276
Paul Bakker5121ce52009-01-03 21:22:43 +0000277 return( delta );
278}
279
Paul Bakker49d75672012-09-26 15:22:07 +0000280#if defined(INTEGRITY)
281void m_sleep( int milliseconds )
282{
283 usleep( milliseconds * 1000 );
284}
285
286#else
287
Paul Bakker5121ce52009-01-03 21:22:43 +0000288static void sighandler( int signum )
289{
290 alarmed = 1;
291 signal( signum, sighandler );
292}
293
294void set_alarm( int seconds )
295{
296 alarmed = 0;
297 signal( SIGALRM, sighandler );
298 alarm( seconds );
299}
300
301void m_sleep( int milliseconds )
302{
303 struct timeval tv;
304
305 tv.tv_sec = milliseconds / 1000;
306 tv.tv_usec = milliseconds * 1000;
307
308 select( 0, NULL, NULL, NULL, &tv );
309}
Paul Bakker49d75672012-09-26 15:22:07 +0000310#endif /* INTEGRITY */
Paul Bakker5121ce52009-01-03 21:22:43 +0000311
312#endif
313
314#endif