Skip to content

Commit 656fd89

Browse files
author
Fox Snowpatch
committed
1 parent 960c1fd commit 656fd89

File tree

22 files changed

+505
-364
lines changed

22 files changed

+505
-364
lines changed

arch/powerpc/kernel/time.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,47 @@ void vtime_task_switch(struct task_struct *prev)
376376
acct->starttime = acct0->starttime;
377377
}
378378
}
379+
380+
#ifdef CONFIG_NO_HZ_COMMON
381+
/**
382+
* vtime_reset - Fast forward vtime entry clocks
383+
*
384+
* Called from dynticks idle IRQ entry to fast-forward the clocks to current time
385+
* so that the IRQ time is still accounted by vtime while nohz cputime is paused.
386+
*/
387+
void vtime_reset(void)
388+
{
389+
struct cpu_accounting_data *acct = get_accounting(current);
390+
391+
acct->starttime = mftb();
392+
#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
393+
acct->startspurr = read_spurr(now);
394+
#endif
395+
}
396+
397+
/**
398+
* vtime_dyntick_start - Inform vtime about entry to idle-dynticks
399+
*
400+
* Called when idle enters in dyntick mode. The idle cputime that elapsed so far
401+
* is accumulated and the tick subsystem takes over the idle cputime accounting.
402+
*/
403+
void vtime_dyntick_start(void)
404+
{
405+
vtime_account_idle(current);
406+
}
407+
408+
/**
409+
* vtime_dyntick_stop - Inform vtime about exit from idle-dynticks
410+
*
411+
* Called when idle exits from dyntick mode. The vtime entry clocks are
412+
* fast-forward to current time so that idle accounting restarts elapsing from
413+
* now.
414+
*/
415+
void vtime_dyntick_stop(void)
416+
{
417+
vtime_reset();
418+
}
419+
#endif /* CONFIG_NO_HZ_COMMON */
379420
#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
380421

381422
void __no_kcsan __delay(unsigned long loops)

arch/s390/include/asm/idle.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@
1212
#include <linux/device.h>
1313

1414
struct s390_idle_data {
15-
unsigned long idle_count;
16-
unsigned long idle_time;
17-
unsigned long clock_idle_enter;
18-
unsigned long timer_idle_enter;
19-
unsigned long mt_cycles_enter[8];
15+
bool idle_dyntick;
16+
unsigned long idle_count;
17+
unsigned long idle_time;
18+
unsigned long clock_idle_enter;
19+
unsigned long timer_idle_enter;
20+
unsigned long mt_cycles_enter[8];
2021
};
2122

2223
extern struct device_attribute dev_attr_idle_count;

arch/s390/kernel/idle.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ void account_idle_time_irq(void)
3535
this_cpu_add(mt_cycles[i], cycles_new[i] - idle->mt_cycles_enter[i]);
3636
}
3737

38+
WRITE_ONCE(idle->idle_count, READ_ONCE(idle->idle_count) + 1);
39+
40+
/* Dyntick idle time accounted by nohz/scheduler */
41+
if (idle->idle_dyntick)
42+
return;
43+
3844
idle_time = lc->int_clock - idle->clock_idle_enter;
3945

4046
lc->steal_timer += idle->clock_idle_enter - lc->last_update_clock;
@@ -45,7 +51,6 @@ void account_idle_time_irq(void)
4551

4652
/* Account time spent with enabled wait psw loaded as idle time. */
4753
WRITE_ONCE(idle->idle_time, READ_ONCE(idle->idle_time) + idle_time);
48-
WRITE_ONCE(idle->idle_count, READ_ONCE(idle->idle_count) + 1);
4954
account_idle_time(cputime_to_nsecs(idle_time));
5055
}
5156

