static NOINLINE_NOCLONE NORETURN void stdarg (int f UNUSED, ...) { sighandler_t sigusr2_orig = signal (SIGUSR2, sigusr2); assert (sigusr2_orig == SIG_DFL); errno = 0; if (ptraceme) { long l = ptrace (PTRACE_TRACEME, 0, NULL, NULL); assert (errno == 0); assert (l == 0); } #ifdef __x86_64__ if (! gencore) { /* Execution will get PC patched into function jmp. */ raise (SIGUSR1); } #endif sigusr2 (SIGUSR2); /* Not reached. */ abort (); }
//PAGEBREAK: 42 // Per-CPU process scheduler. // Each CPU calls scheduler() after setting itself up. // Scheduler never returns. It loops, doing: // - choose a process to run // - swtch to start running that process // - eventually that process transfers control // via swtch back to the scheduler. void scheduler(void) { struct proc *p; uint mask; sighandler_t *handler; for(;;) { // Enable interrupts on this processor. sti(); // Loop over process table looking for process to run. acquire(&ptable.lock); for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) { if(p->state != RUNNABLE) continue; // Switch to chosen process. It is the process's job // to release ptable.lock and then reacquire it // before jumping back to us. proc = p; switchuvm(p); /* A&T - SIGNALS start */ if (p->signal != 0) { /* A&T - were any signals recieved? */ /* cprintf("DEBUG: pid=%d, p->signal=%d\n", p->pid, p->signal); */ mask = (1 << 31); /* the stack is a LIFO structure, so * we'll be pushing the LEAST important * signals first, so they'll run last. */ /* cprintf("DEBUG: mask=%d\n", mask); */ handler = &proc->handlers[31]; while(mask > 8) { /* a mask to check whether a signal's bit is up - not for builtin 3 signal hadlers, since they should be called from kernel space and not userspace. */ if ((p->signal & mask) && (*handler != 0)) register_handler(*handler); /* add the handler to the stack, if it exists */ mask >>= 1; /* move the mask to the next bit to check. */ handler--; /* move the pointer to the next hendler */ } while (mask > 0) { if (p->signal & mask) { if (*handler == 0) /* call the built-in handler */ switch(mask) { case 8: sigchld(); break; case 4: sigusr2(); break; case 2: sigusr1(); break; case 1: sigint(); break; default: break; } else register_handler(*handler); } mask >>= 1; handler--; } p->signal = 0; /* initialize the signal data word to 0 */ } /* A&T - SIGNALS end */ p->state = RUNNING; swtch(&cpu->scheduler, proc->context); switchkvm(); // Process is done running for now. // It should have changed its p->state before coming back. proc = 0; } release(&ptable.lock); }