[PATCH 1/4 v4] kernel/fork.c: new function for max_threads

Heinrich Schuchardt
2015-02-23T20:15:32Z

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 this patch the buggy code is moved to a separate function
set_max_threads. The error is not fixed.

After fixing the problem in a separate patch the new function can be
reused to adjust max_threads after adding or removing memory.

Argument mempages of function fork_init() is removed as totalram_pages
is an exported symbol.

The creation of separate patches for refactoring to a new function
and for fixing the logic was requested by Ingo Molnar.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
init/main.c | 4 ++--
kernel/fork.c | 39 ++++++++++++++++++++++++---------------
2 files changed, 26 insertions(+), 17 deletions(-)

diff --git a/init/main.c b/init/main.c
index 61b99376..21394ec 100644
--- a/init/main.c
+++ b/init/main.c
@@ -94,7 +94,7 @@
static int kernel_init(void *);

extern void init_IRQ(void);
-extern void fork_init(unsigned long);
+extern void fork_init(void);
extern void radix_tree_init(void);
#ifndef CONFIG_DEBUG_RODATA
static inline void mark_rodata_ro(void) { }
@@ -655,7 +655,7 @@ asmlinkage __visible void __init start_kernel(void)
#endif
thread_info_cache_init();
cred_init();
- fork_init(totalram_pages);
+ fork_init();
proc_caches_init();
buffer_init();
key_init();
diff --git a/kernel/fork.c b/kernel/fork.c
index 4dc2dda..3a423b2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -253,27 +253,18 @@ EXPORT_SYMBOL_GPL(__put_task_struct);

void __init __weak arch_task_cache_init(void) { }

-void __init fork_init(unsigned long mempages)
+/*
+ * set_max_threads
+ * The argument is ignored.
+ */
+static void set_max_threads(unsigned int max_threads_suggested)
{
-#ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR
-#ifndef ARCH_MIN_TASKALIGN
-#define ARCH_MIN_TASKALIGN L1_CACHE_BYTES
-#endif
- /* create a slab on which task_structs can be allocated */
- task_struct_cachep =
- kmem_cache_create("task_struct", sizeof(struct task_struct),
- ARCH_MIN_TASKALIGN, SLAB_PANIC | SLAB_NOTRACK, NULL);
-#endif
-
- /* do the arch specific task caches init */
- arch_task_cache_init();
-
/*
* The default maximum number of threads is set to a safe
* value: the thread structures can take up at most half
* of memory.
*/
- max_threads = mempages / (8 * THREAD_SIZE / PAGE_SIZE);
+ max_threads = totalram_pages / (8 * THREAD_SIZE / PAGE_SIZE);

/*
* we need to allow at least 20 threads to boot a system
@@ -287,6 +278,24 @@ void __init fork_init(unsigned long mempages)
init_task.signal->rlim[RLIMIT_NPROC];
}

+void __init fork_init(void)
+{
+#ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR
+#ifndef ARCH_MIN_TASKALIGN
+#define ARCH_MIN_TASKALIGN L1_CACHE_BYTES
+#endif
+ /* create a slab on which task_structs can be allocated */
+ task_struct_cachep =
+ kmem_cache_create("task_struct", sizeof(struct task_struct),
+ ARCH_MIN_TASKALIGN, SLAB_PANIC | SLAB_NOTRACK, NULL);
+#endif
+
+ /* do the arch specific task caches init */
+ arch_task_cache_init();
+
+ set_max_threads(UINT_MAX);
+}
+
int __weak arch_dup_task_struct(struct task_struct *dst,
struct task_struct *src)
{
--
2.1.4