1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _LINUX_SCHED_CPUTIME_H 3 #define _LINUX_SCHED_CPUTIME_H 4 5 #include <linux/static_call_types.h> 6 #include <linux/sched/signal.h> 7 8 /* 9 * cputime accounting APIs: 10 */ 11 12 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN 13 extern bool task_cputime(struct task_struct *t, 14 u64 *utime, u64 *stime); 15 extern u64 task_gtime(struct task_struct *t); 16 #else 17 static inline bool task_cputime(struct task_struct *t, 18 u64 *utime, u64 *stime) 19 { 20 *utime = t->utime; 21 *stime = t->stime; 22 return false; 23 } 24 25 static inline u64 task_gtime(struct task_struct *t) 26 { 27 return t->gtime; 28 } 29 #endif 30 31 #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME 32 static inline void task_cputime_scaled(struct task_struct *t, 33 u64 *utimescaled, 34 u64 *stimescaled) 35 { 36 *utimescaled = t->utimescaled; 37 *stimescaled = t->stimescaled; 38 } 39 #else 40 static inline void task_cputime_scaled(struct task_struct *t, 41 u64 *utimescaled, 42 u64 *stimescaled) 43 { 44 task_cputime(t, utimescaled, stimescaled); 45 } 46 #endif 47 48 extern void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st); 49 extern void thread_group_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st); 50 extern void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev, 51 u64 *ut, u64 *st); 52 53 /* 54 * Thread group CPU time accounting. 55 */ 56 void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times); 57 void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples); 58 59 /* 60 * The following are functions that support scheduler-internal time accounting. 61 * These functions are generally called at the timer tick. None of this depends 62 * on CONFIG_SCHEDSTATS. 63 */ 64 65 /** 66 * get_running_cputimer - return &tsk->signal->cputimer if cputimers are active 67 * 68 * @tsk: Pointer to target task. 69 */ 70 #ifdef CONFIG_POSIX_TIMERS 71 static inline 72 struct thread_group_cputimer *get_running_cputimer(struct task_struct *tsk) 73 { 74 struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; 75 76 /* 77 * Check whether posix CPU timers are active. If not the thread 78 * group accounting is not active either. Lockless check. 79 */ 80 if (!READ_ONCE(tsk->signal->posix_cputimers.timers_active)) 81 return NULL; 82 83 /* 84 * After we flush the task's sum_exec_runtime to sig->sum_sched_runtime 85 * in __exit_signal(), we won't account to the signal struct further 86 * cputime consumed by that task, even though the task can still be 87 * ticking after __exit_signal(). 88 * 89 * In order to keep a consistent behaviour between thread group cputime 90 * and thread group cputimer accounting, lets also ignore the cputime 91 * elapsing after __exit_signal() in any thread group timer running. 92 * 93 * This makes sure that POSIX CPU clocks and timers are synchronized, so 94 * that a POSIX CPU timer won't expire while the corresponding POSIX CPU 95 * clock delta is behind the expiring timer value. 96 */ 97 if (unlikely(!tsk->sighand)) 98 return NULL; 99 100 return cputimer; 101 } 102 #else 103 static inline 104 struct thread_group_cputimer *get_running_cputimer(struct task_struct *tsk) 105 { 106 return NULL; 107 } 108 #endif 109 110 /** 111 * account_group_user_time - Maintain utime for a thread group. 112 * 113 * @tsk: Pointer to task structure. 114 * @cputime: Time value by which to increment the utime field of the 115 * thread_group_cputime structure. 116 * 117 * If thread group time is being maintained, get the structure for the 118 * running CPU and update the utime field there. 119 */ 120 static inline void account_group_user_time(struct task_struct *tsk, 121 u64 cputime) 122 { 123 struct thread_group_cputimer *cputimer = get_running_cputimer(tsk); 124 125 if (!cputimer) 126 return; 127 128 atomic64_add(cputime, &cputimer->cputime_atomic.utime); 129 } 130 131 /** 132 * account_group_system_time - Maintain stime for a thread group. 133 * 134 * @tsk: Pointer to task structure. 135 * @cputime: Time value by which to increment the stime field of the 136 * thread_group_cputime structure. 137 * 138 * If thread group time is being maintained, get the structure for the 139 * running CPU and update the stime field there. 140 */ 141 static inline void account_group_system_time(struct task_struct *tsk, 142 u64 cputime) 143 { 144 struct thread_group_cputimer *cputimer = get_running_cputimer(tsk); 145 146 if (!cputimer) 147 return; 148 149 atomic64_add(cputime, &cputimer->cputime_atomic.stime); 150 } 151 152 /** 153 * account_group_exec_runtime - Maintain exec runtime for a thread group. 154 * 155 * @tsk: Pointer to task structure. 156 * @ns: Time value by which to increment the sum_exec_runtime field 157 * of the thread_group_cputime structure. 158 * 159 * If thread group time is being maintained, get the structure for the 160 * running CPU and update the sum_exec_runtime field there. 161 */ 162 static inline void account_group_exec_runtime(struct task_struct *tsk, 163 unsigned long long ns) 164 { 165 struct thread_group_cputimer *cputimer = get_running_cputimer(tsk); 166 167 if (!cputimer) 168 return; 169 170 atomic64_add(ns, &cputimer->cputime_atomic.sum_exec_runtime); 171 } 172 173 static inline void prev_cputime_init(struct prev_cputime *prev) 174 { 175 #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE 176 prev->utime = prev->stime = 0; 177 raw_spin_lock_init(&prev->lock); 178 #endif 179 } 180 181 extern unsigned long long 182 task_sched_runtime(struct task_struct *task); 183 184 #ifdef CONFIG_PARAVIRT 185 struct static_key; 186 extern struct static_key paravirt_steal_enabled; 187 extern struct static_key paravirt_steal_rq_enabled; 188 189 #ifdef CONFIG_HAVE_PV_STEAL_CLOCK_GEN 190 u64 dummy_steal_clock(int cpu); 191 192 DECLARE_STATIC_CALL(pv_steal_clock, dummy_steal_clock); 193 194 static inline u64 paravirt_steal_clock(int cpu) 195 { 196 return static_call(pv_steal_clock)(cpu); 197 } 198 #endif 199 #endif 200 201 #endif /* _LINUX_SCHED_CPUTIME_H */ 202