void B_proc() { printf("B: 1\n"); swtch(&B, &A); printf("B: 2\n"); swtch(&B, &A); }
void A_proc() { printf("A: 1\n"); swtch(&A, &B); printf("A: 2\n"); swtch(&A, &B); printf("A: 3\n"); swtch(&A, &M); }
void taskA() { int i; for(i=1;i<=9;i++) { printf("A: %d\n",i); swtch(&A, &B); } printf("A: %d\n",i); swtch(&A,&M); }
static void task2() { while (1) { kprint("I AM TASK 2\r"); swtch(&tsk2->context, tsk1->context); } }
// Enter scheduler. Must hold only ptable.lock // and have changed proc->state. void sched(void) { int intena; //show_callstk ("sched"); if(!holding(&ptable.lock)) { panic("sched ptable.lock"); } if(cpu->ncli != 1) { panic("sched locks"); } if(proc->state == RUNNING) { panic("sched running"); } if(int_enabled ()) { panic("sched interruptible"); } intena = cpu->intena; swtch(&proc->context, cpu->scheduler); cpu->intena = intena; }
//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); 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); 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); } }
void scheduler(){ struct proc *p; while(1){ /* set interrupts ??? */ for(p=ptable.proc;p<&ptable.proc[NPROC];p++){ if(p->state!=RUNNABLE){ continue; } /* switch to this process. */ proc=p; switchuvm(p); p->state=RUNNING; swtch(&cpu.scheduler,p->context); /* __asm__ volatile( */ /* "movq %0,%%rsp;" */ /* : */ /* :"r"((char *)(proc->tf) - 8) */ /* : */ /* ); */ /* __asm__ volatile("retq;"); */ } } }
/* * Mark the current thread as sleeping on a shuttle object, and * switch to a new thread. * No locks other than 'l' should be held at this point. */ void shuttle_swtch(kmutex_t *l) { klwp_t *lwp = ttolwp(curthread); thread_lock(curthread); disp_lock_enter_high(&shuttle_lock); lwp->lwp_asleep = 1; /* /proc */ lwp->lwp_sysabort = 0; /* /proc */ lwp->lwp_ru.nvcsw++; curthread->t_flag |= T_WAKEABLE; curthread->t_sobj_ops = &shuttle_sobj_ops; curthread->t_wchan0 = (caddr_t)1; CL_INACTIVE(curthread); DTRACE_SCHED(sleep); THREAD_SLEEP(curthread, &shuttle_lock); (void) new_mstate(curthread, LMS_SLEEP); disp_lock_exit_high(&shuttle_lock); mutex_exit(l); if (ISSIG(curthread, JUSTLOOKING) || MUSTRETURN(curproc, curthread)) setrun(curthread); swtch(); /* * Caller must check for ISSIG/lwp_sysabort conditions * and clear lwp->lwp_asleep/lwp->lwp_sysabort */ }
void testLock(void) { gslLockMode_t mode1 = PERPROC(curProc)->testMode1; bool mode1DontWait = PERPROC(curProc)->testMode1DontWait; gslLockMode_t mode2 = PERPROC(curProc)->testMode2; bool mode2DontWait = PERPROC(curProc)->testMode2DontWait; bool got1 = false, got2 = false; got1 = gslAcquire(&theLock, mode1, mode1DontWait, NULL); if (got1) holderCounts = lcAdd(holderCounts, lcActive(mode1)); swtch(); if (mode2 != -1) { got2 = gslAcquire(&theLock, mode2, mode2DontWait, NULL); if (got2) holderCounts = lcAdd(holderCounts, lcActive(mode2)); swtch(); } // Check for conflicting held locks lockCounts_t otherCounts = lcSubtract(holderCounts, PERPROC(curProc)->perLock.holding); for (int i = 0; i < LC_MAX_MODES; ++i) { if (lcGetActive(otherCounts, i)) { if ((got1 && CONFLICTS(i, mode1)) || (got2 && CONFLICTS(i, mode2))) { fail("Conflicting lock held"); } else if ((got1 && i == mode1) || (got2 && i == mode2)) { observedSharing[i] = true; } } } // I release mode1 first so that my tests for observed sharing // remain simple. Otherwise, if mode1 overshadows mode2, then // it could prevent sharing of mode2, even if mode2 would // otherwise be sharable. (This isn't entirely reliable, but // takes care of most cases) if (got1) { holderCounts = lcSubtract(holderCounts, lcActive(mode1)); // XXX Check lastlocalhold and lasthold gslRelease(&theLock, mode1, NULL, NULL); } if (got2) { holderCounts = lcSubtract(holderCounts, lcActive(mode2)); gslRelease(&theLock, mode2, NULL, NULL); } }
void taskB() { int i; for(i=1;i<=9;i++) { printf("B: %d\n",i); swtch(&B, &M); } }
/* * Like cv_wait_sig_swap but allows the caller to indicate (with a * non-NULL sigret) that they will take care of signalling the cv * after wakeup, if necessary. This is a vile hack that should only * be used when no other option is available; almost all callers * should just use cv_wait_sig_swap (which takes care of the cv_signal * stuff automatically) instead. */ int cv_wait_sig_swap_core(kcondvar_t *cvp, kmutex_t *mp, int *sigret) { kthread_t *t = curthread; proc_t *p = ttoproc(t); klwp_t *lwp = ttolwp(t); int rval = 1; int signalled = 0; if (panicstr) return (rval); /* * The check for t_intr is to catch an interrupt thread * that has not yet unpinned the thread underneath. */ if (lwp == NULL || t->t_intr) { cv_wait(cvp, mp); return (rval); } lwp->lwp_asleep = 1; lwp->lwp_sysabort = 0; thread_lock(t); t->t_kpri_req = 0; /* don't need kernel priority */ cv_block_sig(t, (condvar_impl_t *)cvp); /* I can be swapped now */ curthread->t_schedflag &= ~TS_DONT_SWAP; thread_unlock_nopreempt(t); mutex_exit(mp); if (ISSIG(t, JUSTLOOKING) || MUSTRETURN(p, t)) setrun(t); /* ASSERT(no locks are held) */ swtch(); signalled = (t->t_schedflag & TS_SIGNALLED); t->t_flag &= ~T_WAKEABLE; /* TS_DONT_SWAP set by disp() */ ASSERT(curthread->t_schedflag & TS_DONT_SWAP); mutex_enter(mp); if (ISSIG_PENDING(t, lwp, p)) { mutex_exit(mp); if (issig(FORREAL)) rval = 0; mutex_enter(mp); } if (lwp->lwp_sysabort || MUSTRETURN(p, t)) rval = 0; lwp->lwp_asleep = 0; lwp->lwp_sysabort = 0; if (rval == 0) { if (sigret != NULL) *sigret = signalled; /* just tell the caller */ else if (signalled) cv_signal(cvp); /* avoid consuming the cv_signal() */ } return (rval); }
// 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; initlock(&tlock, "time"); 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; if(count_high_pri() != 0 && p->priority == 1) 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); p->state = RUNNING; //swtch(&cpu->scheduler, proc->context); //switchkvm(); uint ticks0 = 0, ticks1 = 0; acquire(&tlock);//Acquire the timer lock ticks0 = ticks;//Start timer release(&tlock); swtch(&cpu->scheduler, proc->context); acquire(&tlock);//Acquire the timer lock ticks1 = ticks;//Stop timer and add the ticks to htick or ltick depending upon the priority of the process. release(&tlock); if (p->priority == 1) { p->ltick = p->ltick + (ticks1 - ticks0); } else { p->htick = p->htick + (ticks1 - ticks0); } switchkvm(); // Process is done running for now. // It should have changed its p->state before coming back. proc = 0; } release(&ptable.lock); } }
//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; int makeShiftTimer = 0; for(;;){ // Enable interrupts on this processor. sti(); makeShiftTimer++; if (makeShiftTimer >= 10000){ for (p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if (p->pri != 1){ continue; } p->pri = 0; //cprintf("Bumping up: %s", p->name); } makeShiftTimer = 0; } int zeroCount = 0; for (p = ptable.proc; p < &ptable.proc[NPROC]; p++){ zeroCount++; } // cprintf("Number of process on queue 0: %d\n", zeroCount); //don't uncomment this if you want to be able to use the terminal. At all. // 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) || (zeroCount != 0 && p->pri == 1)) //im pretty sure the case for there being nothing on the 0 queue and stuff on the 1 queue is implicit here //we'll wait and see I guess 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); 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); } }
/* * Give up the processor till a wakeup occurs * on chan, at which time the process * enters the scheduling queue at priority pri. * The most important effect of pri is that when * pri<0 a signal cannot disturb the sleep; * if pri>=0 signals will be processed. * Callers of this routine must be prepared for * premature return, and check that the reason for * sleeping has gone away. */ sleep(chan, pri) { register *rp, s; s = PS->integ; rp = u.u_procp; if(pri >= 0) { if(issig()) goto psig; spl6(); rp->p_wchan = chan; rp->p_stat = SWAIT; rp->p_pri = pri; spl0(); if(runin != 0) { runin = 0; wakeup(&runin); } swtch(); if(issig()) goto psig; } else { spl6(); rp->p_wchan = chan; rp->p_stat = SSLEEP; rp->p_pri = pri; spl0(); swtch(); } PS->integ = s; return; /* * If priority was low (>=0) and * there has been a signal, * execute non-local goto to * the qsav location. * (see trap1/trap.c) */ psig: aretu(u.u_qsav); }
//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; int i; #if 0 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->state != UNUSED) cprintf("proc %d has priority %d\n", p->pid, p->priority); } #endif for(;;){ // Enable interrupts on this processor. sti(); acquire(&ptable.lock); // Loop through priority queues looking for runnable processe for(i = 0; i < 32; i++) { if(priority_q[i] != NULL) { p = priority_q[i]; #if 0 } } // Loop over process table looking for process to run. for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ #endif if(p->state != RUNNABLE) panic("Not runnable in ready queue"); // 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; //**** remove //cprintf("remove in scheduler\n"); removefromq(p); //**** 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); }
int main() { int stackA[1024]; int stackB[1024]; A.eip = (int)taskA; B.eip = (int)taskB; A.esp = (int)(&stackA[1023]); B.esp = (int)(&stackB[1023]); int i; for(i=1;i<=8;i++) { swtch(&M, &A); printf("C: %d\n\n",i); } swtch(&M, &A); swtch(&M, &A); return 0; }
int main() { int Astack[1024]; int Bstack[1024]; A.eip = (int)A_proc; A.esp = (int)(&Astack[1023]); B.eip = (int)B_proc; B.esp = (int)(&Bstack[1023]); swtch(&M, &A); return 0; }
// 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; struct cpu *c; int i; trace_frame *curr_trace_frm, *last_trace_frm; c = &cpus[cpu()]; for(;;){ // Enable interrupts on this processor. sti(); // Loop over process table looking for process to run. acquire(&proc_table_lock); for(i = 0; i < NPROC; i++){ p = &proc[i]; if(p->state != RUNNABLE) continue; // Switch to chosen process. It is the process's job // to release proc_table_lock and then reacquire it // before jumping back to us. //cprintf("current: %d\n", p->pid); c->curproc = p; setupsegs(p); p->state = RUNNING; swtch(&c->context, &p->context); if (trace_status == TRACE_ON) { last_trace_frm = &trace[(trace_index - 1) % TRACE_SIZE]; if (last_trace_frm->pid != p->pid) { curr_trace_frm = &trace[trace_index % TRACE_SIZE]; curr_trace_frm->pid = p->pid; curr_trace_frm->quantums = 1; trace_index++; } else if (last_trace_frm->pid == p->pid) { curr_trace_frm = &trace[(trace_index - 1) % TRACE_SIZE]; curr_trace_frm->quantums++; } } // Process is done running for now. // It should have changed its p->state before coming back. c->curproc = 0; setupsegs(0); } release(&proc_table_lock); } }
void SwitchToProccess(struct proc* process) { proc = process; switchuvm(process); process->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; }
static void apix_do_softint_epilog(struct cpu *cpu, uint_t oldpil) { struct machcpu *mcpu = &cpu->cpu_m; kthread_t *t, *it; uint_t pil, basespl; hrtime_t intrtime; hrtime_t now = tsc_read(); it = cpu->cpu_thread; pil = it->t_pil; cpu->cpu_stats.sys.intr[pil - 1]++; ASSERT(cpu->cpu_intr_actv & (1 << pil)); cpu->cpu_intr_actv &= ~(1 << pil); intrtime = now - it->t_intr_start; mcpu->intrstat[pil][0] += intrtime; cpu->cpu_intracct[cpu->cpu_mstate] += intrtime; /* * If there is still an interrupted thread underneath this one * then the interrupt was never blocked and the return is * fairly simple. Otherwise it isn't. */ if ((t = it->t_intr) == NULL) { /* * Put thread back on the interrupt thread list. * This was an interrupt thread, so set CPU's base SPL. */ set_base_spl(); /* mcpu->mcpu_pri = cpu->cpu_base_spl; */ it->t_state = TS_FREE; it->t_link = cpu->cpu_intr_thread; cpu->cpu_intr_thread = it; (void) splhigh(); sti(); swtch(); /*NOTREACHED*/ panic("dosoftint_epilog: swtch returned"); } it->t_link = cpu->cpu_intr_thread; cpu->cpu_intr_thread = it; it->t_state = TS_FREE; cpu->cpu_thread = t; if (t->t_flag & T_INTR_THREAD) t->t_intr_start = now; basespl = cpu->cpu_base_spl; pil = MAX(oldpil, basespl); mcpu->mcpu_pri = pil; }
/* * Block on the indicated condition variable and release the * associated kmutex while blocked. */ void cv_wait(kcondvar_t *cvp, kmutex_t *mp) { if (panicstr) return; ASSERT(curthread->t_schedflag & TS_DONT_SWAP); thread_lock(curthread); /* lock the thread */ cv_block((condvar_impl_t *)cvp); thread_unlock_nopreempt(curthread); /* unlock the waiters field */ mutex_exit(mp); swtch(); mutex_enter(mp); }
void scheduler(void) { struct proc *p; ptable.timeToReset = MAX_TIME_TO_RESET; for(;;){ // Enable interrupts on this processor. sti(); // Check for procs in ready list int pri = 0; for (;;) { acquire(&ptable.lock); if(ptable.pPriQ[pri] != 0) { // Switch to chosen process. It is the process's job // to release ptable.lock and then reacquire it // before jumping back to us. p = ptable.pPriQ[pri]; if (p->state != RUNNABLE) panic("scheduled unready process"); proc = p; switchuvm(p); p->state = RUNNING; ptable.pPriQ[pri] = ptable.pPriQ[pri]->next; p->next = 0; ptable.timeToReset--; if (ptable.timeToReset == 0) resetPri(); // Run priority-reset function 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); pri = 0; break; } else { release(&ptable.lock); if (pri == N_PRI-1) pri = 0; else pri++; } } } }
// Enter scheduler. Must already hold proc_table_lock // and have changed curproc[cpu()]->state. void sched(void) { if(read_eflags()&FL_IF) panic("sched interruptible"); if(cp->state == RUNNING) panic("sched running"); if(!holding(&proc_table_lock)) panic("sched proc_table_lock"); if(cpus[cpu()].ncli != 1) panic("sched locks"); swtch(&cp->context, &cpus[cpu()].context); }
void first() { bwprintf (COM2, "I AM FIRST USER.\n\tMODE IS "); print_mode (); bwputstr (COM2, ".\n\tCREATE???\n"); //int z = Create (0xABCDEF01, (void*)0x10FEDCBA); int z = Create (3, second); int i=0,j=0,k=0; while (1) { bwprintf (COM2, "I AM FIRST USER.\n\tKERNEL SAID %d\n\tMODE IS ",z); print_mode (); bwputstr (COM2, ".\n\tPASS??\n"); i++; if (i>10) j++; if (j>10) k++; i %= 11; j %= 11; // bwprintf (COM2, "(i,j,k) = (%d,%d,%d)\n",i,j,k); Pass(); bwprintf (COM2, "I AM FIRST USER.\n\tMODE IS "); print_mode (); bwputstr (COM2, ".\n\tEXIT????\n"); Exit(); } // int i = 0xFFFFF; int r; while (i--) { bwprintf(COM2, "Hey, I'm a user(%d)!\n", i); r = swtch(i); bwprintf(COM2, "And the kernel gave me %d!\n", r); for (r = 0; r < 500000; ++r); } bwputstr (COM2, "CPU Mode: "); print_mode(); bwputstr (COM2, "\n\n"); int x = 42; int b[5]; b[0] = 0xDEADBEEF; b[1] = 0xDEADBEEF; b[2] = 0xDEADBEEF; b[3] = 0xDEADBEEF; b[4] = 0xDEADBEEF; bwprintf (COM2, "x is %d\n", x); i = 5; while (i--) { bwprintf (COM2, "b[%d] = ", i); bwputr(COM2, b[i]); bwputstr (COM2, "\n");} b[2] -= x; b[3]--; bwputstr (COM2, "now b[2] = b[2] - x and b[3] = b[3] - 1...\n"); i = 5; while (i--) { bwprintf (COM2, "b[%d] = ", i); bwputr(COM2, b[i]); bwputstr (COM2, "\n");} }
int cv_wait_sig(kcondvar_t *cvp, kmutex_t *mp) { kthread_t *t = curthread; proc_t *p = ttoproc(t); klwp_t *lwp = ttolwp(t); int rval = 1; int signalled = 0; if (panicstr) return (rval); /* * The check for t_intr is to catch an interrupt thread * that has not yet unpinned the thread underneath. */ if (lwp == NULL || t->t_intr) { cv_wait(cvp, mp); return (rval); } ASSERT(curthread->t_schedflag & TS_DONT_SWAP); lwp->lwp_asleep = 1; lwp->lwp_sysabort = 0; thread_lock(t); cv_block_sig(t, (condvar_impl_t *)cvp); thread_unlock_nopreempt(t); mutex_exit(mp); if (ISSIG(t, JUSTLOOKING) || MUSTRETURN(p, t)) setrun(t); /* ASSERT(no locks are held) */ swtch(); signalled = (t->t_schedflag & TS_SIGNALLED); t->t_flag &= ~T_WAKEABLE; mutex_enter(mp); if (ISSIG_PENDING(t, lwp, p)) { mutex_exit(mp); if (issig(FORREAL)) rval = 0; mutex_enter(mp); } if (lwp->lwp_sysabort || MUSTRETURN(p, t)) rval = 0; lwp->lwp_asleep = 0; lwp->lwp_sysabort = 0; if (rval == 0 && signalled) /* avoid consuming the cv_signal() */ cv_signal(cvp); return (rval); }
// 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; }
//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, *q; unsigned long long min ; for(;;){ // Enable interrupts on this processor. sti(); // Loop over process table looking for process to run. acquire(&ptable.lock); p = 0; min = INFINITO ; for(q = ptable.proc; q < &ptable.proc[NPROC]; q++){ if (q->state == RUNNABLE){ if (min > q->curr_pass){ p = q; min = q->curr_pass; } } } if (p!=0){ /*Testes if (p->pid > 3){ for(q = ptable.proc; q < &ptable.proc[NPROC]; q++){ cprintf("%d %d %d\n", q->pid, q->Ntickts, q->slices); } cprintf("\n\n\n\n"); } End */ p->slices++; proc = p; switchuvm(p); p->state = RUNNING; swtch(&cpu->scheduler, proc->context); switchkvm(); // Process is done running for now. p->curr_pass+=p->pass; // It should have changed its p->state before coming back. proc = 0; } release(&ptable.lock); } }
//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); uint min_order = 1<<30; uint idx = -1; for (p = ptable.proc; p < &ptable.proc[NPROC]; p++) if (p->state == RUNNABLE && p->order < min_order) { min_order = p->order; idx = p - ptable.proc; } if (idx == -1) { release(&ptable.lock); continue; } //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. p = ptable.proc + idx; 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; //break; //} release(&ptable.lock); } }
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); 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. if (p->allowed_cpu > -1 && p->allowed_cpu == cpu->id) { //cprintf("\n Processing prod %d, at cpu %d", p->pid, cpu->id); } else if (p->allowed_cpu > -1) { //cprintf("\nSkipping proc %d at cpu %d, proc->allowed_cpu %d", p->pid, cpu->id, p->allowed_cpu); continue; } rerun: 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. if (cpu->preempt_disable_count > 0) { // Go back and reschedule the same process goto rerun; } proc = 0; } release(&ptable.lock); } }
//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); /* for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->state != RUNNABLE) continue; */ int i; for(i = 0; i < PRIORITIES; i ++) { p = ready[i]; if(p == 0) 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); p->state = RUNNING; remove_from_ready(p); swtch(&cpu->scheduler, proc->context); switchkvm(); // Process is done running for now. // It should have changed its p->state before coming back. proc = p = 0; /* if(current_priority == 31) current_priority = 0; else current_priority = i + 1; */ } release(&ptable.lock); } }