Discussion:
[time] add support for CLOCK_THREAD_CPUTIME_ID and CLOCK_PROCESS_CPUTIME_ID
(too old to reply)
Christoph Lameter
2004-09-24 12:30:08 UTC
Permalink
Hmm .... some further refinement to properly handle the process clock. The
new thread groups make that possible ...

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-24 05:07:42.000000000 -0700
@@ -133,18 +133,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 +154,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 +190,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 +212,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 +228,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 +1231,18 @@
return -EINVAL;
}

+int do_posix_clock_thread_gettime(struct timespec *tp)
+{
+ jiffies_to_timespec(get_jiffies_64()-current->start_time, tp);
+ return 0;
+}
+
+int do_posix_clock_process_gettime(struct timespec *tp)
+{
+ jiffies_to_timespec(get_jiffies_64()-current->group_leader->start_time, 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 ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Ulrich Drepper
2004-09-25 04:30:09 UTC
Permalink
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Post by Christoph Lameter
+int do_posix_clock_thread_gettime(struct timespec *tp)
+{
+ jiffies_to_timespec(get_jiffies_64()-current->start_time, tp);
+ return 0;
+}
+
+int do_posix_clock_process_gettime(struct timespec *tp)
+{
+ jiffies_to_timespec(get_jiffies_64()-current->group_leader->start_time, tp);
+ return 0;
+}
+
This is pretty useless. Why would you need kernel support for this, it
just measures realtime.

We have an implementation of the CPU time in glibc which can easily be
changed to support clocks of this precision if there are no usable
timestamp counters (which is what is currently used).

And all this is not really what was really meant by "CPU time" in the
POSIX spec. We hijacked this symbol, maybe incorrectly so. What is
really meant is how much time a process/thread actually _uses_ the CPU
(hence the name). I.e., the information contained in struct rusage.

For this I would love to get kernel support and we hopefully have soon a
patch for this.

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

iD8DBQFBVPNJ2ijCOnn/RHQRAjXeAJ0dUlvRmh6eDJLD6BtmjI3CNWC7pQCfZvAG
wSJclC6wagAwrYqL7/rdpVs=
=SLxp
-----END PGP SIGNATURE-----
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-09-25 05:30:09 UTC
Permalink
Post by Ulrich Drepper
This is pretty useless. Why would you need kernel support for this, it
just measures realtime.
Glibc cannot do that reliably on an SMP system with its HP_TIMING
technique. Even systems with "synchronized" CPU timers typically have an
offset between the timers of different CPUs.
Post by Ulrich Drepper
We have an implementation of the CPU time in glibc which can easily be
changed to support clocks of this precision if there are no usable
timestamp counters (which is what is currently used).
Sorry it cannot be easily changed as I have repeatedly experienced.
I have posted lots of patches to address that issue for SMP systems which
were all rejected and you got insulted by my attempt to discuss the
problem and insisted that it was "solved".
Post by Ulrich Drepper
And all this is not really what was really meant by "CPU time" in the
POSIX spec. We hijacked this symbol, maybe incorrectly so. What is
really meant is how much time a process/thread actually _uses_ the CPU
(hence the name). I.e., the information contained in struct rusage.
For this I would love to get kernel support and we hopefully have soon a
patch for this.
Yes this may be easily addressed in the kernel. clock_gettime belongs
completely into the kernel. Could we get glibc to no longer handle clocks
on its own? The glibc code has always been horribly broken on SMP systems
and I fear that lots of software now assumes that CLOCK_PROCESS_CPUTIME_ID
gets you the runtime of the current process. The patch would allow this
software to run reliably on an SMP system.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-09-25 06:00:13 UTC
Permalink
Post by Ulrich Drepper
For this I would love to get kernel support and we hopefully have soon a
patch for this.
Then please sign off on the following patch:

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-24 22:51:51.000000000 -0700
@@ -133,18 +133,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 +154,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 +190,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 +212,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 +228,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 +1231,19 @@
return -EINVAL;
}

+int do_posix_clock_thread_gettime(struct timespec *tp)
+{
+ jiffies_to_timespec(current->signal->cutime + current->signal->cstime, tp);
+ return 0;
+}
+
+int do_posix_clock_process_gettime(struct timespec *tp)
+{
+ jiffies_to_timespec(current->group_leader->signal->cutime +
+ current->group_leader->signal->cstime, 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 ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Ulrich Drepper
2004-09-25 06:20:04 UTC
Permalink
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Sorry, I fail to see the point. The CPUTIME stuff will either way be
entire implemented at userlevel. If we use TSC, we compute the
resolution from the CPU clock speed (no need to comment, I know it's not
reliable everywhere). If we fall back on realtime, we will simply in
glibc map

clock_getres (CLOCK_PROCESS_CPUTIME_ID, &ts)

to

clock_getres (CLOCK_REALTIME, &ts)

The kernel knows nothing about this clock.

The comment changes are OK, of course.

If there is more to change this is in glibc. So far I have not heard of
anybody wanting to use the clocks this way. This is why we do not have
the fallback to realtime implemented. If you say you need it I have no
problem adding appropriate patches.

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

iD8DBQFBVQt32ijCOnn/RHQRAsWHAJ9q1Aztzf7/6TYQbu6X+DNQhFFW5wCfTP57
wbjQQe+iV/s1ODANFFYK+zs=
=JVgJ
-----END PGP SIGNATURE-----
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-09-25 15:00:15 UTC
Permalink
Post by Ulrich Drepper
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Sorry, I fail to see the point. The CPUTIME stuff will either way be
entire implemented at userlevel. If we use TSC, we compute the
resolution from the CPU clock speed (no need to comment, I know it's not
reliable everywhere). If we fall back on realtime, we will simply in
glibc map
I thought I heard you asking for CPUTIME returning the actual cputime
used in the last message. I have proposed falling back to realtime in the
past but that was not acceptable.
Post by Ulrich Drepper
clock_getres (CLOCK_PROCESS_CPUTIME_ID, &ts)
to
clock_getres (CLOCK_REALTIME, &ts)
The kernel knows nothing about this clock.
Yes and glibc will have to get through contortions to
simulate a clock that returns the actual cpu time used. Why not cleanly
do the clock_gettime syscall without doing any redirection of clocks?

Any implementation of the CPUTIME clocks is always easier to do in the
kernel with just a few lines.
Post by Ulrich Drepper
The comment changes are OK, of course.
If there is more to change this is in glibc. So far I have not heard of
anybody wanting to use the clocks this way. This is why we do not have
the fallback to realtime implemented. If you say you need it I have no
problem adding appropriate patches.
Ok, I will dig out my old patch and repost it to glibc-alpha.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Ulrich Drepper
2004-09-25 15:30:13 UTC
Permalink
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Post by Christoph Lameter
Yes and glibc will have to get through contortions to
simulate a clock that returns the actual cpu time used. Why not cleanly
do the clock_gettime syscall without doing any redirection of clocks?
First of all, unnecessary kernel code where it is not needed. And
second, because with the definition of the CPUTIME clock in use for many
years now not all variants can be handled in the kernel. We use this
clock to provide access to the TSC functionality. This is nothing the
kernel does.
Post by Christoph Lameter
Any implementation of the CPUTIME clocks is always easier to do in the
kernel with just a few lines.
No, you don't know the glibc side.
Post by Christoph Lameter
Ok, I will dig out my old patch and repost it to glibc-alpha.
I haven't gotten an answer to the question "is there really any value in
this kind of clock?".

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

iD8DBQFBVYxt2ijCOnn/RHQRAmohAKCVAlRAxIHBi5uHqoKtfjfORQQNiACdHPuD
aCn2+pHl7MnBmWE2CAmSdb8=
=vJAO
-----END PGP SIGNATURE-----
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-09-27 15:10:09 UTC
Permalink
Post by Ulrich Drepper
Post by Christoph Lameter
Yes and glibc will have to get through contortions to
simulate a clock that returns the actual cpu time used. Why not cleanly
do the clock_gettime syscall without doing any redirection of clocks?
First of all, unnecessary kernel code where it is not needed. And
second, because with the definition of the CPUTIME clock in use for many
years now not all variants can be handled in the kernel. We use this
clock to provide access to the TSC functionality. This is nothing the
kernel does.
The kernel can do the same now in a much more reliable way since it can
produce time with nanosecond accuracy.
Post by Ulrich Drepper
Post by Christoph Lameter
Any implementation of the CPUTIME clocks is always easier to do in the
kernel with just a few lines.
No, you don't know the glibc side.
Yes, I do know that in detail. I have proposed numerous patches for this
issue to glibc-alpha.
Post by Ulrich Drepper
Post by Christoph Lameter
Ok, I will dig out my old patch and repost it to glibc-alpha.
I haven't gotten an answer to the question "is there really any value in
this kind of clock?".
My old patches implement what you suggested: fallback to CLOCK_REALTIME in
glibc if the cputimer is not reliable.

I do not really understand your question. The CLOCK_PROCESS_CPUTIME_ID is
a clock mandated by the POSIX standard and it should work reliably. There
is no question that this clock must be provided.

I do not care how it is done as long as it always works reliably. It is IMHO
the best solution to put that into the kernel since glibc does not really
have all the information available to provide this clock (f.e. the
information obtained via TSC is not adjusted properly since the kernel
time adjustments will not be applied to it) but I will respect your
preferred way to solving this issue.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-09-27 15:40:32 UTC
Permalink
Post by Ulrich Drepper
Sorry, I fail to see the point. The CPUTIME stuff will either way be
entire implemented at userlevel. If we use TSC, we compute the
resolution from the CPU clock speed (no need to comment, I know it's not
reliable everywhere). If we fall back on realtime, we will simply in
glibc map
clock_getres (CLOCK_PROCESS_CPUTIME_ID, &ts)
to
clock_getres (CLOCK_REALTIME, &ts)
The kernel knows nothing about this clock.
Ok here is the patch that makes CLOCK_PROCESS_CPUTIME_ID etc fall back to
CLOCK_REALTIME. This IMHO still not a good solution:

1. It directly returns CLOCK_REALTIME. It should deduct time value at
startup. This could be done with some work. The kernel solution would need
no modification for since it always knows the start time of a process
and glibc could drop figuring out a timestamp or time at startup.

2. It only falls back if there is an indication that the cpu counters
are not synchronized. There is no testing of any counter offsets in glibc.
Again the kernel is aware of these offsets, glibc naively assumes that the
counters are in sync and has no means of obtained the information at all.

3. If the cpu counter is used then no time corrections are applied. If
CLOCK_PROCESS_CPUTIME_ID is to return a real time value (in violation
of POSIX AFAIK) then maybe it should return correct time?

4. SMP systems may have processors with different speeds. The cpu timer
(TSC or ITC) may suddenly encounter a cpu timer running at different
speeds if a process is moved to a different cpu. Glibc cannot handle that
situation.

5. Systems may reduce the clock speed and therefore vary the speed of the
CPU counter. Glibc has no awareness of this.

Glibc should not use cpu timers in any way to return time information to
the currently running process. Glibc is not the operating system and does
not have the proper information available to provide time information.
IMHO both clocks CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID must
be handled by the kernel.

Applying the following patch to glibc would at least alleviate the worst
problem of clock_gettime(CLOCK_PROCESS_CPUTIME_ID) returning bogus values
on systems with unsynchronized cpu timers by falling back to
CLOCK_REALTIME.

Index: libc/sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c
===================================================================
--- libc.orig/sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c 2003-12-11 12:46:01.000000000 -0800
+++ libc/sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c 2004-06-15 12:12:34.000000000 -0700
@@ -31,10 +31,10 @@
if (pid != 0 && pid != getpid ())
return EPERM;

- static int itc_usable;
+ extern int hp_reliable;
int retval = ENOENT;

- if (__builtin_expect (itc_usable == 0, 0))
+ if (__builtin_expect (hp_reliable == 0, 0))
{
int newval = 1;
int fd = open ("/proc/sal/itc_drift", O_RDONLY);
@@ -51,10 +51,10 @@
close (fd);
}

- itc_usable = newval;
+ hp_reliable = newval;
}

- if (itc_usable > 0)
+ if (hp_reliable > 0)
{
/* Store the number. */
*clock_id = CLOCK_PROCESS_CPUTIME_ID;
Index: libc/sysdeps/unix/clock_gettime.c
===================================================================
--- libc.orig/sysdeps/unix/clock_gettime.c 2003-06-24 16:58:29.000000000 -0700
+++ libc/sysdeps/unix/clock_gettime.c 2004-06-15 12:11:52.000000000 -0700
@@ -29,7 +29,7 @@
because some jokers are already playing with processors with more
than 4GHz. */
static hp_timing_t freq;
-
+int hp_reliable;

/* This function is defined in the thread library. */
extern int __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
@@ -78,7 +78,15 @@
#if HP_TIMING_AVAIL
/* FALLTHROUGH. */
case CLOCK_PROCESS_CPUTIME_ID:
- {
+ /* If HP timing reliability has not been determined yet then do so now */
+ if (hp_reliable==0)
+ {
+ if (clock_getcpuclockid()==ENOENT)
+ hp_reliable=-1;
+ else
+ hp_reliable=1;
+ }
+ if (hp_reliable>0) {
hp_timing_t tsc;

if (__builtin_expect (freq == 0, 0))
@@ -115,6 +123,9 @@

retval = 0;
}
+ else
+ _set_errno(ENOENT);
+
break;
#endif
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-09-27 21:10:13 UTC
Permalink
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)
{
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
George Anzinger
2004-09-27 23:00:24 UTC
Permalink
Uh, do you have a test program to verify these? I would like to add it to the
support package on sourceforge.

George
Post by Christoph Lameter
Attached follows a patch to implement the POSIX clocks according to the
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
Post by Christoph Lameter
#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;
}
+/*
+ *
+ * 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;
+}
+
+/*
+ *
+ * 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
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
--
George Anzinger ***@mvista.com
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Ulrich Drepper
2004-09-28 19:30:15 UTC
Permalink
-----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-----
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-09-28 19:40:06 UTC
Permalink
Could you forward the messages to him?
Post by Ulrich Drepper
-----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-----
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-09-29 03:30:10 UTC
Permalink
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:

***@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)
{
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
George Anzinger
2004-09-29 17:50:19 UTC
Permalink
Post by Christoph Lameter
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).
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 ***@mvista.com
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-09-29 18:20:18 UTC
Permalink
Post by George Anzinger
Post by Christoph Lameter
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.
Post by George Anzinger
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.
Post by George Anzinger
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();

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
George Anzinger
2004-09-29 19:40:06 UTC
Permalink
Post by Christoph Lameter
Post by George Anzinger
Post by Christoph Lameter
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.
Post by Christoph Lameter
Post by George Anzinger
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.
Post by Christoph Lameter
Post by George Anzinger
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.
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.
Post by Christoph Lameter
--- 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 ***@mvista.com
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-09-29 19:50:11 UTC
Permalink
Post by George Anzinger
Post by Christoph Lameter
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.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Jesper Juhl
2004-09-29 19:50:14 UTC
Permalink
Unrelated to the CLOCK_PROCESS/THREAD_CPUTIME_ID discussion, just wanted
to comment on the 'patches inline vs attached' bit.
Post by George Anzinger
Post by Christoph Lameter
Post by George Anzinger
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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
George Anzinger
2004-09-30 00:20:05 UTC
Permalink
Post by Jesper Juhl
Unrelated to the CLOCK_PROCESS/THREAD_CPUTIME_ID discussion, just wanted
to comment on the 'patches inline vs attached' bit.
Post by George Anzinger
Post by Christoph Lameter
Post by George Anzinger
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?
Post by Jesper Juhl
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 ***@mvista.com
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Paul Jackson
2004-09-30 03:30:17 UTC
Permalink
Post by George Anzinger
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 <***@sgi.com> 1.650.933.1373
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Andrew Morton
2004-10-01 05:40:07 UTC
Permalink
Post by George Anzinger
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 ***@mozilla.org. 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.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Alan Cox
2004-10-01 13:40:09 UTC
Permalink
Post by Andrew Morton
Post by George Anzinger
Guild lines on how to insure this are welcome.
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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Paul Fulghum
2004-10-01 13:50:13 UTC
Permalink
Post by Alan Cox
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
***@microgate.com

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Lee Revell
2004-10-01 20:00:20 UTC
Permalink
Post by Paul Fulghum
Post by Alan Cox
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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
George Anzinger
2004-10-01 22:30:06 UTC
Permalink
Post by Alan Cox
Post by Andrew Morton
Post by George Anzinger
Guild lines on how to insure this are welcome.
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
Post by Alan Cox
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
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
--
George Anzinger ***@mvista.com
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Olaf Dietsche
2004-10-02 16:00:16 UTC
Permalink
Post by George Anzinger
Post by Alan Cox
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" "?
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>

See:
2.1 The Inline Disposition Type
and
3. Examples

Regards, Olaf.
Alan Cox
2004-10-02 16:40:10 UTC
Permalink
Post by Olaf Dietsche
"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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
George Anzinger
2004-10-03 21:40:08 UTC
Permalink
Post by Alan Cox
Post by Olaf Dietsche
"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 ***@mvista.com
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Jim Nelson
2004-10-04 03:10:07 UTC
Permalink
Post by George Anzinger
Post by Alan Cox
Post by Olaf Dietsche
"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... :)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Guennadi Liakhovetski
2004-10-03 22:40:07 UTC
Permalink
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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Jesper Juhl
2004-10-03 23:20:06 UTC
Permalink
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


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Paul Jackson
2004-10-04 06:30:12 UTC
Permalink
Post by Guennadi Liakhovetski
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,
Post by Guennadi Liakhovetski
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 <***@sgi.com> 1.650.933.1373
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Guennadi Liakhovetski
2004-10-04 19:50:06 UTC
Permalink
Post by Paul Jackson
Post by Guennadi Liakhovetski
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,
Post by Guennadi Liakhovetski
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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Ulrich Windl
2004-10-04 07:40:04 UTC
Permalink
Better show how the mail really looks like (source). The let's see whether it's a
decoding or encoding error.

Ulrich
Post by Guennadi Liakhovetski
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
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Jesper Juhl
2004-10-01 09:20:04 UTC
Permalink
Date: Wed, 29 Sep 2004 17:14:38 -0700
Subject: Re: patches inline in mail
Unrelated to the CLOCK_PROCESS/THREAD_CPUTIME_ID discussion, just wanted to
comment on the 'patches inline vs attached' bit.
Post by George Anzinger
Post by Christoph Lameter
Post by George Anzinger
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


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-01 20:10:08 UTC
Permalink
Signed-off-by: Christoph Lameter <***@sgi.com>

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");
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-01 20:20:06 UTC
Permalink
The following patch makes glibc not provide the above clocks and use the
kernel clocks instead if either of the following condition is met:

1. __ASSUME_POSIX_TIMERS is set

2. A call to probe the posix function is made if the corresponding
__NR_clock_* is defined. If the call is successful then the kernel clocks
will be used. Otherwise glibc will fall back to its own implementation of
the clocks.

The clock_gettime clock_settime and clock_res calls will use the corresponding
system calls for other clocks than CLOCK_REALTIME, CLOCK_MONOTONIC,
CLOCK_THREAD_CPUTIME_ID and CLOCK_PROCESS_CPUTIME_ID.

Patch needs some additional testing....

Signed-off-by: Christoph Lameter <***@sgi.com>

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-01 08:57:51.025894976 -0700
@@ -16,61 +16,174 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */

+#include <errno.h>
+#include <stdint.h>
+#include <time.h>
+#include <sys/time.h>
+#include <libc-internal.h>
#include <sysdep.h>
+#include <ldsodefs.h>

#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
-#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: \
- { \
- int e = EINVAL; \
- \
- if (!__libc_missing_posix_timers) \
- { \
- INTERNAL_SYSCALL_DECL (err); \
- int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp); \
- if (!INTERNAL_SYSCALL_ERROR_P (r, err)) \
- { \
- retval = 0; \
- break; \
- } \
- \
- e = INTERNAL_SYSCALL_ERRNO (r, err); \
- if (e == ENOSYS) \
- { \
- __libc_missing_posix_timers = 1; \
- e = EINVAL; \
- } \
- } \
- \
- /* Fallback code. */ \
- if (e == EINVAL && clock_id == CLOCK_REALTIME) \
- HANDLE_REALTIME; \
- else \
- __set_errno (e); \
- } \
- break
+/* This means all clocks are definitely supported in the kernel. */
+int
+clock_gettime (clockid_t clock_id, struct timespec *tp)
+{
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ return 0;
+ return -1;
+}
+
+#else
+
+/*
+ * Need to deal with multiple complex fallback and legacy scenarios
+ *
+ * Give priority to the clock_gettime syscall but fall back if
+ * certain clocks are not available
+ * for CLOCK_REALTIME fall back to gettimeofday
+ * for CLOCK_PROCESS_CPUTIME_ID fall back to HP_TIMING
+ * for CLOCK_THREAD_CPUTIME_ID fall back to pthreads
+ */
+
+int __libc_missing_posix_stdtimers attribute_hidden;
+int __libc_missing_posix_cputimers attribute_hidden;
+
+int
+clock_gettime (clockid_t clock_id, struct timespec *tp)
+{
+ int retval = -1;
+
+ switch (clock_id)
+ {
+#if defined __NR_clock_gettime
+ case CLOCK_REALTIME: case CLOCK_MONOTONIC:
+ {
+ int e = EINVAL;
+
+ if (!__libc_missing_posix_stdtimers)
+ {
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ {
+ retval = 0;
+ break;
+ }
+
+ e = INTERNAL_SYSCALL_ERRNO (r, err);
+ if (e == ENOSYS)
+ {
+ __libc_missing_posix_stdtimers = 1;
+ e = EINVAL;
+ }
+ }
+
+ /* Fallback code. */
+ if (e != EINVAL || clock_id != CLOCK_REALTIME)
+ {
+ __set_errno (e);
+ break;
+ }
+ }
+ /* Fall through */
+#else
+ case CLOCK_REALTIME:
#endif
+ struct timeval tv;
+ retval = gettimeofday (&tv, NULL);
+ if (retval == 0)
+ /* Convert into `timespec'. */
+ TIMEVAL_TO_TIMESPEC (&tv, tp);
+ break;
+
+ case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID:
+#if defined __NR_clock_gettime
+ if (!__libc_missing_posix_cputimers)
+ {
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ {
+ retval = 0;
+ break;
+ }
+
+ if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS)
+ __libc_missing_posix_cputimers = 1;
+ }
+
+#if HP_TIMING_AVAIL
+ /* Fallback code. */
+ {
+/* 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__));
+
+ 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;
+ }
+#endif
+#endif
+ break;
+
+ default:
+#if defined __NR_clock_gettime
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ retval = 0;
+#else
+ __set_errno(EINVAL);
+#endif
+ }
+ return retval;
+}

-#ifdef __NR_clock_gettime
-/* We handled the REALTIME clock here. */
-# define HANDLED_REALTIME 1
#endif

-#include <sysdeps/unix/clock_gettime.c>
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-01 11:09:40.938405496 -0700
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1999,2000,2001,2002,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
@@ -16,61 +16,160 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */

-#include <sysdep.h>
-
+#include <errno.h>
+#include <time.h>
+#include <sys/time.h>
+#include <libc-internal.h>
+#include <ldsodefs.h>
#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
-#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: \
- { \
- int e = EINVAL; \
- \
- if (!__libc_missing_posix_timers) \
- { \
- INTERNAL_SYSCALL_DECL (err); \
- int r = INTERNAL_SYSCALL (clock_settime, err, 2, clock_id, tp); \
- if (!INTERNAL_SYSCALL_ERROR_P (r, err)) \
- { \
- retval = 0; \
- break; \
- } \
- \
- e = INTERNAL_SYSCALL_ERRNO (r, err); \
- if (e == ENOSYS) \
- { \
- __libc_missing_posix_timers = 1; \
- e = EINVAL; \
- } \
- } \
- \
- /* Fallback code. */ \
- if (e == EINVAL && clock_id == CLOCK_REALTIME) \
- HANDLE_REALTIME; \
- else \
- { \
- __set_errno (e); \
- retval = -1; \
- } \
- } \
- break
+/* This means all clocks are definitely supported in the kernel. */
+int
+clock_settime (clockid_t clock_id, struct timespec *tp)
+{
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_settime, err, 2, clock_id, tp);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ return 0;
+ return -1;
+}
+
+#else
+/*
+ * Need to deal with multiple complex fallback and legacy scenarios
+ *
+ * Give priority to the clock_gettime syscall but fall back if
+ * certain clocks are not available
+ * for CLOCK_REALTIME fall back to gettimeofday
+ * for CLOCK_PROCESS_CPUTIME_ID fall back to HP_TIMING
+ * for CLOCK_THREAD_CPUTIME_ID fall back to pthreads
+ */
+
+int __libc_missing_posix_stdtimers attribute_hidden;
+int __libc_missing_posix_cputimers attribute_hidden;
+
+int
+clock_settime (clockid_t clock_id,const struct timespec *tp)
+{
+ int retval = -1;
+
+ switch (clock_id)
+ {
+#if defined __NR_clock_gettime
+ case CLOCK_REALTIME: case CLOCK_MONOTONIC:
+ {
+ int e = EINVAL;
+
+ if (!__libc_missing_posix_stdtimers)
+ {
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_settime, err, 2, clock_id, tp);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ {
+ retval = 0;
+ break;
+ }
+
+ e = INTERNAL_SYSCALL_ERRNO (r, err);
+ if (e == ENOSYS)
+ {
+ __libc_missing_posix_stdtimers = 1;
+ e = EINVAL;
+ }
+ }
+
+ /* Fallback code. */
+ if (e != EINVAL || clock_id != CLOCK_REALTIME)
+ {
+ __set_errno (e);
+ break;
+ }
+ }
+ /* Fall through */
+#else
+ case CLOCK_REALTIME:
+#endif
+ struct timeval tv;
+ TIMESPEC_TO_TIMEVAL (&tv, tp);
+ retval = settimeofday (&tv, NULL);
+ break;
+
+ case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID:
+#if defined __NR_clock_gettime
+ if (!__libc_missing_posix_cputimers)
+ {
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_settime, err, 2, clock_id, tp);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ {
+ retval = 0;
+ break;
+ }
+
+ if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS)
+ __libc_missing_posix_cputimers = 1;
+ }
+
+#if HP_TIMING_AVAIL
+ /* Fallback code. */
+ {
+/* 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_settime (clockid_t clock_id, hp_timing_t offset)
+ __attribute__ ((__weak__));
+
+ hp_timing_t tsc;
+ hp_timing_t usertime;
+
+ 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;
+ }
+
+ /* Get the current counter. */
+ HP_TIMING_NOW (tsc);
+
+ /* 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;
+ }
+#endif
+#endif
+ break;
+
+ default:
+#if defined __NR_clock_gettime
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ retval = 0;
+#else
+ __set_errno(EINVAL);
#endif
+ }
+ return retval;
+}

-#ifdef __NR_clock_settime
-/* We handled the REALTIME clock here. */
-# define HANDLED_REALTIME 1
#endif

-#include <sysdeps/unix/clock_settime.c>
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-01 12:23:50.099030272 -0700
@@ -16,61 +16,159 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */

+#include <errno.h>
+#include <stdint.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <libc-internal.h>
#include <sysdep.h>
+#include <ldsodefs.h>

#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
-#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: \
- { \
- int e = EINVAL; \
- \
- if (!__libc_missing_posix_timers) \
- { \
- INTERNAL_SYSCALL_DECL (err); \
- int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res); \
- if (!INTERNAL_SYSCALL_ERROR_P (r, err)) \
- { \
- retval = 0; \
- break; \
- } \
- \
- e = INTERNAL_SYSCALL_ERRNO (r, err); \
- if (e == ENOSYS) \
- { \
- __libc_missing_posix_timers = 1; \
- e = EINVAL; \
- } \
- } \
- \
- /* Fallback code. */ \
- if (e == EINVAL && clock_id == CLOCK_REALTIME) \
- HANDLE_REALTIME; \
- else \
- __set_errno (e); \
- } \
- break
+/* This means all clocks are definitely supported in the kernel. */
+int
+clock_getres (clockid_t clock_id, struct timespec *res)
+{
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ return 0;
+ return -1;
+}
+
+#else
+
+/*
+ * Need to deal with multiple complex fallback and legacy scenarios
+ *
+ * Give priority to the clock_gettime syscall but fall back if
+ * certain clocks are not available
+ * for CLOCK_REALTIME fall back to gettimeofday
+ * for CLOCK_PROCESS_CPUTIME_ID fall back to HP_TIMING
+ * for CLOCK_THREAD_CPUTIME_ID fall back to pthreads
+ */
+
+int __libc_missing_posix_stdtimers attribute_hidden;
+int __libc_missing_posix_cputimers attribute_hidden;
+
+int
+clock_getres (clockid_t clock_id, struct timespec *res)
+{
+ int retval = -1;
+
+ switch (clock_id)
+ {
+#if defined __NR_clock_gettime
+ case CLOCK_REALTIME: case CLOCK_MONOTONIC:
+ {
+ int e = EINVAL;
+
+ if (!__libc_missing_posix_stdtimers)
+ {
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ {
+ retval = 0;
+ break;
+ }
+
+ e = INTERNAL_SYSCALL_ERRNO (r, err);
+ if (e == ENOSYS)
+ {
+ __libc_missing_posix_stdtimers = 1;
+ e = EINVAL;
+ }
+ }
+
+ /* Fallback code. */
+ if (e != EINVAL || clock_id != CLOCK_REALTIME)
+ {
+ __set_errno (e);
+ break;
+ }
+ }
+ /* Fall through */
+#else
+ case CLOCK_REALTIME:
#endif
+ {
+ long int clk_tck = sysconf (_SC_CLK_TCK);
+
+ if (__builtin_expect (clk_tck != -1, 1))
+ {
+ /* This implementation assumes that the realtime clock has a
+ resolution higher than 1 second. This is the case for any
+ reasonable implementation. */
+ res->tv_sec = 0;
+ res->tv_nsec = 1000000000 / clk_tck;
+
+ retval = 0;
+ }
+ }
+ break;
+
+ case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID:
+#if defined __NR_clock_gettime
+ if (!__libc_missing_posix_cputimers)
+ {
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ {
+ retval = 0;
+ break;
+ }
+
+ if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS)
+ __libc_missing_posix_cputimers = 1;
+ }
+
+#if HP_TIMING_AVAIL
+ /* Fallback code. */
+ static long int nsec;
+ {
+ 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;
+ }
+#endif
+#endif
+ break;
+
+ default:
+#if defined __NR_clock_gettime
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ retval = 0;
+#else
+ __set_errno(EINVAL);
+#endif
+ }
+ return retval;
+}

-#ifdef __NR_clock_getres
-/* We handled the REALTIME clock here. */
-# define HANDLED_REALTIME 1
#endif

-#include <sysdeps/posix/clock_getres.c>
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Ulrich Drepper
2004-10-02 05:40:06 UTC
Permalink
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Post by Christoph Lameter
The following patch makes glibc not provide the above clocks and use the
Did you ever hear about a concept called binary compatiblity? Don't
bother working on any glibc patch.

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

iD8DBQFBXj1a2ijCOnn/RHQRAh31AJ9rZ5+i5x3LkTwEbeMj2DY/uBzPjwCfeAip
zTYpRJb0lfsR5POro22uViM=
=aUP/
-----END PGP SIGNATURE-----
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-04 15:10:11 UTC
Permalink
Post by Ulrich Drepper
Post by Christoph Lameter
The following patch makes glibc not provide the above clocks and use the
Did you ever hear about a concept called binary compatiblity? Don't
bother working on any glibc patch.
I wonder what this is about?

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-04 16:40:07 UTC
Permalink
Post by Ulrich Drepper
Did you ever hear about a concept called binary compatiblity? Don't
bother working on any glibc patch.
The patch provides complete backwards compatibility if _ASSUME_POSIX_TIMERS is not set.

If _ASSUME_POSIX_TIMERS is set then the patch assumes that this also
indicates that the cpu timers are available. Which would break binary
compatibility. Is that what you are referring to?

Also it seems the patch does not address clock_getcpuclockid() etc. I can
add that.

I had to take the material from sysdeps/unix/clock_* and put it into
sysdeps/unix/sysv/linux/clock_* because otherwise I would have broken all
the other users of sysdeps/unix/clock_*. I need the fallback to the
timer syscalls for clockids unknown to glibc that would have meant a
significant change to the code in sysdeps/unix/clock_*

I would be very grateful if you could indicate to me what fixes are
necessary to make the patch acceptable.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Martijn Sipkema
2004-10-06 13:00:32 UTC
Permalink
Post by Ulrich Drepper
Post by Christoph Lameter
The following patch makes glibc not provide the above clocks and use the
Did you ever hear about a concept called binary compatiblity? Don't
bother working on any glibc patch.
The functionality should arguably not have been added to glibc in the first
place since its implementation was incorrect.

--ms


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-01 20:20:07 UTC
Permalink
Changelog
* Add CLOCK_THREAD_CPUTIME and CLOCK_PROCESS_CPUTIME_ID processing
* Add timer_create override for posix clocks
* Complete implementation of nanosleep overrride for posix clocks
* export posix clock registration in include/linux/posix-timers.h
* Allow up to 16 posix clocks

Signed-off-by: Christoph Lameter <***@sgi.com>

Index: linux-2.6.9-rc3/kernel/posix-timers.c
===================================================================
--- linux-2.6.9-rc3.orig/kernel/posix-timers.c 2004-09-29 20:04:47.000000000 -0700
+++ linux-2.6.9-rc3/kernel/posix-timers.c 2004-10-01 12:48:55.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
@@ -197,8 +193,16 @@
static u64 do_posix_clock_monotonic_gettime_parts(
struct timespec *tp, struct timespec *mo);
int do_posix_clock_monotonic_gettime(struct timespec *tp);
-int do_posix_clock_monotonic_settime(struct timespec *tp);
+static int do_posix_clock_monotonic_settime(struct timespec *tp);
+static int do_posix_clock_process_gettime(struct timespec *tp);
+static int do_posix_clock_process_settime(struct timespec *tp);
+static int do_posix_clock_thread_gettime(struct timespec *tp);
+static int do_posix_clock_thread_settime(struct timespec *tp);
static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);
+int do_posix_clock_notimer_create(int which_clock,
+ struct sigevent __user *time_event_spec,
+ timer_t __user *created_timer_id);
+int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec * t);

