Skip to content

Commit

Permalink
Add scaled time to taskstats based process accounting
Browse files Browse the repository at this point in the history
This adds items to the taststats struct to account for user and system
time based on scaling the CPU frequency and instruction issue rates.

Adds account_(user|system)_time_scaled callbacks which architectures
can use to account for time using this mechanism.

Signed-off-by: Michael Neuling <[email protected]>
Cc: Balbir Singh <[email protected]>
Cc: Jay Lan <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
mikey authored and Linus Torvalds committed Oct 18, 2007
1 parent 898eb71 commit c66f08b
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 5 deletions.
2 changes: 2 additions & 0 deletions include/linux/kernel_stat.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ static inline int kstat_irqs(int irq)
}

extern void account_user_time(struct task_struct *, cputime_t);
extern void account_user_time_scaled(struct task_struct *, cputime_t);
extern void account_system_time(struct task_struct *, int, cputime_t);
extern void account_system_time_scaled(struct task_struct *, cputime_t);
extern void account_steal_time(struct task_struct *, cputime_t);

#endif /* _LINUX_KERNEL_STAT_H */
2 changes: 1 addition & 1 deletion include/linux/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,7 @@ struct task_struct {
int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */

unsigned int rt_priority;
cputime_t utime, stime;
cputime_t utime, stime, utimescaled, stimescaled;
cputime_t gtime;
unsigned long nvcsw, nivcsw; /* context switch counts */
struct timespec start_time; /* monotonic time */
Expand Down
11 changes: 9 additions & 2 deletions include/linux/taskstats.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
*/


#define TASKSTATS_VERSION 5
#define TASKSTATS_VERSION 6
#define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN
* in linux/sched.h */

Expand Down Expand Up @@ -85,9 +85,12 @@ struct taskstats {
* On some architectures, value will adjust for cpu time stolen
* from the kernel in involuntary waits due to virtualization.
* Value is cumulative, in nanoseconds, without a corresponding count
* and wraps around to zero silently on overflow
* and wraps around to zero silently on overflow. The
* _scaled_ version accounts for cpus which can scale the
* number of instructions executed each cycle.
*/
__u64 cpu_run_real_total;
__u64 cpu_scaled_run_real_total;

/* cpu "virtual" running time
* Uses time intervals seen by the kernel i.e. no adjustment
Expand Down Expand Up @@ -142,6 +145,10 @@ struct taskstats {
__u64 write_char; /* bytes written */
__u64 read_syscalls; /* read syscalls */
__u64 write_syscalls; /* write syscalls */

/* time accounting for SMT machines */
__u64 ac_utimescaled; /* utime scaled on frequency etc */
__u64 ac_stimescaled; /* stime scaled on frequency etc */
/* Extended accounting fields end */

#define TASKSTATS_HAS_IO_ACCOUNTING
Expand Down
6 changes: 6 additions & 0 deletions kernel/delayacct.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
tmp += timespec_to_ns(&ts);
d->cpu_run_real_total = (tmp < (s64)d->cpu_run_real_total) ? 0 : tmp;

tmp = (s64)d->cpu_scaled_run_real_total;
cputime_to_timespec(tsk->utimescaled + tsk->stimescaled, &ts);
tmp += timespec_to_ns(&ts);
d->cpu_scaled_run_real_total =
(tmp < (s64)d->cpu_scaled_run_real_total) ? 0 : tmp;

/*
* No locking available for sched_info (and too expensive to add one)
* Mitigate by taking snapshot of values
Expand Down
2 changes: 2 additions & 0 deletions kernel/fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
p->utime = cputime_zero;
p->stime = cputime_zero;
p->gtime = cputime_zero;
p->utimescaled = cputime_zero;
p->stimescaled = cputime_zero;

#ifdef CONFIG_TASK_XACCT
p->rchar = 0; /* I/O counter: bytes read */
Expand Down
21 changes: 21 additions & 0 deletions kernel/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -3333,6 +3333,16 @@ void account_guest_time(struct task_struct *p, cputime_t cputime)
cpustat->guest = cputime64_add(cpustat->guest, tmp);
}

/*
* Account scaled user cpu time to a process.
* @p: the process that the cpu time gets accounted to
* @cputime: the cpu time spent in user space since the last update
*/
void account_user_time_scaled(struct task_struct *p, cputime_t cputime)
{
p->utimescaled = cputime_add(p->utimescaled, cputime);
}

/*
* Account system cpu time to a process.
* @p: the process that the cpu time gets accounted to
Expand Down Expand Up @@ -3370,6 +3380,17 @@ void account_system_time(struct task_struct *p, int hardirq_offset,
acct_update_integrals(p);
}

/*
* Account scaled system cpu time to a process.
* @p: the process that the cpu time gets accounted to
* @hardirq_offset: the offset to subtract from hardirq_count()
* @cputime: the cpu time spent in kernel space since the last update
*/
void account_system_time_scaled(struct task_struct *p, cputime_t cputime)
{
p->stimescaled = cputime_add(p->stimescaled, cputime);
}

/*
* Account for involuntary wait time.
* @p: the process from which the cpu time has been stolen
Expand Down
7 changes: 5 additions & 2 deletions kernel/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -826,10 +826,13 @@ void update_process_times(int user_tick)
int cpu = smp_processor_id();

/* Note: this timer irq context must be accounted for as well. */
if (user_tick)
if (user_tick) {
account_user_time(p, jiffies_to_cputime(1));
else
account_user_time_scaled(p, jiffies_to_cputime(1));
} else {
account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1));
account_system_time_scaled(p, jiffies_to_cputime(1));
}
run_local_timers();
if (rcu_pending(cpu))
rcu_check_callbacks(cpu, user_tick);
Expand Down
4 changes: 4 additions & 0 deletions kernel/tsacct.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk)
rcu_read_unlock();
stats->ac_utime = cputime_to_msecs(tsk->utime) * USEC_PER_MSEC;
stats->ac_stime = cputime_to_msecs(tsk->stime) * USEC_PER_MSEC;
stats->ac_utimescaled =
cputime_to_msecs(tsk->utimescaled) * USEC_PER_MSEC;
stats->ac_stimescaled =
cputime_to_msecs(tsk->stimescaled) * USEC_PER_MSEC;
stats->ac_minflt = tsk->min_flt;
stats->ac_majflt = tsk->maj_flt;

Expand Down

0 comments on commit c66f08b

Please sign in to comment.