@@ -61,8 +66,10 @@ void noinstr arch_cpu_idle(void)
6166
set_cpu_flag(CIF_ENABLED_WAIT);
6267
if (smp_cpu_mtid)
6368
stcctm(MT_DIAG, smp_cpu_mtid, (u64 *)&idle->mt_cycles_enter);
64-
idle->clock_idle_enter = get_tod_clock_fast();
65-
idle->timer_idle_enter = get_cpu_timer();
69+
if (!idle->idle_dyntick) {
70+
idle->clock_idle_enter = get_tod_clock_fast();
71+
idle->timer_idle_enter = get_cpu_timer();
72+
}
6673
bpon();
6774
__load_psw_mask(psw_mask);
6875
}

arch/s390/kernel/vtime.c

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <asm/vtimer.h>
1818
#include <asm/vtime.h>
1919
#include <asm/cpu_mf.h>
20+
#include <asm/idle.h>
2021
#include <asm/smp.h>
2122

2223
#include "entry.h"
@@ -111,6 +112,16 @@ static void account_system_index_scaled(struct task_struct *p, u64 cputime,
111112
account_system_index_time(p, cputime_to_nsecs(cputime), index);
112113
}
113114

115+
static inline void vtime_reset_last_update(struct lowcore *lc)
116+
{
117+
asm volatile(
118+
" stpt %0\n" /* Store current cpu timer value */
119+
" stckf %1" /* Store current tod clock value */
120+
: "=Q" (lc->last_update_timer),
121+
"=Q" (lc->last_update_clock)
122+
: : "cc");
123+
}
124+
114125
/*
115126
* Update process times based on virtual cpu times stored by entry.S
116127
* to the lowcore fields user_timer, system_timer & steal_clock.
@@ -122,12 +133,9 @@ static int do_account_vtime(struct task_struct *tsk)
122133

123134
timer = lc->last_update_timer;
124135
clock = lc->last_update_clock;
125-
asm volatile(
126-
" stpt %0\n" /* Store current cpu timer value */
127-
" stckf %1" /* Store current tod clock value */
128-
: "=Q" (lc->last_update_timer),
129-
"=Q" (lc->last_update_clock)
130-
: : "cc");
136+
137+
vtime_reset_last_update(lc);
138+
131139
clock = lc->last_update_clock - clock;
132140
timer -= lc->last_update_timer;
133141

@@ -261,6 +269,43 @@ void vtime_account_hardirq(struct task_struct *tsk)
261269
virt_timer_forward(delta);
262270
}
263271

