diff options
author | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2015-04-16 15:47:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-17 09:04:07 -0400 |
commit | ac1b398de1ef94aeee8ba87b0120763526572a6e (patch) | |
tree | 61e32dcc897d25328065dec06ccc3ab944316e9d /kernel/fork.c | |
parent | ff691f6e03815dc8f99461ea509df863a879fc3a (diff) |
kernel/fork.c: avoid division by zero
PAGE_SIZE is not guaranteed to be equal to or less than 8 times the
THREAD_SIZE.
E.g. architecture hexagon may have page size 1M and thread size 4096.
This would lead to a division by zero in the calculation of max_threads.
With 32-bit calculation there is no solution which delivers valid results
for all possible combinations of the parameters. The code is only called
once. Hence a 64-bit calculation can be used as solution.
[akpm@linux-foundation.org: use clamp_t(), per Oleg]
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 01038e6f51a8..c7f2e1a4187a 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -88,6 +88,16 @@ | |||
88 | #include <trace/events/task.h> | 88 | #include <trace/events/task.h> |
89 | 89 | ||
90 | /* | 90 | /* |
91 | * Minimum number of threads to boot the kernel | ||
92 | */ | ||
93 | #define MIN_THREADS 20 | ||
94 | |||
95 | /* | ||
96 | * Maximum number of threads | ||
97 | */ | ||
98 | #define MAX_THREADS FUTEX_TID_MASK | ||
99 | |||
100 | /* | ||
91 | * Protected counters by write_lock_irq(&tasklist_lock) | 101 | * Protected counters by write_lock_irq(&tasklist_lock) |
92 | */ | 102 | */ |
93 | unsigned long total_forks; /* Handle normal Linux uptimes. */ | 103 | unsigned long total_forks; /* Handle normal Linux uptimes. */ |
@@ -258,18 +268,19 @@ void __init __weak arch_task_cache_init(void) { } | |||
258 | */ | 268 | */ |
259 | static void set_max_threads(void) | 269 | static void set_max_threads(void) |
260 | { | 270 | { |
261 | /* | 271 | u64 threads; |
262 | * The default maximum number of threads is set to a safe | ||
263 | * value: the thread structures can take up at most one | ||
264 | * eighth of the memory. | ||
265 | */ | ||
266 | max_threads = totalram_pages / (8 * THREAD_SIZE / PAGE_SIZE); | ||
267 | 272 | ||
268 | /* | 273 | /* |
269 | * we need to allow at least 20 threads to boot a system | 274 | * The number of threads shall be limited such that the thread |
275 | * structures may only consume a small part of the available memory. | ||
270 | */ | 276 | */ |
271 | if (max_threads < 20) | 277 | if (fls64(totalram_pages) + fls64(PAGE_SIZE) > 64) |
272 | max_threads = 20; | 278 | threads = MAX_THREADS; |
279 | else | ||
280 | threads = div64_u64((u64) totalram_pages * (u64) PAGE_SIZE, | ||
281 | (u64) THREAD_SIZE * 8UL); | ||
282 | |||
283 | max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS); | ||
273 | } | 284 | } |
274 | 285 | ||
275 | void __init fork_init(void) | 286 | void __init fork_init(void) |