diff -urNp ref/arch/um/include/user_util.h o1/arch/um/include/user_util.h --- ref/arch/um/include/user_util.h Sat Jul 20 13:58:53 2002 +++ o1/arch/um/include/user_util.h Sat Jul 20 13:59:07 2002 @@ -111,6 +111,7 @@ extern int arch_handle_signal(int sig, s extern void user_time_init(void); extern unsigned long pid_pc(int pid); extern int arch_fixup(unsigned long address, void *sc_ptr); +extern void forward_pending_sigio(int target); #endif diff -urNp ref/arch/um/kernel/init_task.c o1/arch/um/kernel/init_task.c --- ref/arch/um/kernel/init_task.c Sat Jul 20 13:58:53 2002 +++ o1/arch/um/kernel/init_task.c Sat Jul 20 13:59:07 2002 @@ -6,6 +6,7 @@ #include "linux/mm.h" #include "linux/sched.h" #include "linux/version.h" +#include "linux/sched_runqueue.h" #include "asm/uaccess.h" #include "asm/pgtable.h" #include "user_util.h" diff -urNp ref/arch/um/kernel/process.c o1/arch/um/kernel/process.c --- ref/arch/um/kernel/process.c Sat Jul 20 13:58:53 2002 +++ o1/arch/um/kernel/process.c Sat Jul 20 13:59:07 2002 @@ -233,6 +233,16 @@ int run_kernel_thread(int (*fn)(void *), return(0); } +void forward_pending_sigio(int target) +{ + sigset_t sigs; + + if(sigpending(&sigs)) + panic("forward_pending_sigio : sigpending failed"); + if(sigismember(&sigs, SIGIO)) + kill(target, SIGIO); +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff -urNp ref/arch/um/kernel/process_kern.c o1/arch/um/kernel/process_kern.c --- ref/arch/um/kernel/process_kern.c Sat Jul 20 13:58:53 2002 +++ o1/arch/um/kernel/process_kern.c Sat Jul 20 13:59:11 2002 @@ -138,7 +138,7 @@ unsigned long alloc_stack(int order) return(page); } -extern void schedule_tail(struct task_struct *prev); +asmlinkage void schedule_tail(task_t *prev); static void new_thread_handler(int sig) { @@ -153,8 +153,10 @@ static void new_thread_handler(int sig) free_page(current->thread.temp_stack); set_cmdline("(kernel thread)"); force_flush_all(); +#ifdef CONFIG_SMP if(current->thread.prev_sched != NULL) schedule_tail(current->thread.prev_sched); +#endif current->thread.prev_sched = NULL; change_sig(SIGUSR1, 1); unblock_signals(); @@ -202,7 +204,6 @@ void *_switch_to(void *prev, void *next) unsigned long flags; int vtalrm, alrm, prof, err; char c; - static int reading; from = prev; to = next; @@ -210,46 +211,29 @@ void *_switch_to(void *prev, void *next) to->thread.prev_sched = from; if(CPU(from) == 0) forward_interrupts(to->thread.extern_pid); +#ifdef CONFIG_SMP forward_ipi(cpu_data[CPU(from)].ipi_pipe[0], to->thread.extern_pid); +#endif local_irq_save(flags); vtalrm = change_sig(SIGVTALRM, 0); alrm = change_sig(SIGALRM, 0); prof = change_sig(SIGPROF, 0); + forward_pending_sigio(to->thread.extern_pid); + c = 0; set_current(to); - - reading = 0; err = user_write(to->thread.switch_pipe[1], &c, sizeof(c)); if(err != sizeof(c)) panic("write of switch_pipe failed, errno = %d", -err); - reading = 1; if(from->state == TASK_ZOMBIE) os_kill_process(os_getpid()); err = user_read(from->thread.switch_pipe[0], &c, sizeof(c)); if(err != sizeof(c)) panic("read of switch_pipe failed, errno = %d", -err); - /* This works around a nasty race with 'jail'. If we are switching - * between two threads of a threaded app and the incoming process - * runs before the outgoing process reaches the read, and it makes - * it all the way out to userspace, then it will have write-protected - * the outgoing process stack. Then, when the outgoing process - * returns from the write, it will segfault because it can no longer - * write its own stack. So, in order to avoid that, the incoming - * thread sits in a loop yielding until 'reading' is set. This - * isn't entirely safe, since there may be a reschedule from a timer - * happening between setting 'reading' and sleeping in read. But, - * it should get a whole quantum in which to reach the read and sleep, - * which should be enough. - */ - - if(jail){ - while(!reading) sched_yield(); - } - change_sig(SIGVTALRM, vtalrm); change_sig(SIGALRM, alrm); change_sig(SIGPROF, prof); @@ -289,8 +273,10 @@ void finish_fork_handler(int sig) if(current->mm != current->p_pptr->mm) protect(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); task_protections((unsigned long) current); +#ifdef CONFIG_SMP if(current->thread.prev_sched != NULL) schedule_tail(current->thread.prev_sched); +#endif current->thread.prev_sched = NULL; free_page(current->thread.temp_stack);