1 /* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
22 
23 
24 /*
25   rdtsc3 -- multi-platform timer code
26   pgulutzan@mysql.com, 2005-08-29
27   modified 2008-11-02
28 
29   When you run rdtsc3, it will print the contents of
30   "my_timer_info". The display indicates
31   what timer routine is best for a given platform.
32 
33   For example, this is the display on production.mysql.com,
34   a 2.8GHz Xeon with Linux 2.6.17, gcc 3.3.3:
35 
36   cycles        nanoseconds   microseconds  milliseconds  ticks
37 ------------- ------------- ------------- ------------- -------------
38             1            11            13            18            17
39    2815019607    1000000000       1000000          1049           102
40             1          1000             1             1             1
41            88          4116          3888          4092          2044
42 
43   The first line shows routines, e.g. 1 = MY_TIMER_ROUTINE_ASM_X86.
44   The second line shows frequencies, e.g. 2815019607 is nearly 2.8GHz.
45   The third line shows resolutions, e.g. 1000 = very poor resolution.
46   The fourth line shows overheads, e.g. ticks takes 2044 cycles.
47 */
48 
49 // First include (the generated) my_config.h, to get correct platform defines.
50 #include "my_config.h"
51 #include <gtest/gtest.h>
52 
53 #include "my_global.h"
54 #include "my_rdtsc.h"
55 
56 namespace mysys_my_rdtsc_unittest {
57 
58 const int LOOP_COUNT= 100;
59 
60 class RDTimeStampCounter : public ::testing::Test
61 {
62 protected:
SetUp()63   void SetUp()
64   {
65     test_init();
66   }
67   void test_init();
68 
69   MY_TIMER_INFO myt;
70 };
71 
72 
test_init()73 void RDTimeStampCounter::test_init()
74 {
75   my_timer_init(&myt);
76 
77 /*
78   diag("----- Routine ---------------");
79   diag("myt.cycles.routine          : %13llu", myt.cycles.routine);
80   diag("myt.nanoseconds.routine     : %13llu", myt.nanoseconds.routine);
81   diag("myt.microseconds.routine    : %13llu", myt.microseconds.routine);
82   diag("myt.milliseconds.routine    : %13llu", myt.milliseconds.routine);
83   diag("myt.ticks.routine           : %13llu", myt.ticks.routine);
84 
85   diag("----- Frequency -------------");
86   diag("myt.cycles.frequency        : %13llu", myt.cycles.frequency);
87   diag("myt.nanoseconds.frequency   : %13llu", myt.nanoseconds.frequency);
88   diag("myt.microseconds.frequency  : %13llu", myt.microseconds.frequency);
89   diag("myt.milliseconds.frequency  : %13llu", myt.milliseconds.frequency);
90   diag("myt.ticks.frequency         : %13llu", myt.ticks.frequency);
91 
92   diag("----- Resolution ------------");
93   diag("myt.cycles.resolution       : %13llu", myt.cycles.resolution);
94   diag("myt.nanoseconds.resolution  : %13llu", myt.nanoseconds.resolution);
95   diag("myt.microseconds.resolution : %13llu", myt.microseconds.resolution);
96   diag("myt.milliseconds.resolution : %13llu", myt.milliseconds.resolution);
97   diag("myt.ticks.resolution        : %13llu", myt.ticks.resolution);
98 
99   diag("----- Overhead --------------");
100   diag("myt.cycles.overhead         : %13llu", myt.cycles.overhead);
101   diag("myt.nanoseconds.overhead    : %13llu", myt.nanoseconds.overhead);
102   diag("myt.microseconds.overhead   : %13llu", myt.microseconds.overhead);
103   diag("myt.milliseconds.overhead   : %13llu", myt.milliseconds.overhead);
104   diag("myt.ticks.overhead          : %13llu", myt.ticks.overhead);
105 */
106 }
107 
108 
TEST_F(RDTimeStampCounter,TestCycle)109 TEST_F(RDTimeStampCounter, TestCycle)
110 {
111   ulonglong t1= my_timer_cycles();
112   ulonglong t2;
113   int i;
114   int backward= 0;
115   int nonzero= 0;
116 
117   for (i=0 ; i < LOOP_COUNT ; i++)
118   {
119     t2= my_timer_cycles();
120     if (t1 >= t2)
121       backward++;
122     if (t2 != 0)
123       nonzero++;
124     t1= t2;
125   }
126 
127   /* Expect at most 1 backward, the cycle value can overflow */
128   EXPECT_TRUE((backward <= 1)) << "The cycle timer is strictly increasing";
129 
130   if (myt.cycles.routine != 0)
131     EXPECT_TRUE((nonzero != 0)) << "The cycle timer is implemented";
132   else
133     EXPECT_TRUE((nonzero == 0))
134       << "The cycle timer is not implemented and returns 0";
135 }
136 
137 
TEST_F(RDTimeStampCounter,TestNanosecond)138 TEST_F(RDTimeStampCounter, TestNanosecond)
139 {
140   ulonglong t1= my_timer_nanoseconds();
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_nanoseconds();
149     if (t1 > t2)
150       backward++;
151     if (t2 != 0)
152       nonzero++;
153     t1= t2;
154   }
155 
156   EXPECT_TRUE((backward == 0)) << "The nanosecond timer is increasing";
157 
158   if (myt.nanoseconds.routine != 0)
159     EXPECT_TRUE((nonzero != 0)) << "The nanosecond timer is implemented";
160   else
161     EXPECT_TRUE((nonzero == 0))
162       << "The nanosecond timer is not implemented and returns 0";
163 }
164 
165 
TEST_F(RDTimeStampCounter,TestMicrosecond)166 TEST_F(RDTimeStampCounter, TestMicrosecond)
167 {
168   ulonglong t1= my_timer_microseconds();
169   ulonglong t2;
170   int i;
171   int backward= 0;
172   int nonzero= 0;
173 
174   for (i=0 ; i < LOOP_COUNT ; i++)
175   {
176     t2= my_timer_microseconds();
177     if (t1 > t2)
178       backward++;
179     if (t2 != 0)
180       nonzero++;
181     t1= t2;
182   }
183 
184   EXPECT_TRUE((backward == 0)) << "The microsecond timer is increasing";
185 
186   if (myt.microseconds.routine != 0)
187     EXPECT_TRUE((nonzero != 0)) << "The microsecond timer is implemented";
188   else
189     EXPECT_TRUE((nonzero == 0))
190       << "The microsecond timer is not implemented and returns 0";
191 }
192 
193 
TEST_F(RDTimeStampCounter,TestMillisecond)194 TEST_F(RDTimeStampCounter, TestMillisecond)
195 {
196   ulonglong t1= my_timer_milliseconds();
197   ulonglong t2;
198   int i;
199   int backward= 0;
200   int nonzero= 0;
201 
202   for (i=0 ; i < LOOP_COUNT ; i++)
203   {
204     t2= my_timer_milliseconds();
205     if (t1 > t2)
206       backward++;
207     if (t2 != 0)
208       nonzero++;
209     t1= t2;
210   }
211 
212   EXPECT_TRUE((backward == 0)) << "The millisecond timer is increasing";
213 
214   if (myt.milliseconds.routine != 0)
215     EXPECT_TRUE((nonzero != 0)) << "The millisecond timer is implemented";
216   else
217     EXPECT_TRUE((nonzero == 0))
218       << "The millisecond timer is not implemented and returns 0";
219 }
220 
221 
TEST_F(RDTimeStampCounter,TestTick)222 TEST_F(RDTimeStampCounter, TestTick)
223 {
224   ulonglong t1= my_timer_ticks();
225   ulonglong t2;
226   int i;
227   int backward= 0;
228   int nonzero= 0;
229 
230   for (i=0 ; i < LOOP_COUNT ; i++)
231   {
232     t2= my_timer_ticks();
233     if (t1 > t2)
234       backward++;
235     if (t2 != 0)
236       nonzero++;
237     t1= t2;
238   }
239 
240   EXPECT_TRUE((backward == 0)) << "The tick timer is increasing";
241 
242   if (myt.ticks.routine != 0)
243     EXPECT_TRUE((nonzero != 0)) << "The tick timer is implemented";
244   else
245     EXPECT_TRUE((nonzero == 0))
246       << "The tick timer is not implemented and returns 0";
247 }
248 
249 
250 }
251