void P(struct semaphore* sig){ if (!sig->INT) cli(); sig->value--; if (sig->value < 0){ queue_delete(current_pcb); if (sig->value == -1){ current_pcb->pre_pcb = current_pcb; current_pcb->next_pcb = current_pcb; sig->waitlist = current_pcb; } else queue_insert(sig->waitlist, current_pcb); /*wait*/ proc_run--; if (sig->INT) pick_proc(); else yield(); } if (!sig->INT) sti(); }
/*===========================================================================* * switch_to_user * *===========================================================================*/ PUBLIC void switch_to_user(void) { /* This function is called an instant before proc_ptr is * to be scheduled again. */ /* * if the current process is still runnable check the misc flags and let * it run unless it becomes not runnable in the meantime */ if (proc_is_runnable(proc_ptr)) goto check_misc_flags; /* * if a process becomes not runnable while handling the misc flags, we * need to pick a new one here and start from scratch. Also if the * current process wasn' runnable, we pick a new one here */ not_runnable_pick_new: if (proc_is_preempted(proc_ptr)) { proc_ptr->p_rts_flags &= ~RTS_PREEMPTED; if (proc_is_runnable(proc_ptr)) { if (!is_zero64(proc_ptr->p_cpu_time_left)) enqueue_head(proc_ptr); else enqueue(proc_ptr); } } /* * if we have no process to run, set IDLE as the current process for * time accounting and put the cpu in and idle state. After the next * timer interrupt the execution resumes here and we can pick another * process. If there is still nothing runnable we "schedule" IDLE again */ while (!(proc_ptr = pick_proc())) { proc_ptr = proc_addr(IDLE); if (priv(proc_ptr)->s_flags & BILLABLE) bill_ptr = proc_ptr; idle(); } switch_address_space(proc_ptr); check_misc_flags: assert(proc_ptr); assert(proc_is_runnable(proc_ptr)); while (proc_ptr->p_misc_flags & (MF_KCALL_RESUME | MF_DELIVERMSG | MF_SC_DEFER | MF_SC_TRACE | MF_SC_ACTIVE)) { assert(proc_is_runnable(proc_ptr)); if (proc_ptr->p_misc_flags & MF_KCALL_RESUME) { kernel_call_resume(proc_ptr); } else if (proc_ptr->p_misc_flags & MF_DELIVERMSG) { TRACE(VF_SCHEDULING, printf("delivering to %s / %d\n", proc_ptr->p_name, proc_ptr->p_endpoint);); delivermsg(proc_ptr); }
/*===========================================================================* * schedcheck * *===========================================================================*/ PUBLIC struct proc * schedcheck(void) { /* This function is called an instant before proc_ptr is * to be scheduled again. */ NOREC_ENTER(schedch); vmassert(intr_disabled()); /* * if the current process is still runnable check the misc flags and let * it run unless it becomes not runnable in the meantime */ if (proc_is_runnable(proc_ptr)) goto check_misc_flags; /* * if a process becomes not runnable while handling the misc flags, we * need to pick a new one here and start from scratch. Also if the * current process wasn' runnable, we pick a new one here */ not_runnable_pick_new: if (proc_is_preempted(proc_ptr)) { proc_ptr->p_rts_flags &= ~RTS_PREEMPTED; if (proc_is_runnable(proc_ptr)) enqueue_head(proc_ptr); } /* this enqueues the process again */ if (proc_no_quantum(proc_ptr)) RTS_UNSET(proc_ptr, RTS_NO_QUANTUM); /* * if we have no process to run, set IDLE as the current process for * time accounting and put the cpu in and idle state. After the next * timer interrupt the execution resumes here and we can pick another * process. If there is still nothing runnable we "schedule" IDLE again */ while( !(proc_ptr = pick_proc())) { proc_ptr = proc_addr(IDLE); if (priv(proc_ptr)->s_flags & BILLABLE) bill_ptr = proc_ptr; idle(); } check_misc_flags: vmassert(proc_ptr); vmassert(proc_is_runnable(proc_ptr)); while (proc_ptr->p_misc_flags & (MF_DELIVERMSG | MF_SC_DEFER | MF_SC_TRACE | MF_SC_ACTIVE)) { vmassert(proc_is_runnable(proc_ptr)); if (proc_ptr->p_misc_flags & MF_DELIVERMSG) { TRACE(VF_SCHEDULING, printf("delivering to %s / %d\n", proc_ptr->p_name, proc_ptr->p_endpoint);); if(delivermsg(proc_ptr) == VMSUSPEND) { TRACE(VF_SCHEDULING, printf("suspending %s / %d\n", proc_ptr->p_name, proc_ptr->p_endpoint););