C++: pros and cons of different sleep methods for a specific time duration [duplicate] - c++

I am trying to execute a sleep function that is somewhat accurate. I measured how long my sleep function slept for and put them side by side. The format for the samples down below are: "expected ms:outcome ms".
I have tried many options and I still can't find a solution. Here are the routes I tried:
Route 1
Sleep(<time>)
/* milliseconds */
38.4344 46.4354
41.728 47.7818
0.556 0.0012
43.6532 46.8087
0.4523 0.0009
62.8664 76.995
1.5363 15.4592
75.9435 78.1663
91.5194 92.0786
0.6533 0.001
39.7423 45.6729
0.5022 0.0008
54.7837 60.597
0.4248 0.0011
39.2165 45.6977
0.4854 0.0008
10.6741 15.054
Had little to no noticeable CPU usage which is good but still inaccurate results.
Route 2
/* Windows sleep in 100ns units */
BOOLEAN nanosleep(LONGLONG ns){
/* Declarations */
HANDLE timer; /* Timer handle */
LARGE_INTEGER li; /* Time defintion */
/* Create timer */
if(!(timer = CreateWaitableTimer(NULL, TRUE, NULL)))
return FALSE;
/* Set timer properties */
li.QuadPart = -ns;
if(!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)){
CloseHandle(timer);
return FALSE;
}
/* Start & wait for timer */
WaitForSingleObject(timer, INFINITE);
/* Clean resources */
CloseHandle(timer);
/* Slept without problems */
return TRUE;
}
/* milliseconds */
1.057 14.7561
66.5977 79.4437
0.409 14.7597
152.053 156.757
1.26725 15.747
19.025 30.6343
67.3235 78.678
0.4203 14.4713
65.3507 74.4703
0.4525 14.8102
28.6145 29.7099
72.0035 74.7315
0.5971 14.8625
55.7059 59.3889
0.4791 14.5419
50.9913 61.6719
0.5929 15.5558
Had low CPU usage which was good but was still inaccurate.
I had read somewhere that using MultiMedia Timers would provide accurate sleep.
Code Source
Route 3
void super_sleep(double ms)
{
auto a = std::chrono::steady_clock::now();
while ((std::chrono::steady_clock::now() - a) < std::chrono::milliseconds(static_cast<int>(ms))) {
continue;
}
}
/* milliseconds */
55.7059 55.0006
0.5669 0.0008
66.5977 66.0009
0.4213 0.0009
0.7228 0.0007
7.5374 7.0006
0.8825 0.0007
0.4143 0.0009
59.8062 59.0005
51.7157 51.0006
54.0807 54.0006
11.8834 11.0006
65.3507 65.0004
14.429 14.0006
0.4452 0.0012
1.6797 1.0004
96.0012 96.0006
Worked a lot better than the other attempts but uses up to 7% of my CPU.
I also tried using std::this_thread::sleep_for() and received similar result to Route 2.
I am on Windows 10 20H2, C++17 and i9 9900k.

