Linux nanosleep investigation.
Andrea Arcangeli
andrea@suse.de
Wed Feb 16 17:10:00 GMT 2000
On Wed, 16 Feb 2000, Andrea Arcangeli wrote:
>[ I just noticed a silly bug in my patch (I am returning the
> elapsed time not the remaining time!). sorry, I'll post a new one
> ASAP). ]
The new one is here (if it's not yet in your local mirror you can use the
main site ftp.kernel.org). I took the time to try it out this time ;).
ftp://ftp.*.kernel.org/pub/linux/kernel/people/andrea/patches/v2.2/2.2.14/nanosleep-2.gz
ftp://ftp.*.kernel.org/pub/linux/kernel/people/andrea/patches/v2.3/2.3.46pre1/nanosleep-2.gz
I wrote a little proggy to test it:
--------------------------------------------------------------------------
/*
(C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
Test nanosleep precision in returning the amount of time
that it remains to sleep after getting interrupted. Developed
to test my kernel nanosleep usec precision changes here:
ftp://ftp.*.kernel.org/pub/linux/kernel/people/andrea/patches/v2.2/2.2.14/nanosleep-2.gz
ftp://ftp.*.kernel.org/pub/linux/kernel/people/andrea/patches/v2.3/2.3.46pre1/nanosleep-2.gz
Compile, run and send it a sigterm in less than 20 seconds.
*/
#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
static void sigterm(int sig) { }
int main()
{
struct timespec t, r, ndiff;
int ret;
struct timeval before, after, udiff;
signal(SIGTERM, sigterm);
t.tv_sec = 20;
t.tv_nsec = 3030;
gettimeofday(&before, NULL);
ret = nanosleep(&t, &r);
gettimeofday(&after, NULL);
if (ret >= 0 || errno != EINTR)
{
printf("no intr\n"), exit(0);
}
if (before.tv_usec >= 1000000)
printf("wrong before usec\n"), exit(1);
if (after.tv_usec >= 1000000)
printf("wrong after usec\n"), exit(1);
if (r.tv_nsec >= 1000000000)
printf("wrong r nsec\n"), exit(1);
if (after.tv_usec < before.tv_usec)
{
after.tv_usec += 1000000;
after.tv_sec--;
}
udiff.tv_sec = after.tv_sec - before.tv_sec;
udiff.tv_usec = after.tv_usec - before.tv_usec;
ndiff.tv_sec = udiff.tv_sec;
ndiff.tv_nsec = (long) udiff.tv_usec * 1000;
if (t.tv_nsec < ndiff.tv_nsec)
{
t.tv_nsec += 1000000000;
t.tv_sec--;
}
ndiff.tv_sec = t.tv_sec - ndiff.tv_sec;
ndiff.tv_nsec = t.tv_nsec - ndiff.tv_nsec;
printf("userspace\t%8lu sec %8lu nsec\n", ndiff.tv_sec, ndiff.tv_nsec);
printf("kernel\t\t%8lu sec %8lu nsec\n", r.tv_sec, r.tv_nsec);
return 0;
}
--------------------------------------------------------------------------
It works this way: compile, run and kill the task in less than 20 seconds
(and 3030 nanoseconds :).
Here the output on 2.3.46pre1+nanosleep-2 on alpha:
andrea@alpha:~ > ./a.out & sleep 4 ; killall a.out
[1] 556
userspace 15 sec 984378030 nsec
kernel 15 sec 984378030 nsec
[1]+ Done ./a.out
Same kernel sources but on IA32:
andrea@laser:~ > ./a.out & sleep 2; killall a.out
[1] 283
userspace 17 sec 985671030 nsec
kernel 17 sec 985696030 nsec
[1]+ Done ./a.out
Here a run of the same binary but with 2.2.14aa7 on IA32 _without_
the nanosleep-2 patch applyed:
andrea@laser:~ > ./a.out & sleep 2; killall a.out
[1] 235
userspace 17 sec 943733030 nsec
kernel 17 sec 960000000 nsec
Andrea
More information about the Libc-alpha
mailing list