Date: Wed, 14 Dec 2016 11:24:37 +0200 From: Konstantin Belousov <kostikbel@gmail.com> To: Goran Meki?? <meka@tilda.center> Cc: freebsd-hackers@freebsd.org Subject: Re: How to use sem_timedwait? Message-ID: <20161214092437.GD94325@kib.kiev.ua> In-Reply-To: <20161214074228.zh6q5zya2gszw4g6@hal9000.meka.no-ip.org> References: <20161214074228.zh6q5zya2gszw4g6@hal9000.meka.no-ip.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, Dec 14, 2016 at 08:42:28AM +0100, Goran Meki?? wrote: > Hello, > > I'm trying to understand how sem_timedwait() works. For that I assambled a little program: > > #include <stdio.h> > #include <sys/types.h> > #include <semaphore.h> > #include <errno.h> > #include <time.h> > > > int main() { > sem_t semaphore; > struct timespec ts; > clock_gettime(CLOCK_REALTIME, &ts); > ts.tv_sec += 3; > > sem_init(&semaphore, 0, 0); > int result = sem_timedwait(&semaphore, &ts); > int error = errno; > > printf("The sem_timedwait() should have ended at %lds and %ldns\n", ts.tv_sec, ts.tv_nsec); > clock_gettime(CLOCK_REALTIME, &ts); > printf("The sem_timedwait() exited at %lds and %ldns with %d status\n", ts.tv_sec, ts.tv_nsec, result); > > clock_getres(CLOCK_REALTIME, &ts); > printf("Clock resolution is %lds and %ldns\n", ts.tv_sec, ts.tv_nsec); > > if (result == -1) { > switch (error) { > case EINVAL: > printf("The semaphore does not refer to valid structure\n"); > break; > case ETIMEDOUT: > printf("Timeout occured\n"); > break; > case EINTR: > printf("Interupted\n"); > break; > default: > printf("Unknown error\n"); > break; > } > } > } > > > Running it I get the following output: > > The sem_timedwait() should have ended at 1481700752s and 2050646ns > The sem_timedwait() exited at 1481700752s and 3813780ns with -1 status > Clock resolution is 0s and 1ns > Timeout occured > > > What I want to know is why the number of nanoseconds reported first and second time is not the same if the resolution reported on line 3 is 1ns? It doesn't change much if I use CLOCK_RELATIME_PRECISE. Thank you! Because this is how computers work. The declared resolution is the resolution of the clock_gettime(2) call. While you tried to measure the different actions: de-facto you scheduled a wakeup, then put the thread to sleep, then thread was awaken. The system guarantees that the thread is made runnable due to timeout not earlier than the interval specified. After the thread is marked runnable, it should be selected for CPU, then the syscall must complete which put thread to sleep, then userspace must execute enough to call clock_gettime(), then it should return etc. You end up with 1.7ms difference between requested and actual wakeups in this attempt, which is quite good. Note that system also does some micro-optimizations by trying to collapse wakeups close enough to each other, which might also affect occurences of wakeups.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20161214092437.GD94325>