int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, unsigned long stack_top, struct task_struct * p, struct pt_regs *regs) { int (*tramp)(void *); int new_pid, err; unsigned long stack; if(current->thread.forking) tramp = fork_tramp; else { tramp = new_thread_proc; p->thread.request.u.thread = current->thread.request.u.thread; } err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1); if(err < 0){ printk("copy_thread : pipe failed, err = %d\n", -err); return(err); } stack = alloc_stack(0, 0); if(stack == 0){ printk(KERN_ERR "copy_thread : failed to allocate " "temporary stack\n"); return(-ENOMEM); } clone_flags &= CLONE_VM; p->thread.temp_stack = stack; new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp); if(new_pid < 0){ printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", -new_pid); return(new_pid); } if(current->thread.forking){ sc_to_sc(UPT_SC(&p->thread.regs.regs), UPT_SC(®s->regs)); SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0); if(sp != 0) SC_SP(UPT_SC(&p->thread.regs.regs)) = sp; } p->thread.mode.tt.extern_pid = new_pid; current->thread.request.op = OP_FORK; current->thread.request.u.fork.pid = new_pid; os_usr1_process(os_getpid()); /* 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; return(err); }
int fork_tramp(void *stack) { local_irq_disable(); arch_init_thread(); init_new_thread_stack(stack, finish_fork_handler); os_usr1_process(os_getpid()); change_sig(SIGUSR1, 1); return(0); }
int set_user_mode(void *t) { struct task_struct *task; task = t ? t : current; if(task->thread.mode.tt.tracing) return(1); task->thread.request.op = OP_TRACE_ON; os_usr1_process(os_getpid()); return(0); }
void initial_thread_cb_tt(void (*proc)(void *), void *arg) { if(os_getpid() == tracing_pid){ (*proc)(arg); } else { current->thread.request.op = OP_CB; 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); } }
static int new_thread_proc(void *stack) { /* local_irq_disable is needed to block out signals until this thread is * properly scheduled. Otherwise, the tracing thread will get mighty * upset about any signals that arrive before that. * This has the complication that it sets the saved signal mask in * the sigcontext to block signals. This gets restored when this * thread (or a descendant, since they get a copy of this sigcontext) * returns to userspace. * So, this is compensated for elsewhere. * XXX There is still a small window until local_irq_disable() actually * finishes where signals are possible - shouldn't be a problem in * practice since SIGIO hasn't been forwarded here yet, and the * local_irq_disable should finish before a SIGVTALRM has time to be * delivered. */ local_irq_disable(); init_new_thread_stack(stack, new_thread_handler); os_usr1_process(os_getpid()); change_sig(SIGUSR1, 1); return(0); }
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(); }
void halt_tt(void) { current->thread.request.op = OP_HALT; os_usr1_process(os_getpid()); change_sig(SIGUSR1, 1); }
void reboot_tt(void) { current->thread.request.op = OP_REBOOT; os_usr1_process(os_getpid()); change_sig(SIGUSR1, 1); }
void new_thread_proc(void *stack, void (*handler)(int sig)) { init_new_thread_stack(stack, handler); os_usr1_process(os_getpid()); }