static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
{
@@ -218,6 +222,20 @@
.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,
+ .timer_create = do_posix_clock_notimer_create,
+ .nsleep = do_posix_clock_nonanosleep
+ };
+ 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,
+ .timer_create = do_posix_clock_notimer_create,
+ .nsleep = do_posix_clock_nonanosleep
+ };

#ifdef CONFIG_TIME_INTERPOLATION
/* Clocks are more accurate with time interpolators */
@@ -226,6 +244,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);
@@ -577,6 +597,10 @@
!posix_clocks[which_clock].res)
return -EINVAL;

+ if (posix_clocks[which_clock].timer_create)
+ return posix_clocks[which_clock].timer_create(which_clock,
+ timer_event_spec, created_timer_id);
+
new_timer = alloc_posix_timer();
if (unlikely(!new_timer))
return -EAGAIN;
@@ -1222,11 +1246,88 @@
return 0;
}

-int do_posix_clock_monotonic_settime(struct timespec *tp)
+static int do_posix_clock_monotonic_settime(struct timespec *tp)
{
return -EINVAL;
}

+int do_posix_clock_notimer_create(int which_clock,
+ struct sigevent __user *timer_event_spec,
+ timer_t __user *created_timer_id) {
+ return -EINVAL;
+}
+
+int do_posix_clock_nonanosleep(int which_lock, int flags,struct timespec * t) {
+/* Single Unix specficiation says to return ENOTSUP but we do not have that */
+ 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.
+ */
+static int do_posix_clock_thread_gettime(struct timespec *tp)
+{
+ jiffies_to_timespec(current->utime + current->stime
+ + current->thread_clock_offset, tp);
+ return 0;
+}
+
+static int do_posix_clock_thread_settime(struct timespec *tp)
+{
+ current->thread_clock_offset = timespec_to_jiffies(tp)
+ - current->utime - current->stime;
+ 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.
+ */
+
+static unsigned long process_ticks(void) {
+ unsigned long ticks;
+ task_t *t;
+
+ spin_lock(&current->sighand->siglock);
+ /* 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);
+
+ spin_unlock(&current->sighand->siglock);
+ return ticks;
+}
+
+static int do_posix_clock_process_gettime(struct timespec *tp)
+{
+ jiffies_to_timespec(current->signal->process_clock_offset + process_ticks(), tp);
+ return 0;
+}
+
+static int do_posix_clock_process_settime(struct timespec *tp)
+{
+ current->signal->process_clock_offset = timespec_to_jiffies(tp) - process_ticks();
+ return 0;
+}
+
asmlinkage long
sys_clock_settime(clockid_t which_clock, const struct timespec __user *tp)
{
@@ -1413,7 +1514,10 @@
if ((unsigned) t.tv_nsec >= NSEC_PER_SEC || t.tv_sec < 0)
return -EINVAL;

- ret = do_clock_nanosleep(which_clock, flags, &t);
+ if (posix_clocks[which_clock].nsleep)
+ ret = posix_clocks[which_clock].nsleep(which_clock, flags, &t);
+ else
+ ret = do_clock_nanosleep(which_clock, flags, &t);
/*
* Do this here as do_clock_nanosleep does not have the real address
*/
Index: linux-2.6.9-rc3/include/linux/sched.h
===================================================================
--- linux-2.6.9-rc3.orig/include/linux/sched.h 2004-09-29 20:03:54.000000000 -0700
+++ linux-2.6.9-rc3/include/linux/sched.h 2004-10-01 08:40:30.000000000 -0700
@@ -293,6 +293,7 @@

/* POSIX.1b Interval Timers */
struct list_head posix_timers;
+ int process_clock_offset; /* for CLOCK_PROCESS_CPUTIME_ID */

/* job control IDs */
pid_t pgrp;
@@ -509,6 +510,7 @@
unsigned long utime, stime;
unsigned long nvcsw, nivcsw; /* context switch counts */
u64 start_time;
+ int thread_clock_offset; /* offset to thread_clock for CLOCK_THREAD_CPUTIME_ID */
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
unsigned long min_flt, maj_flt;
/* process credentials */
Index: linux-2.6.9-rc3/include/linux/posix-timers.h
===================================================================
--- linux-2.6.9-rc3.orig/include/linux/posix-timers.h 2004-09-29 20:04:46.000000000 -0700
+++ linux-2.6.9-rc3/include/linux/posix-timers.h 2004-10-01 08:40:30.000000000 -0700
@@ -13,9 +13,10 @@
struct k_clock_abs *abs_struct;
int (*clock_set) (struct timespec * tp);
int (*clock_get) (struct timespec * tp);
- int (*nsleep) (int flags,
- struct timespec * new_setting,
- struct itimerspec * old_setting);
+ int (*timer_create) (int which_clock, struct sigevent __user *timer_event_spec,
+ timer_t __user * created_timer_id);
+ int (*nsleep) (int which_clock, int flags,
+ struct timespec * t);
int (*timer_set) (struct k_itimer * timr, int flags,
struct itimerspec * new_setting,
struct itimerspec * old_setting);
@@ -23,6 +24,16 @@
void (*timer_get) (struct k_itimer * timr,
struct itimerspec * cur_setting);
};
+
+void register_posix_clock(int clock_id, struct k_clock *new_clock);
+
+/* Error handlers for timer_create and nanosleep */
+int do_posix_clock_notimer_create(int which_clock,
+ struct sigevent __user *time_event_spec,
+ timer_t __user *created_timer_id);
+
+int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec * t);
+
struct now_struct {
unsigned long jiffies;
};
@@ -42,3 +53,4 @@
} \
}while (0)
#endif
+
Index: linux-2.6.9-rc3/include/linux/time.h
===================================================================
--- linux-2.6.9-rc3.orig/include/linux/time.h 2004-09-29 20:05:18.000000000 -0700
+++ linux-2.6.9-rc3/include/linux/time.h 2004-10-01 08:40:30.000000000 -0700
@@ -413,7 +413,12 @@
#define CLOCK_REALTIME_HR 4
#define CLOCK_MONOTONIC_HR 5

