|
@@ -74,6 +74,7 @@
|
|
|
#include <linux/uprobes.h>
|
|
|
#include <linux/aio.h>
|
|
|
#include <linux/compiler.h>
|
|
|
+#include <linux/sysctl.h>
|
|
|
|
|
|
#include <asm/pgtable.h>
|
|
|
#include <asm/pgalloc.h>
|
|
@@ -266,7 +267,7 @@ void __init __weak arch_task_cache_init(void) { }
|
|
|
/*
|
|
|
* set_max_threads
|
|
|
*/
|
|
|
-static void set_max_threads(void)
|
|
|
+static void set_max_threads(unsigned int max_threads_suggested)
|
|
|
{
|
|
|
u64 threads;
|
|
|
|
|
@@ -280,6 +281,9 @@ static void set_max_threads(void)
|
|
|
threads = div64_u64((u64) totalram_pages * (u64) PAGE_SIZE,
|
|
|
(u64) THREAD_SIZE * 8UL);
|
|
|
|
|
|
+ if (threads > max_threads_suggested)
|
|
|
+ threads = max_threads_suggested;
|
|
|
+
|
|
|
max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS);
|
|
|
}
|
|
|
|
|
@@ -298,7 +302,7 @@ void __init fork_init(void)
|
|
|
/* do the arch specific task caches init */
|
|
|
arch_task_cache_init();
|
|
|
|
|
|
- set_max_threads();
|
|
|
+ set_max_threads(MAX_THREADS);
|
|
|
|
|
|
init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
|
|
|
init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
|
|
@@ -2020,3 +2024,26 @@ int unshare_files(struct files_struct **displaced)
|
|
|
task_unlock(task);
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+int sysctl_max_threads(struct ctl_table *table, int write,
|
|
|
+ void __user *buffer, size_t *lenp, loff_t *ppos)
|
|
|
+{
|
|
|
+ struct ctl_table t;
|
|
|
+ int ret;
|
|
|
+ int threads = max_threads;
|
|
|
+ int min = MIN_THREADS;
|
|
|
+ int max = MAX_THREADS;
|
|
|
+
|
|
|
+ t = *table;
|
|
|
+ t.data = &threads;
|
|
|
+ t.extra1 = &min;
|
|
|
+ t.extra2 = &max;
|
|
|
+
|
|
|
+ ret = proc_dointvec_minmax(&t, write, buffer, lenp, ppos);
|
|
|
+ if (ret || !write)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ set_max_threads(threads);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|