1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* delayacct.h - per-task delay accounting 3 * 4 * Copyright (C) Shailabh Nagar, IBM Corp. 2006 5 */ 6 7 #ifndef _LINUX_DELAYACCT_H 8 #define _LINUX_DELAYACCT_H 9 10 #include <uapi/linux/taskstats.h> 11 12 #ifdef CONFIG_TASK_DELAY_ACCT 13 struct task_delay_info { 14 raw_spinlock_t lock; 15 16 /* For each stat XXX, add following, aligned appropriately 17 * 18 * struct timespec XXX_start, XXX_end; 19 * u64 XXX_delay; 20 * u32 XXX_count; 21 * 22 * Atomicity of updates to XXX_delay, XXX_count protected by 23 * single lock above (split into XXX_lock if contention is an issue). 24 */ 25 26 /* 27 * XXX_count is incremented on every XXX operation, the delay 28 * associated with the operation is added to XXX_delay. 29 * XXX_delay contains the accumulated delay time in nanoseconds. 30 */ 31 u64 blkio_start; 32 u64 blkio_delay_max; 33 u64 blkio_delay; /* wait for sync block io completion */ 34 u64 swapin_start; 35 u64 swapin_delay_max; 36 u64 swapin_delay; /* wait for swapin */ 37 u32 blkio_count; /* total count of the number of sync block */ 38 /* io operations performed */ 39 u32 swapin_count; /* total count of swapin */ 40 41 u64 freepages_start; 42 u64 freepages_delay_max; 43 u64 freepages_delay; /* wait for memory reclaim */ 44 45 u64 thrashing_start; 46 u64 thrashing_delay_max; 47 u64 thrashing_delay; /* wait for thrashing page */ 48 49 u64 compact_start; 50 u64 compact_delay_max; 51 u64 compact_delay; /* wait for memory compact */ 52 53 u64 wpcopy_start; 54 u64 wpcopy_delay_max; 55 u64 wpcopy_delay; /* wait for write-protect copy */ 56 57 u64 irq_delay_max; 58 u64 irq_delay; /* wait for IRQ/SOFTIRQ */ 59 60 u32 freepages_count; /* total count of memory reclaim */ 61 u32 thrashing_count; /* total count of thrash waits */ 62 u32 compact_count; /* total count of memory compact */ 63 u32 wpcopy_count; /* total count of write-protect copy */ 64 u32 irq_count; /* total count of IRQ/SOFTIRQ */ 65 }; 66 #endif 67 68 #include <linux/sched.h> 69 #include <linux/slab.h> 70 #include <linux/jump_label.h> 71 72 #ifdef CONFIG_TASK_DELAY_ACCT 73 DECLARE_STATIC_KEY_FALSE(delayacct_key); 74 extern int delayacct_on; /* Delay accounting turned on/off */ 75 extern struct kmem_cache *delayacct_cache; 76 extern void delayacct_init(void); 77 78 extern void __delayacct_tsk_init(struct task_struct *); 79 extern void __delayacct_tsk_exit(struct task_struct *); 80 extern void __delayacct_blkio_start(void); 81 extern void __delayacct_blkio_end(struct task_struct *); 82 extern int delayacct_add_tsk(struct taskstats *, struct task_struct *); 83 extern __u64 __delayacct_blkio_ticks(struct task_struct *); 84 extern void __delayacct_freepages_start(void); 85 extern void __delayacct_freepages_end(void); 86 extern void __delayacct_thrashing_start(bool *in_thrashing); 87 extern void __delayacct_thrashing_end(bool *in_thrashing); 88 extern void __delayacct_swapin_start(void); 89 extern void __delayacct_swapin_end(void); 90 extern void __delayacct_compact_start(void); 91 extern void __delayacct_compact_end(void); 92 extern void __delayacct_wpcopy_start(void); 93 extern void __delayacct_wpcopy_end(void); 94 extern void __delayacct_irq(struct task_struct *task, u32 delta); 95 96 static inline void delayacct_tsk_init(struct task_struct *tsk) 97 { 98 /* reinitialize in case parent's non-null pointer was dup'ed*/ 99 tsk->delays = NULL; 100 if (delayacct_on) 101 __delayacct_tsk_init(tsk); 102 } 103 104 /* Free tsk->delays. Called from bad fork and __put_task_struct 105 * where there's no risk of tsk->delays being accessed elsewhere 106 */ 107 static inline void delayacct_tsk_free(struct task_struct *tsk) 108 { 109 if (tsk->delays) 110 kmem_cache_free(delayacct_cache, tsk->delays); 111 tsk->delays = NULL; 112 } 113 114 static inline void delayacct_blkio_start(void) 115 { 116 if (!static_branch_unlikely(&delayacct_key)) 117 return; 118 119 if (current->delays) 120 __delayacct_blkio_start(); 121 } 122 123 static inline void delayacct_blkio_end(struct task_struct *p) 124 { 125 if (!static_branch_unlikely(&delayacct_key)) 126 return; 127 128 if (p->delays) 129 __delayacct_blkio_end(p); 130 } 131 132 static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk) 133 { 134 if (tsk->delays) 135 return __delayacct_blkio_ticks(tsk); 136 return 0; 137 } 138 139 static inline void delayacct_freepages_start(void) 140 { 141 if (!static_branch_unlikely(&delayacct_key)) 142 return; 143 144 if (current->delays) 145 __delayacct_freepages_start(); 146 } 147 148 static inline void delayacct_freepages_end(void) 149 { 150 if (!static_branch_unlikely(&delayacct_key)) 151 return; 152 153 if (current->delays) 154 __delayacct_freepages_end(); 155 } 156 157 static inline void delayacct_thrashing_start(bool *in_thrashing) 158 { 159 if (!static_branch_unlikely(&delayacct_key)) 160 return; 161 162 if (current->delays) 163 __delayacct_thrashing_start(in_thrashing); 164 } 165 166 static inline void delayacct_thrashing_end(bool *in_thrashing) 167 { 168 if (!static_branch_unlikely(&delayacct_key)) 169 return; 170 171 if (current->delays) 172 __delayacct_thrashing_end(in_thrashing); 173 } 174 175 static inline void delayacct_swapin_start(void) 176 { 177 if (!static_branch_unlikely(&delayacct_key)) 178 return; 179 180 if (current->delays) 181 __delayacct_swapin_start(); 182 } 183 184 static inline void delayacct_swapin_end(void) 185 { 186 if (!static_branch_unlikely(&delayacct_key)) 187 return; 188 189 if (current->delays) 190 __delayacct_swapin_end(); 191 } 192 193 static inline void delayacct_compact_start(void) 194 { 195 if (!static_branch_unlikely(&delayacct_key)) 196 return; 197 198 if (current->delays) 199 __delayacct_compact_start(); 200 } 201 202 static inline void delayacct_compact_end(void) 203 { 204 if (!static_branch_unlikely(&delayacct_key)) 205 return; 206 207 if (current->delays) 208 __delayacct_compact_end(); 209 } 210 211 static inline void delayacct_wpcopy_start(void) 212 { 213 if (!static_branch_unlikely(&delayacct_key)) 214 return; 215 216 if (current->delays) 217 __delayacct_wpcopy_start(); 218 } 219 220 static inline void delayacct_wpcopy_end(void) 221 { 222 if (!static_branch_unlikely(&delayacct_key)) 223 return; 224 225 if (current->delays) 226 __delayacct_wpcopy_end(); 227 } 228 229 static inline void delayacct_irq(struct task_struct *task, u32 delta) 230 { 231 if (!static_branch_unlikely(&delayacct_key)) 232 return; 233 234 if (task->delays) 235 __delayacct_irq(task, delta); 236 } 237 238 #else 239 static inline void delayacct_init(void) 240 {} 241 static inline void delayacct_tsk_init(struct task_struct *tsk) 242 {} 243 static inline void delayacct_tsk_free(struct task_struct *tsk) 244 {} 245 static inline void delayacct_blkio_start(void) 246 {} 247 static inline void delayacct_blkio_end(struct task_struct *p) 248 {} 249 static inline int delayacct_add_tsk(struct taskstats *d, 250 struct task_struct *tsk) 251 { return 0; } 252 static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk) 253 { return 0; } 254 static inline int delayacct_is_task_waiting_on_io(struct task_struct *p) 255 { return 0; } 256 static inline void delayacct_freepages_start(void) 257 {} 258 static inline void delayacct_freepages_end(void) 259 {} 260 static inline void delayacct_thrashing_start(bool *in_thrashing) 261 {} 262 static inline void delayacct_thrashing_end(bool *in_thrashing) 263 {} 264 static inline void delayacct_swapin_start(void) 265 {} 266 static inline void delayacct_swapin_end(void) 267 {} 268 static inline void delayacct_compact_start(void) 269 {} 270 static inline void delayacct_compact_end(void) 271 {} 272 static inline void delayacct_wpcopy_start(void) 273 {} 274 static inline void delayacct_wpcopy_end(void) 275 {} 276 static inline void delayacct_irq(struct task_struct *task, u32 delta) 277 {} 278 279 #endif /* CONFIG_TASK_DELAY_ACCT */ 280 281 #endif 282