mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 12:57:06 +09:00
mm: optimize thread stack usage on arm64 [1/1]
PD#SWPL-1219 Problem: On arm64, thread stack is 16KB for each task. If running task number is large, this type of memory may over 40MB. It's a large amount on small memory platform. But most case thread only use less 4KB stack. It's waste of memory and we need optimize it. Solution: 1. Pre-allocate a vmalloc address space for task stack; 2. Only map 1st page for stack and handle page fault in EL1 when stack growth triggered exception; 3. handle stack switch for exception. Verify: p212 Change-Id: I47f511ccfa2868d982bc10a820ed6435b6d52ba9 Signed-off-by: tao zeng <tao.zeng@amlogic.com>
This commit is contained in:
@@ -86,6 +86,10 @@
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_VMAP
|
||||
#include <linux/amlogic/vmap_stack.h>
|
||||
#endif
|
||||
|
||||
#include <trace/events/sched.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
@@ -209,15 +213,22 @@ static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
|
||||
tsk->stack_vm_area = find_vm_area(stack);
|
||||
return stack;
|
||||
#else
|
||||
#ifdef CONFIG_AMLOGIC_VMAP
|
||||
return aml_stack_alloc(node, tsk);
|
||||
#else /* CONFIG_AMLOGIC_VMAP */
|
||||
struct page *page = alloc_pages_node(node, THREADINFO_GFP,
|
||||
THREAD_SIZE_ORDER);
|
||||
|
||||
return page ? page_address(page) : NULL;
|
||||
#endif /* CONFIG_AMLOGIC_VMAP */
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void free_thread_stack(struct task_struct *tsk)
|
||||
{
|
||||
#ifdef CONFIG_AMLOGIC_VMAP
|
||||
aml_stack_free(tsk);
|
||||
#else /* CONFIG_AMLOGIC_VMAP */
|
||||
kaiser_unmap_thread_stack(tsk->stack);
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
if (task_stack_vm_area(tsk)) {
|
||||
@@ -241,6 +252,7 @@ static inline void free_thread_stack(struct task_struct *tsk)
|
||||
#endif
|
||||
|
||||
__free_pages(virt_to_page(tsk->stack), THREAD_SIZE_ORDER);
|
||||
#endif /* CONFIG_AMLOGIC_VMAP */
|
||||
}
|
||||
# else
|
||||
static struct kmem_cache *thread_stack_cache;
|
||||
@@ -285,6 +297,9 @@ static struct kmem_cache *mm_cachep;
|
||||
|
||||
static void account_kernel_stack(struct task_struct *tsk, int account)
|
||||
{
|
||||
#ifdef CONFIG_AMLOGIC_VMAP
|
||||
aml_account_task_stack(tsk, account);
|
||||
#else
|
||||
void *stack = task_stack_page(tsk);
|
||||
struct vm_struct *vm = task_stack_vm_area(tsk);
|
||||
|
||||
@@ -317,6 +332,7 @@ static void account_kernel_stack(struct task_struct *tsk, int account)
|
||||
memcg_kmem_update_page_stat(first_page, MEMCG_KERNEL_STACK_KB,
|
||||
account * (THREAD_SIZE / 1024));
|
||||
}
|
||||
#endif /* CONFIG_AMLOGIC_VMAP*/
|
||||
}
|
||||
|
||||
static void release_task_stack(struct task_struct *tsk)
|
||||
@@ -468,12 +484,23 @@ int __weak arch_dup_task_struct(struct task_struct *dst,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_VMAP
|
||||
static bool first_magic __read_mostly;
|
||||
#endif
|
||||
|
||||
void set_task_stack_end_magic(struct task_struct *tsk)
|
||||
{
|
||||
unsigned long *stackend;
|
||||
|
||||
stackend = end_of_stack(tsk);
|
||||
#ifdef CONFIG_AMLOGIC_VMAP
|
||||
if (unlikely(!first_magic)) {
|
||||
*stackend = STACK_END_MAGIC; /* for overflow detection */
|
||||
first_magic = 1;
|
||||
}
|
||||
#else
|
||||
*stackend = STACK_END_MAGIC; /* for overflow detection */
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
|
||||
|
||||
Reference in New Issue
Block a user