How to sleep for a few microseconds

Consider the following code:

#include <stdio.h> #include <time.h> #include <math.h> // Compile with gcc -lrt -lm -o test_clock test_clock.c #define CLOCK CLOCK_MONOTONIC int main(int argc, char** argv) { double temp, elapsed; int j; struct timespec requestStart, requestEnd, req; // Pseudo-sleep clock_gettime(CLOCK, &requestStart); temp = 0; for(j=0; j < 40; j++) temp += sin(j); clock_gettime(CLOCK, &requestEnd); elapsed = ( requestEnd.tv_sec - requestStart.tv_sec ) / 1e-6 + ( requestEnd.tv_nsec - requestStart.tv_nsec ) / 1e3; printf("Elapsed: %lf us\n", elapsed); // Nanosleep clock_gettime(CLOCK, &requestStart); req.tv_nsec = 5000; req.tv_sec = 0; clock_nanosleep(CLOCK, 0, &req, NULL); clock_gettime(CLOCK, &requestEnd); elapsed = ( requestEnd.tv_sec - requestStart.tv_sec ) / 1e-6 + ( requestEnd.tv_nsec - requestStart.tv_nsec ) / 1e3; printf("Elapsed: %lf us\n", elapsed); } 

On my system 2.6.32 the result

 Elapsed: 5.308000 us Elapsed: 69.142000 us 

I agree that this is most likely because nanosleep () asks the kernel to transfer the process. How can i avoid this? I want to keep ownership of the processor and just stand idle for a while.

+7
source share
7 answers

If you want your app to sleep as accurately as possible, first install the app in real time.

  • use the real-time scheduler class for your program / stream: SCHED_FIFO or SCHED_RR
  • raise the priority of your program / thread
  • and if you are going to "sleep" less than the minimum amount that the kernel will process, manually busywait

Take a look at http://www.drdobbs.com/184402031

And this other question: using a nanoselective high processor?

+7
source

The OS scheduler is not going to do anything like this: "Oh, distract this thread from the processor for exactly 86 clock cycles, and then return it."

You will refuse the processor, you have refused the processor. The OS will bring you back when it is. Most likely, you will have to wait until everything else that works, refuses the processor before you can sneak up again.

+7
source

Well, you need to learn how to live with it, as the man page states, in particular: the actual time slept may be longer, due to system latencies and possible limitations in the timer resolution of the hardware

Now, to answer your question, I think this is because your first cycle is running in the process. In other words, there are no context switches since you are using the CPU and you will do everything that works within your 100 ms quantum provided by the scheduler.

However, there is a good chance that nanosleep will disconnect you, since you are clearly asking to go to bed. It will not be so inefficient as to simply put your process in a tight while loop until the duration ends :-)

This means that you are subject to the vagaries of the scheduler, including the fact that another process can fully use its quanta, therefore, your process can be from there for at least 100 ms. On a sufficiently busy system, this can be quite a long time.

+2
source
 // busy wait for 10 microseconds struct timespec ttime,curtime; // get the time clock_gettime(CLOCK_REALTIME,&ttime); // clear the nanoseconds and keep the seconds in order not to overflow the nanoseconds ttime.tv_nsec = 0; // set it back clock_settime(CLOCK_REALTIME,&ttime); // get the time again clock_gettime(CLOCK_REALTIME,&ttime); // increase the nano seconds by 10*1000 ttime.tv_nsec += 10000; // loop while(true){ clock_gettime(CLOCK_REALTIME,&curtime); if (curtime.tv_nsec > ttime.tv_nsec) break; } 

// this is much better than sleeping.

+2
source

you can use usleep method for sleep in microseconds.

+1
source

Efficiency - Os, allowing you to switch tasks on and off with an accuracy of several measures, would do very little.

There are specialized operating systems that do this - but on conventional hardware you pay a lot of overhead for the hypervisor

0
source

This is the answer to the call - I do not know the corresponding internal components of Linux, I hope that the expert can come and remove it.

One possibility is that 69us is just the raw overhead of assembling and then reconfiguring the stream. Although the dream is short, the kernel can do a great job to execute the context switch (or half the context switch if there is no graph) and then cancel it almost immediately. I do not know how long this “should” take on Linux on a typical PC.

If this does not explain this, the scheduler usually has the concept of a “time list”, that is, how long the scheduled thread will be left to run before the scheduler thinks about switching it, unless it performs self-targeting, otherwise something with a higher priority becomes planned. The kernel will have low-level timers that interrupt interrupts at the end of the time fragment (in addition to interrupts that fire for some other events, such as I / O, which can unlock the stream). When the time list ends, the scheduler can decide whether to continue with the same stream or switch to another.

Thus, it seems that when you are sleeping, either (a) the scheduler does not actually set a timer that will make your thread scheduled at the specified time, it just waits for a time-out, and therefore the processor will work longer than necessary; or (b) it makes your thread scheduled at the indicated time, but when you refused to sleep, it entered some other thread with equal priority, and the scheduler has no reason to prefer it until it’s “your move” "again according to any rules that the scheduler usually uses to decide which thread to schedule.

69us is quite short to be an artifact of time.

You seem to have a rudimentary solution - you can linger for very short periods, sitting in the loop, checking the time, just like a spin lock. However, as everyone else says, in a system other than real time, more or less by definition you cannot require the scheduler to start your thread at any particular time. Even in real time, if you compete with threads of equal priority, you can lose, and if you compete with threads with higher priority, you will lose.

0
source

All Articles