2004-09-27 21:03:31

by Christoph Lameter

[permalink] [raw]
Subject: [RFC] Posix compliant behavior of CLOCK_PROCESS/THREAD_CPUTIME_ID

Attached follows a patch to implement the POSIX clocks according to the
POSIX standard which states in V3 of the Single Unix Specification:

1. CLOCK_PROCESS_CPUTIME_ID

Implementations shall also support the special clockid_t value
CLOCK_PROCESS_CPUTIME_ID, which represents the CPU-time clock of the
calling process when invoking one of the clock_*() or timer_*()
functions. For these clock IDs, the values returned by clock_gettime() and specified
by clock_settime() represent the amount of execution time of the process
associated with the clock.

2. CLOCK_THREAD_CPUTIME_ID

Implementations shall also support the special clockid_t value
CLOCK_THREAD_CPUTIME_ID, which represents the CPU-time clock of the
calling thread when invoking one of the clock_*() or timer_*()
functions. For these clock IDs, the values returned by clock_gettime()
and specified by clock_settime() shall represent the amount of
execution time of the thread associated with the clock.

These times mentioned are CPU processing times and not the time that has
passed since the startup of a process. Glibc currently provides its own
implementation of these two clocks which is designed to return the time
that passed since the startup of a process or a thread.

Moreover this clock is bound to CPU timers which is problematic when the
frequency of the clock changes or the process is moved to a different
processor whose cpu timer may not be fully synchronized to the cpu timer
of the current CPU.

I would like to have the following patch integrated into the kernel. Glibc
would need to be modified to simply generate a system call for clock_* without
doing its own emulation of a clock. CLOCK_PROCESS_CPUTIME_ID and
CLOCK_THREAD_CPUTIME id were never intended to be used as a means to
access a time stamp counter on a CPU and it may be better to find another
means of accesses the cpu time registerss.

The patch is really quite straighforward and only affects one file...

Index: linus/kernel/posix-timers.c
===================================================================
--- linus.orig/kernel/posix-timers.c 2004-09-23 15:12:01.000000000 -0700
+++ linus/kernel/posix-timers.c 2004-09-27 13:42:40.000000000 -0700
@@ -10,6 +10,10 @@
* 2004-06-01 Fix CLOCK_REALTIME clock/timer TIMER_ABSTIME bug.
* Copyright (C) 2004 Boris Hu
*
+ * 2004-07-27 Provide POSIX compliant clocks
+ * CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID.
+ * by Christoph Lameter
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
@@ -133,18 +137,10 @@
* resolution. Here we define the standard CLOCK_REALTIME as a
* 1/HZ resolution clock.
*
- * CPUTIME & THREAD_CPUTIME: We are not, at this time, definding these
- * two clocks (and the other process related clocks (Std
- * 1003.1d-1999). The way these should be supported, we think,
- * is to use large negative numbers for the two clocks that are
- * pinned to the executing process and to use -pid for clocks
- * pinned to particular pids. Calls which supported these clock
- * ids would split early in the function.
- *
* RESOLUTION: Clock resolution is used to round up timer and interval
* times, NOT to report clock times, which are reported with as
* much resolution as the system can muster. In some cases this
- * resolution may depend on the underlaying clock hardware and
+ * resolution may depend on the underlying clock hardware and
* may not be quantifiable until run time, and only then is the
* necessary code is written. The standard says we should say
* something about this issue in the documentation...
@@ -162,7 +158,7 @@
*
* At this time all functions EXCEPT clock_nanosleep can be
* redirected by the CLOCKS structure. Clock_nanosleep is in
- * there, but the code ignors it.
+ * there, but the code ignores it.
*
* Permissions: It is assumed that the clock_settime() function defined
* for each clock will take care of permission checks. Some
@@ -198,6 +194,8 @@
struct timespec *tp, struct timespec *mo);
int do_posix_clock_monotonic_gettime(struct timespec *tp);
int do_posix_clock_monotonic_settime(struct timespec *tp);
+int do_posix_clock_process_gettime(struct timespec *tp);
+int do_posix_clock_thread_gettime(struct timespec *tp);
static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);

static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
@@ -218,6 +216,14 @@
.clock_get = do_posix_clock_monotonic_gettime,
.clock_set = do_posix_clock_monotonic_settime
};
+ struct k_clock clock_thread = {.res = CLOCK_REALTIME_RES,
+ .abs_struct = NULL,
+ .clock_get = do_posix_clock_thread_gettime
+ };
+ struct k_clock clock_process = {.res = CLOCK_REALTIME_RES,
+ .abs_struct = NULL,
+ .clock_get = do_posix_clock_process_gettime
+ };

#ifdef CONFIG_TIME_INTERPOLATION
/* Clocks are more accurate with time interpolators */
@@ -226,6 +232,8 @@

register_posix_clock(CLOCK_REALTIME, &clock_realtime);
register_posix_clock(CLOCK_MONOTONIC, &clock_monotonic);
+ register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &clock_process);
+ register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &clock_thread);

posix_timers_cache = kmem_cache_create("posix_timers_cache",
sizeof (struct k_itimer), 0, 0, NULL, NULL);
@@ -1227,6 +1235,46 @@
return -EINVAL;
}

+/*
+ * Single Unix Specification V3:
+ *
+ * Implementations shall also support the special clockid_t value
+ * CLOCK_THREAD_CPUTIME_ID, which represents the CPU-time clock of the calling
+ * thread when invoking one of the clock_*() or timer_*() functions. For these
+ * clock IDs, the values returned by clock_gettime() and specified by
+ * clock_settime() shall represent the amount of execution time of the thread
+ * associated with the clock.
+ */
+int do_posix_clock_thread_gettime(struct timespec *tp)
+{
+ jiffies_to_timespec(current->signal->cutime + current->signal->cstime, tp);
+ return 0;
+}
+
+/*
+ * Single Unix Specification V3:
+ *
+ * Implementations shall also support the special clockid_t value
+ * CLOCK_PROCESS_CPUTIME_ID, which represents the CPU-time clock of the
+ * calling process when invoking one of the clock_*() or timer_*() functions.
+ * For these clock IDs, the values returned by clock_gettime() and specified
+ * by clock_settime() represent the amount of execution time of the process
+ * associated with the clock.
+ */
+int do_posix_clock_process_gettime(struct timespec *tp)
+{
+ unsigned long ticks = 0;
+ struct task *t;
+
+ /* Add up the cpu time for all the threads of this process */
+ for (t = current; t != current; t = next_thread(p)) {
+ ticks += t->signal->cutime + t->signal->cstime;
+ }
+
+ jiffies_to_timespec(ticks, tp);
+ return 0;
+}
+
asmlinkage long
sys_clock_settime(clockid_t which_clock, const struct timespec __user *tp)
{


2004-09-27 22:56:07

by George Anzinger

[permalink] [raw]
Subject: Re: [RFC] Posix compliant behavior of CLOCK_PROCESS/THREAD_CPUTIME_ID

Uh, do you have a test program to verify these? I would like to add it to the
support package on sourceforge.

George

Christoph Lameter wrote:
> Attached follows a patch to implement the POSIX clocks according to the
> POSIX standard which states in V3 of the Single Unix Specification:
>
> 1. CLOCK_PROCESS_CPUTIME_ID
>
> Implementations shall also support the special clockid_t value
> CLOCK_PROCESS_CPUTIME_ID, which represents the CPU-time clock of the
> calling process when invoking one of the clock_*() or timer_*()
> functions. For these clock IDs, the values returned by clock_gettime() and specified
> by clock_settime() represent the amount of execution time of the process
> associated with the clock.
>
> 2. CLOCK_THREAD_CPUTIME_ID
>
> Implementations shall also support the special clockid_t value
> CLOCK_THREAD_CPUTIME_ID, which represents the CPU-time clock of the
> calling thread when invoking one of the clock_*() or timer_*()
> functions. For these clock IDs, the values returned by clock_gettime()
> and specified by clock_settime() shall represent the amount of
> execution time of the thread associated with the clock.
>
> These times mentioned are CPU processing times and not the time that has
> passed since the startup of a process. Glibc currently provides its own
> implementation of these two clocks which is designed to return the time
> that passed since the startup of a process or a thread.
>
> Moreover this clock is bound to CPU timers which is problematic when the
> frequency of the clock changes or the process is moved to a different
> processor whose cpu timer may not be fully synchronized to the cpu timer
> of the current CPU.
>
> I would like to have the following patch integrated into the kernel. Glibc
> would need to be modified to simply generate a system call for clock_* without
> doing its own emulation of a clock. CLOCK_PROCESS_CPUTIME_ID and
> CLOCK_THREAD_CPUTIME id were never intended to be used as a means to
> access a time stamp counter on a CPU and it may be better to find another
> means of accesses the cpu time registerss.
>
> The patch is really quite straighforward and only affects one file...
>
> Index: linus/kernel/posix-timers.c
> ===================================================================
> --- linus.orig/kernel/posix-timers.c 2004-09-23 15:12:01.000000000 -0700
> +++ linus/kernel/posix-timers.c 2004-09-27 13:42:40.000000000 -0700
> @@ -10,6 +10,10 @@
> * 2004-06-01 Fix CLOCK_REALTIME clock/timer TIMER_ABSTIME bug.
> * Copyright (C) 2004 Boris Hu
> *
> + * 2004-07-27 Provide POSIX compliant clocks
> + * CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID.
> + * by Christoph Lameter
> + *
> * This program is free software; you can redistribute it and/or modify
> * it under the terms of the GNU General Public License as published by
> * the Free Software Foundation; either version 2 of the License, or (at
> @@ -133,18 +137,10 @@
> * resolution. Here we define the standard CLOCK_REALTIME as a
> * 1/HZ resolution clock.
> *
> - * CPUTIME & THREAD_CPUTIME: We are not, at this time, definding these
> - * two clocks (and the other process related clocks (Std
> - * 1003.1d-1999). The way these should be supported, we think,
> - * is to use large negative numbers for the two clocks that are
> - * pinned to the executing process and to use -pid for clocks
> - * pinned to particular pids. Calls which supported these clock
> - * ids would split early in the function.
> - *
> * RESOLUTION: Clock resolution is used to round up timer and interval
> * times, NOT to report clock times, which are reported with as
> * much resolution as the system can muster. In some cases this
> - * resolution may depend on the underlaying clock hardware and
> + * resolution may depend on the underlying clock hardware and
> * may not be quantifiable until run time, and only then is the
> * necessary code is written. The standard says we should say
> * something about this issue in the documentation...
> @@ -162,7 +158,7 @@
> *
> * At this time all functions EXCEPT clock_nanosleep can be
> * redirected by the CLOCKS structure. Clock_nanosleep is in
> - * there, but the code ignors it.
> + * there, but the code ignores it.
> *
> * Permissions: It is assumed that the clock_settime() function defined
> * for each clock will take care of permission checks. Some
> @@ -198,6 +194,8 @@
> struct timespec *tp, struct timespec *mo);
> int do_posix_clock_monotonic_gettime(struct timespec *tp);
> int do_posix_clock_monotonic_settime(struct timespec *tp);
> +int do_posix_clock_process_gettime(struct timespec *tp);
> +int do_posix_clock_thread_gettime(struct timespec *tp);
> static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);
>
> static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
> @@ -218,6 +216,14 @@
> .clock_get = do_posix_clock_monotonic_gettime,
> .clock_set = do_posix_clock_monotonic_settime
> };
> + struct k_clock clock_thread = {.res = CLOCK_REALTIME_RES,
> + .abs_struct = NULL,
> + .clock_get = do_posix_clock_thread_gettime
> + };
> + struct k_clock clock_process = {.res = CLOCK_REALTIME_RES,
> + .abs_struct = NULL,
> + .clock_get = do_posix_clock_process_gettime
> + };

