1 /* Copyright (c) 2008 MySQL AB, 2009 Sun Microsystems, Inc.
2    Use is subject to license terms.
3 
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; version 2 of the License.
7 
8   This program is distributed in the hope that it will be useful,
9   but WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11   GNU General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License
14   along with this program; if not, write to the Free Software
15   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335  USA */
16 
17 /*
18   rdtsc3 -- multi-platform timer code
19   pgulutzan@mysql.com, 2005-08-29
20   modified 2008-11-02
21 
22   When you run rdtsc3, it will print the contents of
23   "my_timer_info". The display indicates
24   what timer routine is best for a given platform.
25 
26   For example, this is the display on production.mysql.com,
27   a 2.8GHz Xeon with Linux 2.6.17, gcc 3.3.3:
28 
29   cycles        nanoseconds   microseconds  milliseconds  ticks
30 ------------- ------------- ------------- ------------- -------------
31             1            11            13            18            17
32    2815019607    1000000000       1000000          1049           102
33             1          1000             1             1             1
34            88          4116          3888          4092          2044
35 
36   The first line shows routines, e.g. 1 = MY_TIMER_ROUTINE_ASM_X86.
37   The second line shows frequencies, e.g. 2815019607 is nearly 2.8GHz.
38   The third line shows resolutions, e.g. 1000 = very poor resolution.
39   The fourth line shows overheads, e.g. ticks takes 2044 cycles.
40 */
41 
42 #include "my_global.h"
43 #include "my_rdtsc.h"
44 #include "tap.h"
45 
46 #define LOOP_COUNT 100
47 
48 MY_TIMER_INFO myt;
49 
test_init()50 void test_init()
51 {
52   my_timer_init(&myt);
53 
54   diag("----- Routine ---------------");
55   diag("myt.cycles.routine          : %13llu", myt.cycles.routine);
56   diag("myt.nanoseconds.routine     : %13llu", myt.nanoseconds.routine);
57   diag("myt.microseconds.routine    : %13llu", myt.microseconds.routine);
58   diag("myt.milliseconds.routine    : %13llu", myt.milliseconds.routine);
59   diag("myt.ticks.routine           : %13llu", myt.ticks.routine);
60 
61   diag("----- Frequency -------------");
62   diag("myt.cycles.frequency        : %13llu", myt.cycles.frequency);
63   diag("myt.nanoseconds.frequency   : %13llu", myt.nanoseconds.frequency);
64   diag("myt.microseconds.frequency  : %13llu", myt.microseconds.frequency);
65   diag("myt.milliseconds.frequency  : %13llu", myt.milliseconds.frequency);
66   diag("myt.ticks.frequency         : %13llu", myt.ticks.frequency);
67 
68   diag("----- Resolution ------------");
69   diag("myt.cycles.resolution       : %13llu", myt.cycles.resolution);
70   diag("myt.nanoseconds.resolution  : %13llu", myt.nanoseconds.resolution);
71   diag("myt.microseconds.resolution : %13llu", myt.microseconds.resolution);
72   diag("myt.milliseconds.resolution : %13llu", myt.milliseconds.resolution);
73   diag("myt.ticks.resolution        : %13llu", myt.ticks.resolution);
74 
75   diag("----- Overhead --------------");
76   diag("myt.cycles.overhead         : %13llu", myt.cycles.overhead);
77   diag("myt.nanoseconds.overhead    : %13llu", myt.nanoseconds.overhead);
78   diag("myt.microseconds.overhead   : %13llu", myt.microseconds.overhead);
79   diag("myt.milliseconds.overhead   : %13llu", myt.milliseconds.overhead);
80   diag("myt.ticks.overhead          : %13llu", myt.ticks.overhead);
81 
82   ok(1, "my_timer_init() did not crash");
83 }
84 
test_cycle()85 void test_cycle()
86 {
87   ulonglong t1= my_timer_cycles();
88   ulonglong t2;
89   int i;
90   int backward= 0;
91   int nonzero= 0;
92 
93   for (i=0 ; i < LOOP_COUNT ; i++)
94   {
95     t2= my_timer_cycles();
96     if (t1 >= t2)
97       backward++;
98     if (t2 != 0)
99       nonzero++;
100     t1= t2;
101   }
102 
103   /* Expect at most 1 backward, the cycle value can overflow */
104   ok((backward <= 1), "The cycle timer is strictly increasing");
105 
106   if (myt.cycles.routine != 0)
107     ok((nonzero != 0), "The cycle timer is implemented");
108   else
109     ok((nonzero == 0), "The cycle timer is not implemented and returns 0");
110 }
111 
test_nanosecond()112 void test_nanosecond()
113 {
114   ulonglong t1= my_timer_nanoseconds();
115   ulonglong t2;
116   int i;
117   int backward= 0;
118   int nonzero= 0;
119 
120   for (i=0 ; i < LOOP_COUNT ; i++)
121   {
122     t2= my_timer_nanoseconds();
123     if (t1 > t2)
124       backward++;
125     if (t2 != 0)
126       nonzero++;
127     t1= t2;
128   }
129 
130   ok((backward == 0), "The nanosecond timer is increasing");
131 
132   if (myt.nanoseconds.routine != 0)
133     ok((nonzero != 0), "The nanosecond timer is implemented");
134   else
135     ok((nonzero == 0), "The nanosecond timer is not implemented and returns 0");
136 }
137 
test_microsecond()138 void test_microsecond()
139 {
140   ulonglong t1= my_timer_microseconds();
141   ulonglong t2;
142   int i;
143   int backward= 0;
144   int nonzero= 0;
145 
146   for (i=0 ; i < LOOP_COUNT ; i++)
147   {
148     t2= my_timer_microseconds();
149     if (t1 > t2)
150       backward++;
151     if (t2 != 0)
152       nonzero++;
153     t1= t2;
154   }
155 
156   ok((backward == 0), "The microsecond timer is increasing");
157 
158   if (myt.microseconds.routine != 0)
159     ok((nonzero != 0), "The microsecond timer is implemented");
160   else
161     ok((nonzero == 0), "The microsecond timer is not implemented and returns 0");
162 }
163 
test_millisecond()164 void test_millisecond()
165 {
166   ulonglong t1= my_timer_milliseconds();
167   ulonglong t2;
168   int i;
169   int backward= 0;
170   int nonzero= 0;
171 
172   for (i=0 ; i < LOOP_COUNT ; i++)
173   {
174     t2= my_timer_milliseconds();
175     if (t1 > t2)
176       backward++;
177     if (t2 != 0)
178       nonzero++;
179     t1= t2;
180   }
181 
182   ok((backward == 0), "The millisecond timer is increasing");
183 
184   if (myt.milliseconds.routine != 0)
185     ok((nonzero != 0), "The millisecond timer is implemented");
186   else
187     ok((nonzero == 0), "The millisecond timer is not implemented and returns 0");
188 }
189 
test_tick()190 void test_tick()
191 {
192   ulonglong t1= my_timer_ticks();
193   ulonglong t2;
194   int i;
195   int backward= 0;
196   int nonzero= 0;
197 
198   for (i=0 ; i < LOOP_COUNT ; i++)
199   {
200     t2= my_timer_ticks();
201     if (t1 > t2)
202       backward++;
203     if (t2 != 0)
204       nonzero++;
205     t1= t2;
206   }
207 
208   ok((backward == 0), "The tick timer is increasing");
209 
210   if (myt.ticks.routine != 0)
211     ok((nonzero != 0), "The tick timer is implemented");
212   else
213     ok((nonzero == 0), "The tick timer is not implemented and returns 0");
214 }
215 
main(int argc,char ** argv)216 int main(int argc __attribute__((unused)),
217          char ** argv __attribute__((unused)))
218 {
219   plan(11);
220 
221   test_init();
222   test_cycle();
223   test_nanosecond();
224   test_microsecond();
225   test_millisecond();
226   test_tick();
227 
228   return 0;
229 }
230 
231