00001 /* 00002 * Portable interface to the CPU cycle counter 00003 * 00004 * Copyright (C) 2006-2007 Christophe Devine 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License along 00017 * with this program; if not, write to the Free Software Foundation, Inc., 00018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00019 */ 00020 00021 #include "xyssl/config.h" 00022 00023 #if defined(XYSSL_TIMING_C) 00024 00025 #include "xyssl/timing.h" 00026 00027 #if defined(WIN32) 00028 00029 #include <windows.h> 00030 #include <winbase.h> 00031 00032 struct _hr_time 00033 { 00034 LARGE_INTEGER start; 00035 }; 00036 00037 #else 00038 00039 #include <unistd.h> 00040 #include <sys/types.h> 00041 #include <sys/time.h> 00042 #include <signal.h> 00043 #include <time.h> 00044 00045 struct _hr_time 00046 { 00047 struct timeval start; 00048 }; 00049 00050 #endif 00051 00052 #if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 00053 00054 unsigned long hardclock( void ) 00055 { 00056 unsigned long tsc; 00057 __asm rdtsc 00058 __asm mov [tsc], eax 00059 return( tsc ); 00060 } 00061 00062 #else 00063 #if defined(__GNUC__) && defined(__i386__) 00064 00065 unsigned long hardclock( void ) 00066 { 00067 unsigned long tsc; 00068 asm( "rdtsc" : "=a" (tsc) ); 00069 return( tsc ); 00070 } 00071 00072 #else 00073 #if defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__)) 00074 00075 unsigned long hardclock( void ) 00076 { 00077 unsigned long lo, hi; 00078 asm( "rdtsc" : "=a" (lo), "=d" (hi) ); 00079 return( lo | (hi << 32) ); 00080 } 00081 00082 #else 00083 #if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) 00084 00085 unsigned long hardclock( void ) 00086 { 00087 unsigned long tbl, tbu0, tbu1; 00088 00089 do 00090 { 00091 asm( "mftbu %0" : "=r" (tbu0) ); 00092 asm( "mftb %0" : "=r" (tbl ) ); 00093 asm( "mftbu %0" : "=r" (tbu1) ); 00094 } 00095 while( tbu0 != tbu1 ); 00096 00097 return( tbl ); 00098 } 00099 00100 #else 00101 #if defined(__GNUC__) && defined(__sparc__) 00102 00103 unsigned long hardclock( void ) 00104 { 00105 unsigned long tick; 00106 asm( ".byte 0x83, 0x41, 0x00, 0x00" ); 00107 asm( "mov %%g1, %0" : "=r" (tick) ); 00108 return( tick ); 00109 } 00110 00111 #else 00112 #if defined(__GNUC__) && defined(__alpha__) 00113 00114 unsigned long hardclock( void ) 00115 { 00116 unsigned long cc; 00117 asm( "rpcc %0" : "=r" (cc) ); 00118 return( cc & 0xFFFFFFFF ); 00119 } 00120 00121 #else 00122 #if defined(__GNUC__) && defined(__ia64__) 00123 00124 unsigned long hardclock( void ) 00125 { 00126 unsigned long itc; 00127 asm( "mov %0 = ar.itc" : "=r" (itc) ); 00128 return( itc ); 00129 } 00130 00131 #else 00132 00133 static int hardclock_init = 0; 00134 static struct timeval tv_init; 00135 00136 unsigned long hardclock( void ) 00137 { 00138 struct timeval tv_cur; 00139 00140 if( hardclock_init == 0 ) 00141 { 00142 gettimeofday( &tv_init, NULL ); 00143 hardclock_init = 1; 00144 } 00145 00146 gettimeofday( &tv_cur, NULL ); 00147 return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 00148 + ( tv_cur.tv_usec - tv_init.tv_usec ) ); 00149 } 00150 00151 #endif /* generic */ 00152 #endif /* IA-64 */ 00153 #endif /* Alpha */ 00154 #endif /* SPARC8 */ 00155 #endif /* PowerPC */ 00156 #endif /* AMD64 */ 00157 #endif /* i586+ */ 00158 00159 int alarmed = 0; 00160 00161 #if defined(WIN32) 00162 00163 unsigned long get_timer( struct hr_time *val, int reset ) 00164 { 00165 unsigned long delta; 00166 LARGE_INTEGER offset, hfreq; 00167 struct _hr_time *t = (struct _hr_time *) val; 00168 00169 QueryPerformanceCounter( &offset ); 00170 QueryPerformanceFrequency( &hfreq ); 00171 00172 delta = (unsigned long)( ( 1000 * 00173 ( offset.QuadPart - t->start.QuadPart ) ) / 00174 hfreq.QuadPart ); 00175 00176 if( reset ) 00177 QueryPerformanceCounter( &t->start ); 00178 00179 return( delta ); 00180 } 00181 00182 DWORD WINAPI TimerProc( LPVOID uElapse ) 00183 { 00184 Sleep( (DWORD) uElapse ); 00185 alarmed = 1; 00186 return( TRUE ); 00187 } 00188 00189 void set_alarm( int seconds ) 00190 { 00191 DWORD ThreadId; 00192 00193 alarmed = 0; 00194 CloseHandle( CreateThread( NULL, 0, TimerProc, 00195 (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) ); 00196 } 00197 00198 void m_sleep( int milliseconds ) 00199 { 00200 Sleep( milliseconds ); 00201 } 00202 00203 #else 00204 00205 unsigned long get_timer( struct hr_time *val, int reset ) 00206 { 00207 unsigned long delta; 00208 struct timeval offset; 00209 struct _hr_time *t = (struct _hr_time *) val; 00210 00211 gettimeofday( &offset, NULL ); 00212 00213 delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 00214 + ( offset.tv_usec - t->start.tv_usec ) / 1000; 00215 00216 if( reset ) 00217 { 00218 t->start.tv_sec = offset.tv_sec; 00219 t->start.tv_usec = offset.tv_usec; 00220 } 00221 00222 return( delta ); 00223 } 00224 00225 static void sighandler( int signum ) 00226 { 00227 alarmed = 1; 00228 signal( signum, sighandler ); 00229 } 00230 00231 void set_alarm( int seconds ) 00232 { 00233 alarmed = 0; 00234 signal( SIGALRM, sighandler ); 00235 alarm( seconds ); 00236 } 00237 00238 void m_sleep( int milliseconds ) 00239 { 00240 struct timeval tv; 00241 00242 tv.tv_sec = milliseconds / 1000; 00243 tv.tv_usec = milliseconds * 1000; 00244 00245 select( 0, NULL, NULL, NULL, &tv ); 00246 } 00247 00248 #endif 00249 00250 #endif