1/* 2 * Portable interface to the CPU cycle counter 3 * 4 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine 5 * 6 * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org> 7 * 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * * Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * * Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * * Neither the names of PolarSSL or XySSL nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36#include "polarssl/config.h" 37 38#if defined(POLARSSL_TIMING_C) 39 40#include "polarssl/timing.h" 41 42#if defined(WIN32) 43 44#include <windows.h> 45#include <winbase.h> 46 47struct _hr_time 48{ 49 LARGE_INTEGER start; 50}; 51 52#else 53 54#include <unistd.h> 55#include <sys/types.h> 56#include <sys/time.h> 57#include <signal.h> 58#include <time.h> 59 60struct _hr_time 61{ 62 struct timeval start; 63}; 64 65#endif 66 67#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 68 69unsigned long hardclock( void ) 70{ 71 unsigned long tsc; 72 __asm rdtsc 73 __asm mov [tsc], eax 74 return( tsc ); 75} 76 77#else 78#if defined(__GNUC__) && defined(__i386__) 79 80unsigned long hardclock( void ) 81{ 82 unsigned long tsc; 83 asm( "rdtsc" : "=a" (tsc) ); 84 return( tsc ); 85} 86 87#else 88#if defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__)) 89 90unsigned long hardclock( void ) 91{ 92 unsigned long lo, hi; 93 asm( "rdtsc" : "=a" (lo), "=d" (hi) ); 94 return( lo | (hi << 32) ); 95} 96 97#else 98#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) 99 100unsigned long hardclock( void ) 101{ 102 unsigned long tbl, tbu0, tbu1; 103 104 do 105 { 106 asm( "mftbu %0" : "=r" (tbu0) ); 107 asm( "mftb %0" : "=r" (tbl ) ); 108 asm( "mftbu %0" : "=r" (tbu1) ); 109 } 110 while( tbu0 != tbu1 ); 111 112 return( tbl ); 113} 114 115#else 116#if defined(__GNUC__) && defined(__sparc__) 117 118unsigned long hardclock( void ) 119{ 120 unsigned long tick; 121 asm( ".byte 0x83, 0x41, 0x00, 0x00" ); 122 asm( "mov %%g1, %0" : "=r" (tick) ); 123 return( tick ); 124} 125 126#else 127#if defined(__GNUC__) && defined(__alpha__) 128 129unsigned long hardclock( void ) 130{ 131 unsigned long cc; 132 asm( "rpcc %0" : "=r" (cc) ); 133 return( cc & 0xFFFFFFFF ); 134} 135 136#else 137#if defined(__GNUC__) && defined(__ia64__) 138 139unsigned long hardclock( void ) 140{ 141 unsigned long itc; 142 asm( "mov %0 = ar.itc" : "=r" (itc) ); 143 return( itc ); 144} 145 146#else 147 148static int hardclock_init = 0; 149static struct timeval tv_init; 150 151unsigned long hardclock( void ) 152{ 153 struct timeval tv_cur; 154 155 if( hardclock_init == 0 ) 156 { 157 gettimeofday( &tv_init, NULL ); 158 hardclock_init = 1; 159 } 160 161 gettimeofday( &tv_cur, NULL ); 162 return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 163 + ( tv_cur.tv_usec - tv_init.tv_usec ) ); 164} 165 166#endif /* generic */ 167#endif /* IA-64 */ 168#endif /* Alpha */ 169#endif /* SPARC8 */ 170#endif /* PowerPC */ 171#endif /* AMD64 */ 172#endif /* i586+ */ 173 174int alarmed = 0; 175 176#if defined(WIN32) 177 178unsigned long get_timer( struct hr_time *val, int reset ) 179{ 180 unsigned long delta; 181 LARGE_INTEGER offset, hfreq; 182 struct _hr_time *t = (struct _hr_time *) val; 183 184 QueryPerformanceCounter( &offset ); 185 QueryPerformanceFrequency( &hfreq ); 186 187 delta = (unsigned long)( ( 1000 * 188 ( offset.QuadPart - t->start.QuadPart ) ) / 189 hfreq.QuadPart ); 190 191 if( reset ) 192 QueryPerformanceCounter( &t->start ); 193 194 return( delta ); 195} 196 197DWORD WINAPI TimerProc( LPVOID uElapse ) 198{ 199 Sleep( (DWORD) uElapse ); 200 alarmed = 1; 201 return( TRUE ); 202} 203 204void set_alarm( int seconds ) 205{ 206 DWORD ThreadId; 207 208 alarmed = 0; 209 CloseHandle( CreateThread( NULL, 0, TimerProc, 210 (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) ); 211} 212 213void m_sleep( int milliseconds ) 214{ 215 Sleep( milliseconds ); 216} 217 218#else 219 220unsigned long get_timer( struct hr_time *val, int reset ) 221{ 222 unsigned long delta; 223 struct timeval offset; 224 struct _hr_time *t = (struct _hr_time *) val; 225 226 gettimeofday( &offset, NULL ); 227 228 delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 229 + ( offset.tv_usec - t->start.tv_usec ) / 1000; 230 231 if( reset ) 232 { 233 t->start.tv_sec = offset.tv_sec; 234 t->start.tv_usec = offset.tv_usec; 235 } 236 237 return( delta ); 238} 239 240static void sighandler( int signum ) 241{ 242 alarmed = 1; 243 signal( signum, sighandler ); 244} 245 246void set_alarm( int seconds ) 247{ 248 alarmed = 0; 249 signal( SIGALRM, sighandler ); 250 alarm( seconds ); 251} 252 253void m_sleep( int milliseconds ) 254{ 255 struct timeval tv; 256 257 tv.tv_sec = milliseconds / 1000; 258 tv.tv_usec = milliseconds * 1000; 259 260 select( 0, NULL, NULL, NULL, &tv ); 261} 262 263#endif 264 265#endif 266