1 /* delayacct.h - per-task delay accounting 2 * 3 * Copyright (C) Shailabh Nagar, IBM Corp. 2006 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 */ 16 17 #ifndef _LINUX_DELAYACCT_H 18 #define _LINUX_DELAYACCT_H 19 20 #include <uapi/linux/taskstats.h> 21 #include <linux/sched.h> 22 #include <linux/slab.h> 23 24 /* 25 * Per-task flags relevant to delay accounting 26 * maintained privately to avoid exhausting similar flags in sched.h:PF_* 27 * Used to set current->delays->flags 28 */ 29 #define DELAYACCT_PF_SWAPIN 0x00000001 /* I am doing a swapin */ 30 #define DELAYACCT_PF_BLKIO 0x00000002 /* I am waiting on IO */ 31 32 #ifdef CONFIG_TASK_DELAY_ACCT 33 struct task_delay_info { 34 spinlock_t lock; 35 unsigned int flags; /* Private per-task flags */ 36 37 /* For each stat XXX, add following, aligned appropriately 38 * 39 * struct timespec XXX_start, XXX_end; 40 * u64 XXX_delay; 41 * u32 XXX_count; 42 * 43 * Atomicity of updates to XXX_delay, XXX_count protected by 44 * single lock above (split into XXX_lock if contention is an issue). 45 */ 46 47 /* 48 * XXX_count is incremented on every XXX operation, the delay 49 * associated with the operation is added to XXX_delay. 50 * XXX_delay contains the accumulated delay time in nanoseconds. 51 */ 52 u64 blkio_start; /* Shared by blkio, swapin */ 53 u64 blkio_delay; /* wait for sync block io completion */ 54 u64 swapin_delay; /* wait for swapin block io completion */ 55 u32 blkio_count; /* total count of the number of sync block */ 56 /* io operations performed */ 57 u32 swapin_count; /* total count of the number of swapin block */ 58 /* io operations performed */ 59 60 u64 freepages_start; 61 u64 freepages_delay; /* wait for memory reclaim */ 62 u32 freepages_count; /* total count of memory reclaim */ 63 }; 64 #endif 65 66 #include <linux/sched.h> 67 #include <linux/slab.h> 68 69 #ifdef CONFIG_TASK_DELAY_ACCT 70 extern int delayacct_on; /* Delay accounting turned on/off */ 71 extern struct kmem_cache *delayacct_cache; 72 extern void delayacct_init(void); 73 extern void __delayacct_tsk_init(struct task_struct *); 74 extern void __delayacct_tsk_exit(struct task_struct *); 75 extern void __delayacct_blkio_start(void); 76 extern void __delayacct_blkio_end(void); 77 extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *); 78 extern __u64 __delayacct_blkio_ticks(struct task_struct *); 79 extern void __delayacct_freepages_start(void); 80 extern void __delayacct_freepages_end(void); 81 82 static inline int delayacct_is_task_waiting_on_io(struct task_struct *p) 83 { 84 if (p->delays) 85 return (p->delays->flags & DELAYACCT_PF_BLKIO); 86 else 87 return 0; 88 } 89 90 static inline void delayacct_set_flag(int flag) 91 { 92 if (current->delays) 93 current->delays->flags |= flag; 94 } 95 96 static inline void delayacct_clear_flag(int flag) 97 { 98 if (current->delays) 99 current->delays->flags &= ~flag; 100 } 101 102 static inline void delayacct_tsk_init(struct task_struct *tsk) 103 { 104 /* reinitialize in case parent's non-null pointer was dup'ed*/ 105 tsk->delays = NULL; 106 if (delayacct_on) 107 __delayacct_tsk_init(tsk); 108 } 109 110 /* Free tsk->delays. Called from bad fork and __put_task_struct 111 * where there's no risk of tsk->delays being accessed elsewhere 112 */ 113 static inline void delayacct_tsk_free(struct task_struct *tsk) 114 { 115 if (tsk->delays) 116 kmem_cache_free(delayacct_cache, tsk->delays); 117 tsk->delays = NULL; 118 } 119 120 static inline void delayacct_blkio_start(void) 121 { 122 delayacct_set_flag(DELAYACCT_PF_BLKIO); 123 if (current->delays) 124 __delayacct_blkio_start(); 125 } 126 127 static inline void delayacct_blkio_end(void) 128 { 129 if (current->delays) 130 __delayacct_blkio_end(); 131 delayacct_clear_flag(DELAYACCT_PF_BLKIO); 132 } 133 134 static inline int delayacct_add_tsk(struct taskstats *d, 135 struct task_struct *tsk) 136 { 137 if (!delayacct_on || !tsk->delays) 138 return 0; 139 return __delayacct_add_tsk(d, tsk); 140 } 141 142 static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk) 143 { 144 if (tsk->delays) 145 return __delayacct_blkio_ticks(tsk); 146 return 0; 147 } 148 149 static inline void delayacct_freepages_start(void) 150 { 151 if (current->delays) 152 __delayacct_freepages_start(); 153 } 154 155 static inline void delayacct_freepages_end(void) 156 { 157 if (current->delays) 158 __delayacct_freepages_end(); 159 } 160 161 #else 162 static inline void delayacct_set_flag(int flag) 163 {} 164 static inline void delayacct_clear_flag(int flag) 165 {} 166 static inline void delayacct_init(void) 167 {} 168 static inline void delayacct_tsk_init(struct task_struct *tsk) 169 {} 170 static inline void delayacct_tsk_free(struct task_struct *tsk) 171 {} 172 static inline void delayacct_blkio_start(void) 173 {} 174 static inline void delayacct_blkio_end(void) 175 {} 176 static inline int delayacct_add_tsk(struct taskstats *d, 177 struct task_struct *tsk) 178 { return 0; } 179 static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk) 180 { return 0; } 181 static inline int delayacct_is_task_waiting_on_io(struct task_struct *p) 182 { return 0; } 183 static inline void delayacct_freepages_start(void) 184 {} 185 static inline void delayacct_freepages_end(void) 186 {} 187 188 #endif /* CONFIG_TASK_DELAY_ACCT */ 189 190 #endif 191