272+
#ifdef CONFIG_NO_HZ_COMMON
273+
/**
274+
* vtime_reset - Fast forward vtime entry clocks
275+
*
276+
* Called from dynticks idle IRQ entry to fast-forward the clocks to current time
277+
* so that the IRQ time is still accounted by vtime while nohz cputime is paused.
278+
*/
279+
void vtime_reset(void)
280+
{
281+
vtime_reset_last_update(get_lowcore());
282+
}
283+
284+
/**
285+
* vtime_dyntick_start - Inform vtime about entry to idle-dynticks
286+
*
287+
* Called when idle enters in dyntick mode. The idle cputime that elapsed so far
288+
* is flushed and the tick subsystem takes over the idle cputime accounting.
289+
*/
290+
void vtime_dyntick_start(void)
291+
{
292+
__this_cpu_write(s390_idle.idle_dyntick, true);
293+
vtime_flush(current);
294+
}
295+
296+
/**
297+
* vtime_dyntick_stop - Inform vtime about exit from idle-dynticks
298+
*
299+
* Called when idle exits from dyntick mode. The vtime entry clocks are
300+
* fast-forward to current time and idle accounting resumes.
301+
*/
302+
void vtime_dyntick_stop(void)
303+
{
304+
vtime_reset_last_update(get_lowcore());
305+
__this_cpu_write(s390_idle.idle_dyntick, false);
306+
}
307+
#endif /* CONFIG_NO_HZ_COMMON */
308+
264309
/*
265310
* Sorted add to a list. List is linear searched until first bigger
266311
* element is found.

drivers/cpufreq/cpufreq.c

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -130,38 +130,11 @@ struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)
130130
}
131131
EXPORT_SYMBOL_GPL(get_governor_parent_kobj);
132132

133-
static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
134-
{
135-
struct kernel_cpustat kcpustat;
136-
u64 cur_wall_time;
137-
u64 idle_time;
138-
u64 busy_time;
139-
140-
cur_wall_time = jiffies64_to_nsecs(get_jiffies_64());
141-
142-
kcpustat_cpu_fetch(&kcpustat, cpu);
143-
144-
busy_time = kcpustat.cpustat[CPUTIME_USER];
145-
busy_time += kcpustat.cpustat[CPUTIME_SYSTEM];
146-
busy_time += kcpustat.cpustat[CPUTIME_IRQ];
147-
busy_time += kcpustat.cpustat[CPUTIME_SOFTIRQ];
148-
busy_time += kcpustat.cpustat[CPUTIME_STEAL];
149-
busy_time += kcpustat.cpustat[CPUTIME_NICE];
150-
151-
idle_time = cur_wall_time - busy_time;
152-
if (wall)
153-
*wall = div_u64(cur_wall_time, NSEC_PER_USEC);
154-
155-
return div_u64(idle_time, NSEC_PER_USEC);
156-
}
157-
158133
u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy)
159134
{
160135
u64 idle_time = get_cpu_idle_time_us(cpu, io_busy ? wall : NULL);
161136

162-
if (idle_time == -1ULL)
163-
return get_cpu_idle_time_jiffy(cpu, wall);
164-
else if (!io_busy)
137+
if (!io_busy)
165138
idle_time += get_cpu_iowait_time_us(cpu, wall);
166139

167140
return idle_time;

drivers/cpufreq/cpufreq_governor.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ void gov_update_cpu_data(struct dbs_data *dbs_data)
105105
j_cdbs->prev_cpu_idle = get_cpu_idle_time(j, &j_cdbs->prev_update_time,
106106
dbs_data->io_is_busy);
107107
if (dbs_data->ignore_nice_load)
108-
j_cdbs->prev_cpu_nice = kcpustat_field(&kcpustat_cpu(j), CPUTIME_NICE, j);
108+
j_cdbs->prev_cpu_nice = kcpustat_field(CPUTIME_NICE, j);
109109
}
110110
}
111111
}
@@ -165,7 +165,7 @@ unsigned int dbs_update(struct cpufreq_policy *policy)
165165
j_cdbs->prev_cpu_idle = cur_idle_time;
166166

167167
if (ignore_nice) {
168-
u64 cur_nice = kcpustat_field(&kcpustat_cpu(j), CPUTIME_NICE, j);
168+
u64 cur_nice = kcpustat_field(CPUTIME_NICE, j);
169169

170170
idle_time += div_u64(cur_nice - j_cdbs->prev_cpu_nice, NSEC_PER_USEC);
171171
j_cdbs->prev_cpu_nice = cur_nice;
@@ -539,7 +539,7 @@ int cpufreq_dbs_governor_start(struct cpufreq_policy *policy)
539539
j_cdbs->prev_load = 0;
540540

541541
if (ignore_nice)
542-
j_cdbs->prev_cpu_nice = kcpustat_field(&kcpustat_cpu(j), CPUTIME_NICE, j);
542+
j_cdbs->prev_cpu_nice = kcpustat_field(CPUTIME_NICE, j);
543543
}
544544

545545
gov->start(policy);

drivers/cpufreq/cpufreq_ondemand.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -334,17 +334,12 @@ static void od_free(struct policy_dbs_info *policy_dbs)
334334
static int od_init(struct dbs_data *dbs_data)
335335
{
336336
struct od_dbs_tuners *tuners;
337-
u64 idle_time;
338-
int cpu;
339337

340338
tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
341339
if (!tuners)
342340
return -ENOMEM;
343341

344-
cpu = get_cpu();
345-
idle_time = get_cpu_idle_time_us(cpu, NULL);
346-
put_cpu();
347-
if (idle_time != -1ULL) {
342+
if (tick_nohz_enabled) {
348343
/* Idle micro accounting is supported. Use finer thresholds */
349344
dbs_data->up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
350345
} else {

drivers/macintosh/rack-meter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ static inline u64 get_cpu_idle_time(unsigned int cpu)
8787
kcpustat->cpustat[CPUTIME_IOWAIT];
8888

8989
if (rackmeter_ignore_nice)
90-
retval += kcpustat_field(kcpustat, CPUTIME_NICE, cpu);
90+
retval += kcpustat_field(CPUTIME_NICE, cpu);
9191

9292
return retval;
9393
}

