// Enter scheduler. Must hold only ptable.lock // and have changed proc->state. Saves and restores // intena because intena is a property of this // kernel thread, not this CPU. It should // be proc->intena and proc->ncli, but that would // break in the few places where a lock is held but // there's no process. void sched(void) { int intena; struct proc *p = myproc(); if(!holding(&ptable.lock)) panic("sched ptable.lock"); if(mycpu()->ncli != 1) panic("sched locks"); if(p->state == RUNNING) panic("sched running"); if(readeflags()&FL_IF) panic("sched interruptible"); intena = mycpu()->intena; swtch(&p->context, mycpu()->scheduler); mycpu()->intena = intena; }
int cpunum(void) { // Cannot call cpu when interrupts are enabled: // result not guaranteed to last long enough to be used! // Would prefer to panic but even printing is chancy here: // almost everything, including cprintf and panic, calls cpu, // often indirectly through acquire and release. if(readeflags()&FL_IF){ static int n; if(n++ == 0) cprintf("cpu called from %x with interrupts enabled\n", __builtin_return_address(0)); } if(lapic) return lapic[ID]>>24; return 0; }
// Enter scheduler. Must hold only ptable.lock // and have changed proc->state. void sched(void) { int intena; if(!holding(&ptable.lock)) panic("sched ptable.lock"); if(cpu->ncli != 1){ cprintf("current proc %d\n cpu->ncli %d\n",proc->pid,cpu->ncli); panic("sched locks"); } if(proc->state == RUNNING) panic("sched running"); if(readeflags()&FL_IF) panic("sched interruptible"); intena = cpu->intena; swtch(&proc->context, cpu->scheduler); cpu->intena = intena; }
void next_task() { uint8_t is_enabled = readeflags() & 0x200; cli(); if (task_count <= 1) { return; } task_t *previous_task = current_task; current_task = current_task->next; switch_task(&(previous_task->regs), current_task->regs); if(is_enabled) { sti(); } }
//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; for(;;){ // Enable interrupts on this processor. sti(); // Loop over process table looking for process to run. acquire(&ptable.lock); #ifndef __ORIGINAL_SCHED__ p = pdequeue(); if(p){ #else for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->state != RUNNABLE) continue; #endif // For debug, checking the scheduled process priority cprintf("cpu %d get process %s, process prio = %d\n",cpunum(),p->name,p->priority); // 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); 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); } } // Enter scheduler. Must hold only ptable.lock // and have changed proc->state. void sched(void) { int intena; if(!holding(&ptable.lock)) panic("sched ptable.lock"); if(cpu->ncli != 1) panic("sched locks"); if(proc->state == RUNNING) panic("sched running"); if(readeflags()&FL_IF) panic("sched interruptible"); intena = cpu->intena; swtch(&proc->context, cpu->scheduler); cpu->intena = intena; }