Skip to content

Commit e540bf3

Browse files
Sebastian Andrzej SiewiorKAGA-KOKO
authored andcommitted
fork: Only cache the VMAP stack in finish_task_switch()
The task stack could be deallocated later, but for fork()/exec() kind of workloads (say a shell script executing several commands) it is important that the stack is released in finish_task_switch() so that in VMAP_STACK case it can be cached and reused in the new task. For PREEMPT_RT it would be good if the wake-up in vfree_atomic() could be avoided in the scheduling path. Far worse are the other free_thread_stack() implementations which invoke __free_pages()/ kmem_cache_free() with disabled preemption. Cache the stack in free_thread_stack() in the VMAP_STACK case and RCU-delay the free path otherwise. Free the stack in the RCU callback. In the VMAP_STACK case this is another opportunity to fill the cache. Signed-off-by: Sebastian Andrzej Siewior <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Acked-by: Andy Lutomirski <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 1a03d3f commit e540bf3

File tree

1 file changed

+63
-13
lines changed

1 file changed

+63
-13
lines changed

kernel/fork.c

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,41 @@ static inline void free_task_struct(struct task_struct *tsk)
193193
#define NR_CACHED_STACKS 2
194194
static DEFINE_PER_CPU(struct vm_struct *, cached_stacks[NR_CACHED_STACKS]);
195195

196+
struct vm_stack {
197+
struct rcu_head rcu;
198+
struct vm_struct *stack_vm_area;
199+
};
200+
201+
static bool try_release_thread_stack_to_cache(struct vm_struct *vm)
202+
{
203+
unsigned int i;
204+
205+
for (i = 0; i < NR_CACHED_STACKS; i++) {
206+
if (this_cpu_cmpxchg(cached_stacks[i], NULL, vm) != NULL)
207+
continue;
208+
return true;
209+
}
210+
return false;
211+
}
212+
213+
static void thread_stack_free_rcu(struct rcu_head *rh)
214+
{
215+
struct vm_stack *vm_stack = container_of(rh, struct vm_stack, rcu);
216+
217+
if (try_release_thread_stack_to_cache(vm_stack->stack_vm_area))
218+
return;
219+
220+
vfree(vm_stack);
221+
}
222+
223+
static void thread_stack_delayed_free(struct task_struct *tsk)
224+
{
225+
struct vm_stack *vm_stack = tsk->stack;
226+
227+
vm_stack->stack_vm_area = tsk->stack_vm_area;
228+
call_rcu(&vm_stack->rcu, thread_stack_free_rcu);
229+
}
230+
196231
static int free_vm_stack_cache(unsigned int cpu)
197232
{
198233
struct vm_struct **cached_vm_stacks = per_cpu_ptr(cached_stacks, cpu);
@@ -296,24 +331,27 @@ static int alloc_thread_stack_node(struct task_struct *tsk, int node)
296331

297332
static void free_thread_stack(struct task_struct *tsk)
298333
{
299-
int i;
334+
if (!try_release_thread_stack_to_cache(tsk->stack_vm_area))
335+
thread_stack_delayed_free(tsk);
300336

301-
for (i = 0; i < NR_CACHED_STACKS; i++) {
302-
if (this_cpu_cmpxchg(cached_stacks[i], NULL,
303-
tsk->stack_vm_area) != NULL)
304-
continue;
305-
306-
tsk->stack = NULL;
307-
tsk->stack_vm_area = NULL;
308-
return;
309-
}
310-
vfree_atomic(tsk->stack);
311337
tsk->stack = NULL;
312338
tsk->stack_vm_area = NULL;
313339
}
314340

315341
# else /* !CONFIG_VMAP_STACK */
316342

343+
static void thread_stack_free_rcu(struct rcu_head *rh)
344+
{
345+
__free_pages(virt_to_page(rh), THREAD_SIZE_ORDER);
346+
}
347+
348+
static void thread_stack_delayed_free(struct task_struct *tsk)
349+
{
350+
struct rcu_head *rh = tsk->stack;
351+
352+
call_rcu(rh, thread_stack_free_rcu);
353+
}
354+
317355
static int alloc_thread_stack_node(struct task_struct *tsk, int node)
318356
{
319357
struct page *page = alloc_pages_node(node, THREADINFO_GFP,
@@ -328,7 +366,7 @@ static int alloc_thread_stack_node(struct task_struct *tsk, int node)
328366

329367
static void free_thread_stack(struct task_struct *tsk)
330368
{
331-
__free_pages(virt_to_page(tsk->stack), THREAD_SIZE_ORDER);
369+
thread_stack_delayed_free(tsk);
332370
tsk->stack = NULL;
333371
}
334372

@@ -337,6 +375,18 @@ static void free_thread_stack(struct task_struct *tsk)
337375

338376
static struct kmem_cache *thread_stack_cache;
339377

378+
static void thread_stack_free_rcu(struct rcu_head *rh)
379+
{
380+
kmem_cache_free(thread_stack_cache, rh);
381+
}
382+
383+
static void thread_stack_delayed_free(struct task_struct *tsk)
384+
{
385+
struct rcu_head *rh = tsk->stack;
386+
387+
call_rcu(rh, thread_stack_free_rcu);
388+
}
389+
340390
static int alloc_thread_stack_node(struct task_struct *tsk, int node)
341391
{
342392
unsigned long *stack;
@@ -348,7 +398,7 @@ static int alloc_thread_stack_node(struct task_struct *tsk, int node)
348398

349399
static void free_thread_stack(struct task_struct *tsk)
350400
{
351-
kmem_cache_free(thread_stack_cache, tsk->stack);
401+
thread_stack_delayed_free(tsk);
352402
tsk->stack = NULL;
353403
}
354404

0 commit comments

Comments
 (0)