mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Committer:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Revision:
0:137634ff4186
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:137634ff4186 1 /*
ansond 0:137634ff4186 2 * Portable interface to the CPU cycle counter
ansond 0:137634ff4186 3 *
ansond 0:137634ff4186 4 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
ansond 0:137634ff4186 5 *
ansond 0:137634ff4186 6 * This file is part of mbed TLS (https://tls.mbed.org)
ansond 0:137634ff4186 7 *
ansond 0:137634ff4186 8 * This program is free software; you can redistribute it and/or modify
ansond 0:137634ff4186 9 * it under the terms of the GNU General Public License as published by
ansond 0:137634ff4186 10 * the Free Software Foundation; either version 2 of the License, or
ansond 0:137634ff4186 11 * (at your option) any later version.
ansond 0:137634ff4186 12 *
ansond 0:137634ff4186 13 * This program is distributed in the hope that it will be useful,
ansond 0:137634ff4186 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ansond 0:137634ff4186 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ansond 0:137634ff4186 16 * GNU General Public License for more details.
ansond 0:137634ff4186 17 *
ansond 0:137634ff4186 18 * You should have received a copy of the GNU General Public License along
ansond 0:137634ff4186 19 * with this program; if not, write to the Free Software Foundation, Inc.,
ansond 0:137634ff4186 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ansond 0:137634ff4186 21 */
ansond 0:137634ff4186 22
ansond 0:137634ff4186 23 #if !defined(POLARSSL_CONFIG_FILE)
ansond 0:137634ff4186 24 #include "polarssl/config.h"
ansond 0:137634ff4186 25 #else
ansond 0:137634ff4186 26 #include POLARSSL_CONFIG_FILE
ansond 0:137634ff4186 27 #endif
ansond 0:137634ff4186 28
ansond 0:137634ff4186 29 #if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_PLATFORM_C)
ansond 0:137634ff4186 30 #include "polarssl/platform.h"
ansond 0:137634ff4186 31 #else
ansond 0:137634ff4186 32 #include <stdio.h>
ansond 0:137634ff4186 33 #define polarssl_printf printf
ansond 0:137634ff4186 34 #endif
ansond 0:137634ff4186 35
ansond 0:137634ff4186 36 #if defined(POLARSSL_TIMING_C) && !defined(POLARSSL_TIMING_ALT)
ansond 0:137634ff4186 37
ansond 0:137634ff4186 38 #include "polarssl/timing.h"
ansond 0:137634ff4186 39
ansond 0:137634ff4186 40 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
ansond 0:137634ff4186 41
ansond 0:137634ff4186 42 #include <windows.h>
ansond 0:137634ff4186 43 #include <winbase.h>
ansond 0:137634ff4186 44
ansond 0:137634ff4186 45 struct _hr_time
ansond 0:137634ff4186 46 {
ansond 0:137634ff4186 47 LARGE_INTEGER start;
ansond 0:137634ff4186 48 };
ansond 0:137634ff4186 49
ansond 0:137634ff4186 50 #else
ansond 0:137634ff4186 51
ansond 0:137634ff4186 52 #include <unistd.h>
ansond 0:137634ff4186 53 #include <sys/types.h>
ansond 0:137634ff4186 54 #include <sys/time.h>
ansond 0:137634ff4186 55 #include <signal.h>
ansond 0:137634ff4186 56 #include <time.h>
ansond 0:137634ff4186 57
ansond 0:137634ff4186 58 struct _hr_time
ansond 0:137634ff4186 59 {
ansond 0:137634ff4186 60 struct timeval start;
ansond 0:137634ff4186 61 };
ansond 0:137634ff4186 62
ansond 0:137634ff4186 63 #endif /* _WIN32 && !EFIX64 && !EFI32 */
ansond 0:137634ff4186 64
ansond 0:137634ff4186 65 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
ansond 0:137634ff4186 66 ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__)
ansond 0:137634ff4186 67
ansond 0:137634ff4186 68 #define POLARSSL_HAVE_HARDCLOCK
ansond 0:137634ff4186 69
ansond 0:137634ff4186 70 unsigned long hardclock( void )
ansond 0:137634ff4186 71 {
ansond 0:137634ff4186 72 unsigned long tsc;
ansond 0:137634ff4186 73 __asm rdtsc
ansond 0:137634ff4186 74 __asm mov [tsc], eax
ansond 0:137634ff4186 75 return( tsc );
ansond 0:137634ff4186 76 }
ansond 0:137634ff4186 77 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
ansond 0:137634ff4186 78 ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */
ansond 0:137634ff4186 79
ansond 0:137634ff4186 80 /* some versions of mingw-64 have 32-bit longs even on x84_64 */
ansond 0:137634ff4186 81 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
ansond 0:137634ff4186 82 defined(__GNUC__) && ( defined(__i386__) || ( \
ansond 0:137634ff4186 83 ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) )
ansond 0:137634ff4186 84
ansond 0:137634ff4186 85 #define POLARSSL_HAVE_HARDCLOCK
ansond 0:137634ff4186 86
ansond 0:137634ff4186 87 unsigned long hardclock( void )
ansond 0:137634ff4186 88 {
ansond 0:137634ff4186 89 unsigned long lo, hi;
ansond 0:137634ff4186 90 asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
ansond 0:137634ff4186 91 return( lo );
ansond 0:137634ff4186 92 }
ansond 0:137634ff4186 93 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
ansond 0:137634ff4186 94 __GNUC__ && __i386__ */
ansond 0:137634ff4186 95
ansond 0:137634ff4186 96 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
ansond 0:137634ff4186 97 defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) )
ansond 0:137634ff4186 98
ansond 0:137634ff4186 99 #define POLARSSL_HAVE_HARDCLOCK
ansond 0:137634ff4186 100
ansond 0:137634ff4186 101 unsigned long hardclock( void )
ansond 0:137634ff4186 102 {
ansond 0:137634ff4186 103 unsigned long lo, hi;
ansond 0:137634ff4186 104 asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
ansond 0:137634ff4186 105 return( lo | ( hi << 32 ) );
ansond 0:137634ff4186 106 }
ansond 0:137634ff4186 107 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
ansond 0:137634ff4186 108 __GNUC__ && ( __amd64__ || __x86_64__ ) */
ansond 0:137634ff4186 109
ansond 0:137634ff4186 110 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
ansond 0:137634ff4186 111 defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) )
ansond 0:137634ff4186 112
ansond 0:137634ff4186 113 #define POLARSSL_HAVE_HARDCLOCK
ansond 0:137634ff4186 114
ansond 0:137634ff4186 115 unsigned long hardclock( void )
ansond 0:137634ff4186 116 {
ansond 0:137634ff4186 117 unsigned long tbl, tbu0, tbu1;
ansond 0:137634ff4186 118
ansond 0:137634ff4186 119 do
ansond 0:137634ff4186 120 {
ansond 0:137634ff4186 121 asm volatile( "mftbu %0" : "=r" (tbu0) );
ansond 0:137634ff4186 122 asm volatile( "mftb %0" : "=r" (tbl ) );
ansond 0:137634ff4186 123 asm volatile( "mftbu %0" : "=r" (tbu1) );
ansond 0:137634ff4186 124 }
ansond 0:137634ff4186 125 while( tbu0 != tbu1 );
ansond 0:137634ff4186 126
ansond 0:137634ff4186 127 return( tbl );
ansond 0:137634ff4186 128 }
ansond 0:137634ff4186 129 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
ansond 0:137634ff4186 130 __GNUC__ && ( __powerpc__ || __ppc__ ) */
ansond 0:137634ff4186 131
ansond 0:137634ff4186 132 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
ansond 0:137634ff4186 133 defined(__GNUC__) && defined(__sparc64__)
ansond 0:137634ff4186 134
ansond 0:137634ff4186 135 #if defined(__OpenBSD__)
ansond 0:137634ff4186 136 #warning OpenBSD does not allow access to tick register using software version instead
ansond 0:137634ff4186 137 #else
ansond 0:137634ff4186 138 #define POLARSSL_HAVE_HARDCLOCK
ansond 0:137634ff4186 139
ansond 0:137634ff4186 140 unsigned long hardclock( void )
ansond 0:137634ff4186 141 {
ansond 0:137634ff4186 142 unsigned long tick;
ansond 0:137634ff4186 143 asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) );
ansond 0:137634ff4186 144 return( tick );
ansond 0:137634ff4186 145 }
ansond 0:137634ff4186 146 #endif /* __OpenBSD__ */
ansond 0:137634ff4186 147 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
ansond 0:137634ff4186 148 __GNUC__ && __sparc64__ */
ansond 0:137634ff4186 149
ansond 0:137634ff4186 150 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
ansond 0:137634ff4186 151 defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__)
ansond 0:137634ff4186 152
ansond 0:137634ff4186 153 #define POLARSSL_HAVE_HARDCLOCK
ansond 0:137634ff4186 154
ansond 0:137634ff4186 155 unsigned long hardclock( void )
ansond 0:137634ff4186 156 {
ansond 0:137634ff4186 157 unsigned long tick;
ansond 0:137634ff4186 158 asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" );
ansond 0:137634ff4186 159 asm volatile( "mov %%g1, %0" : "=r" (tick) );
ansond 0:137634ff4186 160 return( tick );
ansond 0:137634ff4186 161 }
ansond 0:137634ff4186 162 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
ansond 0:137634ff4186 163 __GNUC__ && __sparc__ && !__sparc64__ */
ansond 0:137634ff4186 164
ansond 0:137634ff4186 165 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
ansond 0:137634ff4186 166 defined(__GNUC__) && defined(__alpha__)
ansond 0:137634ff4186 167
ansond 0:137634ff4186 168 #define POLARSSL_HAVE_HARDCLOCK
ansond 0:137634ff4186 169
ansond 0:137634ff4186 170 unsigned long hardclock( void )
ansond 0:137634ff4186 171 {
ansond 0:137634ff4186 172 unsigned long cc;
ansond 0:137634ff4186 173 asm volatile( "rpcc %0" : "=r" (cc) );
ansond 0:137634ff4186 174 return( cc & 0xFFFFFFFF );
ansond 0:137634ff4186 175 }
ansond 0:137634ff4186 176 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
ansond 0:137634ff4186 177 __GNUC__ && __alpha__ */
ansond 0:137634ff4186 178
ansond 0:137634ff4186 179 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(POLARSSL_HAVE_ASM) && \
ansond 0:137634ff4186 180 defined(__GNUC__) && defined(__ia64__)
ansond 0:137634ff4186 181
ansond 0:137634ff4186 182 #define POLARSSL_HAVE_HARDCLOCK
ansond 0:137634ff4186 183
ansond 0:137634ff4186 184 unsigned long hardclock( void )
ansond 0:137634ff4186 185 {
ansond 0:137634ff4186 186 unsigned long itc;
ansond 0:137634ff4186 187 asm volatile( "mov %0 = ar.itc" : "=r" (itc) );
ansond 0:137634ff4186 188 return( itc );
ansond 0:137634ff4186 189 }
ansond 0:137634ff4186 190 #endif /* !POLARSSL_HAVE_HARDCLOCK && POLARSSL_HAVE_ASM &&
ansond 0:137634ff4186 191 __GNUC__ && __ia64__ */
ansond 0:137634ff4186 192
ansond 0:137634ff4186 193 #if !defined(POLARSSL_HAVE_HARDCLOCK) && defined(_MSC_VER) && \
ansond 0:137634ff4186 194 !defined(EFIX64) && !defined(EFI32)
ansond 0:137634ff4186 195
ansond 0:137634ff4186 196 #define POLARSSL_HAVE_HARDCLOCK
ansond 0:137634ff4186 197
ansond 0:137634ff4186 198 unsigned long hardclock( void )
ansond 0:137634ff4186 199 {
ansond 0:137634ff4186 200 LARGE_INTEGER offset;
ansond 0:137634ff4186 201
ansond 0:137634ff4186 202 QueryPerformanceCounter( &offset );
ansond 0:137634ff4186 203
ansond 0:137634ff4186 204 return( (unsigned long)( offset.QuadPart ) );
ansond 0:137634ff4186 205 }
ansond 0:137634ff4186 206 #endif /* !POLARSSL_HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */
ansond 0:137634ff4186 207
ansond 0:137634ff4186 208 #if !defined(POLARSSL_HAVE_HARDCLOCK)
ansond 0:137634ff4186 209
ansond 0:137634ff4186 210 #define POLARSSL_HAVE_HARDCLOCK
ansond 0:137634ff4186 211
ansond 0:137634ff4186 212 static int hardclock_init = 0;
ansond 0:137634ff4186 213 static struct timeval tv_init;
ansond 0:137634ff4186 214
ansond 0:137634ff4186 215 unsigned long hardclock( void )
ansond 0:137634ff4186 216 {
ansond 0:137634ff4186 217 struct timeval tv_cur;
ansond 0:137634ff4186 218
ansond 0:137634ff4186 219 if( hardclock_init == 0 )
ansond 0:137634ff4186 220 {
ansond 0:137634ff4186 221 gettimeofday( &tv_init, NULL );
ansond 0:137634ff4186 222 hardclock_init = 1;
ansond 0:137634ff4186 223 }
ansond 0:137634ff4186 224
ansond 0:137634ff4186 225 gettimeofday( &tv_cur, NULL );
ansond 0:137634ff4186 226 return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000
ansond 0:137634ff4186 227 + ( tv_cur.tv_usec - tv_init.tv_usec ) );
ansond 0:137634ff4186 228 }
ansond 0:137634ff4186 229 #endif /* !POLARSSL_HAVE_HARDCLOCK */
ansond 0:137634ff4186 230
ansond 0:137634ff4186 231 volatile int alarmed = 0;
ansond 0:137634ff4186 232
ansond 0:137634ff4186 233 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
ansond 0:137634ff4186 234
ansond 0:137634ff4186 235 unsigned long get_timer( struct hr_time *val, int reset )
ansond 0:137634ff4186 236 {
ansond 0:137634ff4186 237 unsigned long delta;
ansond 0:137634ff4186 238 LARGE_INTEGER offset, hfreq;
ansond 0:137634ff4186 239 struct _hr_time *t = (struct _hr_time *) val;
ansond 0:137634ff4186 240
ansond 0:137634ff4186 241 QueryPerformanceCounter( &offset );
ansond 0:137634ff4186 242 QueryPerformanceFrequency( &hfreq );
ansond 0:137634ff4186 243
ansond 0:137634ff4186 244 delta = (unsigned long)( ( 1000 *
ansond 0:137634ff4186 245 ( offset.QuadPart - t->start.QuadPart ) ) /
ansond 0:137634ff4186 246 hfreq.QuadPart );
ansond 0:137634ff4186 247
ansond 0:137634ff4186 248 if( reset )
ansond 0:137634ff4186 249 QueryPerformanceCounter( &t->start );
ansond 0:137634ff4186 250
ansond 0:137634ff4186 251 return( delta );
ansond 0:137634ff4186 252 }
ansond 0:137634ff4186 253
ansond 0:137634ff4186 254 /* It's OK to use a global because alarm() is supposed to be global anyway */
ansond 0:137634ff4186 255 static DWORD alarmMs;
ansond 0:137634ff4186 256
ansond 0:137634ff4186 257 static DWORD WINAPI TimerProc( LPVOID TimerContext )
ansond 0:137634ff4186 258 {
ansond 0:137634ff4186 259 ((void) TimerContext);
ansond 0:137634ff4186 260 Sleep( alarmMs );
ansond 0:137634ff4186 261 alarmed = 1;
ansond 0:137634ff4186 262 return( TRUE );
ansond 0:137634ff4186 263 }
ansond 0:137634ff4186 264
ansond 0:137634ff4186 265 void set_alarm( int seconds )
ansond 0:137634ff4186 266 {
ansond 0:137634ff4186 267 DWORD ThreadId;
ansond 0:137634ff4186 268
ansond 0:137634ff4186 269 alarmed = 0;
ansond 0:137634ff4186 270 alarmMs = seconds * 1000;
ansond 0:137634ff4186 271 CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) );
ansond 0:137634ff4186 272 }
ansond 0:137634ff4186 273
ansond 0:137634ff4186 274 void m_sleep( int milliseconds )
ansond 0:137634ff4186 275 {
ansond 0:137634ff4186 276 Sleep( milliseconds );
ansond 0:137634ff4186 277 }
ansond 0:137634ff4186 278
ansond 0:137634ff4186 279 #else /* _WIN32 && !EFIX64 && !EFI32 */
ansond 0:137634ff4186 280
ansond 0:137634ff4186 281 unsigned long get_timer( struct hr_time *val, int reset )
ansond 0:137634ff4186 282 {
ansond 0:137634ff4186 283 unsigned long delta;
ansond 0:137634ff4186 284 struct timeval offset;
ansond 0:137634ff4186 285 struct _hr_time *t = (struct _hr_time *) val;
ansond 0:137634ff4186 286
ansond 0:137634ff4186 287 gettimeofday( &offset, NULL );
ansond 0:137634ff4186 288
ansond 0:137634ff4186 289 if( reset )
ansond 0:137634ff4186 290 {
ansond 0:137634ff4186 291 t->start.tv_sec = offset.tv_sec;
ansond 0:137634ff4186 292 t->start.tv_usec = offset.tv_usec;
ansond 0:137634ff4186 293 return( 0 );
ansond 0:137634ff4186 294 }
ansond 0:137634ff4186 295
ansond 0:137634ff4186 296 delta = ( offset.tv_sec - t->start.tv_sec ) * 1000
ansond 0:137634ff4186 297 + ( offset.tv_usec - t->start.tv_usec ) / 1000;
ansond 0:137634ff4186 298
ansond 0:137634ff4186 299 return( delta );
ansond 0:137634ff4186 300 }
ansond 0:137634ff4186 301
ansond 0:137634ff4186 302 #if defined(INTEGRITY)
ansond 0:137634ff4186 303 void m_sleep( int milliseconds )
ansond 0:137634ff4186 304 {
ansond 0:137634ff4186 305 usleep( milliseconds * 1000 );
ansond 0:137634ff4186 306 }
ansond 0:137634ff4186 307
ansond 0:137634ff4186 308 #else /* INTEGRITY */
ansond 0:137634ff4186 309
ansond 0:137634ff4186 310 static void sighandler( int signum )
ansond 0:137634ff4186 311 {
ansond 0:137634ff4186 312 alarmed = 1;
ansond 0:137634ff4186 313 signal( signum, sighandler );
ansond 0:137634ff4186 314 }
ansond 0:137634ff4186 315
ansond 0:137634ff4186 316 void set_alarm( int seconds )
ansond 0:137634ff4186 317 {
ansond 0:137634ff4186 318 alarmed = 0;
ansond 0:137634ff4186 319 signal( SIGALRM, sighandler );
ansond 0:137634ff4186 320 alarm( seconds );
ansond 0:137634ff4186 321 }
ansond 0:137634ff4186 322
ansond 0:137634ff4186 323 void m_sleep( int milliseconds )
ansond 0:137634ff4186 324 {
ansond 0:137634ff4186 325 struct timeval tv;
ansond 0:137634ff4186 326
ansond 0:137634ff4186 327 tv.tv_sec = milliseconds / 1000;
ansond 0:137634ff4186 328 tv.tv_usec = ( milliseconds % 1000 ) * 1000;
ansond 0:137634ff4186 329
ansond 0:137634ff4186 330 select( 0, NULL, NULL, NULL, &tv );
ansond 0:137634ff4186 331 }
ansond 0:137634ff4186 332 #endif /* INTEGRITY */
ansond 0:137634ff4186 333
ansond 0:137634ff4186 334 #endif /* _WIN32 && !EFIX64 && !EFI32 */
ansond 0:137634ff4186 335
ansond 0:137634ff4186 336 #if defined(POLARSSL_SELF_TEST)
ansond 0:137634ff4186 337
ansond 0:137634ff4186 338 /* To test net_usleep against our functions */
ansond 0:137634ff4186 339 #if defined(POLARSSL_NET_C) && defined(POLARSSL_HAVE_TIME)
ansond 0:137634ff4186 340 #include "polarssl/net.h"
ansond 0:137634ff4186 341 #endif
ansond 0:137634ff4186 342
ansond 0:137634ff4186 343 /*
ansond 0:137634ff4186 344 * Busy-waits for the given number of milliseconds.
ansond 0:137634ff4186 345 * Used for testing hardclock.
ansond 0:137634ff4186 346 */
ansond 0:137634ff4186 347 static void busy_msleep( unsigned long msec )
ansond 0:137634ff4186 348 {
ansond 0:137634ff4186 349 struct hr_time hires;
ansond 0:137634ff4186 350 unsigned long i = 0; /* for busy-waiting */
ansond 0:137634ff4186 351 volatile unsigned long j; /* to prevent optimisation */
ansond 0:137634ff4186 352
ansond 0:137634ff4186 353 (void) get_timer( &hires, 1 );
ansond 0:137634ff4186 354
ansond 0:137634ff4186 355 while( get_timer( &hires, 0 ) < msec )
ansond 0:137634ff4186 356 i++;
ansond 0:137634ff4186 357
ansond 0:137634ff4186 358 j = i;
ansond 0:137634ff4186 359 (void) j;
ansond 0:137634ff4186 360 }
ansond 0:137634ff4186 361
ansond 0:137634ff4186 362 /*
ansond 0:137634ff4186 363 * Checkup routine
ansond 0:137634ff4186 364 *
ansond 0:137634ff4186 365 * Warning: this is work in progress, some tests may not be reliable enough
ansond 0:137634ff4186 366 * yet! False positives may happen.
ansond 0:137634ff4186 367 */
ansond 0:137634ff4186 368 int timing_self_test( int verbose )
ansond 0:137634ff4186 369 {
ansond 0:137634ff4186 370 unsigned long cycles, ratio;
ansond 0:137634ff4186 371 unsigned long millisecs, secs;
ansond 0:137634ff4186 372 int hardfail;
ansond 0:137634ff4186 373 struct hr_time hires;
ansond 0:137634ff4186 374
ansond 0:137634ff4186 375 if( verbose != 0 )
ansond 0:137634ff4186 376 polarssl_printf( " TIMING tests note: will take some time!\n" );
ansond 0:137634ff4186 377
ansond 0:137634ff4186 378 if( verbose != 0 )
ansond 0:137634ff4186 379 polarssl_printf( " TIMING test #1 (m_sleep / get_timer): " );
ansond 0:137634ff4186 380
ansond 0:137634ff4186 381 for( secs = 1; secs <= 3; secs++ )
ansond 0:137634ff4186 382 {
ansond 0:137634ff4186 383 (void) get_timer( &hires, 1 );
ansond 0:137634ff4186 384
ansond 0:137634ff4186 385 m_sleep( (int)( 500 * secs ) );
ansond 0:137634ff4186 386
ansond 0:137634ff4186 387 millisecs = get_timer( &hires, 0 );
ansond 0:137634ff4186 388
ansond 0:137634ff4186 389 if( millisecs < 450 * secs || millisecs > 550 * secs )
ansond 0:137634ff4186 390 {
ansond 0:137634ff4186 391 if( verbose != 0 )
ansond 0:137634ff4186 392 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 393
ansond 0:137634ff4186 394 return( 1 );
ansond 0:137634ff4186 395 }
ansond 0:137634ff4186 396 }
ansond 0:137634ff4186 397
ansond 0:137634ff4186 398 if( verbose != 0 )
ansond 0:137634ff4186 399 polarssl_printf( "passed\n" );
ansond 0:137634ff4186 400
ansond 0:137634ff4186 401 if( verbose != 0 )
ansond 0:137634ff4186 402 polarssl_printf( " TIMING test #2 (set_alarm / get_timer): " );
ansond 0:137634ff4186 403
ansond 0:137634ff4186 404 for( secs = 1; secs <= 3; secs++ )
ansond 0:137634ff4186 405 {
ansond 0:137634ff4186 406 (void) get_timer( &hires, 1 );
ansond 0:137634ff4186 407
ansond 0:137634ff4186 408 set_alarm( (int) secs );
ansond 0:137634ff4186 409 while( !alarmed )
ansond 0:137634ff4186 410 ;
ansond 0:137634ff4186 411
ansond 0:137634ff4186 412 millisecs = get_timer( &hires, 0 );
ansond 0:137634ff4186 413
ansond 0:137634ff4186 414 if( millisecs < 900 * secs || millisecs > 1100 * secs )
ansond 0:137634ff4186 415 {
ansond 0:137634ff4186 416 if( verbose != 0 )
ansond 0:137634ff4186 417 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 418
ansond 0:137634ff4186 419 return( 1 );
ansond 0:137634ff4186 420 }
ansond 0:137634ff4186 421 }
ansond 0:137634ff4186 422
ansond 0:137634ff4186 423 if( verbose != 0 )
ansond 0:137634ff4186 424 polarssl_printf( "passed\n" );
ansond 0:137634ff4186 425
ansond 0:137634ff4186 426 if( verbose != 0 )
ansond 0:137634ff4186 427 polarssl_printf( " TIMING test #3 (hardclock / get_timer): " );
ansond 0:137634ff4186 428
ansond 0:137634ff4186 429 /*
ansond 0:137634ff4186 430 * Allow one failure for possible counter wrapping.
ansond 0:137634ff4186 431 * On a 4Ghz 32-bit machine the cycle counter wraps about once per second;
ansond 0:137634ff4186 432 * since the whole test is about 10ms, it shouldn't happen twice in a row.
ansond 0:137634ff4186 433 */
ansond 0:137634ff4186 434 hardfail = 0;
ansond 0:137634ff4186 435
ansond 0:137634ff4186 436 hard_test:
ansond 0:137634ff4186 437 if( hardfail > 1 )
ansond 0:137634ff4186 438 {
ansond 0:137634ff4186 439 if( verbose != 0 )
ansond 0:137634ff4186 440 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 441
ansond 0:137634ff4186 442 return( 1 );
ansond 0:137634ff4186 443 }
ansond 0:137634ff4186 444
ansond 0:137634ff4186 445 /* Get a reference ratio cycles/ms */
ansond 0:137634ff4186 446 millisecs = 1;
ansond 0:137634ff4186 447 cycles = hardclock();
ansond 0:137634ff4186 448 busy_msleep( millisecs );
ansond 0:137634ff4186 449 cycles = hardclock() - cycles;
ansond 0:137634ff4186 450 ratio = cycles / millisecs;
ansond 0:137634ff4186 451
ansond 0:137634ff4186 452 /* Check that the ratio is mostly constant */
ansond 0:137634ff4186 453 for( millisecs = 2; millisecs <= 4; millisecs++ )
ansond 0:137634ff4186 454 {
ansond 0:137634ff4186 455 cycles = hardclock();
ansond 0:137634ff4186 456 busy_msleep( millisecs );
ansond 0:137634ff4186 457 cycles = hardclock() - cycles;
ansond 0:137634ff4186 458
ansond 0:137634ff4186 459 /* Allow variation up to 20% */
ansond 0:137634ff4186 460 if( cycles / millisecs < ratio - ratio / 5 ||
ansond 0:137634ff4186 461 cycles / millisecs > ratio + ratio / 5 )
ansond 0:137634ff4186 462 {
ansond 0:137634ff4186 463 hardfail++;
ansond 0:137634ff4186 464 goto hard_test;
ansond 0:137634ff4186 465 }
ansond 0:137634ff4186 466 }
ansond 0:137634ff4186 467
ansond 0:137634ff4186 468 if( verbose != 0 )
ansond 0:137634ff4186 469 polarssl_printf( "passed\n" );
ansond 0:137634ff4186 470
ansond 0:137634ff4186 471 #if defined(POLARSSL_NET_C) && defined(POLARSSL_HAVE_TIME)
ansond 0:137634ff4186 472 if( verbose != 0 )
ansond 0:137634ff4186 473 polarssl_printf( " TIMING test #4 (net_usleep/ get_timer): " );
ansond 0:137634ff4186 474
ansond 0:137634ff4186 475 for( secs = 1; secs <= 3; secs++ )
ansond 0:137634ff4186 476 {
ansond 0:137634ff4186 477 (void) get_timer( &hires, 1 );
ansond 0:137634ff4186 478
ansond 0:137634ff4186 479 net_usleep( 500000 * secs );
ansond 0:137634ff4186 480
ansond 0:137634ff4186 481 millisecs = get_timer( &hires, 0 );
ansond 0:137634ff4186 482
ansond 0:137634ff4186 483 if( millisecs < 450 * secs || millisecs > 550 * secs )
ansond 0:137634ff4186 484 {
ansond 0:137634ff4186 485 if( verbose != 0 )
ansond 0:137634ff4186 486 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 487
ansond 0:137634ff4186 488 return( 1 );
ansond 0:137634ff4186 489 }
ansond 0:137634ff4186 490 }
ansond 0:137634ff4186 491
ansond 0:137634ff4186 492 if( verbose != 0 )
ansond 0:137634ff4186 493 polarssl_printf( "passed\n" );
ansond 0:137634ff4186 494 #endif /* POLARSSL_NET_C */
ansond 0:137634ff4186 495
ansond 0:137634ff4186 496 if( verbose != 0 )
ansond 0:137634ff4186 497 polarssl_printf( "\n" );
ansond 0:137634ff4186 498
ansond 0:137634ff4186 499 return( 0 );
ansond 0:137634ff4186 500 }
ansond 0:137634ff4186 501
ansond 0:137634ff4186 502 #endif /* POLARSSL_SELF_TEST */
ansond 0:137634ff4186 503
ansond 0:137634ff4186 504 #endif /* POLARSSL_TIMING_C && !POLARSSL_TIMING_ALT */
ansond 0:137634ff4186 505