You will have to supply functions to return errors for the unimplemented calls.
Otherwise the caller will end up in the CLOCK_REALTIME code which will just
not work.

Also, to trap calls to clock_nanosleep() you will need to start running it
through the same dispatch table. (See notes on this in the comments.).

-g
>
> #ifdef CONFIG_TIME_INTERPOLATION
> /* Clocks are more accurate with time interpolators */
> @@ -226,6 +232,8 @@
>
> register_posix_clock(CLOCK_REALTIME, &clock_realtime);
> register_posix_clock(CLOCK_MONOTONIC, &clock_monotonic);
> + register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &clock_process);
> + register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &clock_thread);
>
> posix_timers_cache = kmem_cache_create("posix_timers_cache",
> sizeof (struct k_itimer), 0, 0, NULL, NULL);
> @@ -1227,6 +1235,46 @@
> return -EINVAL;
> }
>
> +/*
> + * Single Unix Specification V3:
> + *
> + * Implementations shall also support the special clockid_t value
> + * CLOCK_THREAD_CPUTIME_ID, which represents the CPU-time clock of the calling
> + * thread when invoking one of the clock_*() or timer_*() functions. For these
> + * clock IDs, the values returned by clock_gettime() and specified by
> + * clock_settime() shall represent the amount of execution time of the thread
> + * associated with the clock.
> + */
> +int do_posix_clock_thread_gettime(struct timespec *tp)
> +{
> + jiffies_to_timespec(current->signal->cutime + current->signal->cstime, tp);
> + return 0;
> +}
> +
> +/*
> + * Single Unix Specification V3:
> + *
> + * Implementations shall also support the special clockid_t value
> + * CLOCK_PROCESS_CPUTIME_ID, which represents the CPU-time clock of the
> + * calling process when invoking one of the clock_*() or timer_*() functions.
> + * For these clock IDs, the values returned by clock_gettime() and specified
> + * by clock_settime() represent the amount of execution time of the process
> + * associated with the clock.
> + */
> +int do_posix_clock_process_gettime(struct timespec *tp)
> +{
> + unsigned long ticks = 0;
> + struct task *t;
> +
> + /* Add up the cpu time for all the threads of this process */
> + for (t = current; t != current; t = next_thread(p)) {
> + ticks += t->signal->cutime + t->signal->cstime;
> + }
> +
> + jiffies_to_timespec(ticks, tp);
> + return 0;
> +}
> +
> asmlinkage long
> sys_clock_settime(clockid_t which_clock, const struct timespec __user *tp)
> {
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>

--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-09-28 19:20:21

by Ulrich Drepper

[permalink] [raw]
Subject: Re: [RFC] Posix compliant behavior of CLOCK_PROCESS/THREAD_CPUTIME_ID

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I'm not the right person to comment on this, I hope Roland will. Roland
has been working on an implementation of this clock. I think the
situation is quite a bit more complicated than your patch suggests. So,
please wait until he has time to comment.

- --
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)

iD8DBQFBWbkg2ijCOnn/RHQRArRbAJ9jEv/jwYuHuxQeT7fITmBAixaP2wCfcu0e
Ysb9uKlNxF58eycti8tA2us=
=AHNp
-----END PGP SIGNATURE-----

2004-09-28 19:28:20

by Christoph Lameter

[permalink] [raw]
Subject: Re: [RFC] Posix compliant behavior of CLOCK_PROCESS/THREAD_CPUTIME_ID

Could you forward the messages to him?

On Tue, 28 Sep 2004, Ulrich Drepper wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> I'm not the right person to comment on this, I hope Roland will. Roland
> has been working on an implementation of this clock. I think the
> situation is quite a bit more complicated than your patch suggests. So,
> please wait until he has time to comment.
>
> - --
> ➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.2.6 (GNU/Linux)
>
> iD8DBQFBWbkg2ijCOnn/RHQRArRbAJ9jEv/jwYuHuxQeT7fITmBAixaP2wCfcu0e
> Ysb9uKlNxF58eycti8tA2us=
> =AHNp
> -----END PGP SIGNATURE-----
>

2004-09-29 03:27:20

by Christoph Lameter

[permalink] [raw]
Subject: Posix compliant CLOCK_PROCESS/THREAD_CPUTIME_ID V4

George asked for a test program so I wrote one and debugged the patch.
The test program uses syscall to bypass glibc processing. I have been
working on a patch for glibc but that gets a bit complicated
because backwards compatibility has to be kept. Maybe tomorrow.
Found also that glibc allows the setting of these clocks so I also
implemented that and used it in the test program. Setting these
clocks modifies stime and utime directly, which may not be such a good
idea. Do we really need to be able to set these clocks?

So it actually works now. Test output, test program and revised patch:

christoph@athlon:~$ ./test_cputime
Single Thread Testing
CLOCK_THREAD_CPUTIME_ID= 0.373943152 resolution= 0.000999848
CLOCK_PROCESS_CPUTIME_ID= 0.373943152 resolution= 0.000999848
Multi Thread Testing
Starting Thread: 0 1 2 3 4 5 6 7 8 9
Joining Thread: 0 1 2 3 4 5 6 7 8 9
0 Cycles= 0 Thread= 0.000000000ns Process= 0.000000000ns
1 Cycles=1000000 Thread= 0.037994224ns Process= 0.507922784ns
2 Cycles=2000000 Thread= 0.073988752ns Process= 0.097985104ns
3 Cycles=3000000 Thread= 0.108983432ns Process= 0.612906824ns
4 Cycles=4000000 Thread= 0.146977656ns Process= 0.657899984ns
5 Cycles=5000000 Thread= 0.182972184ns Process= 0.739887520ns
6 Cycles=6000000 Thread= 0.217966864ns Process= 1.456778536ns
7 Cycles=7000000 Thread= 0.254961240ns Process= 1.461777776ns
8 Cycles=8000000 Thread= 0.290955768ns Process= 1.627752544ns
9 Cycles=9000000 Thread= 0.326950296ns Process= 1.641750416ns

Clock status at the end of the timer tests:
Gettimeofday() = 1096427813.738929000
CLOCK_REALTIME= 1096427813.738941000 resolution= 0.000999848
CLOCK_MONOTONIC= 161.938418328 resolution= 0.000999848
CLOCK_PROCESS_CPUTIME_ID= 1.641750416 resolution= 0.000999848
CLOCK_THREAD_CPUTIME_ID= 0.000000000 resolution= 0.000999848

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <asm/unistd.h>
#include <pthread.h>

#define clock_getres(x,y) syscall(__NR_clock_getres, x,y)
#define clock_gettime(x,y) syscall(__NR_clock_gettime, x, y)
#define clock_settime(x,y) syscall(__NR_clock_settime, x, y)

void pr(int clock,const char *n)
{
struct timespec tv = {1,2};
struct timespec res = {3,4};
int rc;


rc=clock_getres(clock,&res);
if (rc) {
printf("getres return code on %s=%d errno=%d\n",n,rc,errno);
}
rc=clock_gettime(clock,&tv);
if (rc) {
printf("gettime return code on %s=%d errno=%d\n",n,rc, errno);
}
else
printf("%25s=% 11d.%09d resolution=% 2d.%09d\n",n,tv.tv_sec,tv.tv_nsec,res.tv_sec,res.tv_nsec);
}

int y;

void kx(long long x) {
y=x;
};

struct timespec zero;

pthread_t thread[10];

struct tinfo {
int i;
struct timespec ttime,ptime;
} tinf[10];

void *thread_function(void *x) {
struct tinfo *t=x;
int i;

for(i=1;i< t->i;i++) kx(1000000000000LL/i);
clock_gettime(CLOCK_THREAD_CPUTIME_ID,&t->ttime);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&t->ptime);
}

int main(char argc, char *argv[])
{
struct timespec tv;
int i;

/* Waste some time */
printf("Single Thread Testing\n");

for(i=1;i<10000000;i++) kx(1000000000000LL/i);
pr(CLOCK_THREAD_CPUTIME_ID,"CLOCK_THREAD_CPUTIME_ID");
pr(CLOCK_PROCESS_CPUTIME_ID,"CLOCK_PROCESS_CPUTIME_ID");
/* Waste some more time in threads */
printf("Multi Thread Testing\nStarting Thread:");
clock_settime(CLOCK_PROCESS_CPUTIME_ID,&zero);
for(i=0;i<10;i++) {
tinf[i].i=i*1000000;
if (pthread_create(&thread[i], NULL, thread_function, tinf+i))
perror("thread");
else
printf(" %d",i);
}
printf("\n Joining Thread:");
for(i=0;i<10;i++) if (pthread_join( thread[i], NULL)) perror("join"); else printf(" %d",i);
printf("\n");
for(i=0;i<10;i++) {
printf("%d Cycles=%7d Thread=% 3d.%09dns Process=% 3d.%09dns\n",i,tinf[i].i,tinf[i].ttime.tv_sec,tinf[i].ttime.tv_nsec,tinf[i].ptime.tv_sec,tinf[i].ptime.tv_nsec);
}
gettimeofday((struct timeval *)&tv);
tv.tv_nsec = tv.tv_nsec*1000;
printf("\nClock status at the end of the timer tests:\n");
printf(" Gettimeofday() =% 11d.%09d\n",tv.tv_sec,tv.tv_nsec);
pr(CLOCK_REALTIME,"CLOCK_REALTIME");
pr(CLOCK_MONOTONIC,"CLOCK_MONOTONIC");
pr(CLOCK_PROCESS_CPUTIME_ID,"CLOCK_PROCESS_CPUTIME_ID");
pr(CLOCK_THREAD_CPUTIME_ID,"CLOCK_THREAD_CPUTIME_ID");
printf("\n");
}

