On Thu, Oct 30, 2003 at 10:49:38PM +0200, Ami Chayun wrote:
I have a question regarding short sleeps (under 10 millisec).
I require to implement sleep with about 1-10 microsec accuracy (that's no problem), but I require to sleep for times ranging between 1 microsec to 1 millisec.
usleep?
Its manpage states: This function is obsolete. Use nanosleep(2) or setitimer(2) instead.
But nanosleep(2) won't do the trick. If the machine is idle, nanosleep(2) will cause the kernel to issue a HLT instruction from which will wake up only upon the next interrupt; the only interrupt that's guaranteed to occur is the timer interrupt, up to 1/HZ = 10 millisec (in kernel 2.4) later -- much worse than the desired accuracy of 1-10. Similarly, if some other task takes over the CPU then it might be preempted only at the next timer interrupt.
nanosleep(2) *can* perform accurate busy-wait delays, but will do so only for for pauses up to 2ms and "if the process is scheduled under a real-time policy like SCHED_FIFO or SCHED_RR". I happened to look this up in the 2.4 kernel source and yup, that's exactly what it does.
So the solution is to do a busy-wait loop by yourself, in userspace. Modern x86 CPUs have an RDTSC instruction which reads a CPU cycle count -- this is the best way to make time measurements in the relevant scale. The code should look something like this (courtesy of the kernel source):
#define rdtscl(low) asm volatile("rdtsc" : "=a" (low) : : "edx") #define rep_nop asm volatile("rep;nop") static void rdtsc_delay(unsigned long loops) { unsigned long bclock, now; rdtscl(bclock); do { rep_nop(); // reduce CPU power consumption rdtscl(now); } while ((now-bclock) < loops); }
If you need loops>2^32, either wrap it by an outer loop or replace all longs by long longs and replace rdtscl by
#define rdtscll(val) asm volatile("rdtsc" : "=A" (val))
You can find the number of loops per second by doing some calibration at program startup (be careful if it's a laptop with variable CPU speed).
Eran
================================================================= To unsubscribe, send mail to [EMAIL PROTECTED] with the word "unsubscribe" in the message body, e.g., run the command echo unsubscribe | mail [EMAIL PROTECTED]