One way to get pretty good accuracy (but not perfect since Windows isn't a Real Time OS), is to use one of the standard sleep functions, but sleep short - and then busy-wait the remaining time. That usually keeps the CPU usage low.
template<class T, class U>
void Sleep(std::chrono::duration<T,U> ss) {
auto target = std::chrono::steady_clock::now() + ss; // the target end time
// Sleep short. 5 ms is just an example. You need to trim that parameter.
std::this_thread::sleep_until(target - std::chrono::milliseconds(5));
// busy-wait the remaining time
while(std::chrono::steady_clock::now() < target) {}
}

Related

ESP32: Attaching an interrupt directly to system time

Currently I'm setting a separate hardware timer to the system time periodically to trigger timed interrupts. It's working fine but for elegance sake, but I wondered if it was possible to attach an interrupt directly to the system time
The events are pretty fast: one every 260 microseconds
ESP32 has a few clocks used for system time. The default full power clock is an 80 MHz called APB_CLK. But even the slow RTC clock has 6.6667 μs resolution. (Documentation here: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/system_time.html)
I have a GPS module that I use to update the system time periodically using adjtime(3). The advantage of that being that it gradually adjusts the system time monotonically. Also system time calls are thread safe
I'm using the Arduino IDE, so my knowledge of accessing registers and interrupts directly is poor. Here's a semi boiled down version of what I'm doing. Bit banging a synchronized digital signal. Rotating in 160 bit pages that are prepped from the other core. It's not all of my code, so something not important might be missing:
#define CPU_SPEED 40
hw_timer_t* timer = NULL;
PageData pages[2];
PageData* timerCurrentPage = &pages[0];
PageData* loopCurrentPage = &pages[1];
TaskHandle_t prepTaskHandle;
volatile int bitCount = 0;
void IRAM_ATTR onTimer() {
int level = timerCurrentPage->data[bitCount];
dac_output_voltage(DAC_CHANNEL_1, level?high:low);
bitCount++;
if(bitCount<160) {
timerAlarmWrite(timer, (timerCurrentPage->startTick+timerCurrentPage->ticksPerPage*bitCount), false);
} else {
if(timerCurrentPage == &pages[0]) timerCurrentPage = &pages[1];
else timerCurrentPage = &pages[0];
bitCount = 0;
timerAlarmWrite(timer, (timerCurrentPage->startTick), false);
vTaskResume(prepTaskHandle);
}
}
uint64_t nowTick() {
timeval timeStruct;
gettimeofday(&timeStruct, NULL);
uint64_t result = (uint64_t)timeStruct.tv_sec*1000000UL + (uint64_t)timeStruct.tv_usec;
return result;
}
void gpsUpdate(uint64_t micros) {
int64_t now = nowTick();
int64_t offset = micros - now;
timeval adjustStruct = {0,offset};
adjtime(&adjustStruct,NULL);
}
void setup() {
setCpuFrequencyMhz(CPU_SPEED);
timer = timerBegin(0, CPU_SPEED, true);
timerWrite(timer, nowTick());
timerAttachInterrupt(timer, &onTimer, true);
setPage(&pages[0]);
xTaskCreatePinnedToCore(
prepLoop, /* Task function. */
"Prep Task", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&prepTaskHandle, /* Task handle to keep track of created task */
1); /* pin task to core 0 */
timerAlarmWrite(timer, (timerCurrentPage->startTick), false);
}
//On Core 1
void prepLoop() {
while(1) {
vTaskSuspend(NULL); //prepTaskHandle
timerWrite(timer, nowTick());
if(loopCurrentPage == &pages[0]) loopCurrentPage = &pages[1];
else loopCurrentPage = &pages[0];
setPage(loopCurrentPage);
}
}

Event Scheduling in C++

I am building an application where in I receive socket data. I need to reply this received data after few seconds(say 8 sec after). So I want to know is there a way to schedule an event which sends the socket data after 8 seconds automatically. I don't like to sleep unnecessarily for 8 seconds in the receiving thread or any other thread. This is what I have written so far for receiving socket data which is a pthread.
long DataSock_fd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
StSocketAddress.sin_family=AF_INET; //address family
StSocketAddress.sin_addr.s_addr=inet_addr("10.10.10.10"); //load ip address
StSocketAddress.sin_port=htons(1234); //load port number
//bind the above socket to the above mentioned address, if result is less than 0(error in binding)
if(bind(DataSock_fd,(struct sockaddr *)&StSocketAddress,sizeof(StSocketAddress))<0)
{
close(DataSock_fd); //close the socket
perror("error while binding\n");
exit(EXIT_FAILURE); //exit the program
}
char Buff[1024];
long lSize = recvfrom(DataSock_fd,(char *)Buff,sizeof(Buff),0,NULL,NULL);
But I am stuck at scheduling an event that sends data after 8 seconds.
Take a look at this SO answer.
You could use <async> like this to solve your problem:
auto f = std::async(std::launch::async, [] {
std::this_thread::sleep_for(std::chrono::seconds(5));
printf("(5 seconds later) Hello");
});
you can either use boost::sleep, or chrono:: sleep_for or chrono:: sleep_until,
but if you don't want to call sleep, my best suggestion for you is to use std::mutex and lock the thread that receive the information from Time.currenttime -startTime == 8.
Approach-1
Since you don't have a C++11 enabled compiler, and am assuming you are not using frameworks such as Qt/boost etc.. Please check if the following code answer your question. It is a simple async timer implementation using pthreads
Sample code:
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#define TIME_TO_WAIT_FOR_SEND_SECS (8)
#define FAIL_STATUS_CODE (-1)
#define SUCCESS_STATUS_CODE (0)
typedef void (*TimerThreadCbk)(void *);
typedef struct tTimerThreadInitParams
{
int m_DurationSecs; /* Duration of the timer */
TimerThreadCbk m_Callback; /* Timer callback */
void * m_pAppData; /* App data */
}tTimerThreadInitParams;
void PrintCurrTime()
{
time_t timer;
char buffer[26];
struct tm* tm_info;
time(&timer);
tm_info = localtime(&timer);
strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
puts(buffer);
}
void* TimerThreadEntry(void *a_pTimerThreadInitParams)
{
tTimerThreadInitParams *pTimerThreadInitParams = (tTimerThreadInitParams *)a_pTimerThreadInitParams;
if(NULL != pTimerThreadInitParams)
{
/*Do validattion of init params */
sleep(pTimerThreadInitParams->m_DurationSecs);
pTimerThreadInitParams->m_Callback(pTimerThreadInitParams->m_pAppData);
}
else
{
printf("pTimerThreadInitParams is (nil)\n");
}
}
TimerCallbackForSend(void *a_pAppData)
{
(void)a_pAppData;
/* Perform action on timer expiry using a_pAppData */
printf("TimerCallbackForSend trigggered at: ");
PrintCurrTime();
}
int main()
{
/* Timer thread initialization parameters */
pthread_t TimerThread;
tTimerThreadInitParams TimerInitParams = {};
TimerInitParams.m_DurationSecs = TIME_TO_WAIT_FOR_SEND_SECS;
TimerInitParams.m_Callback = (TimerThreadCbk) TimerCallbackForSend;
/* Print current time */
printf("Starting timer at:");
PrintCurrTime();
/* Create timer thread*/
if(pthread_create(&TimerThread, NULL, TimerThreadEntry, &TimerInitParams))
{
fprintf(stderr, "Error creating thread\n");
return FAIL_STATUS_CODE;
}
else
{
printf("TimerThread created\n");
}
/* wait for the second thread to finish */
if(pthread_join(TimerThread, NULL))
{
fprintf(stderr, "Error joining thread\n");
return FAIL_STATUS_CODE;
}
else
{
printf("TimerThread finished\n");
}
return SUCCESS_STATUS_CODE;
}
Sample output:
Starting timer at:2017-08-08 20:55:33
TimerThread created
TimerCallbackForSend trigggered at: 2017-08-08 20:55:41
TimerThread finished
Notes:
This is a scratch custom implementation. You can rename main as ScheduleTimer, which will be a generic API which spawns a thread and invokes the registered callback in its own context.
Just now saw that you don't want to sleep in any of the threads.
Approach-2
Refer C: SIGALRM - alarm to display message every second for SIGALRM. May be in the signal handler you can post an event to the queue which your thread will be monitoring
Sleeping, whether by a C++ wrapper or by the system's nanosleep function -- it cannot be said often enough -- is... wrong. Unless precision and reliability doesn't matter at all, do not sleep. Never.
For anything related to timing, use a timer.
If portability is not a high priority, and since the question is tagged "Linux", a timerfd would be one of the best solutions.
The timerfd can be waited upon with select/poll/epoll while waiting for something to be received, and other stuff (signals, events) at the same time. That's very elegant, and it is quite performant, too.
Admitted, since you are using UDP, there is the temptation to not wait for readiness in the first place but to just have recvfrom block. There is however nothing inherently wrong with waiting for readiness. For moderate loads, the extra syscall doesn't matter, but for ultra-high loads, you might even consider going a step further into non-portable land and use recvmmsg to receive several datagrams in one go as indicated by the number of datagrams reported by epoll (see code example on the recvmmsg man page, which combines recvmmsg with epoll_wait).
With an eventfd, you have everything in one single event loop, in one single thread, reliable and efficient. No trickery needed, no need to be extra smart, no worries about concurrency issues.

Speed control in 100Hz to 10KHz range reading small records from file on windows

I have developed a complex program for a client on windows desktop. I am required to control the speed reading multiple small records ( ~20bytes ) in sequence from two large files. Running on my systems I can get reasonable control in the range 10 to 1000Hz The client reports that when he runs on his systems that he can only get a maximum about 100 reads per second.
The speed control does not need to be very precise, just 20% might be acceptable, but it should be consistent - increasing the speed setting should increase the speed in the expected proportion.
I have implemented the reads using the C++ library ( ifstream ) and the windows API ( CreateFile, with the prefetch cache optimized for sequential access ). The performance is similar.
The client has turned off his virus protection, windows search indexing and all other running applications with no significant change
Update:
I have discovered that the problem is not with the disk reads themselves, but with the code that throttles down the maximum read speed to the required rate. If I disable this code and let the reads run free, the client machines are capable of almost 50,000 reads per second. ( This is too fast for the rest of the application to keep up, so it must be throttled back ) So the problem is with the sub millisecond timers used to throttle back the read speed to something the application can handle. On my machines I can get sub millisecond delays, but the same code on the client machine will only allow a delay of a millisecond or more.
To demonstrate the problem and satisfy the folks who insist on seeing some code, here is a greatly simplified test showing the problem when the timer is not capable of delivering short delays.
#include <windows.h>
#include <iostream>
#include <chrono>
#include <boost/asio.hpp>
#include "cRunCount.h"
using namespace std;
/** Length of timed wait */
int WaitMicroSecs;
boost::asio::deadline_timer * myPlaybackTimer;
/** Frequency counter from https://github.com/JamesBremner/raven-set
Construct to report after 500 calls
*/
raven::set::cRunCount myRunCounter( 500 );
void StartWait();
/** Called when timer expires
In production code this would start the next read
but for this test it simply restarts the timer
*/
void handle_expire(const boost::system::error_code& /*e*/)
{
if( myRunCounter.Count() )
{
// The run counter has been called 500 times, output report
cout << WaitMicroSecs << " microsecs ( nominal "
<< 1000000 / WaitMicroSecs << " Hz ) -> "
<< myRunCounter.Hz() << " Hz\n";
// check if test complete
if( WaitMicroSecs == 1 )
exit(0);
// next test nominally ten times faster
WaitMicroSecs /= 10;
}
// start next timed wait
StartWait();
}
/** Called to start a new timed wait */
void StartWait()
{
myPlaybackTimer->expires_from_now(
boost::posix_time::microseconds( WaitMicroSecs ) );
myPlaybackTimer->async_wait( handle_expire );
}
int main( int argc, char * argv[])
{
WaitMicroSecs = 100000;
boost::asio::io_service io_service;
myPlaybackTimer = new boost::asio::deadline_timer( io_service );
// Start first wait
StartWait();
// start event loop
io_service.run();
return 0;
}
The output from this is:
100000 microsecs ( nominal 10 Hz ) -> 9.17304 Hz
10000 microsecs ( nominal 100 Hz ) -> 64.2066 Hz
1000 microsecs ( nominal 1000 Hz ) -> 65.4417 Hz
100 microsecs ( nominal 10000 Hz ) -> 78.407 Hz
10 microsecs ( nominal 100000 Hz ) -> 75.6637 Hz
1 microsecs ( nominal 1000000 Hz ) -> 69.206 Hz
Notice how the the frequency is fine with a 100 millisecond delay, and almost OK with a 10 millisecond delay but anything shorter does not in fact deliver the nominal frequency - is in fact no quicker
In the production code, I use the high performance counter which delivers better results on my machine. Here are the results for this
100000 microsecs ( nominal 10 Hz ) -> 9.29206 Hz
10000 microsecs ( nominal 100 Hz ) -> 81.1589 Hz
1000 microsecs ( nominal 1000 Hz ) -> 733.746 Hz
100 microsecs ( nominal 10000 Hz ) -> 345.407 Hz
10 microsecs ( nominal 100000 Hz ) -> 126.579 Hz
1 microsecs ( nominal 1000000 Hz ) -> 1994.5 Hz
Here the delay seems fairly reasonable down to 1 millisecond, but anything shorted becomes erratic.
Similar results are obtained on the client's machines, which solves the original problem!
Update:
Following a suggestion from Hans Passant I have concluded that the clock interrupt rate must be low on the client's machines. I have added a call to timeBeginPeriod() to ensure that it runs at the fastest possible speed, 1 millisecond. Still waiting for test report from the client.
I have concluded that since the interrupt clock will not run faster than 1 millisecond, frequencies in the 1 to 10KHz range will not be possible using a timer. So I have developed a busy loop timer running in its own thread to serve the purpose. This seems to work well, despite the extravagant use of CPU cycles. The test program code:
#include <windows.h>
#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
#include <boost/asio.hpp>
#include <boost/asio/high_resolution_timer.hpp>
#include "cRunCount.h"
using namespace std;
/** Length of timed wait */
int WaitMicroSecs;
/** Target frequency */
int TargetHz;
/** The event loop */
boost::asio::io_service io_service;
/** Timer used when wait is more than 1 millisecond */
boost::asio::high_resolution_timer * myPlaybackTimer;
/** Thread where busy loop timer runs */
std::thread * BusyLoopThread;
/** Frequency counter from https://github.com/JamesBremner/raven-set
Construct to report after 2000 calls
*/
raven::set::cRunCount myRunCounter( 2000 );
/** Function forward declerations */
void StartWait();
void handle_expire(const boost::system::error_code& );
/** Flag used by busy loop timer to indicate completion */
bool BusyLoopTimerDone;
/** protection against data races on busy loop completion flag */
std::mutex M;
/** The Busy Loop timer, runs in own thread */
void BusyLoopTimer()
{
__int64 myTimeStart, t, myFreq;
float MicroSecs;
QueryPerformanceCounter( (LARGE_INTEGER *)&myTimeStart );
QueryPerformanceFrequency( (LARGE_INTEGER *)&myFreq );
do
{
int loopCount = 200;
// the busy loop
while( loopCount > 0 )
loopCount--;
QueryPerformanceCounter( (LARGE_INTEGER *)&t );
MicroSecs = 1000000.0 * (float)(t-myTimeStart) / (float)myFreq;
}
// keep on going until specified wait has been reached
while( MicroSecs < WaitMicroSecs );
// flag completion
std::lock_guard<std::mutex> lock( M );
BusyLoopTimerDone = true;
// the thread now completes
}
void CheckBusyLoopDone()
{
// read completion flag
bool done;
{
std::lock_guard<std::mutex> lock( M );
done = BusyLoopTimerDone;
}
if( ! done )
{
// still running
// post the next check
// in a real application, this would allow other processing
// to execute in this thread
io_service.post( CheckBusyLoopDone );
}
else
{
// busy loop timer completed
// execute completion handler
handle_expire( boost::system::error_code() );
}
}
/** Set up for next tests */
void NextTestDelay()
{
// check if test is over
if( TargetHz >= 5000 )
{
cout << "Test completed\n";
io_service.stop();
}
// target frequency for next tests
TargetHz += 1000;
// fudge factor
const int overheadmsecs = 120;
// Calculate microseconds wait required
WaitMicroSecs = 1000000 / TargetHz - overheadmsecs;
}
/** Called when timer expires
In production code this would start the next read
but for this test it simply restarts the timer
*/
void handle_expire(const boost::system::error_code& /*e*/)
{
// Do some thread cleanup
// this does not seem to be neccessary
// since the thread finishes when it completes anyway
// and it adds a noticeable overhead
// BusyLoopThread->join();
// delete BusyLoopThread;
if( myRunCounter.Count() )
{
// The run counter has been called reuired times, output report
cout << "Target " << TargetHz << " Hz Actual: "
// << WaitMicroSecs << " microsecs ( nominal "
// << 1000000 / WaitMicroSecs << " Hz ) -> "
<< (int)myRunCounter.Hz() << " Hz, delta "
<< (int)(myRunCounter.Hz() - TargetHz) << "\n";
// check if test complete
NextTestDelay();
}
// start next timed wait
StartWait();
}
/** Called to start a new timed wait */
void StartWait()
{
if( WaitMicroSecs > 1000 )
{
// use high performance timer
// which should be reliable for waits longer than a millisecond
myPlaybackTimer->expires_from_now(
std::chrono::microseconds( WaitMicroSecs ) );
myPlaybackTimer->async_wait( handle_expire );
}
else
{
// too fast for clock interupt timer
// so start busy loop timer in its own thread
BusyLoopTimerDone = false;
BusyLoopThread = new std::thread( BusyLoopTimer );
io_service.post( CheckBusyLoopDone );
}
}
int main( int argc, char * argv[])
{
cout << "Busy Loop timer\n";
// ensure that the interrupt clock rate is at its maximum
// 1 millisecond
MMRESULT res = timeBeginPeriod( 1 );
if( res != TIMERR_NOERROR )
{
cout << "timeBeginPeriod no can do\n";
exit(1);
}
TargetHz = 0;
NextTestDelay();
myPlaybackTimer = new boost::asio::high_resolution_timer( io_service );
// Start first wait
StartWait();
// start event loop
io_service.run();
return 0;
}
Results
Busy Loop timer
Target 1000 Hz Actual: 987 Hz, delta -12
Target 2000 Hz Actual: 1983 Hz, delta -16
Target 3000 Hz Actual: 2976 Hz, delta -23
Target 4000 Hz Actual: 4086 Hz, delta 86
Target 5000 Hz Actual: 4919 Hz, delta -80
Test completed
This has been tested at the client's site and gives similar results.
Continuous Busy Loop Timer
The above code requires a new thread to be created for each wait time request. Since my application does many tens of thousands of wait time requests, I am concerned about the impact on the main processing thread. So I have developed a continuous busy loop timer - this runs continuously and services wait time requests one at a time. This appears to work well, but the calibration overhead allowance is more complex for reasons I do not know, which is a bit of a concern. The test code is here.
first: do a benchmark program for reading chunk from a file at diffrent sizes. See what size offers the best performance.
Find a way to read this into memory and assign the info to objects. You could try to somehow map your objects over the memory directly. Maeby placement new could help.

Is it dangerous to rely on overflow?

The following is a delay function I found in our firmware. It looks a little dangerous or, at the least, confusing to the reader.
Global Variable
static int32u masterTimerCounter; // 32-bit unsigned timer counter
System Tick Interrupt Handler
/* Called Every Millisecond */
void sysTickIrqHandler(void)
{
masterTimerCounter++;
}
Set Timer Expiration Function
void setTimerExpiration(int32u *timerExpiration, int32u delay)
{
*timerExpiration = masterTimerCounter + delay;
}
Check If Timer Expired Function
boolean timerExpired(int32u timerExpiration, int32u delay)
{
if((masterTimerCounter - timerExpiration) < delay)
return TRUE; // Timer has expired
else
return FALSE; // Timer still active
}
Set Timer Expriation And Block Until Timer Expired
int32u timerExpiration;
setTimerExpiration(&timerExpiration, 15); // Set expiration timer to 15 milliseconds
while(!timerExpired(timerExpiration, 15) // Block until timer has expired
continue;
Question
As you can see in timerExpired(), masterTimerCounter is subtracted by timerExpiration. If the timer hasn't expired yet, the computation will result in a very large number (because both of the operands are unsigned numbers). When the timer has expired the computation will result in a value less than the delay amount.
Though this seems to work fine, it seems like it can be dangerous or, at the least, be confusing to the reader (I had to read it several times to understand the original programmer's intent).
If I had to write something similar to this, I would define the timerExpired function as follows:
boolean timerExpired(int32u timerExpiration)
{
if(timerExpiration > masterTimerCounter)
return FALSE; // Timer still active
else
return TRUE; // Timer has expired
}
Should I redefine 'timerExpired()`?
Note: Function and variable names have been changed to protect the innocent.
Note that the original logic was something like: is the absolute expiry time in the past, but less than a full delay period ago. Maybe we could express it loosely as did this timer fire recently.
Your modified logic is just is the absolute expiry time in the past, which is different.
You can trivially avoid the risk of underflow by simply adding timerExpiration to each side of the inequality:
boolean timerExpired(int32u timerExpiration, int32u delay)
{
// WAS: (masterTimerCounter - timerExpiration) < delay
if(masterTimerCounter < timerExpiration + delay)
return TRUE; // Timer has expired
else
return FALSE; // Timer still active
}
but this changes the behaviour, since you say the original will always be false if masterTimerCounter < timerExpiration. You can get the original behaviour without the confusing underflow by checking this explicitly:
boolean timerExpired(int32u timerExpiration, int32u delay)
{
if(masterTimerCounter > timerExpiration && // did it expire ...
masterTimerCounter < timerExpiration + delay) // ... recently?
return TRUE; // Timer has expired
else
return FALSE; // Timer still active
}
That firmware code makes no sense.
int32u expire;
setTimerExpiration(&expire, 0);
timerExpired(expire, 0); // is always false, unless the timer overflows
The issue with your way is that if masterTimerCounter + delay causes a rollover of the 32 bit int, than the timerExpired test passes right away.
I think the most straightforward way to do integer timers in the presence of possible rollover is like this:
void startTimer(int32u *timerValue)
{
*timerValue = masterTimerCounter;
}
Check If Timer Expired Function
boolean timerExpired(int32u timerVal, int32u delay)
{
if ((masterTimerCounter - timerVal) >= delay)
return TRUE; // Timer has expired
else
return FALSE; // Timer still active
}
Usage:
int32u timer;
startTimer(&timer); // Start timing
while(!timerExpired(timer, 15) // Block for 15 ticks
continue;
Even if the subtraction in timerExpired underflows this returns the correct results.

clock_gettime returns some extrange values

I'm trying to profile a program with this class:
namespace smtx{
class CPerformance_clock
{
timespec t1;
timespec diff(timespec start, timespec end)
{
timespec temp;
if ((end.tv_nsec-start.tv_nsec)<0) {
temp.tv_sec = end.tv_sec-start.tv_sec-1;
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
} else {
temp.tv_sec = end.tv_sec-start.tv_sec;
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
}
return temp;
}
public :
CPerformance_clock(){}
/**
* Starts the clock by taking the initial measure
*/
void start()
{
assert(clock_gettime(CLOCK_MONOTONIC_RAW,&t1) == 0);
}
long int getElapsedTime()
{
timespec t2, final;
assert (clock_gettime(CLOCK_MONOTONIC_RAW,&t2) == 0);
final = diff(t1, t2);
return (final.tv_sec * 1000000000) + final.tv_nsec;
}
void restart()
{
clock_gettime(CLOCK_REALTIME,&t1);
}
};
};
I control min, max and average time, with this code
if(t > max_time)
{
max_time = t;
}
if(t < min_time)
{
min_time = t;
}
++count_time;
sum_time += t;
chunk_sum_time +=t;
++chunk_count_time;
Nothing extraordinary at all.
But when I execute the program, the max time allways have a extrange time value:
Min time: 831 ns at 40784 , Max_time: 9773850 ns at 1123
The max time is far long that the total execution time, so I don't understand this. I do not make any conversion o division in the process of display data, to don't lose data.
I've readed this post, Linux clock_gettime(CLOCK_MONOTONIC) strange non-monotonic behavior , but my kernel is newest, though is an ubuntu too.
To finish, I made test with CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_MONOTONIC_RAW, and nothing solves this issue.
Also, I'm not sure that this matters but I'm programming and executing this program on a virtual machine.
Some help?
EDIT: To put an example of my problem: I process 4.000.000 of results in about 60 seconds. The average time of each result is 4000 nano seconds. An strange error could be 14 seconds, but the program run smooth and in any moment stops for 14 seconds.
In executions of 500.000 results (execued in 3 seconds) I get similar MAX_TIMEs, like 9 seconds.
Thanks in advance
The fluctuation is caused by the OS scheduler. It pauses your process and gives a chance to an other process to run.
Can you report back results with CLOCK_PROCESS_CPUTIME_ID?