Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

alpha: reorganize copy_process(), prepare to saner fork_idle()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro 25906730 b960f303

+14 -21
+14 -21
arch/alpha/kernel/process.c
··· 266 266 int 267 267 copy_thread(unsigned long clone_flags, unsigned long usp, 268 268 unsigned long arg, 269 - struct task_struct * p, struct pt_regs * regs) 269 + struct task_struct *p, struct pt_regs *wontuse) 270 270 { 271 271 extern void ret_from_fork(void); 272 272 extern void ret_from_kernel_thread(void); 273 273 274 274 struct thread_info *childti = task_thread_info(p); 275 275 struct pt_regs *childregs = task_pt_regs(p); 276 + struct pt_regs *regs = current_pt_regs(); 276 277 struct switch_stack *childstack, *stack; 277 278 unsigned long settls; 278 279 279 280 childstack = ((struct switch_stack *) childregs) - 1; 280 - if (unlikely(!regs)) { 281 + childti->pcb.ksp = (unsigned long) childstack; 282 + childti->pcb.flags = 1; /* set FEN, clear everything else */ 283 + 284 + if (unlikely(p->flags & PF_KTHREAD)) { 281 285 /* kernel thread */ 282 286 memset(childstack, 0, 283 287 sizeof(struct switch_stack) + sizeof(struct pt_regs)); ··· 290 286 childstack->r10 = arg; 291 287 childregs->hae = alpha_mv.hae_cache, 292 288 childti->pcb.usp = 0; 293 - childti->pcb.ksp = (unsigned long) childstack; 294 - childti->pcb.flags = 1; /* set FEN, clear everything else */ 295 289 return 0; 296 290 } 291 + /* Note: if CLONE_SETTLS is not set, then we must inherit the 292 + value from the parent, which will have been set by the block 293 + copy in dup_task_struct. This is non-intuitive, but is 294 + required for proper operation in the case of a threaded 295 + application calling fork. */ 296 + if (clone_flags & CLONE_SETTLS) 297 + childti->pcb.unique = regs->r20; 298 + childti->pcb.usp = usp ?: rdusp(); 297 299 *childregs = *regs; 298 - settls = regs->r20; 299 300 childregs->r0 = 0; 300 301 childregs->r19 = 0; 301 302 childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ ··· 308 299 stack = ((struct switch_stack *) regs) - 1; 309 300 *childstack = *stack; 310 301 childstack->r26 = (unsigned long) ret_from_fork; 311 - childti->pcb.usp = usp ?: rdusp(); 312 - childti->pcb.ksp = (unsigned long) childstack; 313 - childti->pcb.flags = 1; /* set FEN, clear everything else */ 314 - 315 - /* Set a new TLS for the child thread? Peek back into the 316 - syscall arguments that we saved on syscall entry. Oops, 317 - except we'd have clobbered it with the parent/child set 318 - of r20. Read the saved copy. */ 319 - /* Note: if CLONE_SETTLS is not set, then we must inherit the 320 - value from the parent, which will have been set by the block 321 - copy in dup_task_struct. This is non-intuitive, but is 322 - required for proper operation in the case of a threaded 323 - application calling fork. */ 324 - if (clone_flags & CLONE_SETTLS) 325 - childti->pcb.unique = settls; 326 - 327 302 return 0; 328 303 } 329 304