private static int Calibrate() { const int referenceCount = 1000; return(Enumerable.Range(0, referenceCount) .Aggregate( (long)0, (a, i) => { var t1 = new Interop.timespec(); var t2 = new Interop.timespec(); t1.tv_sec = (IntPtr)0; t1.tv_nsec = (IntPtr)1000000; var start = DateTime.UtcNow.Ticks; Interop.nanosleep(ref t1, ref t2); return a + ((DateTime.UtcNow.Ticks - start) * 100 - 1000000); }, a => (int)(a / referenceCount))); }
/// <summary> /// Sleeps the specified delay. /// </summary> /// <param name="delay">The delay.</param> public static void Sleep(TimeSpan delay) { // Based on [BCM2835 C library](http://www.open.com.au/mikem/bcm2835/) // Calling nanosleep() takes at least 100-200 us, so use it for // long waits and use a busy wait on the hires timer for the rest. var start = DateTime.UtcNow.Ticks; var millisecondDelay = (decimal)delay.TotalMilliseconds; if (millisecondDelay >= 100) { // Do not use high resolution timer for long interval (>= 100ms) Thread.Sleep(delay); } else if (millisecondDelay > 0.450m) { var t1 = new Interop.timespec(); var t2 = new Interop.timespec(); // Use nanosleep if interval is higher than 450µs t1.tv_sec = (IntPtr)0; t1.tv_nsec = (IntPtr)((long)(millisecondDelay * 1000000) - nanoSleepOffset); Interop.nanosleep(ref t1, ref t2); } else { while (true) { if ((DateTime.UtcNow.Ticks - start) * 0.0001m >= millisecondDelay) { break; } } } }