Reputation: 5452
I am writing a thread library, and when scheduling the threads I need to know how long they've been ready. Every Thread instance has a timeval _timeInReady
field, and when I push an instance to the ready queue I call this function:
void Thread::startTiming() {
gettimeofday(&_timeInReady, NULL);
}
When I want to check the current _timeInReady
value I call:
double Thread::getTimeInReady() const {
return TIME(_timeInReady.tv_sec,_timeInReady.tv_usec);
}
Where TIME is #define TIME(a,b) ((a*1000000) + b)
So that I get the total time in microseconds.
My problem is that for some reason, I get crazy negative values (such as -10293843) when I check that field after a while.
Any ideas? Thanks!
Upvotes: 4
Views: 5907
Reputation: 1122
Try this for getting time for 32-bit systems :-
struct timeval time;
gettimeofday(&time, NULL);
unsigned long long secTime = ((unsigned long long)time.tv_sec) * 1000 + ((unsigned long long)(time.tv_usec))/1000;
Upvotes: 0
Reputation: 168616
On my computer, all of tv_sec
, tv_usec
, and 1000000
are signed 32-bit quantities. Signed 32-bit values overflow when asked to hold a number bigger than 2^31 or so.
As a result, this expression:
((x.tv_sec*1000000) + x.tv_usec)
will overflow in 2^31 / 10^6
seconds, or about 2,147 seconds. As long as your program only deals in time intervals shorter than 35 minutes, you should be okay.
If you'd like to represent values >= 35 minutes, try replacing your #define
with this:
#define TIME(a,b) ((a*1000000ull) + b)
Through the standard promotions, this change will cause all of your math to be performed with unsigned long long
values.
You may, but need not, change your double
to uint64_t
. That's up to you.
Upvotes: 1
Reputation: 122381
You should return the result as a 64-bit unsigned integer, as you want an integer microsecond result, not a fractional second (which would imply returning double
):
unsigned long long Thread::getTimeInReady() const
{
return (unsigned long long)_timeInReady.tv_sec * 1000000ULL +
(unsigned long long)_timeInReady.tv_usec;
}
Your system might have uint64_t
which is a more concise than unsigned long long
, or you could typedef
it.
Upvotes: 6