Update of /cvsroot/linux-vax/kernel-2.5/arch/vax/kernel
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6348
Modified Files:
process.c
Log Message:
Fix kernel_thread(). I'm surprised it ever worked!
Firstly, GCC 4.1 doesn't seem to notice the "clobbers AP" in the
asm() block, and tries to use the modified AP to get fn and arg
in the call to kernel_thread_exit(). Secondly, there is no
guarantee that the location AP points to will still contain
the argument list (CLONE_VM turns off copy-on-write, so if the
parent runs first and overwrites that portion of memory, AP will
point to garbage). For some reason, this never occurred with the
old toolchain, but happens with our GGC4.1 toolchain. So, we
pull fn and arg into R2 and R3, and do all the work within
the asm() block.
Index: process.c
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.5/arch/vax/kernel/process.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- process.c 9 May 2005 20:34:28 -0000 1.29
+++ process.c 29 May 2005 12:10:54 -0000 1.30
@@ -174,19 +174,14 @@
*/
}
-static ATTRIB_NORET void kernel_thread_exit(int exitcode)
-{
- __chmk(__NR_exit);
- while (1)
- /* Keep GCC happy */;
-}
-
/*
* Create a kernel thread
*/
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
asm(
+ " movl %2,%%r2 \n"
+ " movl %3,%%r3 \n"
" clrl -(%%sp) \n"
" movl %0, -(%%sp) \n"
" pushl $0x2 \n"
@@ -196,20 +191,20 @@
" beql child \n"
" ret \n"
"child: \n"
+ " pushl %%r3 \n"
+ " calls $1, *%%r2 \n"
+ " pushl %%r0 \n"
+ " movl %%sp, %%ap \n"
+ " chmk %4 \n"
: /* no outputs */
- : "g"(flags | CLONE_VM), "g"(__NR_clone)
- : "r0", "ap");
+ : "g"(flags | CLONE_VM), "g"(__NR_clone), "g"(fn), "g"(arg), "g"(__NR_exit)
+ : "r0", "r2", "r3");
/*
- * In child. At this point SP points to the very top of
- * our kernel stack, so we cannot pop anything off. That
- * means that we can never return from here.
+ * We never actually get here - there is a RET embedded above which
+ * returns in the parent, and the child exits with the CHMK __NR_exit
*/
-#ifdef VAX_PROCESS_DEBUG
- printk("kernel_thread: task %p, pid %d, calling thread function at %08lx\n",
- current, current->pid, (unsigned long) fn);
-#endif
- kernel_thread_exit(fn(arg));
+ return 0;
}
int sys_clone(unsigned long clone_flags, unsigned long newsp, struct pt_regs *regs)
|