-#define MAX_CLOCKS 6
+/*
+ * The IDs of various hardware clocks
+ */
+
+
+#define MAX_CLOCKS 16
#define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC | \
CLOCK_REALTIME_HR | CLOCK_MONOTONIC_HR)
#define CLOCKS_MONO (CLOCK_MONOTONIC & CLOCK_MONOTONIC_HR)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Andrew Morton
2004-10-01 21:30:13 UTC
Permalink
Post by Christoph Lameter
--- linux-2.6.9-rc3.orig/kernel/posix-timers.c 2004-09-29 20:04:47.000000000 -0700
+++ linux-2.6.9-rc3/kernel/posix-timers.c 2004-10-01 12:48:55.000000000 -0700
...
+int do_posix_clock_notimer_create(int which_clock,
+ struct sigevent __user *time_event_spec,
+ timer_t __user *created_timer_id);
+int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec * t);
These guys are already declared in posix-timers.h.

I'll fix that up, queue the patch up.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-01 20:20:07 UTC
Permalink
Changelog:
* Add CLOCK_SGI_CYCLE provided by drivers/char/mmtimer

Index: linux-2.6.9-rc3/include/linux/time.h
===================================================================
--- linux-2.6.9-rc3.orig/include/linux/time.h 2004-10-01 08:40:30.000000000 -0700
+++ linux-2.6.9-rc3/include/linux/time.h 2004-10-01 09:09:28.000000000 -0700
@@ -416,7 +416,7 @@
/*
* The IDs of various hardware clocks
*/
-
+#define CLOCK_SGI_CYCLE 10

#define MAX_CLOCKS 16
#define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC | \
Index: linux-2.6.9-rc3/drivers/char/mmtimer.c
===================================================================
--- linux-2.6.9-rc3.orig/drivers/char/mmtimer.c 2004-09-29 20:05:19.000000000 -0700
+++ linux-2.6.9-rc3/drivers/char/mmtimer.c 2004-10-01 10:07:11.000000000 -0700
@@ -28,6 +28,7 @@
#include <asm/uaccess.h>
#include <asm/sn/addrs.h>
#include <asm/sn/clksupport.h>
+#include <linux/posix-timers.h>

MODULE_AUTHOR("Jesse Barnes <***@sgi.com>");
MODULE_DESCRIPTION("Multimedia timer support");
@@ -177,6 +178,45 @@
&mmtimer_fops
};

+static struct timespec sgi_clock_offset;
+static int sgi_clock_period;
+
+static int sgi_clock_get(struct timespec *tp) {
+ u64 nsec;
+
+ nsec = readq(RTC_COUNTER_ADDR) * sgi_clock_period
+ + sgi_clock_offset.tv_nsec;
+ tp->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &tp->tv_nsec)
+ + sgi_clock_offset.tv_sec;
+ return 0;
+};
+
+static int sgi_clock_set(struct timespec *tp) {
+
+ u64 nsec;
+ u64 rem;
+
+ nsec = readq(RTC_COUNTER_ADDR) * sgi_clock_period;
+
+ sgi_clock_offset.tv_sec = tp->tv_sec - div_long_long_rem(nsec, NSEC_PER_SEC, &rem);
+
+ if (rem <= tp->tv_nsec)
+ sgi_clock_offset.tv_nsec = tp->tv_sec - rem;
+ else {
+ sgi_clock_offset.tv_nsec = tp->tv_sec + NSEC_PER_SEC - rem;
+ sgi_clock_offset.tv_sec--;
+ }
+ return 0;
+}
+
+static struct k_clock sgi_clock = {
+ .res = 0,
+ .clock_set = sgi_clock_set,
+ .clock_get = sgi_clock_get,
+ .timer_create = do_posix_clock_notimer_create,
+ .nsleep = do_posix_clock_nonanosleep
+};
+
/**
* mmtimer_init - device initialization routine
*
@@ -206,6 +246,9 @@
return -1;
}

+ sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second;
+ register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock);
+
printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION,
sn_rtc_cycles_per_second/(unsigned long)1E6);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-07 05:10:04 UTC
Permalink
Posix compliant cpu clocks: V7 [0/3] Rationale and test program

Signed-off-by: Christoph Lameter <***@sgi.com>

Changes from V5:
* add a simple means of accessing other processes cputimers.
* Simplified glibc patch that makes glibc return errors when
an applications accesses cputimers and is run with glibc under a kernel
not providing cputimers. This may allow the detection of applications that
need to be updated since they depend on the earlier non posix compliant
version of glibc. Also should be more readable since the sections
are no longer moved betweeen directory hierachies.
* remove ability to set process and thread clocks.

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 patch also implements the 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.

Todo:
- The timer API to generate events by a non tick based timer is not
usable in its current state. The posix timer API seems to be only
useful at this point to define clock_get/set. Need to revise this.
- Implement timed interrupts in mmtimer after API is revised.

The patchset consists of the following components:

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

[1/2] 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/2] Glibc patch: Use kernel clocks and also makes glibc able to use any
posix clock provided by the kernel so that posix clocks by driver
may be accessed. Break apps that use the old cputimer based
CLOCK_*_CPUTIME_IDs on kernels that do not support CLOCK_*_CPUTIME_ID.

The mmtimer patch is unchanged from V6 and stays as is in 2.6.9-rc3-mm2.
But I expect to update the driver as soon as the interface to setup hardware
timer interrupts is usable.

Rolands patches:
----------------
This patch is not as comprehensive as Rolands but also not as invasive.
Roland's high resolution time through tsc is a hack but would significantly
improve the statistics we get for a process. However, we may get the same
result in a cleaner way after John Stultz and my plan for revising the
time subsystem is through. This would replace jiffies with nanoseconds
for time keeping throughout the kernel.

Nanosecond accuracy is already available through getnstimeofday() on some
platforms. Some of the functionality in Roland's patch may be implemented in a
TSC independent way using this function.

The use of negative pid values in certain numeric ranges for selecting the
type of clock is something that is also in a simplerr way present in
my patch. I do not like this and would rather see this incorporated in
glibc if the glibc people can come up with a sane implementation.

Single Thread Testing
CLOCK_THREAD_CPUTIME_ID= 0.494140878 resolution= 0.000976563
CLOCK_PROCESS_CPUTIME_ID= 0.494140878 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.495117441ns
1 Cycles=1000000 Thread= 0.140625072ns Process= 2.523438792ns
2 Cycles=2000000 Thread= 0.966797370ns Process= 8.512699671ns
3 Cycles=3000000 Thread= 0.806641038ns Process= 7.561527309ns
4 Cycles=4000000 Thread= 1.865235330ns Process= 12.891608163ns
5 Cycles=5000000 Thread= 1.604493009ns Process= 11.528326215ns
6 Cycles=6000000 Thread= 2.086915131ns Process= 13.500983475ns
7 Cycles=7000000 Thread= 2.245118337ns Process= 13.947272766ns
8 Cycles=8000000 Thread= 1.604493009ns Process= 12.252935961ns
9 Cycles=9000000 Thread= 2.160157356ns Process= 13.977546219ns

Clock status at the end of the timer tests:
Gettimeofday() = 1097084999.489938000
CLOCK_REALTIME= 1097084999.490116229 resolution= 0.000000040
CLOCK_MONOTONIC= 177.071675109 resolution= 0.000000040
CLOCK_PROCESS_CPUTIME_ID= 13.978522782 resolution= 0.000976563
CLOCK_THREAD_CPUTIME_ID= 0.497070567 resolution= 0.000976563
CLOCK_SGI_CYCLE= 229.967982280 resolution= 0.000000040
PROCESS clock of 1 (init)= 4.833986850 resolution= 0.000976563
THREAD clock of 1 (init)= 0.009765630 resolution= 0.000976563



#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");
pr(-1,"PROCESS clock of 1 (init)");
pr(-1 - 4*1024*1024,"THREAD clock of 1 (init)");
printf("\n");
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-12 20:30:16 UTC
Permalink
I ran some test programs and discovered that the periodic timer support
is broken. The timer is triggered once and then never again. Single shot
timers work fine. 2.6.9-rc1 is fine. The first kernel that I tested where
I noticed the breakage was 2.6.9-rc1-bk17. 2.6.9-rc2 and following all
cannot do periodic timer signals.

I looked through the changelog but I cannot see anything that would cause
the problem. Roland's patch surely could not have done this.

Will try to track this down further, time permitting...
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
George Anzinger
2004-10-12 22:30:15 UTC
Permalink
Post by Christoph Lameter
I ran some test programs and discovered that the periodic timer support
is broken. The timer is triggered once and then never again. Single shot
timers work fine. 2.6.9-rc1 is fine. The first kernel that I tested where
I noticed the breakage was 2.6.9-rc1-bk17. 2.6.9-rc2 and following all
cannot do periodic timer signals.
I looked through the changelog but I cannot see anything that would cause
the problem. Roland's patch surely could not have done this.
Will try to track this down further, time permitting...
The most likely thing would be failure to do the call back from the signal
delivery code.
--
George Anzinger ***@mvista.com
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Alexander Nyberg
2004-10-13 18:20:05 UTC
Permalink
Post by Christoph Lameter
I ran some test programs and discovered that the periodic timer support
is broken. The timer is triggered once and then never again. Single shot
timers work fine. 2.6.9-rc1 is fine. The first kernel that I tested where
I noticed the breakage was 2.6.9-rc1-bk17. 2.6.9-rc2 and following all
cannot do periodic timer signals.
I looked through the changelog but I cannot see anything that would cause
the problem. Roland's patch surely could not have done this.
Will try to track this down further, time permitting...
I took a bit of a look at this, and it looks like some things changed
with the introduction of the flexible mmap in 2.6.9-rc1-bk1.

If you run the program below it will work, doing as expected. Now
comment out the the line "memset(&sa, 0, sizeof(struct sigaction));"
and program won't run as expected.

Now do "echo -n 1 > /proc/sys/vm/legacy_va_layout" and run the same
program again (the one with memset commented out).

Turning on signal debugging tells us that with legacy_va_layout=0
"SIG deliver (a.out:415): sp=bffff6c0 pc=08048434 ra=00000000"
where ra is the 8-byte instruction that's supposed to get us back to
sys_sigreturn().

Me thinks someone somewhere is using some of the bits that we
"accidently" pass via sa.sa_flags by not setting it to 0, the regular
flags don't seem to show this behaviour, and I couldn't see any real
checking of the passed value of sa.sa_flags.

---------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>

void sighandler(int signal)
{
printf("hihi\n");
}

int main()
{
struct itimerval timeval;
struct sigaction sa;

memset(&timeval, 0, sizeof(struct timeval));
memset(&sa, 0, sizeof(struct sigaction));

sa.sa_handler = &sighandler;
sigfillset(&sa.sa_mask);

sigaction(SIGALRM, &sa, NULL);

timeval.it_interval.tv_sec = 2;
timeval.it_interval.tv_usec = 0;

timeval.it_value.tv_sec = 2;
timeval.it_value.tv_usec = 0;

if (setitimer(ITIMER_REAL, &timeval, NULL))
printf("Nooo!\n");

for(;;)
;

return 0;
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-13 18:20:09 UTC
Permalink
Post by Alexander Nyberg
Me thinks someone somewhere is using some of the bits that we
"accidently" pass via sa.sa_flags by not setting it to 0, the regular
flags don't seem to show this behaviour, and I couldn't see any real
checking of the passed value of sa.sa_flags.
Nope. It was my screwed up setting of the resolution of CLOCK_REALTIME and
CLOCK_MONOTONIC. Fix was submitted to Linus and Andrew.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-07 05:10:05 UTC
Permalink
Index: linux-2.6.9-rc3/kernel/posix-timers.c
===================================================================
--- linux-2.6.9-rc3.orig/kernel/posix-timers.c 2004-09-29 20:04:47.000000000 -0700
+++ linux-2.6.9-rc3/kernel/posix-timers.c 2004-10-06 10:39:52.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
@@ -192,12 +188,13 @@
#define p_timer_del(clock,a) \
if_clock_do((clock)->timer_del, do_timer_delete, (a))

-void register_posix_clock(int clock_id, struct k_clock *new_clock);
static int do_posix_gettime(struct k_clock *clock, struct timespec *tp);
static u64 do_posix_clock_monotonic_gettime_parts(
struct timespec *tp, struct timespec *mo);
int do_posix_clock_monotonic_gettime(struct timespec *tp);
-int do_posix_clock_monotonic_settime(struct timespec *tp);
+static int do_posix_clock_monotonic_settime(struct timespec *tp);
+static int do_posix_clock_process_gettime(struct timespec *tp);
+static 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)
@@ -216,7 +213,21 @@
struct k_clock clock_monotonic = {.res = CLOCK_REALTIME_RES,
.abs_struct = NULL,
.clock_get = do_posix_clock_monotonic_gettime,
- .clock_set = do_posix_clock_monotonic_settime
+ .clock_set = do_posix_clock_nosettime
+ };
+ struct k_clock clock_thread = {.res = CLOCK_REALTIME_RES,
+ .abs_struct = NULL,
+ .clock_get = do_posix_clock_thread_gettime,
+ .clock_set = do_posix_clock_nosettime,
+ .timer_create = do_posix_clock_notimer_create,
+ .nsleep = do_posix_clock_nonanosleep
+ };
+ struct k_clock clock_process = {.res = CLOCK_REALTIME_RES,
+ .abs_struct = NULL,
+ .clock_get = do_posix_clock_process_gettime,
+ .clock_set = do_posix_clock_nosettime,
+ .timer_create = do_posix_clock_notimer_create,
+ .nsleep = do_posix_clock_nonanosleep
};

#ifdef CONFIG_TIME_INTERPOLATION
@@ -226,6 +237,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);
@@ -577,6 +590,10 @@
!posix_clocks[which_clock].res)
return -EINVAL;

+ if (posix_clocks[which_clock].timer_create)
+ return posix_clocks[which_clock].timer_create(which_clock,
+ timer_event_spec, created_timer_id);
+
new_timer = alloc_posix_timer();
if (unlikely(!new_timer))
return -EAGAIN;
@@ -1222,16 +1239,87 @@
return 0;
}

-int do_posix_clock_monotonic_settime(struct timespec *tp)
+int do_posix_clock_nosettime(struct timespec *tp)
{
return -EINVAL;
}

+int do_posix_clock_notimer_create(int which_clock,
+ struct sigevent __user *timer_event_spec,
+ timer_t __user *created_timer_id) {
+ return -EINVAL;
+}
+
+int do_posix_clock_nonanosleep(int which_lock, int flags,struct timespec * t) {
+/* Single Unix specficiation says to return ENOTSUP but we do not have that */
+ return -EINVAL;
+}
+
+static unsigned long process_ticks(task_t *p) {
+ unsigned long ticks;
+ task_t *t;
+
+ spin_lock(&p->sighand->siglock);
+ /* The signal structure is shared between all threads */
+ ticks = p->signal->utime + p->signal->stime;
+
+ /* Add up the cpu time for all the still running threads of this process */
+ t = p;
+ do {
+ ticks += t->utime + t->stime;
+ t = next_thread(t);
+ } while (t != p);
+
+ spin_unlock(&p->sighand->siglock);
+ return ticks;
+}
+
+static inline unsigned long thread_ticks(task_t *p) {
+ return p->utime + current->stime;
+}
+
+/*
+ * 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.
+ */
+static int do_posix_clock_thread_gettime(struct timespec *tp)
+{
+ jiffies_to_timespec(thread_ticks(current), 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.
+ */
+
+static int do_posix_clock_process_gettime(struct timespec *tp)
+{
+ jiffies_to_timespec(process_ticks(current), tp);
+ return 0;
+}
+
asmlinkage long
sys_clock_settime(clockid_t which_clock, const struct timespec __user *tp)
{
struct timespec new_tp;

+ /* Cannot set process specific clocks */
+ if (which_clock<0)
+ return -EINVAL;
+
if ((unsigned) which_clock >= MAX_CLOCKS ||
!posix_clocks[which_clock].res)
return -EINVAL;
@@ -1249,6 +1337,29 @@
struct timespec rtn_tp;
int error = 0;

+ /* Process process specific clocks */
+ if (which_clock < 0) {
+ task_t *t;
+ int pid = -which_clock;
+
+ if (pid < PID_MAX_LIMIT) {
+ if (t = find_task_by_pid(pid)) {
+ jiffies_to_timespec(process_ticks(t), tp);
+ return 0;
+ }
+ return -EINVAL;
+ }
+ if (pid < 2*PID_MAX_LIMIT) {
+ if (t = find_task_by_pid(pid - PID_MAX_LIMIT)) {
+ jiffies_to_timespec(thread_ticks(t), tp);
+ return 0;
+ }
+ return -EINVAL;
+ }
+ /* More process specific clocks could follow here */
+ return -EINVAL;
+ }
+
if ((unsigned) which_clock >= MAX_CLOCKS ||
!posix_clocks[which_clock].res)
return -EINVAL;
@@ -1267,6 +1378,9 @@
{
struct timespec rtn_tp;

+ /* All process clocks have the resolution of CLOCK_PROCESS_CPUTIME_ID */
+ if (which_clock < 0 ) which_clock = CLOCK_PROCESS_CPUTIME_ID;
+
if ((unsigned) which_clock >= MAX_CLOCKS ||
!posix_clocks[which_clock].res)
return -EINVAL;
@@ -1413,7 +1527,10 @@
if ((unsigned) t.tv_nsec >= NSEC_PER_SEC || t.tv_sec < 0)
return -EINVAL;

- ret = do_clock_nanosleep(which_clock, flags, &t);
+ if (posix_clocks[which_clock].nsleep)
+ ret = posix_clocks[which_clock].nsleep(which_clock, flags, &t);
+ else
+ ret = do_clock_nanosleep(which_clock, flags, &t);
/*
* Do this here as do_clock_nanosleep does not have the real address
*/
Index: linux-2.6.9-rc3/include/linux/posix-timers.h
===================================================================
--- linux-2.6.9-rc3.orig/include/linux/posix-timers.h 2004-09-29 20:04:46.000000000 -0700
+++ linux-2.6.9-rc3/include/linux/posix-timers.h 2004-10-06 10:33:52.000000000 -0700
@@ -13,9 +13,10 @@
struct k_clock_abs *abs_struct;
int (*clock_set) (struct timespec * tp);
int (*clock_get) (struct timespec * tp);
- int (*nsleep) (int flags,
- struct timespec * new_setting,
- struct itimerspec * old_setting);
+ int (*timer_create) (int which_clock, struct sigevent __user *timer_event_spec,
+ timer_t __user * created_timer_id);
+ int (*nsleep) (int which_clock, int flags,
+ struct timespec * t);
int (*timer_set) (struct k_itimer * timr, int flags,
struct itimerspec * new_setting,
struct itimerspec * old_setting);
@@ -23,6 +24,17 @@
void (*timer_get) (struct k_itimer * timr,
struct itimerspec * cur_setting);
};
+
+void register_posix_clock(int clock_id, struct k_clock *new_clock);
+
+/* Error handlers for timer_create, nanosleep and settime */
+int do_posix_clock_notimer_create(int which_clock,
+ struct sigevent __user *time_event_spec,
+ timer_t __user *created_timer_id);
+
+int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec * t);
+int do_posix_clock_nosettime(struct timespec *tp);
+
struct now_struct {
unsigned long jiffies;
};
@@ -42,3 +54,4 @@
} \
}while (0)
#endif
+
Index: linux-2.6.9-rc3/include/linux/time.h
===================================================================
--- linux-2.6.9-rc3.orig/include/linux/time.h 2004-09-29 20:05:18.000000000 -0700
+++ linux-2.6.9-rc3/include/linux/time.h 2004-10-06 10:33:52.000000000 -0700
@@ -413,7 +413,12 @@
#define CLOCK_REALTIME_HR 4
#define CLOCK_MONOTONIC_HR 5

-#define MAX_CLOCKS 6
+/*
+ * The IDs of various hardware clocks
+ */
+
+
+#define MAX_CLOCKS 16
#define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC | \
CLOCK_REALTIME_HR | CLOCK_MONOTONIC_HR)
#define CLOCKS_MONO (CLOCK_MONOTONIC & CLOCK_MONOTONIC_HR)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-07 05:10:06 UTC
Permalink
Posix compliant CLOCK_THREAD_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID

The following patch makes glibc not provide the above clocks. Glibc will
either return an error or use the kernel interface.
This also defines all the posix clock routines in such a way that these
function work as documented by posix. It allows the specification of pids
when invoking clock_getcpuclockid() and pthread_getcpuclockid to obtain
the process or task clock of any process in the system.

Patch is cleaned up so that is does not move sections of code around.

Signed-off-by: Christoph Lameter <***@sgi.com>

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-06 21:13:00.382271104 -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-06 21:19:57.842807456 -0700
@@ -20,24 +20,20 @@

#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 { \
+ INTERNAL_SYSCALL_DECL(err); \
+ retval = INTERNAL_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 +61,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-06 15:34:17.994743608 -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-09-28 15:22:02.595913136 -0700
+++ /dev/null1970-01-01 00:00:00.000000000 +0000
@@ -1,65 +0,0 @@
-/* Copyright (C) 2000, 2001, 2003 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>
-
-
-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;
-
- static int itc_usable;
- int retval = ENOENT;
-
- if (__builtin_expect (itc_usable == 0, 0))
- {
- int newval = 1;
- int fd = open ("/proc/sal/itc_drift", O_RDONLY);
- if (__builtin_expect (fd != -1, 1))
- {
- char buf[16];
- /* We expect the file to contain a single digit followed by
- a newline. If the format changes we better not rely on
- the file content. */
- if (read (fd, buf, sizeof buf) != 2 || buf[0] != '0'
- || buf[1] != '\n')
- newval = -1;
-
- close (fd);
- }
-
- itc_usable = newval;
- }
-
- if (itc_usable > 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-06 21:22:01.041078472 -0700
@@ -20,21 +20,18 @@

#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 { \
+ INTERNAL_SYSCALL_DECL(err); \
+ retval = INTERNAL_SYSCALL(clock_settime, err, 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 +61,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-06 21:33:48.687499864 -0700
@@ -0,0 +1,44 @@
+
+/* 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>
+
+int
+clock_getcpuclockid (pid_t pid, clockid_t *clock_id)
+{
+ if (pid != 0 && pid != getpid ())
+#ifdef __ASSUME_POSIX_TIMERS
+ return -pid;
+#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-06 14:48:30.854372424 -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-06 15:56:49.504282928 -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-06 12:03:27.941843960 -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-06 12:40:44.548828016 -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-06 21:21:03.551818168 -0700
@@ -20,24 +20,19 @@

#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 { \
+ INTERNAL_SYSCALL_DECL(err); \
+ retval = INTERNAL_SYSCALL(clock_gettime, err, 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 +59,7 @@
HANDLE_REALTIME; \
else \
__set_errno (e); \
- } \
- break
+ }
#endif

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

#include <sysdeps/unix/clock_gettime.c>
+
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-22 05:00:09 UTC
Permalink
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 <***@sgi.com>

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>
+

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Roland McGrath
2004-10-01 22:20:08 UTC
Permalink
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
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-01 23:40:07 UTC
Permalink
Post by Roland McGrath
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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Christoph Lameter
2004-10-04 19:00:17 UTC
Permalink
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;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Loading...