blob: fd9c2927f8bc36cc6225150d92874eae520597fd [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Portable interface to the CPU cycle counter
3 *
Manuel Pégourié-Gonnard0edee5e2015-01-26 15:29:40 +00004 * Copyright (C) 2006-2010, ARM Limited, All Rights Reserved
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
Manuel Pégourié-Gonnard0edee5e2015-01-26 15:29:40 +00006 * This file is part of mbed TLS (https://www.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
232DWORD WINAPI TimerProc( LPVOID uElapse )
233{
234 Sleep( (DWORD) uElapse );
235 alarmed = 1;
236 return( TRUE );
237}
238
239void set_alarm( int seconds )
240{
241 DWORD ThreadId;
242
243 alarmed = 0;
244 CloseHandle( CreateThread( NULL, 0, TimerProc,
245 (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) );
246}
247
248void m_sleep( int milliseconds )
249{
250 Sleep( milliseconds );
251}
252
253#else
254
255unsigned long get_timer( struct hr_time *val, int reset )
256{
257 unsigned long delta;
258 struct timeval offset;
259 struct _hr_time *t = (struct _hr_time *) val;
260
261 gettimeofday( &offset, NULL );
262
Paul Bakker5121ce52009-01-03 21:22:43 +0000263 if( reset )
264 {
265 t->start.tv_sec = offset.tv_sec;
266 t->start.tv_usec = offset.tv_usec;
Alfred Klompd6d5ef22014-07-14 22:32:21 +0200267 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000268 }
269
Alfred Klompd6d5ef22014-07-14 22:32:21 +0200270 delta = ( offset.tv_sec - t->start.tv_sec ) * 1000
271 + ( offset.tv_usec - t->start.tv_usec ) / 1000;
272
Paul Bakker5121ce52009-01-03 21:22:43 +0000273 return( delta );
274}
275
Paul Bakker49d75672012-09-26 15:22:07 +0000276#if defined(INTEGRITY)
277void m_sleep( int milliseconds )
278{
279 usleep( milliseconds * 1000 );
280}
281
282#else
283
Paul Bakker5121ce52009-01-03 21:22:43 +0000284static void sighandler( int signum )
285{
286 alarmed = 1;
287 signal( signum, sighandler );
288}
289
290void set_alarm( int seconds )
291{
292 alarmed = 0;
293 signal( SIGALRM, sighandler );
294 alarm( seconds );
295}
296
297void m_sleep( int milliseconds )
298{
299 struct timeval tv;
300
301 tv.tv_sec = milliseconds / 1000;
302 tv.tv_usec = milliseconds * 1000;
303
304 select( 0, NULL, NULL, NULL, &tv );
305}
Paul Bakker49d75672012-09-26 15:22:07 +0000306#endif /* INTEGRITY */
Paul Bakker5121ce52009-01-03 21:22:43 +0000307
308#endif
309
310#endif