fs/proc/stat.c

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,38 +22,6 @@
2222
#define arch_irq_stat() 0
2323
#endif
2424

25-
u64 get_idle_time(struct kernel_cpustat *kcs, int cpu)
26-
{
27-
u64 idle, idle_usecs = -1ULL;
28-
29-
if (cpu_online(cpu))
30-
idle_usecs = get_cpu_idle_time_us(cpu, NULL);
31-
32-
if (idle_usecs == -1ULL)
33-
/* !NO_HZ or cpu offline so we can rely on cpustat.idle */
34-
idle = kcs->cpustat[CPUTIME_IDLE];
35-
else
36-
idle = idle_usecs * NSEC_PER_USEC;
37-
38-
return idle;
39-
}
40-
41-
static u64 get_iowait_time(struct kernel_cpustat *kcs, int cpu)
42-
{
43-
u64 iowait, iowait_usecs = -1ULL;
44-
45-
if (cpu_online(cpu))
46-
iowait_usecs = get_cpu_iowait_time_us(cpu, NULL);
47-
48-
if (iowait_usecs == -1ULL)
49-
/* !NO_HZ or cpu offline so we can rely on cpustat.iowait */
50-
iowait = kcs->cpustat[CPUTIME_IOWAIT];
51-
else
52-
iowait = iowait_usecs * NSEC_PER_USEC;
53-
54-
return iowait;
55-
}
56-
5725
static void show_irq_gap(struct seq_file *p, unsigned int gap)
5826
{
5927
static const char zeros[] = " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0";
@@ -105,8 +73,8 @@ static int show_stat(struct seq_file *p, void *v)
10573
user += cpustat[CPUTIME_USER];
10674
nice += cpustat[CPUTIME_NICE];
10775
system += cpustat[CPUTIME_SYSTEM];
108-
idle += get_idle_time(&kcpustat, i);
109-
iowait += get_iowait_time(&kcpustat, i);
76+
idle += cpustat[CPUTIME_IDLE];
77+
iowait += cpustat[CPUTIME_IOWAIT];
11078
irq += cpustat[CPUTIME_IRQ];
11179
softirq += cpustat[CPUTIME_SOFTIRQ];
11280
steal += cpustat[CPUTIME_STEAL];
@@ -146,8 +114,8 @@ static int show_stat(struct seq_file *p, void *v)
146114
user = cpustat[CPUTIME_USER];
147115
nice = cpustat[CPUTIME_NICE];
148116
system = cpustat[CPUTIME_SYSTEM];
149-
idle = get_idle_time(&kcpustat, i);
150-
iowait = get_iowait_time(&kcpustat, i);
117+
idle = cpustat[CPUTIME_IDLE];
118+
iowait = cpustat[CPUTIME_IOWAIT];
151119
irq = cpustat[CPUTIME_IRQ];
152120
softirq = cpustat[CPUTIME_SOFTIRQ];
153121
steal = cpustat[CPUTIME_STEAL];

fs/proc/uptime.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,8 @@ static int uptime_proc_show(struct seq_file *m, void *v)
1818
int i;
1919

2020
idle_nsec = 0;
21-
for_each_possible_cpu(i) {
22-
struct kernel_cpustat kcs;
23-
24-
kcpustat_cpu_fetch(&kcs, i);
25-
idle_nsec += get_idle_time(&kcs, i);
26-
}
21+
for_each_possible_cpu(i)
22+
idle_nsec += kcpustat_field(CPUTIME_IDLE, i);
2723

2824
ktime_get_boottime_ts64(&uptime);
2925
timens_add_boottime(&uptime);

0 commit comments

Comments
 (0)