
From: Jeff Dike <jdike@addtoit.com>

On 2.4 hosts signals are delivered in numeric order when there are multiple
pending at a given time.  UML developed a subtle dependency on this
ordering, which broke on 2.6 hosts and the separate process and thread
signal queues.

This patch eliminates that dependency.

Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/um/kernel/process.c         |    2 +-
 25-akpm/arch/um/kernel/tt/exec_kern.c    |    3 +++
 25-akpm/arch/um/kernel/tt/process_kern.c |   18 +++++++++++++++++-
 25-akpm/arch/um/kernel/tt/trap_user.c    |    2 --
 25-akpm/arch/um/os-Linux/process.c       |    4 ----
 5 files changed, 21 insertions(+), 8 deletions(-)

diff -puN arch/um/kernel/process.c~uml-eliminate-signal-order-delivery-dependency arch/um/kernel/process.c
--- 25/arch/um/kernel/process.c~uml-eliminate-signal-order-delivery-dependency	Tue Sep 14 18:29:24 2004
+++ 25-akpm/arch/um/kernel/process.c	Tue Sep 14 18:29:24 2004
@@ -70,7 +70,7 @@ void init_new_thread_signals(int altstac
 	set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags, 
 		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
 	set_handler(SIGUSR2, (__sighandler_t) sig_handler, 
-		    SA_NOMASK | flags, -1);
+		    flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
 	signal(SIGHUP, SIG_IGN);
 
 	init_irq_signals(altstack);
diff -puN arch/um/kernel/tt/exec_kern.c~uml-eliminate-signal-order-delivery-dependency arch/um/kernel/tt/exec_kern.c
--- 25/arch/um/kernel/tt/exec_kern.c~uml-eliminate-signal-order-delivery-dependency	Tue Sep 14 18:29:24 2004
+++ 25-akpm/arch/um/kernel/tt/exec_kern.c	Tue Sep 14 18:29:24 2004
@@ -14,6 +14,7 @@
 #include "kern_util.h"
 #include "irq_user.h"
 #include "time_user.h"
+#include "signal_user.h"
 #include "mem_user.h"
 #include "os.h"
 #include "tlb.h"
@@ -53,7 +54,9 @@ void flush_thread_tt(void)
 	current->thread.request.u.exec.pid = new_pid;
 	unprotect_stack((unsigned long) current_thread);
 	os_usr1_process(os_getpid());
+	change_sig(SIGUSR1, 1);
 
+	change_sig(SIGUSR1, 0);
 	enable_timer();
 	free_page(stack);
 	protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
diff -puN arch/um/kernel/tt/process_kern.c~uml-eliminate-signal-order-delivery-dependency arch/um/kernel/tt/process_kern.c
--- 25/arch/um/kernel/tt/process_kern.c~uml-eliminate-signal-order-delivery-dependency	Tue Sep 14 18:29:24 2004
+++ 25-akpm/arch/um/kernel/tt/process_kern.c	Tue Sep 14 18:29:24 2004
@@ -201,6 +201,7 @@ static int new_thread_proc(void *stack)
 	local_irq_disable();
 	init_new_thread_stack(stack, new_thread_handler);
 	os_usr1_process(os_getpid());
+	change_sig(SIGUSR1, 1);
 	return(0);
 }
 
@@ -244,6 +245,7 @@ int fork_tramp(void *stack)
 	init_new_thread_stack(stack, finish_fork_handler);
 
 	os_usr1_process(os_getpid());
+	change_sig(SIGUSR1, 1);
 	return(0);
 }
 
@@ -295,19 +297,30 @@ int copy_thread_tt(int nr, unsigned long
 	current->thread.request.op = OP_FORK;
 	current->thread.request.u.fork.pid = new_pid;
 	os_usr1_process(os_getpid());
-	return(0);
+
+	/* Enable the signal and then disable it to ensure that it is handled
+	 * here, and nowhere else.
+	 */
+	change_sig(SIGUSR1, 1);
+
+	change_sig(SIGUSR1, 0);
+	err = 0;
+ out:
+	return(err);
 }
 
 void reboot_tt(void)
 {
 	current->thread.request.op = OP_REBOOT;
 	os_usr1_process(os_getpid());
+	change_sig(SIGUSR1, 1);
 }
 
 void halt_tt(void)
 {
 	current->thread.request.op = OP_HALT;
 	os_usr1_process(os_getpid());
+	change_sig(SIGUSR1, 1);
 }
 
 void kill_off_processes_tt(void)
@@ -334,6 +347,9 @@ void initial_thread_cb_tt(void (*proc)(v
 		current->thread.request.u.cb.proc = proc;
 		current->thread.request.u.cb.arg = arg;
 		os_usr1_process(os_getpid());
+		change_sig(SIGUSR1, 1);
+
+		change_sig(SIGUSR1, 0);
 	}
 }
 
diff -puN arch/um/kernel/tt/trap_user.c~uml-eliminate-signal-order-delivery-dependency arch/um/kernel/tt/trap_user.c
--- 25/arch/um/kernel/tt/trap_user.c~uml-eliminate-signal-order-delivery-dependency	Tue Sep 14 18:29:24 2004
+++ 25-akpm/arch/um/kernel/tt/trap_user.c	Tue Sep 14 18:29:24 2004
@@ -37,7 +37,6 @@ void sig_handler_common_tt(int sig, void
 	if(sig != SIGUSR2) 
 		r->syscall = -1;
 
-	change_sig(SIGUSR1, 1);
 	info = &sig_info[sig];
 	if(!info->is_irq) unblock_signals();
 
@@ -46,7 +45,6 @@ void sig_handler_common_tt(int sig, void
 	if(is_user){
 		interrupt_end();
 		block_signals();
-		change_sig(SIGUSR1, 0);
 		set_user_mode(NULL);
 	}
 	*r = save_regs;
diff -puN arch/um/os-Linux/process.c~uml-eliminate-signal-order-delivery-dependency arch/um/os-Linux/process.c
--- 25/arch/um/os-Linux/process.c~uml-eliminate-signal-order-delivery-dependency	Tue Sep 14 18:29:24 2004
+++ 25-akpm/arch/um/os-Linux/process.c	Tue Sep 14 18:29:24 2004
@@ -96,11 +96,7 @@ void os_kill_process(int pid, int reap_c
 
 void os_usr1_process(int pid)
 {
-#ifdef __NR_tkill
-	syscall(__NR_tkill, pid, SIGUSR1);
-#else
 	kill(pid, SIGUSR1);
-#endif
 }
 
 int os_getpid(void)
_
