timing: mark alarmed variable volatile
[tropicssl.git] / library / timing.c
blob22c182380a1d4ce0eb32fa0f6e12c6626ac6071c
1 /*
2 * Portable interface to the CPU cycle counter
4 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
6 * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
8 * All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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.
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.
36 #include "tropicssl/config.h"
38 #if defined(TROPICSSL_TIMING_C)
40 #include "tropicssl/timing.h"
42 #if defined(WIN32)
44 #include <windows.h>
45 #include <winbase.h>
47 struct _hr_time {
48 LARGE_INTEGER start;
51 #else
53 #include <unistd.h>
54 #include <sys/types.h>
55 #include <sys/time.h>
56 #include <signal.h>
57 #include <time.h>
59 struct _hr_time {
60 struct timeval start;
63 #endif
65 #if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
67 unsigned long hardclock(void)
69 unsigned long tsc;
70 __asm rdtsc __asm mov[tsc], eax return (tsc);
73 #else
74 #if defined(__GNUC__) && defined(__i386__)
76 unsigned long hardclock(void)
78 unsigned long tsc;
79 asm("rdtsc":"=a"(tsc));
80 return (tsc);
83 #else
84 #if defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__))
86 unsigned long hardclock(void)
88 unsigned long lo, hi;
89 asm("rdtsc":"=a"(lo), "=d"(hi));
90 return (lo | (hi << 32));
93 #else
94 #if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
96 unsigned long hardclock(void)
98 unsigned long tbl, tbu0, tbu1;
100 do {
101 asm("mftbu %0":"=r"(tbu0));
102 asm("mftb %0":"=r"(tbl));
103 asm("mftbu %0":"=r"(tbu1));
104 } while (tbu0 != tbu1);
106 return (tbl);
109 #else
110 #if defined(__GNUC__) && defined(__sparc__)
112 unsigned long hardclock(void)
114 unsigned long tick;
115 asm(".byte 0x83, 0x41, 0x00, 0x00");
116 asm("mov %%g1, %0":"=r"(tick));
117 return (tick);
120 #else
121 #if defined(__GNUC__) && defined(__alpha__)
123 unsigned long hardclock(void)
125 unsigned long cc;
126 asm("rpcc %0":"=r"(cc));
127 return (cc & 0xFFFFFFFF);
130 #else
131 #if defined(__GNUC__) && defined(__ia64__)
133 unsigned long hardclock(void)
135 unsigned long itc;
136 asm("mov %0 = ar.itc":"=r"(itc));
137 return (itc);
140 #else
142 static int hardclock_init = 0;
143 static struct timeval tv_init;
145 unsigned long hardclock(void)
147 struct timeval tv_cur;
149 if (hardclock_init == 0) {
150 gettimeofday(&tv_init, NULL);
151 hardclock_init = 1;
154 gettimeofday(&tv_cur, NULL);
155 return ((tv_cur.tv_sec - tv_init.tv_sec) * 1000000
156 + (tv_cur.tv_usec - tv_init.tv_usec));
159 #endif /* generic */
160 #endif /* IA-64 */
161 #endif /* Alpha */
162 #endif /* SPARC8 */
163 #endif /* PowerPC */
164 #endif /* AMD64 */
165 #endif /* i586+ */
167 volatile int alarmed = 0;
169 #if defined(WIN32)
171 unsigned long get_timer(struct hr_time *val, int reset)
173 unsigned long delta;
174 LARGE_INTEGER offset, hfreq;
175 struct _hr_time *t = (struct _hr_time *)val;
177 QueryPerformanceCounter(&offset);
178 QueryPerformanceFrequency(&hfreq);
180 delta = (unsigned long)((1000 *
181 (offset.QuadPart - t->start.QuadPart)) /
182 hfreq.QuadPart);
184 if (reset)
185 QueryPerformanceCounter(&t->start);
187 return (delta);
190 DWORD WINAPI TimerProc(LPVOID uElapse)
192 Sleep((DWORD) uElapse);
193 alarmed = 1;
194 return (TRUE);
197 void set_alarm(int seconds)
199 DWORD ThreadId;
201 alarmed = 0;
202 CloseHandle(CreateThread(NULL, 0, TimerProc,
203 (LPVOID) (seconds * 1000), 0, &ThreadId));
206 void m_sleep(int milliseconds)
208 Sleep(milliseconds);
211 #else
213 unsigned long get_timer(struct hr_time *val, int reset)
215 unsigned long delta;
216 struct timeval offset;
217 struct _hr_time *t = (struct _hr_time *)val;
219 gettimeofday(&offset, NULL);
221 delta = (offset.tv_sec - t->start.tv_sec) * 1000
222 + (offset.tv_usec - t->start.tv_usec) / 1000;
224 if (reset) {
225 t->start.tv_sec = offset.tv_sec;
226 t->start.tv_usec = offset.tv_usec;
229 return (delta);
232 static void sighandler(int signum)
234 alarmed = 1;
235 signal(signum, sighandler);
238 void set_alarm(int seconds)
240 alarmed = 0;
241 signal(SIGALRM, sighandler);
242 alarm(seconds);
245 void m_sleep(int milliseconds)
247 struct timeval tv;
249 tv.tv_sec = milliseconds / 1000;
250 tv.tv_usec = milliseconds * 1000;
252 select(0, NULL, NULL, NULL, &tv);
255 #endif
257 #endif