1 /*
2  * cycles.c - measures CPU cycles using architecture specific extensions.
3  *
4  * Currently just for the pentium using the RDTSC instruction
5  *
6  * Copyright (c) 1998 Phil Maker <pjm@gnu.org>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $Id: cycles.c,v 1.1.1.1 1999/09/12 03:26:50 pjm Exp $
31  */
32 
33 #include <nana-config.h>
34 
35 #if HAVE_CYCLES /* only compile this file if we can measure CPU cycles */
36 
37 #include <now.h>
38 #include <cycles.h>
39 
40 /*
41  * measure - does a single measurement using a spin loop running for
42  *   duration. Sets min/max appropriately (note: min is the smallest
43  *   number of the cps which is the LONGEST time!)
44  *
45  * Assumptions:
46  *
47  *   1. We can be preempted by another process at any time;
48  *      hence the min..max return values.
49  *   2. We use doubles for some of the calculations and this
50  *      should be allright since the number of cycles occurring
51  *      during a single measurement should be representable in
52  *      in a double (I hope).
53  */
54 
measure(double duration,CYCLES * min,CYCLES * max)55 static void measure(double duration, CYCLES *min, CYCLES *max) {
56   double start_min, start_max, end_min, end_max;
57   CYCLES start, end;
58 
59   start_min = now();
60   start = cycles();
61   start_max = now();
62 
63   do {
64     end_min = now();
65   } while((end_min - start_min) < duration);
66 
67   end = cycles();
68   end_max = now();
69 
70   *max = (CYCLES) (((double)(end - start))/(end_min - start_max));
71   *min = (CYCLES) (((double)(end - start))/(end_max - start_min));
72 }
73 
74 static CYCLES min_cps, max_cps;
75 
76 /*
77  * cycles_per_second - performs n measurements of duration d and returns
78  *   the maximum value which should be fairly close to the correct
79  *   value (and pigs fly). The values min_cps and max_cps are reset
80  *   upon every call to this routine.
81  */
82 
cycles_per_second(double d,int n)83 CYCLES cycles_per_second(double d, int n) {
84   int i;
85   CYCLES min, max;
86 
87   measure(d, &min_cps, &max_cps);
88   for(i = 1; i < n; i++) {
89     measure(d, &min, &max);
90     if(min < min_cps) {
91       min_cps = min;
92     }
93     if(max > max_cps) {
94       max_cps = max;
95     }
96   }
97   return max_cps;
98 }
99 
cycles_per_second_min()100 CYCLES cycles_per_second_min() {
101   return min_cps;
102 }
103 
cycles_per_second_max()104 CYCLES cycles_per_second_max() {
105   return max_cps;
106 }
107 
cycles_diff(CYCLES start,CYCLES stop)108 double cycles_diff(CYCLES start, CYCLES stop) {
109   return ((double)(stop - start))/((double) max_cps);
110 
111 }
112 
113 #endif /* HAVE_CYCLES */
114 
115