int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) { sigjmp_buf **switch_buf = switch_buf_ptr; int n; set_handler(SIGWINCH, (__sighandler_t) sig_handler, SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, SIGVTALRM, -1); *fork_buf_ptr = &initial_jmpbuf; n = sigsetjmp(initial_jmpbuf, 1); switch(n){ case INIT_JMP_NEW_THREAD: new_thread_proc((void *) stack, new_thread_handler); break; case INIT_JMP_REMOVE_SIGSTACK: remove_sigstack(); break; case INIT_JMP_CALLBACK: (*cb_proc)(cb_arg); siglongjmp(*cb_back, 1); break; case INIT_JMP_HALT: kmalloc_ok = 0; return(0); case INIT_JMP_REBOOT: kmalloc_ok = 0; return(1); default: panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); } siglongjmp(**switch_buf, 1); }
int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) { sigjmp_buf **switch_buf = switch_buf_ptr; int n; *fork_buf_ptr = &initial_jmpbuf; n = sigsetjmp(initial_jmpbuf, 1); if(n == 0) new_thread_proc((void *) stack, new_thread_handler); else if(n == 1) remove_sigstack(); else if(n == 2){ (*cb_proc)(cb_arg); siglongjmp(*cb_back, 1); } else if(n == 3){ kmalloc_ok = 0; return(0); } else if(n == 4){ kmalloc_ok = 0; return(1); } siglongjmp(**switch_buf, 1); }
void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, void (*handler)(int)) { unsigned long flags; sigjmp_buf switch_buf, fork_buf; *switch_buf_ptr = &switch_buf; *fork_buf_ptr = &fork_buf; /* Somewhat subtle - siglongjmp restores the signal mask before doing * the longjmp. This means that when jumping from one stack to another * when the target stack has interrupts enabled, an interrupt may occur * on the source stack. This is bad when starting up a process because * it's not supposed to get timer ticks until it has been scheduled. * So, we disable interrupts around the sigsetjmp to ensure that * they can't happen until we get back here where they are safe. */ flags = get_signals(); block_signals(); if(sigsetjmp(fork_buf, 1) == 0) new_thread_proc(stack, handler); remove_sigstack(); set_signals(flags); }
void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, void (*handler)(int)) { sigjmp_buf switch_buf, fork_buf; *switch_buf_ptr = &switch_buf; *fork_buf_ptr = &fork_buf; if(sigsetjmp(fork_buf, 1) == 0) new_thread_proc(stack, handler); remove_sigstack(); }