summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2005-03-07 18:15:56 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-03-07 18:15:56 -0800
commita78331f2168ef1e67b53a0f8218c70a19f0b2a4c (patch)
treef4eb09ae45b8d6fb1c8b36e3860178beee6416a1 /include
parent8b9cfca63e45badb418550c61397be4c33022752 (diff)
[PATCH] posix-timers: high-resolution CPU clocks for POSIX clock_* syscalls
This patch provides support for thread and process CPU time clocks in the POSIX clock interface. Both the existing utime and utime+stime information (already available via getrusage et al) can be used, as well as a new (potentially) more precise and accurate clock (which cannot distinguish user from system time). The clock used is that provided by the `sched_clock' function already used internally by the scheduler. This gives a way for platforms to provide the highest-resolution CPU time tracking that is available cheaply, and some already do so (such as x86 using TSC). Because this clock is already sampled internally by the scheduler, this new tracking adds only the tiniest new overhead to accomplish the bookkeeping. Some notes: This allows per-thread clocks to be accessed only by other threads in the same process. The only POSIX calls that access these are defined only for in-process use, and having this check is necessary for the userland implementations of the POSIX clock functions to robustly refuse stale clockid_t's in the face of potential PID reuse. This makes no constraint on who can see whose per-process clocks. This information is already available for the VIRT and PROF (i.e. utime and stime) information via /proc. I am open to suggestions on if/how security constraints on who can see whose clocks should be imposed. The SCHED clock information is now available only via clock_* syscalls. This means that per-thread information is not available outside the process. Perhaps /proc should show sched_time as well? This would let ps et al show this more-accurate information. When this code is merged, it will be supported in glibc. I have written the support and added some test programs for glibc, which are what I mainly used to test the new kernel code. You can get those here: http://people.redhat.com/roland/glibc/kernel-cpuclocks.patch Signed-off-by: Roland McGrath <roland@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/posix-timers.h32
-rw-r--r--include/linux/sched.h10
2 files changed, 41 insertions, 1 deletions
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 61f4b12d82c1..a0140c8f72b7 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -4,6 +4,23 @@
#include <linux/spinlock.h>
#include <linux/list.h>
+#define CPUCLOCK_PID(clock) ((pid_t) ~((clock) >> 3))
+#define CPUCLOCK_PERTHREAD(clock) \
+ (((clock) & (clockid_t) CPUCLOCK_PERTHREAD_MASK) != 0)
+#define CPUCLOCK_PID_MASK 7
+#define CPUCLOCK_PERTHREAD_MASK 4
+#define CPUCLOCK_WHICH(clock) ((clock) & (clockid_t) CPUCLOCK_CLOCK_MASK)
+#define CPUCLOCK_CLOCK_MASK 3
+#define CPUCLOCK_PROF 0
+#define CPUCLOCK_VIRT 1
+#define CPUCLOCK_SCHED 2
+#define CPUCLOCK_MAX 3
+
+#define MAKE_PROCESS_CPUCLOCK(pid, clock) \
+ ((~(clockid_t) (pid) << 3) | (clockid_t) (clock))
+#define MAKE_THREAD_CPUCLOCK(tid, clock) \
+ MAKE_PROCESS_CPUCLOCK((tid), (clock) | CPUCLOCK_PERTHREAD_MASK)
+
/* POSIX.1b interval timer structure. */
struct k_itimer {
struct list_head list; /* free/ allocate list */
@@ -72,5 +89,18 @@ struct now_struct {
(timr)->it_overrun += orun; \
} \
}while (0)
-#endif
+int posix_cpu_clock_getres(clockid_t which_clock, struct timespec *);
+int posix_cpu_clock_get(clockid_t which_clock, struct timespec *);
+int posix_cpu_clock_set(clockid_t which_clock, const struct timespec *tp);
+int posix_cpu_timer_create(struct k_itimer *);
+int posix_cpu_nsleep(clockid_t, int, struct timespec *);
+#define posix_cpu_timer_create do_posix_clock_notimer_create
+#define posix_cpu_nsleep do_posix_clock_nonanosleep
+int posix_cpu_timer_set(struct k_itimer *, int,
+ struct itimerspec *, struct itimerspec *);
+int posix_cpu_timer_del(struct k_itimer *);
+void posix_cpu_timer_get(struct k_itimer *, struct itimerspec *);
+
+
+#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index fb151e634c9e..5fff51dc7c32 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -321,6 +321,14 @@ struct signal_struct {
unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
/*
+ * Cumulative ns of scheduled CPU time for dead threads in the
+ * group, not including a zombie group leader. (This only differs
+ * from jiffies_to_ns(utime + stime) if sched_clock uses something
+ * other than jiffies.)
+ */
+ unsigned long long sched_time;
+
+ /*
* We don't bother to synchronize most readers of this at all,
* because there is no reader checking a limit that actually needs
* to get both rlim_cur and rlim_max atomically, and either one
@@ -541,6 +549,7 @@ struct task_struct {
unsigned long sleep_avg;
unsigned long long timestamp, last_ran;
+ unsigned long long sched_time; /* sched_clock time spent running */
int activated;
unsigned long policy;
@@ -776,6 +785,7 @@ static inline int set_cpus_allowed(task_t *p, cpumask_t new_mask)
#endif
extern unsigned long long sched_clock(void);
+extern unsigned long long current_sched_time(const task_t *current_task);
/* sched_exec is called by processes performing an exec */
#ifdef CONFIG_SMP