diff options
| author | Frank Mayhar <fmayhar@google.com> | 2008-09-12 12:54:39 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-09-23 07:38:44 -0400 |
| commit | bb34d92f643086d546b49cef680f6f305ed84414 (patch) | |
| tree | 275887040c96971e133fa20d99517c1fcea76415 /include/linux | |
| parent | 5ce73a4a5a4893a1aa4cdeed1b1a5a6de42c43b6 (diff) | |
timers: fix itimer/many thread hang, v2
This is the second resubmission of the posix timer rework patch, posted
a few days ago.
This includes the changes from the previous resubmittion, which addressed
Oleg Nesterov's comments, removing the RCU stuff from the patch and
un-inlining the thread_group_cputime() function for SMP.
In addition, per Ingo Molnar it simplifies the UP code, consolidating much
of it with the SMP version and depending on lower-level SMP/UP handling to
take care of the differences.
It also cleans up some UP compile errors, moves the scheduler stats-related
macros into kernel/sched_stats.h, cleans up a merge error in
kernel/fork.c and has a few other minor fixes and cleanups as suggested
by Oleg and Ingo. Thanks for the review, guys.
Signed-off-by: Frank Mayhar <fmayhar@google.com>
Cc: Roland McGrath <roland@redhat.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/kernel_stat.h | 1 | ||||
| -rw-r--r-- | include/linux/sched.h | 183 |
2 files changed, 6 insertions, 178 deletions
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index cf9f40a91c9c..cac3750cd65e 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h | |||
| @@ -52,6 +52,7 @@ static inline int kstat_irqs(int irq) | |||
| 52 | return sum; | 52 | return sum; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | extern unsigned long long task_delta_exec(struct task_struct *); | ||
| 55 | extern void account_user_time(struct task_struct *, cputime_t); | 56 | extern void account_user_time(struct task_struct *, cputime_t); |
| 56 | extern void account_user_time_scaled(struct task_struct *, cputime_t); | 57 | extern void account_user_time_scaled(struct task_struct *, cputime_t); |
| 57 | extern void account_system_time(struct task_struct *, int, cputime_t); | 58 | extern void account_system_time(struct task_struct *, int, cputime_t); |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 7ce8d4e53565..b982fb48c8f0 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -454,15 +454,9 @@ struct task_cputime { | |||
| 454 | * This structure contains the version of task_cputime, above, that is | 454 | * This structure contains the version of task_cputime, above, that is |
| 455 | * used for thread group CPU clock calculations. | 455 | * used for thread group CPU clock calculations. |
| 456 | */ | 456 | */ |
| 457 | #ifdef CONFIG_SMP | ||
| 458 | struct thread_group_cputime { | 457 | struct thread_group_cputime { |
| 459 | struct task_cputime *totals; | 458 | struct task_cputime *totals; |
| 460 | }; | 459 | }; |
| 461 | #else | ||
| 462 | struct thread_group_cputime { | ||
| 463 | struct task_cputime totals; | ||
| 464 | }; | ||
| 465 | #endif | ||
| 466 | 460 | ||
| 467 | /* | 461 | /* |
| 468 | * NOTE! "signal_struct" does not have it's own | 462 | * NOTE! "signal_struct" does not have it's own |
| @@ -2124,193 +2118,26 @@ static inline int spin_needbreak(spinlock_t *lock) | |||
| 2124 | /* | 2118 | /* |
| 2125 | * Thread group CPU time accounting. | 2119 | * Thread group CPU time accounting. |
| 2126 | */ | 2120 | */ |
| 2127 | #ifdef CONFIG_SMP | ||
| 2128 | 2121 | ||
| 2129 | extern int thread_group_cputime_alloc_smp(struct task_struct *); | 2122 | extern int thread_group_cputime_alloc(struct task_struct *); |
| 2130 | extern void thread_group_cputime_smp(struct task_struct *, struct task_cputime *); | 2123 | extern void thread_group_cputime(struct task_struct *, struct task_cputime *); |
| 2131 | 2124 | ||
| 2132 | static inline void thread_group_cputime_init(struct signal_struct *sig) | 2125 | static inline void thread_group_cputime_init(struct signal_struct *sig) |
| 2133 | { | 2126 | { |
| 2134 | sig->cputime.totals = NULL; | 2127 | sig->cputime.totals = NULL; |
| 2135 | } | 2128 | } |
| 2136 | 2129 | ||
| 2137 | static inline int thread_group_cputime_clone_thread(struct task_struct *curr, | 2130 | static inline int thread_group_cputime_clone_thread(struct task_struct *curr) |
| 2138 | struct task_struct *new) | ||
| 2139 | { | 2131 | { |
| 2140 | if (curr->signal->cputime.totals) | 2132 | if (curr->signal->cputime.totals) |
| 2141 | return 0; | 2133 | return 0; |
| 2142 | return thread_group_cputime_alloc_smp(curr); | 2134 | return thread_group_cputime_alloc(curr); |
| 2143 | } | 2135 | } |
| 2144 | 2136 | ||
| 2145 | static inline void thread_group_cputime_free(struct signal_struct *sig) | ||
| 2146 | { | ||
| 2147 | free_percpu(sig->cputime.totals); | ||
| 2148 | } | ||
| 2149 | |||
| 2150 | /** | ||
| 2151 | * thread_group_cputime - Sum the thread group time fields across all CPUs. | ||
| 2152 | * | ||
| 2153 | * This is a wrapper for the real routine, thread_group_cputime_smp(). See | ||
| 2154 | * that routine for details. | ||
| 2155 | */ | ||
| 2156 | static inline void thread_group_cputime( | ||
| 2157 | struct task_struct *tsk, | ||
| 2158 | struct task_cputime *times) | ||
| 2159 | { | ||
| 2160 | thread_group_cputime_smp(tsk, times); | ||
| 2161 | } | ||
| 2162 | |||
| 2163 | /** | ||
| 2164 | * thread_group_cputime_account_user - Maintain utime for a thread group. | ||
| 2165 | * | ||
| 2166 | * @tgtimes: Pointer to thread_group_cputime structure. | ||
| 2167 | * @cputime: Time value by which to increment the utime field of that | ||
| 2168 | * structure. | ||
| 2169 | * | ||
| 2170 | * If thread group time is being maintained, get the structure for the | ||
| 2171 | * running CPU and update the utime field there. | ||
| 2172 | */ | ||
| 2173 | static inline void thread_group_cputime_account_user( | ||
| 2174 | struct thread_group_cputime *tgtimes, | ||
| 2175 | cputime_t cputime) | ||
| 2176 | { | ||
| 2177 | if (tgtimes->totals) { | ||
| 2178 | struct task_cputime *times; | ||
| 2179 | |||
| 2180 | times = per_cpu_ptr(tgtimes->totals, get_cpu()); | ||
| 2181 | times->utime = cputime_add(times->utime, cputime); | ||
| 2182 | put_cpu_no_resched(); | ||
| 2183 | } | ||
| 2184 | } | ||
| 2185 | |||
| 2186 | /** | ||
| 2187 | * thread_group_cputime_account_system - Maintain stime for a thread group. | ||
| 2188 | * | ||
| 2189 | * @tgtimes: Pointer to thread_group_cputime structure. | ||
| 2190 | * @cputime: Time value by which to increment the stime field of that | ||
| 2191 | * structure. | ||
| 2192 | * | ||
| 2193 | * If thread group time is being maintained, get the structure for the | ||
| 2194 | * running CPU and update the stime field there. | ||
| 2195 | */ | ||
| 2196 | static inline void thread_group_cputime_account_system( | ||
| 2197 | struct thread_group_cputime *tgtimes, | ||
| 2198 | cputime_t cputime) | ||
| 2199 | { | ||
| 2200 | if (tgtimes->totals) { | ||
| 2201 | struct task_cputime *times; | ||
| 2202 | |||
| 2203 | times = per_cpu_ptr(tgtimes->totals, get_cpu()); | ||
| 2204 | times->stime = cputime_add(times->stime, cputime); | ||
| 2205 | put_cpu_no_resched(); | ||
| 2206 | } | ||
| 2207 | } | ||
| 2208 | |||
| 2209 | /** | ||
| 2210 | * thread_group_cputime_account_exec_runtime - Maintain exec runtime for a | ||
| 2211 | * thread group. | ||
| 2212 | * | ||
| 2213 | * @tgtimes: Pointer to thread_group_cputime structure. | ||
| 2214 | * @ns: Time value by which to increment the sum_exec_runtime field | ||
| 2215 | * of that structure. | ||
| 2216 | * | ||
| 2217 | * If thread group time is being maintained, get the structure for the | ||
| 2218 | * running CPU and update the sum_exec_runtime field there. | ||
| 2219 | */ | ||
| 2220 | static inline void thread_group_cputime_account_exec_runtime( | ||
| 2221 | struct thread_group_cputime *tgtimes, | ||
| 2222 | unsigned long long ns) | ||
| 2223 | { | ||
| 2224 | if (tgtimes->totals) { | ||
| 2225 | struct task_cputime *times; | ||
| 2226 | |||
| 2227 | times = per_cpu_ptr(tgtimes->totals, get_cpu()); | ||
| 2228 | times->sum_exec_runtime += ns; | ||
| 2229 | put_cpu_no_resched(); | ||
| 2230 | } | ||
| 2231 | } | ||
| 2232 | |||
| 2233 | #else /* CONFIG_SMP */ | ||
| 2234 | |||
| 2235 | static inline void thread_group_cputime_init(struct signal_struct *sig) | ||
| 2236 | { | ||
| 2237 | sig->cputime.totals.utime = cputime_zero; | ||
| 2238 | sig->cputime.totals.stime = cputime_zero; | ||
| 2239 | sig->cputime.totals.sum_exec_runtime = 0; | ||
| 2240 | } | ||
| 2241 | |||
| 2242 | static inline int thread_group_cputime_alloc(struct task_struct *tsk) | ||
| 2243 | { | ||
| 2244 | return 0; | ||
| 2245 | } | ||
| 2246 | 2137 | ||
| 2247 | static inline void thread_group_cputime_free(struct signal_struct *sig) | 2138 | static inline void thread_group_cputime_free(struct signal_struct *sig) |
| 2248 | { | 2139 | { |
| 2249 | } | 2140 | free_percpu(sig->cputime.totals); |
| 2250 | |||
| 2251 | static inline int thread_group_cputime_clone_thread(struct task_struct *curr, | ||
| 2252 | struct task_struct *tsk) | ||
| 2253 | { | ||
| 2254 | return 0; | ||
| 2255 | } | ||
| 2256 | |||
| 2257 | static inline void thread_group_cputime(struct task_struct *tsk, | ||
| 2258 | struct task_cputime *cputime) | ||
| 2259 | { | ||
| 2260 | *cputime = tsk->signal->cputime.totals; | ||
| 2261 | } | ||
| 2262 | |||
| 2263 | static inline void thread_group_cputime_account_user( | ||
| 2264 | struct thread_group_cputime *tgtimes, | ||
| 2265 | cputime_t cputime) | ||
| 2266 | { | ||
| 2267 | tgtimes->totals.utime = cputime_add(tgtimes->totals.utime, cputime); | ||
| 2268 | } | ||
| 2269 | |||
| 2270 | static inline void thread_group_cputime_account_system( | ||
| 2271 | struct thread_group_cputime *tgtimes, | ||
| 2272 | cputime_t cputime) | ||
| 2273 | { | ||
| 2274 | tgtimes->totals.stime = cputime_add(tgtimes->totals.stime, cputime); | ||
| 2275 | } | ||
| 2276 | |||
| 2277 | static inline void thread_group_cputime_account_exec_runtime( | ||
| 2278 | struct thread_group_cputime *tgtimes, | ||
| 2279 | unsigned long long ns) | ||
| 2280 | { | ||
| 2281 | tgtimes->totals.sum_exec_runtime += ns; | ||
| 2282 | } | ||
| 2283 | |||
| 2284 | #endif /* CONFIG_SMP */ | ||
| 2285 | |||
| 2286 | static inline void account_group_user_time(struct task_struct *tsk, | ||
| 2287 | cputime_t cputime) | ||
| 2288 | { | ||
| 2289 | struct signal_struct *sig; | ||
| 2290 | |||
| 2291 | sig = tsk->signal; | ||
| 2292 | if (likely(sig)) | ||
| 2293 | thread_group_cputime_account_user(&sig->cputime, cputime); | ||
| 2294 | } | ||
| 2295 | |||
| 2296 | static inline void account_group_system_time(struct task_struct *tsk, | ||
| 2297 | cputime_t cputime) | ||
| 2298 | { | ||
| 2299 | struct signal_struct *sig; | ||
| 2300 | |||
| 2301 | sig = tsk->signal; | ||
| 2302 | if (likely(sig)) | ||
| 2303 | thread_group_cputime_account_system(&sig->cputime, cputime); | ||
| 2304 | } | ||
| 2305 | |||
| 2306 | static inline void account_group_exec_runtime(struct task_struct *tsk, | ||
| 2307 | unsigned long long ns) | ||
| 2308 | { | ||
| 2309 | struct signal_struct *sig; | ||
| 2310 | |||
| 2311 | sig = tsk->signal; | ||
| 2312 | if (likely(sig)) | ||
| 2313 | thread_group_cputime_account_exec_runtime(&sig->cputime, ns); | ||
| 2314 | } | 2141 | } |
| 2315 | 2142 | ||
| 2316 | /* | 2143 | /* |
