This is the mail archive of the libc-alpha@sourceware.cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Linux nanosleep investigation.


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]