Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
timing.c
00001 /* 00002 * Portable interface to the CPU cycle counter 00003 * 00004 * Copyright (C) 2006-2014, Brainspark B.V. 00005 * 00006 * This file is part of PolarSSL (http://www.polarssl.org) 00007 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> 00008 * 00009 * All rights reserved. 00010 * 00011 * This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License along 00022 * with this program; if not, write to the Free Software Foundation, Inc., 00023 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00024 */ 00025 00026 #if !defined(POLARSSL_CONFIG_FILE) 00027 #include "polarssl/config.h" 00028 #else 00029 #include POLARSSL_CONFIG_FILE 00030 #endif 00031 00032 #if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_PLATFORM_C) 00033 #include "polarssl/platform.h" 00034 #else 00035 #include <stdio.h> 00036 #define polarssl_printf printf 00037 #endif 00038 00039 #if defined(POLARSSL_TIMING_C) && !defined(POLARSSL_TIMING_ALT) 00040 00041 #include "polarssl/timing.h" 00042 00043 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) 00044 00045 #include <windows.h> 00046 #include <winbase.h> 00047 00048 struct _hr_time 00049 { 00050 LARGE_INTEGER start; 00051 }; 00052 00053 #else 00054 00055 #include <unistd.h> 00056 #include <sys/types.h> 00057 #include <sys/time.h> 00058 #include <signal.h> 00059 #include <time.h> 00060 00061 struct _hr_time 00062 { 00063 struct timeval start; 00064 }; 00065 00066 #endif /* _WIN32 && !EFIX64 && !EFI32 */ 00067 00068 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ 00069 (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) 00070 00071 #define POLARSSL_HAVE_HARDCLOCK 00072 00073 unsigned long hardclock( void ) 00074 { 00075 unsigned long tsc; 00076 __asm rdtsc 00077 __asm mov [tsc], eax 00078 return( tsc ); 00079 } 00080 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && 00081 ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ 00082 00083 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ 00084 defined(__GNUC__) && defined(__i386__) 00085 00086 #define POLARSSL_HAVE_HARDCLOCK 00087 00088 unsigned long hardclock( void ) 00089 { 00090 unsigned long lo, hi; 00091 asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); 00092 return( lo ); 00093 } 00094 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && 00095 __GNUC__ && __i386__ */ 00096 00097 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ 00098 defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__)) 00099 00100 #define POLARSSL_HAVE_HARDCLOCK 00101 00102 unsigned long hardclock( void ) 00103 { 00104 unsigned long lo, hi; 00105 asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); 00106 return( lo | (hi << 32) ); 00107 } 00108 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && 00109 __GNUC__ && ( __amd64__ || __x86_64__ ) */ 00110 00111 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ 00112 defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__)) 00113 00114 #define POLARSSL_HAVE_HARDCLOCK 00115 00116 unsigned long hardclock( void ) 00117 { 00118 unsigned long tbl, tbu0, tbu1; 00119 00120 do 00121 { 00122 asm volatile( "mftbu %0" : "=r" (tbu0) ); 00123 asm volatile( "mftb %0" : "=r" (tbl ) ); 00124 asm volatile( "mftbu %0" : "=r" (tbu1) ); 00125 } 00126 while( tbu0 != tbu1 ); 00127 00128 return( tbl ); 00129 } 00130 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && 00131 __GNUC__ && ( __powerpc__ || __ppc__ ) */ 00132 00133 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ 00134 defined(__GNUC__) && defined(__sparc64__) 00135 00136 #if defined(__OpenBSD__) 00137 #warning OpenBSD does not allow access to tick register using software version instead 00138 #else 00139 #define POLARSSL_HAVE_HARDCLOCK 00140 00141 unsigned long hardclock( void ) 00142 { 00143 unsigned long tick; 00144 asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) ); 00145 return( tick ); 00146 } 00147 #endif /* __OpenBSD__ */ 00148 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && 00149 __GNUC__ && __sparc64__ */ 00150 00151 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ 00152 defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) 00153 00154 #define POLARSSL_HAVE_HARDCLOCK 00155 00156 unsigned long hardclock( void ) 00157 { 00158 unsigned long tick; 00159 asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" ); 00160 asm volatile( "mov %%g1, %0" : "=r" (tick) ); 00161 return( tick ); 00162 } 00163 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && 00164 __GNUC__ && __sparc__ && !__sparc64__ */ 00165 00166 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ 00167 defined(__GNUC__) && defined(__alpha__) 00168 00169 #define POLARSSL_HAVE_HARDCLOCK 00170 00171 unsigned long hardclock( void ) 00172 { 00173 unsigned long cc; 00174 asm volatile( "rpcc %0" : "=r" (cc) ); 00175 return( cc & 0xFFFFFFFF ); 00176 } 00177 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && 00178 __GNUC__ && __alpha__ */ 00179 00180 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \ 00181 defined(__GNUC__) && defined(__ia64__) 00182 00183 #define POLARSSL_HAVE_HARDCLOCK 00184 00185 unsigned long hardclock( void ) 00186 { 00187 unsigned long itc; 00188 asm volatile( "mov %0 = ar.itc" : "=r" (itc) ); 00189 return( itc ); 00190 } 00191 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM && 00192 __GNUC__ && __ia64__ */ 00193 00194 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(_MSC_VER) && \ 00195 !defined(EFIX64) && !defined(EFI32) 00196 00197 #define POLARSSL_HAVE_HARDCLOCK 00198 00199 unsigned long hardclock( void ) 00200 { 00201 LARGE_INTEGER offset; 00202 00203 QueryPerformanceCounter( &offset ); 00204 00205 return (unsigned long)( offset.QuadPart ); 00206 } 00207 #endif /* !POLARSSL_HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ 00208 00209 #if !defined(POLARSSL_HAVE_HARDCLOCK) 00210 00211 #define POLARSSL_HAVE_HARDCLOCK 00212 00213 static int hardclock_init = 0; 00214 static struct timeval tv_init; 00215 00216 unsigned long hardclock( void ) 00217 { 00218 struct timeval tv_cur; 00219 00220 if( hardclock_init == 0 ) 00221 { 00222 gettimeofday( &tv_init, NULL ); 00223 hardclock_init = 1; 00224 } 00225 00226 gettimeofday( &tv_cur, NULL ); 00227 return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 00228 + ( tv_cur.tv_usec - tv_init.tv_usec ) ); 00229 } 00230 #endif /* !POLARSSL_HAVE_HARDCLOCK */ 00231 00232 volatile int alarmed = 0; 00233 00234 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) 00235 00236 unsigned long get_timer( struct hr_time *val, int reset ) 00237 { 00238 unsigned long delta; 00239 LARGE_INTEGER offset, hfreq; 00240 struct _hr_time *t = (struct _hr_time *) val; 00241 00242 QueryPerformanceCounter( &offset ); 00243 QueryPerformanceFrequency( &hfreq ); 00244 00245 delta = (unsigned long)( ( 1000 * 00246 ( offset.QuadPart - t->start.QuadPart ) ) / 00247 hfreq.QuadPart ); 00248 00249 if( reset ) 00250 QueryPerformanceCounter( &t->start ); 00251 00252 return( delta ); 00253 } 00254 00255 DWORD WINAPI TimerProc( LPVOID uElapse ) 00256 { 00257 Sleep( (DWORD) uElapse ); 00258 alarmed = 1; 00259 return( TRUE ); 00260 } 00261 00262 void set_alarm( int seconds ) 00263 { 00264 DWORD ThreadId; 00265 00266 alarmed = 0; 00267 CloseHandle( CreateThread( NULL, 0, TimerProc, 00268 (LPVOID) ( seconds * 1000 ), 0, &ThreadId ) ); 00269 } 00270 00271 void m_sleep( int milliseconds ) 00272 { 00273 Sleep( milliseconds ); 00274 } 00275 00276 #else /* _WIN32 && !EFIX64 && !EFI32 */ 00277 00278 unsigned long get_timer( struct hr_time *val, int reset ) 00279 { 00280 unsigned long delta; 00281 struct timeval offset; 00282 struct _hr_time *t = (struct _hr_time *) val; 00283 00284 gettimeofday( &offset, NULL ); 00285 00286 delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 00287 + ( offset.tv_usec - t->start.tv_usec ) / 1000; 00288 00289 if( reset ) 00290 { 00291 t->start.tv_sec = offset.tv_sec; 00292 t->start.tv_usec = offset.tv_usec; 00293 } 00294 00295 return( delta ); 00296 } 00297 00298 #if defined(INTEGRITY) 00299 void m_sleep( int milliseconds ) 00300 { 00301 usleep( milliseconds * 1000 ); 00302 } 00303 00304 #else /* INTEGRITY */ 00305 00306 static void sighandler( int signum ) 00307 { 00308 alarmed = 1; 00309 signal( signum, sighandler ); 00310 } 00311 00312 void set_alarm( int seconds ) 00313 { 00314 alarmed = 0; 00315 signal( SIGALRM, sighandler ); 00316 alarm( seconds ); 00317 } 00318 00319 void m_sleep( int milliseconds ) 00320 { 00321 struct timeval tv; 00322 00323 tv.tv_sec = milliseconds / 1000; 00324 tv.tv_usec = ( milliseconds % 1000 ) * 1000; 00325 00326 select( 0, NULL, NULL, NULL, &tv ); 00327 } 00328 #endif /* INTEGRITY */ 00329 00330 #endif /* _WIN32 && !EFIX64 && !EFI32 */ 00331 00332 #if defined(POLARSSL_SELF_TEST) 00333 00334 /* To test net_usleep against our functions */ 00335 #if defined(POLARSSL_NET_C) 00336 #include "polarssl/net.h" 00337 #endif 00338 00339 /* 00340 * Checkup routine 00341 * 00342 * Warning: this is work in progress, some tests may not be reliable enough 00343 * yet! False positives may happen. 00344 */ 00345 int timing_self_test( int verbose ) 00346 { 00347 unsigned long cycles, ratio; 00348 unsigned long millisecs, secs; 00349 int hardfail; 00350 struct hr_time hires; 00351 00352 if( verbose != 0) 00353 polarssl_printf( " TIMING tests warning: will take some time!\n" ); 00354 00355 if( verbose != 0 ) 00356 polarssl_printf( " TIMING test #1 (m_sleep / get_timer): " ); 00357 00358 for( secs = 1; secs <= 3; secs++ ) 00359 { 00360 (void) get_timer( &hires, 1 ); 00361 00362 m_sleep( 500 * secs ); 00363 00364 millisecs = get_timer( &hires, 0 ); 00365 00366 if( millisecs < 450 * secs || millisecs > 550 * secs ) 00367 { 00368 if( verbose != 0 ) 00369 polarssl_printf( "failed\n" ); 00370 00371 return( 1 ); 00372 } 00373 } 00374 00375 if( verbose != 0 ) 00376 polarssl_printf( "passed\n" ); 00377 00378 if( verbose != 0 ) 00379 polarssl_printf( " TIMING test #2 (set_alarm / get_timer): " ); 00380 00381 for( secs = 1; secs <= 3; secs++ ) 00382 { 00383 (void) get_timer( &hires, 1 ); 00384 00385 set_alarm( secs ); 00386 while( !alarmed ) 00387 ; 00388 00389 millisecs = get_timer( &hires, 0 ); 00390 00391 if( millisecs < 900 * secs || millisecs > 1100 * secs ) 00392 { 00393 if( verbose != 0 ) 00394 polarssl_printf( "failed\n" ); 00395 00396 return( 1 ); 00397 } 00398 } 00399 00400 if( verbose != 0 ) 00401 polarssl_printf( "passed\n" ); 00402 00403 if( verbose != 0 ) 00404 polarssl_printf( " TIMING test #3 (hardclock / m_sleep ): " ); 00405 00406 /* 00407 * Allow one failure for possible counter wrapping. 00408 * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; 00409 * since the whole test is about 10ms, it shouldn't happen twice in a row. 00410 */ 00411 hardfail = 0; 00412 00413 hard_test: 00414 if( hardfail > 1 ) 00415 { 00416 if( verbose != 0 ) 00417 polarssl_printf( "failed\n" ); 00418 00419 return( 1 ); 00420 } 00421 00422 /* Get a reference ratio cycles/ms */ 00423 cycles = hardclock(); 00424 m_sleep( 1 ); 00425 cycles = hardclock() - cycles; 00426 ratio = cycles / 1; 00427 00428 for( millisecs = 2; millisecs <= 4; millisecs++ ) 00429 { 00430 cycles = hardclock(); 00431 m_sleep( millisecs ); 00432 cycles = hardclock() - cycles; 00433 00434 /* Allow variation up to 20% */ 00435 if( cycles / millisecs < ratio - ratio / 5 || 00436 cycles / millisecs > ratio + ratio / 5 ) 00437 { 00438 hardfail++; 00439 goto hard_test; 00440 } 00441 } 00442 00443 if( verbose != 0 ) 00444 polarssl_printf( "passed\n" ); 00445 00446 if( verbose != 0 ) 00447 polarssl_printf( "\n" ); 00448 00449 #if defined(POLARSSL_NET_C) 00450 if( verbose != 0 ) 00451 polarssl_printf( " TIMING test #4 (net_usleep/ get_timer): " ); 00452 00453 for( secs = 1; secs <= 3; secs++ ) 00454 { 00455 (void) get_timer( &hires, 1 ); 00456 00457 net_usleep( 500000 * secs ); 00458 00459 millisecs = get_timer( &hires, 0 ); 00460 00461 if( millisecs < 450 * secs || millisecs > 550 * secs ) 00462 { 00463 if( verbose != 0 ) 00464 polarssl_printf( "failed\n" ); 00465 00466 return( 1 ); 00467 } 00468 } 00469 00470 if( verbose != 0 ) 00471 polarssl_printf( "passed\n" ); 00472 #endif /* POLARSSL_NET_C */ 00473 00474 return( 0 ); 00475 } 00476 00477 #endif /* POLARSSL_SELF_TEST */ 00478 00479 #endif /* POLARSSL_TIMING_C && !POLARSSL_TIMING_ALT */ 00480 00481
Generated on Tue Jul 12 2022 19:40:21 by
1.7.2