]>
Commit | Line | Data |
---|---|---|
295125c5 | 1 | /* High precision, low overhead timing functions. IA-64 version. |
27ef89fb | 2 | Copyright (C) 2001, 2002 Free Software Foundation, Inc. |
295125c5 UD |
3 | This file is part of the GNU C Library. |
4 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 2001. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
7 | modify it under the terms of the GNU Lesser General Public |
8 | License as published by the Free Software Foundation; either | |
9 | version 2.1 of the License, or (at your option) any later version. | |
295125c5 UD |
10 | |
11 | The GNU C Library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 14 | Lesser General Public License for more details. |
295125c5 | 15 | |
41bdb6e2 AJ |
16 | You should have received a copy of the GNU Lesser General Public |
17 | License along with the GNU C Library; if not, write to the Free | |
18 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
19 | 02111-1307 USA. */ | |
295125c5 UD |
20 | |
21 | #ifndef _HP_TIMING_H | |
22 | #define _HP_TIMING_H 1 | |
23 | ||
24 | #include <string.h> | |
25 | #include <sys/param.h> | |
26 | #include <stdio-common/_itoa.h> | |
27 | #include <ia64intrin.h> | |
28 | ||
29 | /* The macros defined here use the timestamp counter in IA-64. They | |
30 | provide a very accurate way to measure the time with very little | |
31 | overhead. The time values themself have no real meaning, only | |
32 | differences are interesting. | |
33 | ||
34 | The list of macros we need includes the following: | |
35 | ||
36 | - HP_TIMING_AVAIL: test for availability. | |
37 | ||
38 | - HP_TIMING_INLINE: this macro is non-zero if the functionality is not | |
39 | implemented using function calls but instead uses some inlined code | |
40 | which might simply consist of a few assembler instructions. We have to | |
41 | know this since we might want to use the macros here in places where we | |
42 | cannot make function calls. | |
43 | ||
44 | - hp_timing_t: This is the type for variables used to store the time | |
45 | values. | |
46 | ||
47 | - HP_TIMING_ZERO: clear `hp_timing_t' object. | |
48 | ||
49 | - HP_TIMING_NOW: place timestamp for current time in variable given as | |
50 | parameter. | |
51 | ||
52 | - HP_TIMING_DIFF_INIT: do whatever is necessary to be able to use the | |
53 | HP_TIMING_DIFF macro. | |
54 | ||
55 | - HP_TIMING_DIFF: compute difference between two times and store it | |
56 | in a third. Source and destination might overlap. | |
57 | ||
58 | - HP_TIMING_ACCUM: add time difference to another variable. This might | |
59 | be a bit more complicated to implement for some platforms as the | |
60 | operation should be thread-safe and 64bit arithmetic on 32bit platforms | |
61 | is not. | |
62 | ||
63 | - HP_TIMING_ACCUM_NT: this is the variant for situations where we know | |
64 | there are no threads involved. | |
65 | ||
66 | - HP_TIMING_PRINT: write decimal representation of the timing value into | |
67 | the given string. This operation need not be inline even though | |
68 | HP_TIMING_INLINE is specified. | |
69 | ||
70 | */ | |
71 | ||
72 | /* We always assume having the timestamp register. */ | |
73 | #define HP_TIMING_AVAIL (1) | |
74 | ||
75 | /* We indeed have inlined functions. */ | |
76 | #define HP_TIMING_INLINE (1) | |
77 | ||
78 | /* We use 64bit values for the times. */ | |
79 | typedef unsigned long int hp_timing_t; | |
80 | ||
295125c5 UD |
81 | /* Set timestamp value to zero. */ |
82 | #define HP_TIMING_ZERO(Var) (Var) = (0) | |
83 | ||
84 | ||
85 | /* The Itanium/Merced has a bug where the ar.itc register value read | |
86 | is not correct in some situations. The solution is to read again. | |
87 | For now we always do this until we know how to recognize a fixed | |
88 | processor implementation. */ | |
89 | #define REPEAT_READ(val) __builtin_expect ((int) val == -1, 0) | |
90 | ||
b4123507 | 91 | /* That's quite simple. Use the `ar.itc' instruction. */ |
295125c5 UD |
92 | #define HP_TIMING_NOW(Var) \ |
93 | ({ unsigned long int __itc; \ | |
94 | do \ | |
95 | asm volatile ("mov %0=ar.itc" : "=r" (__itc) : : "memory"); \ | |
96 | while (REPEAT_READ (__itc)); \ | |
97 | Var = __itc; }) | |
98 | ||
99 | /* Use two 'ar.itc' instructions in a row to find out how long it takes. */ | |
100 | #define HP_TIMING_DIFF_INIT() \ | |
101 | do { \ | |
102 | int __cnt = 5; \ | |
27ef89fb | 103 | GL(dl_hp_timing_overhead) = ~0ul; \ |
295125c5 UD |
104 | do \ |
105 | { \ | |
106 | hp_timing_t __t1, __t2; \ | |
107 | HP_TIMING_NOW (__t1); \ | |
108 | HP_TIMING_NOW (__t2); \ | |
27ef89fb UD |
109 | if (__t2 - __t1 < GL(dl_hp_timing_overhead)) \ |
110 | GL(dl_hp_timing_overhead) = __t2 - __t1; \ | |
295125c5 UD |
111 | } \ |
112 | while (--__cnt > 0); \ | |
113 | } while (0) | |
114 | ||
115 | /* It's simple arithmetic for us. */ | |
116 | #define HP_TIMING_DIFF(Diff, Start, End) (Diff) = ((End) - (Start)) | |
117 | ||
118 | /* We have to jump through hoops to get this correctly implemented. */ | |
119 | #define HP_TIMING_ACCUM(Sum, Diff) \ | |
120 | do { \ | |
121 | hp_timing_t __oldval; \ | |
27ef89fb | 122 | hp_timing_t __diff = (Diff) - GL(dl_hp_timing_overhead); \ |
295125c5 UD |
123 | hp_timing_t __newval; \ |
124 | do \ | |
125 | { \ | |
126 | __oldval = (Sum); \ | |
127 | __newval = __oldval + __diff; \ | |
128 | } \ | |
129 | while (! __sync_bool_compare_and_swap (&Sum, __oldvar, __newval)); \ | |
130 | } while (0) | |
131 | ||
132 | /* No threads, no extra work. */ | |
133 | #define HP_TIMING_ACCUM_NT(Sum, Diff) (Sum) += (Diff) | |
134 | ||
135 | /* Print the time value. */ | |
136 | #define HP_TIMING_PRINT(Buf, Len, Val) \ | |
137 | do { \ | |
138 | char __buf[20]; \ | |
139 | char *__cp = _itoa_word (Val, __buf + sizeof (__buf), 10, 0); \ | |
140 | int __len = (Len); \ | |
141 | char *__dest = (Buf); \ | |
142 | while (__len-- > 0 && __cp < __buf + sizeof (__buf)) \ | |
143 | *__dest++ = *__cp++; \ | |
6dd67bd5 UD |
144 | memcpy (__dest, " clock cycles", MIN (__len, \ |
145 | (int) sizeof (" clock cycles"))); \ | |
295125c5 UD |
146 | } while (0) |
147 | ||
148 | #endif /* hp-timing.h */ |