static void new_thread_handler(int sig) { unsigned long disable; int (*fn)(void *); void *arg; fn = current->thread.request.u.thread.proc; arg = current->thread.request.u.thread.arg; UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) | (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1)); SC_SIGMASK(UPT_SC(¤t->thread.regs.regs)) &= ~disable; suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); force_flush_all(); if(current->thread.prev_sched != NULL) schedule_tail(current->thread.prev_sched); current->thread.prev_sched = NULL; init_new_thread_signals(); enable_timer(); free_page(current->thread.temp_stack); set_cmdline("(kernel thread)"); change_sig(SIGUSR1, 1); change_sig(SIGPROF, 1); local_irq_enable(); if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) do_exit(0); /* XXX No set_user_mode here because a newly execed process will * immediately segfault on its non-existent IP, coming straight back * to the signal handler, which will call set_user_mode on its way * out. This should probably change since it's confusing. */ }
void finish_fork_handler(int sig) { UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); force_flush_all(); if(current->thread.prev_sched != NULL) schedule_tail(current->thread.prev_sched); current->thread.prev_sched = NULL; enable_timer(); change_sig(SIGVTALRM, 1); local_irq_enable(); if(current->mm != current->parent->mm) protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); task_protections((unsigned long) current_thread); free_page(current->thread.temp_stack); local_irq_disable(); change_sig(SIGUSR1, 0); set_user_mode(current); }
void fork_handler(int sig) { os_usr1_signal(1); thread_wait(¤t->thread.mode.skas.switch_buf, current->thread.mode.skas.fork_buf); force_flush_all(); if(current->thread.prev_sched == NULL) panic("blech"); schedule_tail(current->thread.prev_sched); /* XXX: if interrupt_end() calls schedule, this call to * arch_switch_to_skas isn't needed. We could want to apply this to * improve performance. -bb */ arch_switch_to_skas(current->thread.prev_sched, current); current->thread.prev_sched = NULL; /* Handle any immediate reschedules or signals */ interrupt_end(); userspace(¤t->thread.regs.regs); }
void flush_thread_tt(void) { unsigned long stack; int new_pid; stack = alloc_stack(0, 0); if(stack == 0){ printk(KERN_ERR "flush_thread : failed to allocate temporary stack\n"); do_exit(SIGKILL); } new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp); if(new_pid < 0){ printk(KERN_ERR "flush_thread : new thread failed, errno = %d\n", -new_pid); do_exit(SIGKILL); } if(current_thread->cpu == 0) forward_interrupts(new_pid); current->thread.request.op = OP_EXEC; 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); stack_protections((unsigned long) current_thread); force_flush_all(); unblock_signals(); }