diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 864ebae595b90de516c6c54b08cef9ac123a071b..37e0f22bcb39c11291aa950f01e3579162a185bb 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -470,14 +470,24 @@ static int cpufreq_stats_update(unsigned int cpu) void cpufreq_task_stats_init(struct task_struct *p) { - size_t alloc_size; - void *temp; unsigned long flags; - spin_lock_irqsave(&task_time_in_state_lock, flags); p->time_in_state = NULL; spin_unlock_irqrestore(&task_time_in_state_lock, flags); WRITE_ONCE(p->max_states, 0); + spin_lock_irqsave(&task_concurrent_active_time_lock, flags); + p->concurrent_active_time = NULL; + spin_unlock_irqrestore(&task_concurrent_active_time_lock, flags); + spin_lock_irqsave(&task_concurrent_policy_time_lock, flags); + p->concurrent_policy_time = NULL; + spin_unlock_irqrestore(&task_concurrent_policy_time_lock, flags); +} + +void cpufreq_task_stats_alloc(struct task_struct *p) +{ + size_t alloc_size; + void *temp; + unsigned long flags; if (!all_freq_table || !cpufreq_all_freq_init) return; @@ -1343,6 +1353,13 @@ static int process_notifier(struct notifier_block *self, return NOTIFY_OK; } +void cpufreq_task_stats_free(struct task_struct *p) +{ + kfree(p->time_in_state); + kfree(p->concurrent_active_time); + kfree(p->concurrent_policy_time); +} + static const struct seq_operations uid_time_in_state_seq_ops = { .start = uid_seq_start, .next = uid_seq_next, diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 84f6b21be137884ab2fd17215314cf7e9ec0df5f..52a6ea074d3032d6a08ec1a36d073c486f4bbaa6 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -655,6 +655,8 @@ int cpufreq_generic_init(struct cpufreq_policy *policy, void acct_update_power(struct task_struct *p, cputime_t cputime); void cpufreq_task_stats_init(struct task_struct *p); +void cpufreq_task_stats_alloc(struct task_struct *p); +void cpufreq_task_stats_free(struct task_struct *p); void cpufreq_task_stats_remove_uids(uid_t uid_start, uid_t uid_end); int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *p); @@ -667,6 +669,8 @@ int single_uid_time_in_state_open(struct inode *inode, struct file *file); static inline void acct_update_power(struct task_struct *p, cputime_t cputime) {} static inline void cpufreq_task_stats_init(struct task_struct *p) {} +static inline void cpufreq_task_stats_alloc(struct task_struct *p) {} +static inline void cpufreq_task_stats_free(struct task_struct *p) {} static inline void cpufreq_task_stats_exit(struct task_struct *p) {} static inline void cpufreq_task_stats_remove_uids(uid_t uid_start, uid_t uid_end) {} diff --git a/kernel/fork.c b/kernel/fork.c index c3061638a6c7f6dbeb93240f29686ae362e37e14..0817e3747dea73ef46207294f89859f61d3a211f 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -76,6 +76,7 @@ #include <linux/aio.h> #include <linux/compiler.h> #include <linux/kcov.h> +#include <linux/cpufreq.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> @@ -217,6 +218,9 @@ static void account_kernel_stack(unsigned long *stack, int account) void free_task(struct task_struct *tsk) { +#ifdef CONFIG_CPU_FREQ_STAT + cpufreq_task_stats_free(tsk); +#endif account_kernel_stack(tsk->stack, -1); arch_release_thread_stack(tsk->stack); free_thread_stack(tsk->stack); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 1493b0a118d3cff3aa72ffc251f83ca0644e2416..9a70b45236a8460dcc46e1c5edecded919315114 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2130,6 +2130,10 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p) memset(&p->se.statistics, 0, sizeof(p->se.statistics)); #endif +#ifdef CONFIG_CPU_FREQ_STAT + cpufreq_task_stats_init(p); +#endif + RB_CLEAR_NODE(&p->dl.rb_node); init_dl_task_timer(&p->dl); __dl_clear_params(p); @@ -2215,11 +2219,12 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p) unsigned long flags; int cpu = get_cpu(); + __sched_fork(clone_flags, p); + #ifdef CONFIG_CPU_FREQ_STAT - cpufreq_task_stats_init(p); + cpufreq_task_stats_alloc(p); #endif - __sched_fork(clone_flags, p); /* * We mark the process as running here. This guarantees that * nobody will actually run it, and a signal or other external