LKML Archive on lore.kernel.org
 help / color / Atom feed
* process time < thread time?
@ 2011-09-01  3:07 David Miller
  2011-09-01  9:56 ` Thomas Gleixner
  0 siblings, 1 reply; 7+ messages in thread
From: David Miller @ 2011-09-01  3:07 UTC (permalink / raw)
  To: peterz; +Cc: tglx, linux-kernel


If someone who understands our thread/process time implementation can
look into this, I'd appreciate it.

Attached below is a watered-down version of rt/tst-cpuclock2.c from
GLIBC.  Just build it with "gcc -o test test.c -lpthread -lrt" or
similar.

Run it several times, and you will see cases where the main thread
will measure a process clock difference before and after the nanosleep
which is smaller than the cpu-burner thread's individual thread clock
difference.  This doesn't make any sense since the cpu-burner thread
is part of the top-level process's thread group.

I've reproduced this on both x86-64 and sparc64 (using both 32-bit and
64-bit binaries).

For example:

[davem@boricha build-x86_64-linux]$ ./test
process: before(0.001221967) after(0.498624371) diff(497402404)
thread:  before(0.000081692) after(0.498316431) diff(498234739)
self:    before(0.001223521) after(0.001240219) diff(16698)
[davem@boricha build-x86_64-linux]$ 

The diff of 'process' should always be >= the diff of 'thread'.

I make sure to wrap the 'thread' clock measurements the most tightly
around the nanosleep() call, and that the 'process' clock measurements
are the outer-most ones.

I suspect this might be some kind of artifact of how the partial
runqueue ->clock and ->clock_task updates work?  Maybe some weird
interaction with ->skip_clock_update?

Or is this some known issue?

Thanks!

--------------------
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>

static pthread_barrier_t barrier;

static void *chew_cpu(void *arg)
{
	pthread_barrier_wait(&barrier);
	while (1)
		__asm__ __volatile__("" : : : "memory");
	return NULL;
}

int main(void)
{
	clockid_t process_clock, my_thread_clock, th_clock;
	struct timespec process_before, process_after;
	struct timespec me_before, me_after;
	struct timespec th_before, th_after;
	struct timespec sleeptime;
	unsigned long diff;
	pthread_t th;
	int err;

	err = clock_getcpuclockid(0, &process_clock);
	if (err)
		return 1;

	err = pthread_getcpuclockid(pthread_self(), &my_thread_clock);
	if (err)
		return 1;

	pthread_barrier_init(&barrier, NULL, 2);
	err = pthread_create(&th, NULL, chew_cpu, NULL);
	if (err)
		return 1;

	err = pthread_getcpuclockid(th, &th_clock);
	if (err)
		return 1;

	pthread_barrier_wait(&barrier);

	err = clock_gettime(process_clock, &process_before);
	if (err)
		return 1;

	err = clock_gettime(my_thread_clock, &me_before);
	if (err)
		return 1;

	err = clock_gettime(th_clock, &th_before);
	if (err)
		return 1;

	sleeptime.tv_sec = 0;
	sleeptime.tv_nsec = 500000000;
	nanosleep(&sleeptime, NULL);

	err = clock_gettime(th_clock, &th_after);
	if (err)
		return 1;

	err = clock_gettime(my_thread_clock, &me_after);
	if (err)
		return 1;

	err = clock_gettime(process_clock, &process_after);
	if (err)
		return 1;

	diff = process_after.tv_nsec - process_before.tv_nsec;
	printf("process: before(%lu.%.9lu) after(%lu.%.9lu) diff(%lu)\n",
	       process_before.tv_sec, process_before.tv_nsec,
	       process_after.tv_sec, process_after.tv_nsec, diff);
	diff = th_after.tv_nsec - th_before.tv_nsec;
	printf("thread:  before(%lu.%.9lu) after(%lu.%.9lu) diff(%lu)\n",
	       th_before.tv_sec, th_before.tv_nsec,
	       th_after.tv_sec, th_after.tv_nsec, diff);
	diff = me_after.tv_nsec - me_before.tv_nsec;
	printf("self:    before(%lu.%.9lu) after(%lu.%.9lu) diff(%lu)\n",
	       me_before.tv_sec, me_before.tv_nsec,
	       me_after.tv_sec, me_after.tv_nsec, diff);

	return 0;
}

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, back to index

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-01  3:07 process time < thread time? David Miller
2011-09-01  9:56 ` Thomas Gleixner
2011-09-01 10:11   ` Peter Zijlstra
2011-09-01 10:39     ` Thomas Gleixner
2011-09-01 10:54       ` Peter Zijlstra
2011-09-01 14:54         ` Thomas Gleixner
2011-09-01 14:56         ` David Miller

LKML Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/lkml/0 lkml/git/0.git
	git clone --mirror https://lore.kernel.org/lkml/1 lkml/git/1.git
	git clone --mirror https://lore.kernel.org/lkml/2 lkml/git/2.git
	git clone --mirror https://lore.kernel.org/lkml/3 lkml/git/3.git
	git clone --mirror https://lore.kernel.org/lkml/4 lkml/git/4.git
	git clone --mirror https://lore.kernel.org/lkml/5 lkml/git/5.git
	git clone --mirror https://lore.kernel.org/lkml/6 lkml/git/6.git
	git clone --mirror https://lore.kernel.org/lkml/7 lkml/git/7.git
	git clone --mirror https://lore.kernel.org/lkml/8 lkml/git/8.git
	git clone --mirror https://lore.kernel.org/lkml/9 lkml/git/9.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 lkml lkml/ https://lore.kernel.org/lkml \
		linux-kernel@vger.kernel.org
	public-inbox-index lkml

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git