Commit bc4cf2bb authored by Chris Metcalf's avatar Chris Metcalf

arch/tile: handle CLONE_SETTLS in copy_thread(), not user space

Previously we were just setting up the "tp" register in the
new task as started by clone() in libc.  However, this is not
quite right, since in principle a signal might be delivered to
the new task before it had its TLS set up.  (Of course, this race
window still exists for resetting the libc getpid() cached value
in the new task, in principle.  But in any case, we are now doing
this exactly the way all other architectures do it.)

This change is important for 2.6.37 since the tile glibc we will
be submitting upstream will not set TLS in user space any more,
so it will only work on a kernel that has this fix.  It should
also be taken for 2.6.36.x in the stable tree if possible.
Signed-off-by: default avatarChris Metcalf <cmetcalf@tilera.com>
Cc: stable <stable@kernel.org>
parent 5111711d
...@@ -211,6 +211,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, ...@@ -211,6 +211,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
childregs->regs[0] = 0; /* return value is zero */ childregs->regs[0] = 0; /* return value is zero */
childregs->sp = sp; /* override with new user stack pointer */ childregs->sp = sp; /* override with new user stack pointer */
/*
* If CLONE_SETTLS is set, set "tp" in the new task to "r4",
* which is passed in as arg #5 to sys_clone().
*/
if (clone_flags & CLONE_SETTLS)
childregs->tp = regs->regs[4];
/* /*
* Copy the callee-saved registers from the passed pt_regs struct * Copy the callee-saved registers from the passed pt_regs struct
* into the context-switch callee-saved registers area. * into the context-switch callee-saved registers area.
...@@ -539,6 +546,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev, ...@@ -539,6 +546,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
return __switch_to(prev, next, next_current_ksp0(next)); return __switch_to(prev, next, next_current_ksp0(next));
} }
/* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */
SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
void __user *, parent_tidptr, void __user *, child_tidptr, void __user *, parent_tidptr, void __user *, child_tidptr,
struct pt_regs *, regs) struct pt_regs *, regs)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment