Statistics
| Branch: | Revision:

root / include / cstopwatch.h @ master

History | View | Annotate | Download (5.88 KB)

1
//==========================================================================
2
//   CSTOPWATCH.H  -  header for
3
//                OMNeT++/OMNEST
4
//           Discrete System Simulation in C++
5
//
6
//  Stop watches to measure time intervals. Especially for debug purpose.
7
//
8
//  Declaration of the following classes:
9
//    cStopWatch : Stop watch to measure time intervals. Especially for debug purpose.
10
//    cStopwatch : Alternative stop watch implementation
11
//
12
//==========================================================================
13
//
14

    
15
/*--------------------------------------------------------------*
16
 Copyright (C) 2009 Georg Kunz
17
 Copyright (C) 2010 Mirko Stoffers
18

19
 This file is distributed WITHOUT ANY WARRANTY. See the file
20
 `license' for details on this and other legal matters.
21
 *--------------------------------------------------------------*/
22

    
23
#pragma once
24

    
25
#include <time.h>
26
#include <assert.h>
27
#include <stdio.h>
28

    
29
#include "simkerneldefs.h"
30

    
31
/**
32
 *
33
 * @ingroup Horizon
34
 */
35
class SIM_API cStopWatch
36
{
37
private:
38

    
39
    /*
40
     *  timespecs to measure start time, stop time, and value for accumulations
41
     */
42
    struct timespec lastStart, lastStop, currentValue;
43

    
44
    /*
45
     *  flag indicating whether the watch is currently running or not.
46
     */
47
    bool running;
48

    
49
    /*
50
     * flag indicating whether or not the TSC was successfully calibrated.
51
     */
52
    bool calibrated;
53

    
54
    /*
55
     * number of elapsed CPU ticks when starting the stopwatch.
56
     */
57
    unsigned long long startTicks;
58

    
59
    /*
60
     * number of elapsed CPU ticks when stopping the stopwatch.
61
     */
62
    unsigned long long stopTicks;
63

    
64
    /*
65
     * number of CPU ticks per second on the current hardware platform
66
     */
67
    unsigned long long ticksPerSecond;
68

    
69

    
70
public:
71

    
72
    /**
73
     * Constructor.
74
     */
75
    cStopWatch();
76

    
77
    /*
78
     * Start stop watch. May only be called when watch is not running!
79
     */
80
    inline void start()
81
    {
82
        assert(!running);
83
        running = true;
84

    
85
        clock_gettime(CLOCK_REALTIME, &lastStart);
86
    }
87

    
88
    /*
89
     * Stop stop watch. May only be called when watch is running!
90
     */
91
    inline void stop()
92
    {
93
        assert(running);
94
        running = false;
95

    
96
        clock_gettime(CLOCK_REALTIME, &lastStop);
97

    
98
        currentValue.tv_nsec += lastStop.tv_nsec - lastStart.tv_nsec;
99
        if (currentValue.tv_nsec < 0)
100
        {
101
            currentValue.tv_nsec += 1000000000;
102
            currentValue.tv_sec += lastStop.tv_sec - lastStart.tv_sec - 1;
103
        }
104
        else
105
        {
106
            currentValue.tv_sec += lastStop.tv_sec - lastStart.tv_sec;
107
        }
108
    }
109

    
110
    /*
111
     * Reset stop watch. May only be called when watch is not running!
112
     */
113
    inline void reset()
114
    {
115
        assert(!running);
116
        currentValue.tv_nsec = 0;
117
        currentValue.tv_sec = 0;
118
        startTicks = 0;
119
        stopTicks = 0;
120
    }
121

    
122
    /*
123
     * Current value. May only be called when watch is not running!
124
     */
125
    inline timespec getTime() const
126
    {
127
        assert(!running);
128
        return currentValue;
129
    }
130

    
131
    /*
132
     * Current value as string. Please allocate enough space in stringbuffer!
133
     * May only be called when watch is not running!
134
     * @param stringbuffer buffer into that result is stored
135
     * @param bufferSize size of stringbuffer
136
     */
137
    inline void getTime(char* const stringbuffer, const size_t bufferSize) const
138
    {
139
        assert(!running);
140
        snprintf(stringbuffer, bufferSize - 1, "%f", currentValue.tv_sec
141
                + currentValue.tv_nsec / 1.0e9);
142
    }
143

    
144
    /*
145
     * Stops stop watch, resets it, and returns value after stopping.
146
     * May only be called when watch is running!
147
     */
148
    inline timespec stopNreset()
149
    {
150
        if (running)
151
            stop();
152
        timespec t = getTime();
153
        reset();
154
        return t;
155
    }
156

    
157
    /*
158
     * Stops stop watch, resets it, and stores value after stopping as string.
159
     * Please allocate enough space in stringbuffer!
160
     * @param stringbuffer buffer into that result is stored
161
     * @param bufferSize size of stringbuffer
162
     * May only be called when watch is running!
163
     */
164
    inline void stopNreset(char* const stringbuffer, const size_t bufferSize)
165
    {
166
        if (running)
167
            stop();
168
        getTime(stringbuffer, bufferSize);
169
        reset();
170
    }
171

    
172
    /**
173
     * Start counting the number of CPU ticks.
174
     */
175
    inline void startTicking()
176
    {
177
        assert(!running && calibrated);
178
        running = true;
179
        startTicks = rdtsc();
180
    }
181

    
182
    /**
183
     * Stop counting the number of CPU ticks.
184
     */
185
    inline void stopTicking()
186
    {
187
        assert(running && calibrated);
188
        running = false;
189
        stopTicks = rdtsc();
190
    }
191

    
192
    /**
193
     * Return the number of elapsed CPU ticks between start and stop.
194
     */
195
    inline unsigned long long getTicks()
196
    {
197
        assert(!running && calibrated);
198
        return stopTicks - startTicks;
199
    }
200

    
201
    /**
202
     * Return the number of elapsed seconds based on the tick count.
203
     */
204
    inline double getTicksTime()
205
    {
206
        assert(!running && calibrated);
207
        unsigned long long deltaTicks = stopTicks - startTicks;
208
        return ((double)deltaTicks) / ((double)ticksPerSecond);
209
    }
210

    
211
    /**
212
     * Return the number of ticks per seconds as measured by the calibration.
213
     */
214
    inline unsigned long long getTicksPerSecond()
215
    {
216
        assert(calibrated);
217
        return ticksPerSecond;
218
    }
219

    
220
    /**
221
     * calibrate the TSC, i.e., determine the number of ticks per second.
222
     */
223
    inline void calibrateTSC()
224
    {
225
        assert(!running);
226
        calibrated = calibrate();
227
    }
228

    
229
private:
230

    
231
    /**
232
     * Read the value of the TSC register.
233
     */
234
    inline unsigned long long rdtsc()
235
    {
236
        unsigned a, d;
237
        __asm__ volatile("rdtsc" : "=a" (a), "=d" (d));
238
        return ((unsigned long long) a) | (((unsigned long long) d) << 32);
239
    }
240

    
241
    /**
242
     * perform the TSC calibration.
243
     */
244
    bool calibrate();
245
};