From: Paolo 'Blaisorblade' Giarrusso <[email-masked]>

From: Bodo Stroesser <[email-masked]>,
      Paolo 'Blaisorblade' Giarrusso <[email-masked]>
Cc: Ulrich Drepper <[email-masked]>

Using NPTL, getpid() sometimes delivers the wrong pid, since it uses the
one buffered in TLS from previous calls.  This buffered pid isn't
discarded, when a child is created by a clone().

So, as a workaround, UML should use a direct kernel call to bypass the lib.

Also, I (Paolo) went replacing all remaining calls of getpid() with
os_getpid(), to make sure they use the syscall and not the normal glibc
definition.

Signed-off-by: Bodo Stroesser <[email-masked]>
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <[email-masked]>
Signed-off-by: Andrew Morton <[email-masked]>
---

 25-akpm/arch/um/kernel/frame.c        |    8 ++++----
 25-akpm/arch/um/kernel/main.c         |    3 ++-
 25-akpm/arch/um/kernel/skas/process.c |    2 +-
 25-akpm/arch/um/os-Linux/process.c    |    4 ++++
 4 files changed, 11 insertions(+), 6 deletions(-)

diff -puN arch/um/kernel/frame.c~uml-use-sys_getpid-bypassing-glibc-fixes-uml-on-gentoo arch/um/kernel/frame.c
--- 25/arch/um/kernel/frame.c~uml-use-sys_getpid-bypassing-glibc-fixes-uml-on-gentoo	Wed Nov 10 13:40:04 2004
+++ 25-akpm/arch/um/kernel/frame.c	Wed Nov 10 13:40:04 2004
@@ -140,7 +140,7 @@ static void child_common(struct common_r
 	}
 	if(sigaltstack(&ss, NULL) < 0){
 		printf("sigaltstack failed - errno = %d\n", errno);
-		kill(getpid(), SIGKILL);
+		kill(os_getpid(), SIGKILL);
 	}
 
 	if(restorer){
@@ -162,7 +162,7 @@ static void child_common(struct common_r
 	
 	if(err < 0){
 		printf("sigaction failed - errno = %d\n", errno);
-		kill(getpid(), SIGKILL);
+		kill(os_getpid(), SIGKILL);
 	}
 
 	os_stop_process(os_getpid());
@@ -191,7 +191,7 @@ static void sc_handler(int sig, struct s
 	setup_arch_frame_raw(&raw_sc->common.arch, &sc + 1, raw_sc->common.sr);
 
 	os_stop_process(os_getpid());
-	kill(getpid(), SIGKILL);
+	kill(os_getpid(), SIGKILL);
 }
 
 static int sc_child(void *arg)
@@ -229,7 +229,7 @@ static void si_handler(int sig, siginfo_
 			     ucontext->uc_mcontext.fpregs, raw_si->common.sr);
 	
 	os_stop_process(os_getpid());
-	kill(getpid(), SIGKILL);
+	kill(os_getpid(), SIGKILL);
 }
 
 static int si_child(void *arg)
diff -puN arch/um/kernel/main.c~uml-use-sys_getpid-bypassing-glibc-fixes-uml-on-gentoo arch/um/kernel/main.c
--- 25/arch/um/kernel/main.c~uml-use-sys_getpid-bypassing-glibc-fixes-uml-on-gentoo	Wed Nov 10 13:40:04 2004
+++ 25-akpm/arch/um/kernel/main.c	Wed Nov 10 13:40:04 2004
@@ -26,6 +26,7 @@
 #include "uml-config.h"
 #include "irq_user.h"
 #include "time_user.h"
+#include "os.h"
 
 /* Set in set_stklim, which is called from main and __wrap_malloc.
  * __wrap_malloc only calls it if main hasn't started.
@@ -175,7 +176,7 @@ int main(int argc, char **argv, char **e
 }
 
 #define CAN_KMALLOC() \
-	(kmalloc_ok && CHOOSE_MODE((getpid() != tracing_pid), 1))
+	(kmalloc_ok && CHOOSE_MODE((os_getpid() != tracing_pid), 1))
 
 extern void *__real_malloc(int);
 
diff -puN arch/um/kernel/skas/process.c~uml-use-sys_getpid-bypassing-glibc-fixes-uml-on-gentoo arch/um/kernel/skas/process.c
--- 25/arch/um/kernel/skas/process.c~uml-use-sys_getpid-bypassing-glibc-fixes-uml-on-gentoo	Wed Nov 10 13:40:04 2004
+++ 25-akpm/arch/um/kernel/skas/process.c	Wed Nov 10 13:40:04 2004
@@ -30,7 +30,7 @@
 
 int is_skas_winch(int pid, int fd, void *data)
 {
-	if(pid != getpid())
+	if(pid != os_getpid())
 		return(0);
 
 	register_winch_irq(-1, fd, -1, data);
diff -puN arch/um/os-Linux/process.c~uml-use-sys_getpid-bypassing-glibc-fixes-uml-on-gentoo arch/um/os-Linux/process.c
--- 25/arch/um/os-Linux/process.c~uml-use-sys_getpid-bypassing-glibc-fixes-uml-on-gentoo	Wed Nov 10 13:40:04 2004
+++ 25-akpm/arch/um/os-Linux/process.c	Wed Nov 10 13:40:04 2004
@@ -107,6 +107,10 @@ void os_usr1_process(int pid)
 	kill(pid, SIGUSR1);
 }
 
+/*Don't use the glibc version, which caches the result in TLS. It misses some
+ * syscalls, and also breaks with clone(), which does not unshare the TLS.*/
+inline _syscall0(pid_t, getpid)
+
 int os_getpid(void)
 {
 	return(getpid());
_