Index: linux-2.6.9-rc2/kernel/posix-timers.c
===================================================================
--- linux-2.6.9-rc2.orig/kernel/posix-timers.c 2004-09-12 22:32:48.000000000 -0700
+++ linux-2.6.9-rc2/kernel/posix-timers.c 2004-09-28 19:49:59.919624581 -0700
@@ -10,6 +10,10 @@
* 2004-06-01 Fix CLOCK_REALTIME clock/timer TIMER_ABSTIME bug.
* Copyright (C) 2004 Boris Hu
*
+ * 2004-07-27 Provide POSIX compliant clocks
+ * CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID.
+ * by Christoph Lameter
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
@@ -133,18 +137,10 @@
* resolution. Here we define the standard CLOCK_REALTIME as a
* 1/HZ resolution clock.
*
- * CPUTIME & THREAD_CPUTIME: We are not, at this time, definding these
- * two clocks (and the other process related clocks (Std
- * 1003.1d-1999). The way these should be supported, we think,
- * is to use large negative numbers for the two clocks that are
- * pinned to the executing process and to use -pid for clocks
- * pinned to particular pids. Calls which supported these clock
- * ids would split early in the function.
- *
* RESOLUTION: Clock resolution is used to round up timer and interval
* times, NOT to report clock times, which are reported with as
* much resolution as the system can muster. In some cases this
- * resolution may depend on the underlaying clock hardware and
+ * resolution may depend on the underlying clock hardware and
* may not be quantifiable until run time, and only then is the
* necessary code is written. The standard says we should say
* something about this issue in the documentation...
@@ -162,7 +158,7 @@
*
* At this time all functions EXCEPT clock_nanosleep can be
* redirected by the CLOCKS structure. Clock_nanosleep is in
- * there, but the code ignors it.
+ * there, but the code ignores it.
*
* Permissions: It is assumed that the clock_settime() function defined
* for each clock will take care of permission checks. Some
@@ -198,6 +194,10 @@
struct timespec *tp, struct timespec *mo);
int do_posix_clock_monotonic_gettime(struct timespec *tp);
int do_posix_clock_monotonic_settime(struct timespec *tp);
+int do_posix_clock_process_gettime(struct timespec *tp);
+int do_posix_clock_process_settime(struct timespec *tp);
+int do_posix_clock_thread_gettime(struct timespec *tp);
+int do_posix_clock_thread_settime(struct timespec *tp);
static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);

static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
@@ -218,6 +218,16 @@
.clock_get = do_posix_clock_monotonic_gettime,
.clock_set = do_posix_clock_monotonic_settime
};
+ struct k_clock clock_thread = {.res = CLOCK_REALTIME_RES,
+ .abs_struct = NULL,
+ .clock_get = do_posix_clock_thread_gettime,
+ .clock_set = do_posix_clock_thread_settime
+ };
+ struct k_clock clock_process = {.res = CLOCK_REALTIME_RES,
+ .abs_struct = NULL,
+ .clock_get = do_posix_clock_process_gettime,
+ .clock_set = do_posix_clock_process_settime
+ };

#ifdef CONFIG_TIME_INTERPOLATION
/* Clocks are more accurate with time interpolators */
@@ -226,6 +236,8 @@

register_posix_clock(CLOCK_REALTIME, &clock_realtime);
register_posix_clock(CLOCK_MONOTONIC, &clock_monotonic);
+ register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &clock_process);
+ register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &clock_thread);

posix_timers_cache = kmem_cache_create("posix_timers_cache",
sizeof (struct k_itimer), 0, 0, NULL, NULL);
@@ -1227,6 +1239,76 @@
return -EINVAL;
}

+/*
+ * Single Unix Specification V3:
+ *
+ * Implementations shall also support the special clockid_t value
+ * CLOCK_THREAD_CPUTIME_ID, which represents the CPU-time clock of the calling
+ * thread when invoking one of the clock_*() or timer_*() functions. For these
+ * clock IDs, the values returned by clock_gettime() and specified by
+ * clock_settime() shall represent the amount of execution time of the thread
+ * associated with the clock.
+ */
+int do_posix_clock_thread_gettime(struct timespec *tp)
+{
+ jiffies_to_timespec(current->utime + current->stime, tp);
+ return 0;
+}
+
+int do_posix_clock_thread_settime(struct timespec *tp)
+{
+ current->stime = 0;
+ current->utime = timespec_to_jiffies(tp);
+ return 0;
+}
+
+/*
+ * Single Unix Specification V3:
+ *
+ * Implementations shall also support the special clockid_t value
+ * CLOCK_PROCESS_CPUTIME_ID, which represents the CPU-time clock of the
+ * calling process when invoking one of the clock_*() or timer_*() functions.
+ * For these clock IDs, the values returned by clock_gettime() and specified
+ * by clock_settime() represent the amount of execution time of the process
+ * associated with the clock.
+ */
+int do_posix_clock_process_gettime(struct timespec *tp)
+{
+ unsigned long ticks;
+ task_t *t;
+
+ /* The signal structure is shared between all threads */
+ ticks = current->signal->utime + current->signal->stime;
+
+ /* Add up the cpu time for all the still running threads of this process */
+ t = current;
+ do {
+ ticks += t->utime + t->stime;
+ t = next_thread(t);
+ } while (t != current);
+
+ jiffies_to_timespec(ticks, tp);
+ return 0;
+}
+
+int do_posix_clock_process_settime(struct timespec *tp)
+{
+ task_t *t;
+ /*
+ * Set all other threads to zero cs/cutime and then set up the
+ * desired time in the current thread
+ */
+
+ for (t = next_thread(current); t != current; t = next_thread(t))
+ {
+ t->stime = 0;
+ t->utime = 0;
+ }
+
+ do_posix_clock_thread_settime(tp);
+ return 0;
+}
+
asmlinkage long
sys_clock_settime(clockid_t which_clock, const struct timespec __user *tp)
{

2004-09-29 17:47:48

by George Anzinger

[permalink] [raw]
Subject: Re: Posix compliant CLOCK_PROCESS/THREAD_CPUTIME_ID V4

Christoph Lameter wrote:
> George asked for a test program so I wrote one and debugged the patch.
> The test program uses syscall to bypass glibc processing. I have been
> working on a patch for glibc but that gets a bit complicated
> because backwards compatibility has to be kept. Maybe tomorrow.
> Found also that glibc allows the setting of these clocks so I also
> implemented that and used it in the test program. Setting these
> clocks modifies stime and utime directly, which may not be such a good
> idea. Do we really need to be able to set these clocks?

Another way of doing this is to save these values in the task structure. If
null, use the direct value of stime, utime, if not, adjust by the saved value
(i.e. saved value would represent time zero).
>
> So it actually works now. Test output, test program and revised patch:

Please, when sending patches, attach them. This avoids problems with mailers,
on both ends, messing with white space. They still appear in line, at least in
some mailers (mozilla in my case).

As to the test program, what happens when you attempt to set up a timer on these
clocks? (No, I don't think it should work, but we DO want to properly error
out. And the test should verify that this happens.) By the way, if you use the
support package from sourceforge, you will find a lot of test harness stuff.


~
--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-09-29 18:16:22

by Christoph Lameter

[permalink] [raw]
Subject: Re: Posix compliant CLOCK_PROCESS/THREAD_CPUTIME_ID V4

On Wed, 29 Sep 2004, George Anzinger wrote:

> Christoph Lameter wrote:
> > George asked for a test program so I wrote one and debugged the patch.
> > The test program uses syscall to bypass glibc processing. I have been
> > working on a patch for glibc but that gets a bit complicated
> > because backwards compatibility has to be kept. Maybe tomorrow.
> > Found also that glibc allows the setting of these clocks so I also
> > implemented that and used it in the test program. Setting these
> > clocks modifies stime and utime directly, which may not be such a good
> > idea. Do we really need to be able to set these clocks?
>
> Another way of doing this is to save these values in the task structure. If
> null, use the direct value of stime, utime, if not, adjust by the saved value
> (i.e. saved value would represent time zero).

But this would require two additional int field in task_t just for that
rarely used functionality.

> Please, when sending patches, attach them. This avoids problems with mailers,
> on both ends, messing with white space. They still appear in line, at least in
> some mailers (mozilla in my case).

The custom on lkml, for Linus and Andrew is to send them inline. I also
prefer them inline. Will try to remember sending attachments when sending a
patch to you.

> As to the test program, what happens when you attempt to set up a timer on these
> clocks? (No, I don't think it should work, but we DO want to properly error
> out. And the test should verify that this happens.) By the way, if you use the
> support package from sourceforge, you will find a lot of test harness stuff.

That is an interesting issue. If that would work correctly one could
trigger an signal if more than a certain amount of cputime is used.
It looks though that it will create an interrupt based on real time.

SuS says:

Each implementation defines a set of clocks that can be used as timing
bases for per-process timers. All implementations support a clock_id of
CLOCK_REALTIME.

So restrict timer_create to CLOCK_REALTIME and CLOCK_MONOTONIC? Is it
necessary to be able to derive a timer from a timer derives from those
two?

something like the following (just inlined for the discussion ...)?

--- linux-2.6.9-rc2.orig/kernel/posix-timers.c 2004-09-28 20:29:28.000000000 -0700
+++ linux-2.6.9-rc2/kernel/posix-timers.c 2004-09-29 11:12:37.814713085 -0700
@@ -585,8 +585,8 @@
sigevent_t event;
int it_id_set = IT_ID_NOT_SET;

- if ((unsigned) which_clock >= MAX_CLOCKS ||
- !posix_clocks[which_clock].res)
+ if ((unsigned) which_clock != CLOCK_REALTIME &&
+ (unsigned) which_clock != CLOCK_MONOTONIC)
return -EINVAL;

new_timer = alloc_posix_timer();

2004-09-29 19:28:15

by George Anzinger

[permalink] [raw]
Subject: Re: Posix compliant CLOCK_PROCESS/THREAD_CPUTIME_ID V4

Christoph Lameter wrote:
> On Wed, 29 Sep 2004, George Anzinger wrote:
>
>
>>Christoph Lameter wrote:
>>
>>>George asked for a test program so I wrote one and debugged the patch.
>>>The test program uses syscall to bypass glibc processing. I have been
>>>working on a patch for glibc but that gets a bit complicated
>>>because backwards compatibility has to be kept. Maybe tomorrow.
>>>Found also that glibc allows the setting of these clocks so I also
>>>implemented that and used it in the test program. Setting these
>>>clocks modifies stime and utime directly, which may not be such a good
>>>idea. Do we really need to be able to set these clocks?
>>
>>Another way of doing this is to save these values in the task structure. If
>>null, use the direct value of stime, utime, if not, adjust by the saved value
>>(i.e. saved value would represent time zero).
>
>
> But this would require two additional int field in task_t just for that
> rarely used functionality.

Exactly. What does the community want? An alternative is to allocate a small
block of memory for this and managed it from the posix-timers.c code. It would
only be referenced by get_clock and set_clock. And be released by the
exit_itimers() code.
>
>
>>Please, when sending patches, attach them. This avoids problems with mailers,
>>on both ends, messing with white space. They still appear in line, at least in
>>some mailers (mozilla in my case).
>
>
> The custom on lkml, for Linus and Andrew is to send them inline. I also
> prefer them inline. Will try to remember sending attachments when sending a
> patch to you.

I think they WILL be inline as well as attached if you attach them. The
difference is that in both presentations neither mailer will mess with white
space. This means that long lines will not be wrapped and tabs vs space will
not be changed.

Try sending yourself one and see it this is not true for your mailer.

>
>>As to the test program, what happens when you attempt to set up a timer on these
>>clocks? (No, I don't think it should work, but we DO want to properly error
>>out. And the test should verify that this happens.) By the way, if you use the
>>support package from sourceforge, you will find a lot of test harness stuff.
>
>
> That is an interesting issue. If that would work correctly one could
> trigger an signal if more than a certain amount of cputime is used.
> It looks though that it will create an interrupt based on real time.
>
> SuS says:
>
> Each implementation defines a set of clocks that can be used as timing
> bases for per-process timers. All implementations support a clock_id of
> CLOCK_REALTIME.
>
> So restrict timer_create to CLOCK_REALTIME and CLOCK_MONOTONIC? Is it
> necessary to be able to derive a timer from a timer derives from those
> two?
>
> something like the following (just inlined for the discussion ...)?

NO. This is handled through the dispatch table (as set up when you register the
clock). You just supply a timer_create() function that returns the right error.
Likewise, attempts to use clock_nanosleep(). The issue with clock_nanosleep,
however, is that it, at this time, is not sent through the dispatch table. This
should be changed to, again call the same error function.
>
> --- linux-2.6.9-rc2.orig/kernel/posix-timers.c 2004-09-28 20:29:28.000000000 -0700
> +++ linux-2.6.9-rc2/kernel/posix-timers.c 2004-09-29 11:12:37.814713085 -0700
> @@ -585,8 +585,8 @@
> sigevent_t event;
> int it_id_set = IT_ID_NOT_SET;
>
> - if ((unsigned) which_clock >= MAX_CLOCKS ||
> - !posix_clocks[which_clock].res)
> + if ((unsigned) which_clock != CLOCK_REALTIME &&
> + (unsigned) which_clock != CLOCK_MONOTONIC)
> return -EINVAL;
>
> new_timer = alloc_posix_timer();
>

--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-09-29 19:37:36

by Christoph Lameter

[permalink] [raw]
Subject: Posix compliant CLOCK_PROCESS/THREAD_CPUTIME_ID V5

This version uses an offset field in the task and signal structs
to store offsets for the thread and process clock. It also includes
the check in timer_create for REALTIME or MONOTONIC. The
clocks are now independent and therefore the thread clock is not
clearedby clock_settime(CLOCK_PROCESS_CPUTIME_ID) in the testrun:

Single Thread Testing
CLOCK_THREAD_CPUTIME_ID= 0.374943000 resolution= 0.000999848
CLOCK_PROCESS_CPUTIME_ID= 0.374943000 resolution= 0.000999848
Multi Thread Testing
Starting Thread: 0 1 2 3 4 5 6 7 8 9
Joining Thread: 0 1 2 3 4 5 6 7 8 9
0 Cycles= 0 Thread= 0.000000000ns Process= 0.000999848ns
1 Cycles=1000000 Thread= 0.036994376ns Process= 0.315951968ns
2 Cycles=2000000 Thread= 0.073988752ns Process= 0.086986776ns
3 Cycles=3000000 Thread= 0.109983280ns Process= 0.517921264ns
4 Cycles=4000000 Thread= 0.146977656ns Process= 0.563914272ns
5 Cycles=5000000 Thread= 0.180972488ns Process= 1.043841312ns
6 Cycles=6000000 Thread= 0.218966712ns Process= 1.112830824ns
7 Cycles=7000000 Thread= 0.254961240ns Process= 1.620753608ns
8 Cycles=8000000 Thread= 0.290955768ns Process= 1.490773368ns
9 Cycles=9000000 Thread= 0.326950296ns Process= 1.641750416ns

Clock status at the end of the timer tests:
Gettimeofday() = 1096484938.561351000
CLOCK_REALTIME= 1096484938.561363000 resolution= 0.000999848
CLOCK_MONOTONIC= 157.633669432 resolution= 0.000999848
CLOCK_PROCESS_CPUTIME_ID= 1.641750416 resolution= 0.000999848
CLOCK_THREAD_CPUTIME_ID= 0.375942848 resolution= 0.000999848


Attachments:
thread_process_time_v5 (7.10 kB)
V5 of patch
test_cputime.c (2.46 kB)
Test program
Download all attachments

2004-09-29 19:40:08

by Christoph Lameter

[permalink] [raw]
Subject: Re: Posix compliant CLOCK_PROCESS/THREAD_CPUTIME_ID V4

On Wed, 29 Sep 2004, George Anzinger wrote:

> > So restrict timer_create to CLOCK_REALTIME and CLOCK_MONOTONIC? Is it
> > necessary to be able to derive a timer from a timer derives from those
> > two?
> >
> > something like the following (just inlined for the discussion ...)?
>
> NO. This is handled through the dispatch table (as set up when you register the
> clock). You just supply a timer_create() function that returns the right error.
> Likewise, attempts to use clock_nanosleep(). The issue with clock_nanosleep,
> however, is that it, at this time, is not sent through the dispatch table. This
> should be changed to, again call the same error function.

Ok. I gotta look at this again.

2004-09-29 19:46:03

by Jesper Juhl

[permalink] [raw]
Subject: Re: Posix compliant CLOCK_PROCESS/THREAD_CPUTIME_ID V4


Unrelated to the CLOCK_PROCESS/THREAD_CPUTIME_ID discussion, just wanted
to comment on the 'patches inline vs attached' bit.

On Wed, 29 Sep 2004, George Anzinger wrote:

> Christoph Lameter wrote:
> > On Wed, 29 Sep 2004, George Anzinger wrote:
> >
> > > Christoph Lameter wrote:
> > >
> > > Please, when sending patches, attach them. This avoids problems with
> > > mailers,
> > > on both ends, messing with white space. They still appear in line, at
> > > least in
> > > some mailers (mozilla in my case).
> >
> >
> > The custom on lkml, for Linus and Andrew is to send them inline. I also
> > prefer them inline. Will try to remember sending attachments when sending a
> > patch to you.
>
> I think they WILL be inline as well as attached if you attach them. The
> difference is that in both presentations neither mailer will mess with white
> space. This means that long lines will not be wrapped and tabs vs space will
> not be changed.
>
Not all mailers show attachments inline. Mailers that do usually depend on
the mimetype of the attachment when choosing to show inline or not. pine
(my personal favorite) show attachments with a text/plain and similar
mime-type inline, but a not all mailers use that (I see a lot of attached
patches on lkml that don't show inline, and that's somewhat annoying).

It's also harder to reply and comment on bits of a patch when your mailer
does not include attachments inline in a reply (even if it did show them
inline while reading the mail).
Having to save the patch, open it in a text editor and then cut'n'paste
bits of it into the reply mail is a pain. Same goes for having to save &
open it in order to read it in the first place.

--
Jesper Juhl

2004-09-30 00:15:24

by George Anzinger

[permalink] [raw]
Subject: Re: patches inline in mail

Jesper Juhl wrote:
> Unrelated to the CLOCK_PROCESS/THREAD_CPUTIME_ID discussion, just wanted
> to comment on the 'patches inline vs attached' bit.
>
> On Wed, 29 Sep 2004, George Anzinger wrote:
>
>
>>Christoph Lameter wrote:
>>
>>>On Wed, 29 Sep 2004, George Anzinger wrote:
>>>
>>>
>>>>Christoph Lameter wrote:
>>>>
>>>>Please, when sending patches, attach them. This avoids problems with
>>>>mailers,
>>>>on both ends, messing with white space. They still appear in line, at
>>>>least in
>>>>some mailers (mozilla in my case).
>>>
>>>
>>>The custom on lkml, for Linus and Andrew is to send them inline. I also
>>>prefer them inline. Will try to remember sending attachments when sending a
>>>patch to you.
>>
>>I think they WILL be inline as well as attached if you attach them. The
>>difference is that in both presentations neither mailer will mess with white
>>space. This means that long lines will not be wrapped and tabs vs space will
>>not be changed.
>>
>
> Not all mailers show attachments inline. Mailers that do usually depend on
> the mimetype of the attachment when choosing to show inline or not. pine
> (my personal favorite) show attachments with a text/plain and similar
> mime-type inline, but a not all mailers use that (I see a lot of attached
> patches on lkml that don't show inline, and that's somewhat annoying).

So we should make sure that the mailer uses the right mime-type. I suppose that
depends on the mailer?
>
> It's also harder to reply and comment on bits of a patch when your mailer
> does not include attachments inline in a reply (even if it did show them
> inline while reading the mail).
> Having to save the patch, open it in a text editor and then cut'n'paste
> bits of it into the reply mail is a pain. Same goes for having to save &
> open it in order to read it in the first place.

We agree. Still, I have been bitten too many times by misshandled white space
to trust pure inlineing. Likewise on picking it up one would usually past it in
the mail (I suppose) where as the attachment is through the mailer and less
prone to missing a character.

The best answer, I think, is attachments that show as inline AND stay that way
on the reply.

Guild lines on how to insure this are welcome.
--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-09-30 03:26:06

by Paul Jackson

[permalink] [raw]
Subject: Re: patches inline in mail

George wrote:
> Still, I have been bitten too many times by misshandled white space
> to trust pure inlineing.

I use a script to send any patches I care much about, rather than my
email client. The script sends the file directly to my SMTP server.

Especially when sending more than one related patch, I find it much more
accurate to prepare the small text file indicating To, Cc, Bcc, Subject,
local-patch-pathname for each patch in the set at my leisure, in my text
editor, until it all looks right, then issue a single command to send it
all off.

Email clients, especially the gui ones I'm fond of, are not well
suited to such work.

There are various such 'patch-bomb' scripts out there - mine is
available at:

http://www.speakeasy.org/~pj99/sgi/sendpatchset

See the embedded Usage string for documentation.

The script checks out everything it can, including file paths and email
addresses (by verifying them with the SMTP server) before it sends
anything, further increasing the chance that if something is sent, it's
all sent and correctly so.

--
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373

2004-10-01 05:33:55

by Andrew Morton

[permalink] [raw]
Subject: Re: patches inline in mail

George Anzinger <[email protected]> wrote:
>
> We agree. Still, I have been bitten too many times by misshandled white space
> to trust pure inlineing. Likewise on picking it up one would usually past it in
> the mail (I suppose) where as the attachment is through the mailer and less
> prone to missing a character.
>
> The best answer, I think, is attachments that show as inline AND stay that way
> on the reply.
>
> Guild lines on how to insure this are welcome.

Send angry email to [email protected]. AFAICT it's impossible with
recent mailnews.

Slightly more on-topic:

+int do_posix_clock_process_gettime(struct timespec *tp);
+int do_posix_clock_process_settime(struct timespec *tp);
+int do_posix_clock_thread_gettime(struct timespec *tp);
+int do_posix_clock_thread_settime(struct timespec *tp);

These should all be given static scope.

And it would be nice to structure the code so the forward decl isn't
needed, if poss.

2004-10-01 09:07:02

by Jesper Juhl

[permalink] [raw]
Subject: Re: patches inline in mail

On Wed, 29 Sep 2004, George Anzinger wrote:

> Date: Wed, 29 Sep 2004 17:14:38 -0700
> From: George Anzinger <[email protected]>
> To: Jesper Juhl <[email protected]>
> Cc: Christoph Lameter <[email protected]>, Ulrich Drepper <[email protected]>,
> [email protected], [email protected], [email protected],
> [email protected], [email protected]
> Subject: Re: patches inline in mail
>
> Jesper Juhl wrote:
> > Unrelated to the CLOCK_PROCESS/THREAD_CPUTIME_ID discussion, just wanted to
> > comment on the 'patches inline vs attached' bit.
> >
> > On Wed, 29 Sep 2004, George Anzinger wrote:
> >
> >
> > > Christoph Lameter wrote:
> > >
> > > > On Wed, 29 Sep 2004, George Anzinger wrote:
> > > >
> > > >
> > > > > Christoph Lameter wrote:
> > > > >
> > > > > Please, when sending patches, attach them. This avoids problems with
> > > > > mailers,
> > > > > on both ends, messing with white space. They still appear in line, at
> > > > > least in
> > > > > some mailers (mozilla in my case).
> > > >
> > > >
> > > > The custom on lkml, for Linus and Andrew is to send them inline. I also
> > > > prefer them inline. Will try to remember sending attachments when
> > > > sending a
> > > > patch to you.
> > >
> > > I think they WILL be inline as well as attached if you attach them. The
> > > difference is that in both presentations neither mailer will mess with
> > > white
> > > space. This means that long lines will not be wrapped and tabs vs space
> > > will
> > > not be changed.
> > >
> >
> > Not all mailers show attachments inline. Mailers that do usually depend on
> > the mimetype of the attachment when choosing to show inline or not. pine (my
> > personal favorite) show attachments with a text/plain and similar mime-type
> > inline, but a not all mailers use that (I see a lot of attached patches on
> > lkml that don't show inline, and that's somewhat annoying).
>
> So we should make sure that the mailer uses the right mime-type. I suppose
> that depends on the mailer?
> >
> > It's also harder to reply and comment on bits of a patch when your mailer
> > does not include attachments inline in a reply (even if it did show them
> > inline while reading the mail).
> > Having to save the patch, open it in a text editor and then cut'n'paste bits
> > of it into the reply mail is a pain. Same goes for having to save & open it
> > in order to read it in the first place.
>
> We agree. Still, I have been bitten too many times by misshandled white space
> to trust pure inlineing. Likewise on picking it up one would usually past it
> in the mail (I suppose) where as the attachment is through the mailer and less
> prone to missing a character.
>

When I include patches inline in mails I use pine's "Read File"
functionality. Pressing CTRL+R and then specifying a filename causes pine
to read the file and place it inline exactely as read from the file. So no
whitespace damage by cut'n'paste.
I don't know, but I would suspect that other mailers would have similar
functionality.??


> The best answer, I think, is attachments that show as inline AND stay that way
> on the reply.
>
That would be just as fine as plain inline, but I think it'll be difficult
to find a way to do that that works universally with all mailers.


--
Jesper Juhl


2004-10-01 13:31:27

by Alan

[permalink] [raw]
Subject: Re: patches inline in mail

On Gwe, 2004-10-01 at 06:29, Andrew Morton wrote:
> > Guild lines on how to insure this are welcome.
>
> Send angry email to [email protected]. AFAICT it's impossible with
> recent mailnews.

The mozilla behaviour is RFC compliant[1]. Use text/plain attachments
and mark them "to view" and it should do happier things. (Except with
Linus cos Mr Dinosaur[2] doesn't believe in MIME yet)

I've not been able to coax Evolution into not chewing on non attached
text either (again RFC compliant but not useful). If anyone knows a
magic incantation for it I'd love to know.

(and it might be a good addition to the lkml faq)

Alan
[1] Yes the RFC is stupid but its the spec nowdays
[2] Thankfully not purple and singing

2004-10-01 13:43:19

by Paul Fulghum

[permalink] [raw]
Subject: Re: patches inline in mail

On Fri, 2004-10-01 at 07:28, Alan Cox wrote:
> I've not been able to coax Evolution into not chewing on non attached
> text either (again RFC compliant but not useful). If anyone knows a
> magic incantation for it I'd love to know.

Select 'Preformat' instead of 'Normal' style and
do Insert->Text File. That works for me.

--
Paul Fulghum
[email protected]

2004-10-01 19:53:31

by Lee Revell

[permalink] [raw]
Subject: Re: patches inline in mail

On Fri, 2004-10-01 at 09:42, Paul Fulghum wrote:
> On Fri, 2004-10-01 at 07:28, Alan Cox wrote:
> > I've not been able to coax Evolution into not chewing on non attached
> > text either (again RFC compliant but not useful). If anyone knows a
> > magic incantation for it I'd love to know.
>
> Select 'Preformat' instead of 'Normal' style and
> do Insert->Text File. That works for me.

You can also just copy and paste into Evolution as long as 'Preformat'
is set. I just use 'diff -Nru foo bar | xclip'. The problem is that
'Preformat' is a property of a given text range in the message; there is
no way to set 'Preformat' for all input. So, if you paste with the
mouse and you don't hit the cursor exactly, Evolution will use 'Normal'
style and mangle the text.

It would be better if you could right click anywhere in the message and
have a 'Paste as preformatted' option.

Anyway this is OT, so LKML should be removed from any followups.

Lee

2004-10-01 20:01:00

by Christoph Lameter

[permalink] [raw]
Subject: Posix compliant cpu clocks V6 [0/3]: Rationale and test program

Signed-off-by: Christoph Lameter <[email protected]>

Changes from V5: Add glibc patch, mmtimer patch, error checking.

POSIX clocks are to be implemented in the following way according
to V3 of the Single Unix Specification:

1. CLOCK_PROCESS_CPUTIME_ID

Implementations shall also support the special clockid_t value
CLOCK_PROCESS_CPUTIME_ID, which represents the CPU-time clock of the
calling process when invoking one of the clock_*() or timer_*()
functions. For these clock IDs, the values returned by clock_gettime() and
specified by clock_settime() represent the amount of execution time of the
process associated with the clock.

2. CLOCK_THREAD_CPUTIME_ID

Implementations shall also support the special clockid_t value
CLOCK_THREAD_CPUTIME_ID, which represents the CPU-time clock of the
calling thread when invoking one of the clock_*() or timer_*()
functions. For these clock IDs, the values returned by clock_gettime()
and specified by clock_settime() shall represent the amount of
execution time of the thread associated with the clock.

These times mentioned are CPU processing times and not the time that has
passed since the startup of a process. Glibc currently provides its own
implementation of these two clocks which is designed to return the time
that passed since the startup of a process or a thread.

Moreover Glibc's clocks are bound to CPU timers which is problematic when the
frequency of the clock changes or the process is moved to a different
processor whose cpu timer may not be fully synchronized to the cpu timer
of the current CPU. This patchset results in a both clocks working reliably.

The patchset consists of the following components:

[0/3] Contains an explanation as to why these patches are necessary
as well as a test program and the output of a sample run.

[1/3] Linux Kernel Patch: Implements the two clocks and enhances some
pieces of the posix-timers implementation in the kernel for these
clocks and also makes it possible for device drivers to define
additional clocks.

[2/3] Glibc patch: Makes glibc not provide its own clocks if the kernel
provides them and also makes glibc able to use any posix clock provided
by the kernel so that posix clocks by driver may be accessed.

[3/3] Kernel patch for mmtimer. Sets up a posix clock CLOCK_SGI_CYCLE
that can currently only provide time but the clock will be used in the
future to generate signals using timer_create and friends.

Test program output
==================

Single Thread Testing
CLOCK_THREAD_CPUTIME_ID= 0.495117441 resolution= 0.000976563
CLOCK_PROCESS_CPUTIME_ID= 32.496110388 resolution= 0.000976563
Multi Thread Testing
Starting Thread: 0 1 2 3 4 5 6 7 8 9
Joining Thread: 0 1 2 3 4 5 6 7 8 9
0 Cycles= 0 Thread= 0.000000000ns Process= 0.000976563ns
1 Cycles=1000000 Thread= 1.368164763ns Process= 11.063482227ns
2 Cycles=2000000 Thread= 0.748047258ns Process= 6.340823559ns
3 Cycles=3000000 Thread= 0.672851907ns Process= 5.271487074ns
4 Cycles=4000000 Thread= 1.352539755ns Process= 10.551763215ns
5 Cycles=5000000 Thread= 2.007813528ns Process= 13.094733267ns
6 Cycles=6000000 Thread= 1.479492945ns Process= 12.622076775ns
7 Cycles=7000000 Thread= 1.733399325ns Process= 12.136724964ns
8 Cycles=8000000 Thread= 2.012696343ns Process= 13.690436697ns
9 Cycles=9000000 Thread= 2.331055881ns Process= 13.708991394ns

Clock status at the end of the timer tests:
Gettimeofday() = 1096659625.612416000
CLOCK_REALTIME= 1096659625.612603129 resolution= 0.000000040
CLOCK_MONOTONIC= 9024.882157828 resolution= 0.000000040
CLOCK_PROCESS_CPUTIME_ID= 13.709967957 resolution= 0.000976563
CLOCK_THREAD_CPUTIME_ID= 0.498047130 resolution= 0.000976563
CLOCK_SGI_CYCLE= 9077.595920640 resolution= 0.000000040


Test program
============

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <asm/unistd.h>
#include <pthread.h>

#define clock_getres(x,y) syscall(__NR_clock_getres, x,y)
#define clock_gettime(x,y) syscall(__NR_clock_gettime, x, y)
#define clock_settime(x,y) syscall(__NR_clock_settime, x, y)

void pr(int clock,const char *n)
{
struct timespec tv = {1,2};
struct timespec res = {3,4};
int rc;


rc=clock_getres(clock,&res);
if (rc) {
printf("getres return code on %s=%d errno=%d\n",n,rc,errno);
}
rc=clock_gettime(clock,&tv);
if (rc) {
printf("gettime return code on %s=%d errno=%d\n",n,rc, errno);
}
else
printf("%25s=% 11d.%09d resolution=% 2d.%09d\n",n,tv.tv_sec,tv.tv_nsec,res.tv_sec,res.tv_nsec);
}

int y;

void kx(long long x) {
y=x;
};

struct timespec zero;

pthread_t thread[10];

struct tinfo {
int i;
struct timespec ttime,ptime;
} tinf[10];

void *thread_function(void *x) {
struct tinfo *t=x;
int i;

for(i=1;i< t->i;i++) kx(1000000000000LL/i);
clock_gettime(CLOCK_THREAD_CPUTIME_ID,&t->ttime);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&t->ptime);
}

int main(char argc, char *argv[])
{
struct timespec tv;
int i;

/* Waste some time */
printf("Single Thread Testing\n");

for(i=1;i<10000000;i++) kx(1000000000000LL/i);
pr(CLOCK_THREAD_CPUTIME_ID,"CLOCK_THREAD_CPUTIME_ID");
pr(CLOCK_PROCESS_CPUTIME_ID,"CLOCK_PROCESS_CPUTIME_ID");
/* Waste some more time in threads */
printf("Multi Thread Testing\nStarting Thread:");
clock_settime(CLOCK_PROCESS_CPUTIME_ID,&zero);
for(i=0;i<10;i++) {
tinf[i].i=i*1000000;
if (pthread_create(&thread[i], NULL, thread_function, tinf+i))
perror("thread");
else
printf(" %d",i);
}
printf("\n Joining Thread:");
for(i=0;i<10;i++) if (pthread_join( thread[i], NULL)) perror("join"); else printf(" %d",i);
printf("\n");
for(i=0;i<10;i++) {
printf("%d Cycles=%7d Thread=% 3d.%09dns Process=% 3d.%09dns\n",i,tinf[i].i,tinf[i].ttime.tv_sec,tinf[i].ttime.tv_nsec,tinf[i].ptime.tv_sec,tinf[i].ptime.tv_nsec);
}
gettimeofday((struct timeval *)&tv);
tv.tv_nsec = tv.tv_nsec*1000;
printf("\nClock status at the end of the timer tests:\n");
printf(" Gettimeofday() =% 11d.%09d\n",tv.tv_sec,tv.tv_nsec);
pr(CLOCK_REALTIME,"CLOCK_REALTIME");
pr(CLOCK_MONOTONIC,"CLOCK_MONOTONIC");
pr(CLOCK_PROCESS_CPUTIME_ID,"CLOCK_PROCESS_CPUTIME_ID");
pr(CLOCK_THREAD_CPUTIME_ID,"CLOCK_THREAD_CPUTIME_ID");
pr(10,"CLOCK_SGI_CYCLE");
printf("\n");
}

2004-10-01 22:06:14

by Roland McGrath

[permalink] [raw]
Subject: Re: [RFC] Posix compliant behavior of CLOCK_PROCESS/THREAD_CPUTIME_ID

Sorry I haven't replied sooner. I don't think the facility offered by your
patch is enough by itself to be worth doing. That information about a
process is already available to itself via getrusage/times, though those
don't offer a per-thread sample.

I have been working on an alternate patch that implements more complete CPU
clock functionality. This includes access to other threads' and process'
times, potentially finer-grained information (based on sched_clock), and
timers. I will post this code when it's ready, hopefully soon.

As to supporting clock_settime, I think that is just plain not desireable.
I am not aware of any actual demand for it, and POSIX certainly does not
require that it be permitted. It's certainly undesireable to let a process
reset its actual totals as reported by getrusage, process accounting, etc.;
I gather your later revisions have at least avoided that pitfall. But I
don't really see the utility in letting applications use clock_settime on
their CPU clocks either. They can just save the starting value at the time
they would use clock_settime to reset it to zero, and compute the delta later.



Thanks,
Roland

2004-10-01 22:06:20

by George Anzinger

[permalink] [raw]
Subject: Re: patches inline in mail

Alan Cox wrote:
> On Gwe, 2004-10-01 at 06:29, Andrew Morton wrote:
>
>>> Guild lines on how to insure this are welcome.
>>
>>Send angry email to [email protected]. AFAICT it's impossible with
>>recent mailnews.
>
>
> The mozilla behaviour is RFC compliant[1]. Use text/plain attachments
> and mark them "to view" and it should do happier things. (Except with
> Linus cos Mr Dinosaur[2] doesn't believe in MIME yet)

Just how does one "mark them "to view" "?

George
>
> I've not been able to coax Evolution into not chewing on non attached
> text either (again RFC compliant but not useful). If anyone knows a
> magic incantation for it I'd love to know.
>
> (and it might be a good addition to the lkml faq)
>
> Alan
> [1] Yes the RFC is stupid but its the spec nowdays
> [2] Thankfully not purple and singing
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>

--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-10-01 23:32:57

by Christoph Lameter

[permalink] [raw]
Subject: Re: [RFC] Posix compliant behavior of CLOCK_PROCESS/THREAD_CPUTIME_ID

On Fri, 1 Oct 2004, Roland McGrath wrote:

> I have been working on an alternate patch that implements more complete CPU
> clock functionality. This includes access to other threads' and process'
> times, potentially finer-grained information (based on sched_clock), and
> timers. I will post this code when it's ready, hopefully soon.

Umm... How would you do that in a posix compliant way? This information is
already available via /proc

2004-10-02 16:33:00

by Alan

[permalink] [raw]
Subject: Re: patches inline in mail

On Sad, 2004-10-02 at 16:52, Olaf Dietsche wrote:
> I don't know how to do this with mozilla, but I suppose it's:
> "Content-Disposition: inline"
>
> RFC 2183 <ftp://ftp.rfc-editor.org/in-notes/rfc2183.txt>

Yep - that worked 8)

Evolution has an option on attachments for this

2004-10-03 21:36:53

by George Anzinger

[permalink] [raw]
Subject: Re: patches inline in mail

Alan Cox wrote:
> On Sad, 2004-10-02 at 16:52, Olaf Dietsche wrote:
>
>>I don't know how to do this with mozilla, but I suppose it's:
>>"Content-Disposition: inline"
>>
>>RFC 2183 <ftp://ftp.rfc-editor.org/in-notes/rfc2183.txt>
>
>
> Yep - that worked 8)
>
> Evolution has an option on attachments for this

