/*---------------------------------------------------------------------------*/ static void call_process(struct process *p, process_event_t ev, process_data_t data) { int ret; #if DEBUG if(p->state == PROCESS_STATE_CALLED) { printf("process: process '%s' called again with event %d\n", PROCESS_NAME_STRING(p), ev); } #endif /* DEBUG */ if((p->state & PROCESS_STATE_RUNNING) && p->thread != NULL) { PRINTF("process: calling process '%s' with event %d\n", PROCESS_NAME_STRING(p), ev); process_current = p; p->state = PROCESS_STATE_CALLED; ret = p->thread(&p->pt, ev, data); if(ret == PT_EXITED || ret == PT_ENDED || ev == PROCESS_EVENT_EXIT) { exit_process(p, p); } else { p->state = PROCESS_STATE_RUNNING; } } }
void _exit(int rc) { if(current->proc->flags & PROC_FLAG_DEBUG) { debug("[info]EXIT(%x)\n", rc); print_areas(current->proc); } int i; process_t *p = current->proc; for(i = 0; i < NUM_FILEDES; i++) { if(p->fd[i]) { close(i); } } exit_process(current->proc, rc); current->state = THREAD_STATE_FINISHED; schedule(); debug("[error]ERROR! REACHED END OF EXIT SYSCALL!\n"); for(;;); }
/*---------------------------------------------------------------------------*/ static void call_process(struct process *p, process_event_t ev, process_data_t data) { int ret; if((p->state & PROCESS_STATE_RUNNING) && p->thread != 0) { process_current = p; p->state = PROCESS_STATE_CALLED; ret = p->thread(&p->pt, ev, data); if(ret == PT_EXITED || ret == PT_ENDED || ev == PROCESS_EVENT_EXIT) { exit_process(p, p); } else { p->state = PROCESS_STATE_RUNNING; } } }
/*---------------------------------------------------------------------------*/ void process_exit(struct process *p) { exit_process(p, PROCESS_CURRENT()); }
void interrupt(registers_t *reg) { // The processor responds to a system call interrupt by saving some of // the application's state on the kernel's stack, then jumping to // kernel assembly code (in mpos-int.S, for your information). // That code saves more registers on the kernel's stack, then calls // interrupt(). The first thing we must do, then, is copy the saved // registers into the 'current' process descriptor. current->p_registers = *reg; switch (reg->reg_intno) { case INT_SYS_GETPID: // The 'sys_getpid' system call returns the current // process's process ID. System calls return results to user // code by putting those results in a register. Like Linux, // we use %eax for system call return values. The code is // surprisingly simple: current->p_registers.reg_eax = current->p_pid; run(current); case INT_SYS_FORK: // The 'sys_fork' system call should create a new process. // You will have to complete the do_fork() function! current->p_registers.reg_eax = do_fork(current); run(current); case INT_SYS_YIELD: // The 'sys_yield' system call asks the kernel to schedule a // different process. (MiniprocOS is cooperatively // scheduled, so we need a special system call to do this.) // The schedule() function picks another process and runs it. schedule(); case INT_SYS_EXIT: // 'sys_exit' exits the current process, which is marked as // non-runnable. // The process stored its exit status in the %eax register // before calling the system call. The %eax REGISTER has // changed by now, but we can read the APPLICATION's setting // for this register out of 'current->p_registers'. exit_process(current->p_pid); //current->p_state = P_ZOMBIE; //current->p_exit_status = current->p_registers.reg_eax; schedule(); case INT_SYS_WAIT: { // 'sys_wait' is called to retrieve a process's exit status. // It's an error to call sys_wait for: // * A process ID that's out of range (<= 0 or >= NPROCS). // * The current process. // * A process that doesn't exist (p_state == P_EMPTY). // (In the Unix operating system, only process P's parent // can call sys_wait(P). In MiniprocOS, we allow ANY // process to call sys_wait(P).) pid_t p = current->p_registers.reg_eax; if (p <= 0 || p >= NPROCS || p == current->p_pid // to check if ID is valid || proc_array[p].p_state == P_EMPTY) current->p_registers.reg_eax = -1; else if (proc_array[p].p_state == P_ZOMBIE){ // to check if process already exited current->p_registers.reg_eax = proc_array[p].p_exit_status; proc_array[p].p_state = P_EMPTY; //sets the state to empty so that it can be reaped later } else{ // blocks the current process current->p_state = P_BLOCKED; // waiting on proc_array[p] current->p_wait_on = p; } schedule(); break; } // case INT_SYS_NEWTHREAD: // current->p_registers.reg_eax=do_newthread(current, current->p_registers.reg_ebx); // run(current); // case INT_SYS_KILL: // exit_process(current->p_registers.reg_ebx); // schedule(); default: while (1) /* do nothing */; } }
void sys_exit(){ exit_process(); }