blob: 7bed3f68fb9d214fa253947508e536b9b0a4e7c5 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Portable interface to the CPU cycle counter
3 *
Paul Bakker83ded912010-03-21 17:46:26 +00004 * Copyright (C) 2006-2010, Paul Bakker <polarssl_maintainer at polarssl.org>
Paul Bakker77b385e2009-07-28 17:23:11 +00005 * All rights reserved.
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00006 *
Paul Bakker5121ce52009-01-03 21:22:43 +00007 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
Paul Bakker40e46942009-01-03 21:51:57 +000022#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000023
Paul Bakker40e46942009-01-03 21:51:57 +000024#if defined(POLARSSL_TIMING_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000025
Paul Bakker40e46942009-01-03 21:51:57 +000026#include "polarssl/timing.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000027
Paul Bakkerff60ee62010-03-16 21:09:09 +000028#if defined(_WIN32)
Paul Bakker5121ce52009-01-03 21:22:43 +000029
30#include <windows.h>
31#include <winbase.h>
32
33struct _hr_time
34{
35 LARGE_INTEGER start;
36};
37
38#else
39
40#include <unistd.h>
41#include <sys/types.h>
42#include <sys/time.h>
43#include <signal.h>
44#include <time.h>
45
46struct _hr_time
47{
48 struct timeval start;
49};
50
51#endif
52
Paul Bakker34a90562009-04-19 21:17:09 +000053#if defined(POLARSSL_HAVE_ASM) && \
54 (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
Paul Bakker5121ce52009-01-03 21:22:43 +000055
56unsigned long hardclock( void )
57{
58 unsigned long tsc;
59 __asm rdtsc
60 __asm mov [tsc], eax
61 return( tsc );
62}
63
64#else
Paul Bakker34a90562009-04-19 21:17:09 +000065#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__)
Paul Bakker5121ce52009-01-03 21:22:43 +000066
67unsigned long hardclock( void )
68{
69 unsigned long tsc;
70 asm( "rdtsc" : "=a" (tsc) );
71 return( tsc );
72}
73
74#else
Paul Bakker34a90562009-04-19 21:17:09 +000075#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && \
76 (defined(__amd64__) || defined(__x86_64__))
Paul Bakker5121ce52009-01-03 21:22:43 +000077
78unsigned long hardclock( void )
79{
80 unsigned long lo, hi;
81 asm( "rdtsc" : "=a" (lo), "=d" (hi) );
82 return( lo | (hi << 32) );
83}
84
85#else
Paul Bakker34a90562009-04-19 21:17:09 +000086#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && \
87 (defined(__powerpc__) || defined(__ppc__))
Paul Bakker5121ce52009-01-03 21:22:43 +000088
89unsigned long hardclock( void )
90{
91 unsigned long tbl, tbu0, tbu1;
92
93 do
94 {
95 asm( "mftbu %0" : "=r" (tbu0) );
96 asm( "mftb %0" : "=r" (tbl ) );
97 asm( "mftbu %0" : "=r" (tbu1) );
98 }
99 while( tbu0 != tbu1 );
100
101 return( tbl );
102}
103
104#else
Paul Bakker34a90562009-04-19 21:17:09 +0000105#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__sparc__)
Paul Bakker5121ce52009-01-03 21:22:43 +0000106
107unsigned long hardclock( void )
108{
109 unsigned long tick;
110 asm( ".byte 0x83, 0x41, 0x00, 0x00" );
111 asm( "mov %%g1, %0" : "=r" (tick) );
112 return( tick );
113}
114
115#else
Paul Bakker34a90562009-04-19 21:17:09 +0000116#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__alpha__)
Paul Bakker5121ce52009-01-03 21:22:43 +0000117
118unsigned long hardclock( void )
119{
120 unsigned long cc;
121 asm( "rpcc %0" : "=r" (cc) );
122 return( cc & 0xFFFFFFFF );
123}
124
125#else
Paul Bakker34a90562009-04-19 21:17:09 +0000126#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__ia64__)
Paul Bakker5121ce52009-01-03 21:22:43 +0000127
128unsigned long hardclock( void )
129{
130 unsigned long itc;
131 asm( "mov %0 = ar.itc" : "=r" (itc) );
132 return( itc );
133}
134
135#else
136
137static int hardclock_init = 0;
138static struct timeval tv_init;
139
140unsigned long hardclock( void )
141{
142 struct timeval tv_cur;
143
144 if( hardclock_init == 0 )
145 {
146 gettimeofday( &tv_init, NULL );
147 hardclock_init = 1;
148 }
149
150 gettimeofday( &tv_cur, NULL );
151 return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000
152 + ( tv_cur.tv_usec - tv_init.tv_usec ) );
153}
154
155#endif /* generic */
156#endif /* IA-64 */
157#endif /* Alpha */
158#endif /* SPARC8 */
159#endif /* PowerPC */
160#endif /* AMD64 */
161#endif /* i586+ */
162
163int alarmed = 0;
164
Paul Bakkerff60ee62010-03-16 21:09:09 +0000165#if defined(_WIN32)
Paul Bakker5121ce52009-01-03 21:22:43 +0000166
167unsigned long get_timer( struct hr_time *val, int reset )
168{
169 unsigned long delta;
170 LARGE_INTEGER offset, hfreq;
171 struct _hr_time *t = (struct _hr_time *) val;
172
173 QueryPerformanceCounter( &offset );
174 QueryPerformanceFrequency( &hfreq );
175
176 delta = (unsigned long)( ( 1000 *
177 ( offset.QuadPart - t->start.QuadPart ) ) /
178 hfreq.QuadPart );
179
180 if( reset )
181 QueryPerformanceCounter( &t->start );
182
183 return( delta );
184}
185
186DWORD WINAPI TimerProc( LPVOID uElapse )
187{
188 Sleep( (DWORD) uElapse );
189 alarmed = 1;
190 return( TRUE );
191}
192
193void set_alarm( int seconds )
194{
195 DWORD ThreadId;
196
197 alarmed = 0;
198 CloseHandle( CreateThread( NULL, 0, TimerProc,
199 (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) );
200}
201
202void m_sleep( int milliseconds )
203{
204 Sleep( milliseconds );
205}
206
207#else
208
209unsigned long get_timer( struct hr_time *val, int reset )
210{
211 unsigned long delta;
212 struct timeval offset;
213 struct _hr_time *t = (struct _hr_time *) val;
214
215 gettimeofday( &offset, NULL );
216
217 delta = ( offset.tv_sec - t->start.tv_sec ) * 1000
218 + ( offset.tv_usec - t->start.tv_usec ) / 1000;
219
220 if( reset )
221 {
222 t->start.tv_sec = offset.tv_sec;
223 t->start.tv_usec = offset.tv_usec;
224 }
225
226 return( delta );
227}
228
229static void sighandler( int signum )
230{
231 alarmed = 1;
232 signal( signum, sighandler );
233}
234
235void set_alarm( int seconds )
236{
237 alarmed = 0;
238 signal( SIGALRM, sighandler );
239 alarm( seconds );
240}
241
242void m_sleep( int milliseconds )
243{
244 struct timeval tv;
245
246 tv.tv_sec = milliseconds / 1000;
247 tv.tv_usec = milliseconds * 1000;
248
249 select( 0, NULL, NULL, NULL, &tv );
250}
251
252#endif
253
254#endif