So where is the mozilla expert when he is needed??
>
--
George Anzinger [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

2004-10-03 22:33:21

by Guennadi Liakhovetski

[permalink] [raw]
Subject: [OT] Re: patches inline in mail

Hello

While we are at it, maybe someone could help me with my "antient" pine
too. When sending patches inline (Ctrl-R) it looks fine up in the email,
also when I am reading my own email as it came to the list, e.g.

@@ -8,9 +8,9 @@
static void __inline__
dc390_freetag (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
{
- if (pSRB->TagNumber < 255) {

However, everybody (not pine-users) complains, that white spaces got
corrupted. And if I export the email I see

@@ -8,9 +8,9 @@
static void __inline__
dc390_freetag (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
{
- if (pSRB->TagNumber < 255) {

(notice the extra space). What is going on there and is there a solution
(apart from switching to another mailing or sending as attachments)?

Thanks
Guennadi
---
Guennadi Liakhovetski

2004-10-03 23:11:39

by Jesper Juhl

[permalink] [raw]
Subject: Re: [OT] Re: patches inline in mail

On Sun, 3 Oct 2004, Guennadi Liakhovetski wrote:

> Hello
>
> While we are at it, maybe someone could help me with my "antient" pine too.
> When sending patches inline (Ctrl-R) it looks fine up in the email, also when
> I am reading my own email as it came to the list, e.g.
>
[...]
>
> (notice the extra space). What is going on there and is there a solution
> (apart from switching to another mailing or sending as attachments)?
>

Recent Pine versions support a feature called flowed text that can
whitespace damage your inline patches, you want to turn that off. Could
probably also be some other setting that's causing it, but I haven't
delved into it any deeper since my pine config seems to work well (at
least I'm not getting any complains about damage when I use Ctrl+R to
insert patches).
If you want it I can send you my .pinerc off-list, just ask for it in
private email.

--
Jesper Juhl


2004-10-04 03:00:33

by Jim Nelson

[permalink] [raw]
Subject: Re: patches inline in mail

George Anzinger wrote:

> Alan Cox wrote:
>
>> On Sad, 2004-10-02 at 16:52, Olaf Dietsche wrote:
>>
>>> I don't know how to do this with mozilla, but I suppose it's:
>>> "Content-Disposition: inline"
>>>
>>> RFC 2183 <ftp://ftp.rfc-editor.org/in-notes/rfc2183.txt>
>>
>>
>>
>> Yep - that worked 8)
>>
>> Evolution has an option on attachments for this
>
>
> So where is the mozilla expert when he is needed??
>
>>

Dunno if you're being humorous or not, but here's how I did it.

In the menu bar, hit edit, preferences,(brings up a new window) mail and
newsgroups, composition, and at the top of the screen is the "forwarding
messages" option box - select inline.

At least that's how it works in 1.7 - haven't used the older variants in
a while... :)

2004-10-04 06:22:42

by Paul Jackson

[permalink] [raw]
Subject: Re: [OT] Re: patches inline in mail

Guennadi wrote:
> However, everybody (not pine-users) complains, that white spaces got
> corrupted. And if I export the email I see ...

I complained about the same extra space to a colleague of mine,
Simon Derr <[email protected]>.

A day later, Simon wrote back to me:
> I think I found the culprit:
> pine 4.60 and later have a feature about 'flowed text' that has to be
> explicitely turned off and that messes with whitespaces.

And indeed, that fixed his patches, from my perspective.

--
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <[email protected]> 1.650.933.1373

2004-10-04 07:27:45

by Ulrich Windl

[permalink] [raw]
Subject: Re: [OT] Re: patches inline in mail

Better show how the mail really looks like (source). The let's see whether it's a
decoding or encoding error.

Ulrich

On 3 Oct 2004 at 23:01, Guennadi Liakhovetski wrote:

> Hello
>
> While we are at it, maybe someone could help me with my "antient" pine
> too. When sending patches inline (Ctrl-R) it looks fine up in the email,
> also when I am reading my own email as it came to the list, e.g.
>
> @@ -8,9 +8,9 @@
> static void __inline__
> dc390_freetag (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
> {
> - if (pSRB->TagNumber < 255) {
>
> However, everybody (not pine-users) complains, that white spaces got
> corrupted. And if I export the email I see
>
> @@ -8,9 +8,9 @@
> static void __inline__
> dc390_freetag (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
> {
> - if (pSRB->TagNumber < 255) {
>
> (notice the extra space). What is going on there and is there a solution
> (apart from switching to another mailing or sending as attachments)?
>
> Thanks
> Guennadi
> ---
> Guennadi Liakhovetski
>


2004-10-04 18:51:13

by Christoph Lameter

[permalink] [raw]
Subject: RFC: Posix compliant clock_getclockcpuid(pid) to access other processes clocks

Here is a small idea for a kernel patch that implements access to other
process clocks via

clock_gettime(-PID,&timespec)

as Roland proposed and thus allows a full posix compliant implementation
of clock_getclockcpuid() in glibc.

clock_getclockcpuid(pid) would need to be changed to do

if (pid == 0)
return CLOCK_PROCESS_CPUTIME_ID;
else
return -1;

I may be able to finish this and send this to Andrew
by tomorrow.

Index: linus/kernel/posix-timers.c
===================================================================
--- linus.orig/kernel/posix-timers.c 2004-10-04 10:35:59.000000000 -0700
+++ linus/kernel/posix-timers.c 2004-10-04 11:38:06.000000000 -0700
@@ -1293,31 +1293,31 @@
* associated with the clock.
*/

-unsigned long process_ticks(void) {
+unsigned long process_ticks(task_t *c) {
unsigned long ticks;
task_t *t;

/* The signal structure is shared between all threads */
- ticks = current->signal->utime + current->signal->stime;
+ ticks = c->signal->utime + c->signal->stime;

/* Add up the cpu time for all the still running threads of this process */
- t = current;
+ t = c;
do {
ticks += t->utime + t->stime;
t = next_thread(t);
- } while (t != current);
+ } while (t != c);
return ticks;
}

int do_posix_clock_process_gettime(struct timespec *tp)
{
- jiffies_to_timespec(current->signal->process_clock_offset + process_ticks(), tp);
+ jiffies_to_timespec(current->signal->process_clock_offset + process_ticks(current), tp);
return 0;
}

int do_posix_clock_process_settime(struct timespec *tp)
{
- current->signal->process_clock_offset = timespec_to_jiffies(tp) - process_ticks();
+ current->signal->process_clock_offset = timespec_to_jiffies(tp) - process_ticks(current);
return 0;
}

@@ -1326,11 +1326,15 @@
{
struct timespec new_tp;

+ if (copy_from_user(&new_tp, tp, sizeof (*tp)))
+ return -EFAULT;
+ if (which_clock < 0) {
+ /* Setting of other processes clocks is not allowed */
+ return -EPERM;
+ }
if ((unsigned) which_clock >= MAX_CLOCKS ||
!posix_clocks[which_clock].res)
return -EINVAL;
- if (copy_from_user(&new_tp, tp, sizeof (*tp)))
- return -EFAULT;
if (posix_clocks[which_clock].clock_set)
return posix_clocks[which_clock].clock_set(&new_tp);

@@ -1343,6 +1347,15 @@
struct timespec rtn_tp;
int error = 0;

+ if (which_clock < 0) {
+ /* Obtain the clock from another process */
+ int pid = -which_clock;
+ task_t *c = find_task_by_pid(pid);
+
+ if (!c) return -EINVAL;
+ jiffies_to_timespec(c->signal->process_clock_offset + process_ticks(c), tp);
+ return 0;
+ }
if ((unsigned) which_clock >= MAX_CLOCKS ||
!posix_clocks[which_clock].res)
return -EINVAL;
@@ -1361,6 +1374,10 @@
{
struct timespec rtn_tp;

+ if (which_clock < 0) {
+ /* A process clock is desired. They all have the same resolution so... */
+ which_clock = CLOCK_PROCESS_CPUTIME_ID;
+ }
if ((unsigned) which_clock >= MAX_CLOCKS ||
!posix_clocks[which_clock].res)
return -EINVAL;

2004-10-04 19:30:08

by Guennadi Liakhovetski

[permalink] [raw]
Subject: Re: [OT] Re: patches inline in mail

On Sun, 3 Oct 2004, Paul Jackson wrote:

> Guennadi wrote:
> > However, everybody (not pine-users) complains, that white spaces got
> > corrupted. And if I export the email I see ...
>
> I complained about the same extra space to a colleague of mine,
> Simon Derr <[email protected]>.
>
> A day later, Simon wrote back to me:
> > I think I found the culprit:
> > pine 4.60 and later have a feature about 'flowed text' that has to be
> > explicitely turned off and that messes with whitespaces.
>
> And indeed, that fixed his patches, from my perspective.

Thanks to all, who replied. This:

--- .pinerc~ Sat Oct 2 22:59:50 2004
+++ .pinerc Mon Oct 4 20:13:03 2004
@@ -82,6 +82,7 @@
signature-at-bottom,
no-pass-control-characters-as-is,
prefer-plain-text,
+ quell-flowed-text,
slash-collapses-entire-thread,
enable-bounce-cmd,
enable-msg-view-urls,

helped (I hope).

Thanks
Guennadi
---
Guennadi Liakhovetski

2004-10-22 04:43:37

by Christoph Lameter

[permalink] [raw]
Subject: Posix compliant process clock patch for the linux arch in glibc

Patches were recently accepted into Linus tree for 2.6.10 to implement
posix compliant process clocks. The current glibc code does not provide
access to process and thread clocks of other processes and contains an
implementation of CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID
that returns the time that the process/thread has been running instead of
the cputime spend on the process. This patch makes glibc to use the new
linux kernel abilities instead of improvising these clocks. In addition
clockids unknown to glibc are forwarded the kernel instead of glibc
returning an error immediately. This allow the use of new clocks provided
by the kernel such as CLOCK_SGI_CYCLE.

POSIX clocks are to be implemented in the following way according
to V3 of the Single Unix Specification:

1. CLOCK_PROCESS_CPUTIME_ID

Implementations shall also support the special clockid_t value
CLOCK_PROCESS_CPUTIME_ID, which represents the CPU-time clock of the
calling process when invoking one of the clock_*() or timer_*()
functions. For these clock IDs, the values returned by clock_gettime() and
specified by clock_settime() represent the amount of execution time of the
process associated with the clock.

2. CLOCK_THREAD_CPUTIME_ID

Implementations shall also support the special clockid_t value
CLOCK_THREAD_CPUTIME_ID, which represents the CPU-time clock of the
calling thread when invoking one of the clock_*() or timer_*()
functions. For these clock IDs, the values returned by clock_gettime()
and specified by clock_settime() shall represent the amount of
execution time of the thread associated with the clock.

These times mentioned are CPU processing times and not the time that has
passed since the startup of a process. Glibc currently provides its own
implementation of these two clocks which is designed to return the time
that passed since the startup of a process or a thread.

Moreover glibc's clocks are bound to CPU timers which is problematic when
the frequency of the clock changes or the process is moved to a different
processor whose cpu timer may not be fully synchronized to the cpu timer
of the current CPU. The use of th kernel posix timer function results in
both clocks always working reliably.

The patch also implements access to other the thread and process clocks
of linux processes by using negative clockid's:

1. For CLOCK_PROCESS_CPUTIME_ID: -pid
2. For CLOCK_THREAD_CPUTIME_ID: -(pid + PID_MAX_LIMIT)

This allows

clock_getcpuclockid(pid) to return -pid

and

pthread_getcpuiclock(pid) to return -(pid + PID_MAX_LIMIT)

to allow access to the corresponding clocks.

This patch will make attempts to use process clocks or CLOCK_PROCESS_CPUTIME_ID and
CLOCK_THREAD_CPUTIME_ID return error codes on kernels earlier than 2.6.10 because glibc
is current not able to provide these clocks in POSIX conformant way on its own.

Software written under Linux that assumes these clocks to return high precision light
weight real time values derived from a cpu timer (as in the current emulation by glibc)
will break!

Feedback would be appreciated especially since I am not a glibc expert.

Signed-off-by: Christoph Lameter <[email protected]>

Index: libc/nptl/sysdeps/pthread/pthread_getcpuclockid.c
===================================================================
--- libc.orig/nptl/sysdeps/pthread/pthread_getcpuclockid.c 2003-06-24 16:53:20.000000000 -0700
+++ libc/nptl/sysdeps/pthread/pthread_getcpuclockid.c 2004-10-21 11:05:11.295178056 -0700
@@ -20,7 +20,7 @@
#include <pthreadP.h>
#include <sys/time.h>
#include <tls.h>
-
+#include <linux/threads.h>

int
pthread_getcpuclockid (threadid, clockid)
@@ -35,19 +35,8 @@
return ESRCH;

#ifdef CLOCK_THREAD_CPUTIME_ID
- /* We need to store the thread ID in the CLOCKID variable together
- with a number identifying the clock. We reserve the low 3 bits
- for the clock ID and the rest for the thread ID. This is
- problematic if the thread ID is too large. But 29 bits should be
- fine.
-
- If some day more clock IDs are needed the ID part can be
- enlarged. The IDs are entirely internal. */
- if (pd->tid >= 1 << (8 * sizeof (*clockid) - CLOCK_IDFIELD_SIZE))
- return ERANGE;
-
/* Store the number. */
- *clockid = CLOCK_THREAD_CPUTIME_ID | (pd->tid << CLOCK_IDFIELD_SIZE);
+ *clockid = - (pd->tid + PID_MAX_LIMIT);

return 0;
#else
Index: libc/sysdeps/unix/sysv/linux/clock_getres.c
===================================================================
--- libc.orig/sysdeps/unix/sysv/linux/clock_getres.c 2004-09-28 15:22:02.351950224 -0700
+++ libc/sysdeps/unix/sysv/linux/clock_getres.c 2004-10-21 11:05:11.297177752 -0700
@@ -20,24 +20,17 @@

#include "kernel-features.h"

-
#ifdef __ASSUME_POSIX_TIMERS
-/* This means the REALTIME and MONOTONIC clock are definitely
- supported in the kernel. */
-# define SYSDEP_GETRES \
- case CLOCK_REALTIME: \
- case CLOCK_MONOTONIC: \
- retval = INLINE_SYSCALL (clock_getres, 2, clock_id, res); \
- break
+/* we have to rely on the kernel */
+#define SYSDEP_DEFAULT_GETRES retval = INLINE_SYSCALL(clock_getres, err, 2, clock_id, res)
+
#elif defined __NR_clock_getres
/* Is the syscall known to exist? */
extern int __libc_missing_posix_timers attribute_hidden;

/* The REALTIME and MONOTONIC clock might be available. Try the
syscall first. */
-# define SYSDEP_GETRES \
- case CLOCK_REALTIME: \
- case CLOCK_MONOTONIC: \
+# define SYSDEP_DEFAULT_GETRES \
{ \
int e = EINVAL; \
\
@@ -65,7 +58,7 @@
else \
__set_errno (e); \
} \
- break
+
#endif

#ifdef __NR_clock_getres
Index: libc/sysdeps/unix/clock_gettime.c
===================================================================
--- libc.orig/sysdeps/unix/clock_gettime.c 2004-09-28 15:22:02.192974392 -0700
+++ libc/sysdeps/unix/clock_gettime.c 2004-10-21 11:05:11.300177296 -0700
@@ -23,21 +23,6 @@
#include <libc-internal.h>
#include <ldsodefs.h>

-
-#if HP_TIMING_AVAIL
-/* Clock frequency of the processor. We make it a 64-bit variable
- because some jokers are already playing with processors with more
- than 4GHz. */
-static hp_timing_t freq;
-
-
-/* This function is defined in the thread library. */
-extern int __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
- struct timespec *tp)
- __attribute__ ((__weak__));
-#endif
-
-
/* Get current value of CLOCK and store it in TP. */
int
clock_gettime (clockid_t clock_id, struct timespec *tp)
@@ -66,58 +51,14 @@
#endif

default:
-#if HP_TIMING_AVAIL
- if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
- != CLOCK_THREAD_CPUTIME_ID)
-#endif
+#ifdef SYSDEP_DEFAULT_GETTIME
+ SYSDEP_DEFAULT_GETTIME;
+#else
{
__set_errno (EINVAL);
break;
}
-
-#if HP_TIMING_AVAIL
- /* FALLTHROUGH. */
- case CLOCK_PROCESS_CPUTIME_ID:
- {
- hp_timing_t tsc;
-
- if (__builtin_expect (freq == 0, 0))
- {
- /* This can only happen if we haven't initialized the `freq'
- variable yet. Do this now. We don't have to protect this
- code against multiple execution since all of them should
- lead to the same result. */
- freq = __get_clockfreq ();
- if (__builtin_expect (freq == 0, 0))
- /* Something went wrong. */
- break;
- }
-
- if (clock_id != CLOCK_PROCESS_CPUTIME_ID
- && __pthread_clock_gettime != NULL)
- {
- retval = __pthread_clock_gettime (clock_id, freq, tp);
- break;
- }
-
- /* Get the current counter. */
- HP_TIMING_NOW (tsc);
-
- /* Compute the offset since the start time of the process. */
- tsc -= GL(dl_cpuclock_offset);
-
- /* Compute the seconds. */
- tp->tv_sec = tsc / freq;
-
- /* And the nanoseconds. This computation should be stable until
- we get machines with about 16GHz frequency. */
- tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq;
-
- retval = 0;
- }
- break;
#endif
}
-
return retval;
}
Index: libc/sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c
===================================================================
--- libc.orig/sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c 2004-10-21 11:04:12.855062304 -0700
+++ /dev/null1970-01-01 00:00:00.000000000 +0000
@@ -1,47 +0,0 @@
-/* Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#include <errno.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-
-
-#include "has_cpuclock.c"
-
-
-int
-clock_getcpuclockid (pid_t pid, clockid_t *clock_id)
-{
- /* We don't allow any process ID but our own. */
- if (pid != 0 && pid != getpid ())
- return EPERM;
-
- int retval = ENOENT;
-
- if (has_cpuclock () > 0)
- {
- /* Store the number. */
- *clock_id = CLOCK_PROCESS_CPUTIME_ID;
- retval = 0;
- }
-
- return retval;
-}
Index: libc/sysdeps/unix/sysv/linux/clock_settime.c
===================================================================
--- libc.orig/sysdeps/unix/sysv/linux/clock_settime.c 2004-10-01 10:27:15.007445832 -0700
+++ libc/sysdeps/unix/sysv/linux/clock_settime.c 2004-10-21 11:05:11.326173344 -0700
@@ -20,21 +20,15 @@

#include "kernel-features.h"

-
#ifdef __ASSUME_POSIX_TIMERS
-/* This means the REALTIME clock is definitely supported in the
- kernel. */
-# define SYSDEP_SETTIME \
- case CLOCK_REALTIME: \
- retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp); \
- break
+#define SYSDEP_DEFAULT_SETTIME retval = INLINE_SYSCALL(clock_settime, 2, clock_id, tp)
+
#elif defined __NR_clock_settime
/* Is the syscall known to exist? */
extern int __libc_missing_posix_timers attribute_hidden;

/* The REALTIME clock might be available. Try the syscall first. */
-# define SYSDEP_SETTIME \
- case CLOCK_REALTIME: \
+# define SYSDEP_DEFAULT_SETTIME \
{ \
int e = EINVAL; \
\
@@ -64,8 +58,7 @@
__set_errno (e); \
retval = -1; \
} \
- } \
- break
+ }
#endif

#ifdef __NR_clock_settime
Index: libc/sysdeps/unix/sysv/linux/clock_getcpuclockid.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ libc/sysdeps/unix/sysv/linux/clock_getcpuclockid.c 2004-10-21 11:05:11.327173192 -0700
@@ -0,0 +1,46 @@
+
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+#include <kernel-features.h>
+
+int
+clock_getcpuclockid (pid_t pid, clockid_t *clock_id)
+{
+ if (pid != 0 && pid != getpid ())
+#ifdef __ASSUME_POSIX_TIMERS
+ *clock_id = -pid;
+ return 0;
+#else
+/* We don't allow any process ID but our own. */
+ return EPERM;
+#endif
+
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+ /* Store the number. */
+ *clock_id = CLOCK_PROCESS_CPUTIME_ID;
+
+ return 0;
+#else
+ /* We don't have a timer for that. */
+ return ENOENT;
+#endif
+}
Index: libc/sysdeps/posix/clock_getres.c
===================================================================
--- libc.orig/sysdeps/posix/clock_getres.c 2004-09-28 15:22:02.032998712 -0700
+++ libc/sysdeps/posix/clock_getres.c 2004-10-21 11:05:11.329172888 -0700
@@ -23,13 +23,6 @@
#include <sys/param.h>
#include <libc-internal.h>

-
-#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
-/* Clock frequency of the processor. */
-static long int nsec;
-#endif
-
-
/* Get resolution of clock. */
int
clock_getres (clockid_t clock_id, struct timespec *res)
@@ -65,44 +58,15 @@
#endif /* handled REALTIME */

default:
-#if HP_TIMING_AVAIL
- if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
- != CLOCK_THREAD_CPUTIME_ID)
-#endif
- {
+#ifdef SYSDEP_DEFAULT_GETRES
+ SYSDEP_DEFAULT_GETRES;
+#else
+ {
__set_errno (EINVAL);
break;
}
-
-#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
- /* FALLTHROUGH. */
- case CLOCK_PROCESS_CPUTIME_ID:
- {
- if (__builtin_expect (nsec == 0, 0))
- {
- hp_timing_t freq;
-
- /* This can only happen if we haven't initialized the `freq'
- variable yet. Do this now. We don't have to protect this
- code against multiple execution since all of them should
- lead to the same result. */
- freq = __get_clockfreq ();
- if (__builtin_expect (freq == 0, 0))
- /* Something went wrong. */
- break;
-
- nsec = MAX (UINT64_C (1000000000) / freq, 1);
- }
-
- /* File in the values. The seconds are always zero (unless we
- have a 1Hz machine). */
- res->tv_sec = 0;
- res->tv_nsec = nsec;
-
- retval = 0;
- }
- break;
#endif
+
}

return retval;
Index: libc/sysdeps/unix/clock_settime.c
===================================================================
--- libc.orig/sysdeps/unix/clock_settime.c 2004-10-01 10:26:04.247203024 -0700
+++ libc/sysdeps/unix/clock_settime.c 2004-10-21 11:05:11.331172584 -0700
@@ -22,20 +22,6 @@
#include <libc-internal.h>
#include <ldsodefs.h>

-
-#if HP_TIMING_AVAIL
-/* Clock frequency of the processor. We make it a 64-bit variable
- because some jokers are already playing with processors with more
- than 4GHz. */
-static hp_timing_t freq;
-
-
-/* This function is defined in the thread library. */
-extern void __pthread_clock_settime (clockid_t clock_id, hp_timing_t offset)
- __attribute__ ((__weak__));
-#endif
-
-
/* Set CLOCK to value TP. */
int
clock_settime (clockid_t clock_id, const struct timespec *tp)
@@ -70,56 +56,16 @@
#endif

default:
-#if HP_TIMING_AVAIL
- if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
- != CLOCK_THREAD_CPUTIME_ID)
-#endif
+#ifdef SYSDEP_DEFAULT_SETTIME
+ SYSDEP_DEFAULT_SETTIME;
+#else
{
__set_errno (EINVAL);
retval = -1;
break;
}

-#if HP_TIMING_AVAIL
- /* FALLTHROUGH. */
- case CLOCK_PROCESS_CPUTIME_ID:
- {
- hp_timing_t tsc;
- hp_timing_t usertime;
-
- /* First thing is to get the current time. */
- HP_TIMING_NOW (tsc);
-
- if (__builtin_expect (freq == 0, 0))
- {
- /* This can only happen if we haven't initialized the `freq'
- variable yet. Do this now. We don't have to protect this
- code against multiple execution since all of them should
- lead to the same result. */
- freq = __get_clockfreq ();
- if (__builtin_expect (freq == 0, 0))
- {
- /* Something went wrong. */
- retval = -1;
- break;
- }
- }
-
- /* Convert the user-provided time into CPU ticks. */
- usertime = tp->tv_sec * freq + (tp->tv_nsec * freq) / 1000000000ull;
-
- /* Determine the offset and use it as the new base value. */
- if (clock_id == CLOCK_PROCESS_CPUTIME_ID
- || __pthread_clock_settime == NULL)
- GL(dl_cpuclock_offset) = tsc - usertime;
- else
- __pthread_clock_settime (clock_id, tsc - usertime);
-
- retval = 0;
- }
- break;
#endif
}
-
return retval;
}
Index: libc/sysdeps/unix/sysv/linux/kernel-features.h
===================================================================
--- libc.orig/sysdeps/unix/sysv/linux/kernel-features.h 2004-09-23 16:40:16.491315016 -0700
+++ libc/sysdeps/unix/sysv/linux/kernel-features.h 2004-10-21 11:05:11.333172280 -0700
@@ -419,3 +419,11 @@
#if __LINUX_KERNEL_VERSION >= 0x020609 && defined __alpha__
#define __ASSUME_IEEE_RAISE_EXCEPTION 1
#endif
+
+/* Starting with version 2.6.9, CLOCK_PROCESS/THREAD_CPUTIME_ID are supported
+ * with clock_gettime and also negative clockids to access other processes clocks
+ */
+
+#if __LINUX_KERNEL_VERSION >= 0x020609
+#define __ASSUME_POSIX_IMPROVED 1
+#endif
Index: libc/linuxthreads/sysdeps/pthread/getcpuclockid.c
===================================================================
--- libc.orig/linuxthreads/sysdeps/pthread/getcpuclockid.c 2004-07-12 09:16:56.800919000 -0700
+++ libc/linuxthreads/sysdeps/pthread/getcpuclockid.c 2004-10-21 11:05:11.334172128 -0700
@@ -21,25 +21,14 @@
#include <sys/time.h>
#include <time.h>
#include <internals.h>
+#include <linux/threads.h>

int
pthread_getcpuclockid (pthread_t thread_id, clockid_t *clock_id)
{
#ifdef CLOCK_THREAD_CPUTIME_ID
- /* We need to store the thread ID in the CLOCKID variable together
- with a number identifying the clock. We reserve the low 3 bits
- for the clock ID and the rest for the thread ID. This is
- problematic if the thread ID is too large. But 29 bits should be
- fine.
-
- If some day more clock IDs are needed the ID part can be
- enlarged. The IDs are entirely internal. */
- if (2 * PTHREAD_THREADS_MAX
- >= 1 << (8 * sizeof (*clock_id) - CLOCK_IDFIELD_SIZE))
- return ERANGE;
-
/* Store the number. */
- *clock_id = CLOCK_THREAD_CPUTIME_ID | (thread_id << CLOCK_IDFIELD_SIZE);
+ *clock_id = - (thread_id + PID_MAX_LIMIT);

return 0;
#else
Index: libc/sysdeps/unix/sysv/linux/clock_gettime.c
===================================================================
--- libc.orig/sysdeps/unix/sysv/linux/clock_gettime.c 2004-09-28 15:22:02.359949008 -0700
+++ libc/sysdeps/unix/sysv/linux/clock_gettime.c 2004-10-21 11:05:11.336171824 -0700
@@ -20,24 +20,16 @@

#include "kernel-features.h"

-
#ifdef __ASSUME_POSIX_TIMERS
-/* This means the REALTIME and MONOTONIC clock are definitely
- supported in the kernel. */
-# define SYSDEP_GETTIME \
- case CLOCK_REALTIME: \
- case CLOCK_MONOTONIC: \
- retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \
- break
+#define SYSDEP_DEFAULT_GETTIME retval = INLINE_SYSCALL(clock_gettime, 2, clock_id, tp)
+
#elif defined __NR_clock_gettime
/* Is the syscall known to exist? */
int __libc_missing_posix_timers attribute_hidden;

/* The REALTIME and MONOTONIC clock might be available. Try the
syscall first. */
-# define SYSDEP_GETTIME \
- case CLOCK_REALTIME: \
- case CLOCK_MONOTONIC: \
+# define SYSDEP_DEFAULT_GETTIME \
{ \
int e = EINVAL; \
\
@@ -64,8 +56,7 @@
HANDLE_REALTIME; \
else \
__set_errno (e); \
- } \
- break
+ }
#endif

#ifdef __NR_clock_gettime
@@ -74,3 +65,4 @@
#endif

#include <sysdeps/unix/clock_gettime.c>
+