aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c16
1 files changed, 5 insertions, 11 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index 0f69a3e5281e..d2b9d7c31eaf 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -205,19 +205,17 @@ static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
205 void *stack; 205 void *stack;
206 int i; 206 int i;
207 207
208 local_irq_disable();
209 for (i = 0; i < NR_CACHED_STACKS; i++) { 208 for (i = 0; i < NR_CACHED_STACKS; i++) {
210 struct vm_struct *s = this_cpu_read(cached_stacks[i]); 209 struct vm_struct *s;
210
211 s = this_cpu_xchg(cached_stacks[i], NULL);
211 212
212 if (!s) 213 if (!s)
213 continue; 214 continue;
214 this_cpu_write(cached_stacks[i], NULL);
215 215
216 tsk->stack_vm_area = s; 216 tsk->stack_vm_area = s;
217 local_irq_enable();
218 return s->addr; 217 return s->addr;
219 } 218 }
220 local_irq_enable();
221 219
222 stack = __vmalloc_node_range(THREAD_SIZE, THREAD_SIZE, 220 stack = __vmalloc_node_range(THREAD_SIZE, THREAD_SIZE,
223 VMALLOC_START, VMALLOC_END, 221 VMALLOC_START, VMALLOC_END,
@@ -245,19 +243,15 @@ static inline void free_thread_stack(struct task_struct *tsk)
245{ 243{
246#ifdef CONFIG_VMAP_STACK 244#ifdef CONFIG_VMAP_STACK
247 if (task_stack_vm_area(tsk)) { 245 if (task_stack_vm_area(tsk)) {
248 unsigned long flags;
249 int i; 246 int i;
250 247
251 local_irq_save(flags);
252 for (i = 0; i < NR_CACHED_STACKS; i++) { 248 for (i = 0; i < NR_CACHED_STACKS; i++) {
253 if (this_cpu_read(cached_stacks[i])) 249 if (this_cpu_cmpxchg(cached_stacks[i],
250 NULL, tsk->stack_vm_area) != NULL)
254 continue; 251 continue;
255 252
256 this_cpu_write(cached_stacks[i], tsk->stack_vm_area);
257 local_irq_restore(flags);
258 return; 253 return;
259 } 254 }
260 local_irq_restore(flags);
261 255
262 vfree_atomic(tsk->stack); 256 vfree_atomic(tsk->stack);
263 return; 257 return;