scheduler
This commit is contained in:
parent
a168c989cf
commit
0a1e889d54
@ -79,18 +79,13 @@ void printstr(char *s);
|
||||
void printint(int n);
|
||||
|
||||
// proc.c
|
||||
void exit(int);
|
||||
void proc_mapstacks(pagetable_t);
|
||||
pagetable_t proc_pagetable(struct proc *);
|
||||
void proc_freepagetable(pagetable_t, uint64);
|
||||
int kill(int);
|
||||
int killed(struct proc *);
|
||||
void setkilled(struct proc *);
|
||||
struct cpu *mycpu(void);
|
||||
struct proc *myproc();
|
||||
void procinit(void);
|
||||
void scheduler(void) __attribute__((noreturn));
|
||||
void sched(void);
|
||||
void sleep_lock(void *, struct spinlock *);
|
||||
void userinit(void);
|
||||
int wait(uint64);
|
||||
|
@ -109,11 +109,6 @@ userinit(void)
|
||||
// Caller must hold wait_lock.
|
||||
void reparent(struct proc *p);
|
||||
|
||||
// Exit the current process. Does not return.
|
||||
// An exited process remains in the zombie state
|
||||
// until its parent calls wait().
|
||||
void exit(int status);
|
||||
|
||||
// Wait for a child process to exit and return its pid.
|
||||
// Return -1 if this process has no children.
|
||||
int
|
||||
@ -163,52 +158,6 @@ wait(uint64 addr)
|
||||
}
|
||||
}
|
||||
|
||||
// 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 = mycpu();
|
||||
|
||||
c->proc = 0;
|
||||
for(;;){
|
||||
// Avoid deadlock by ensuring that devices can interrupt.
|
||||
intr_on();
|
||||
|
||||
for(p = proc; p < &proc[NPROC]; p++) {
|
||||
acquire(&p->lock);
|
||||
if(p->state == RUNNABLE) {
|
||||
// Switch to chosen process. It is the process's job
|
||||
// to release its lock and then reacquire it
|
||||
// before jumping back to us.
|
||||
p->state = RUNNING;
|
||||
c->proc = p;
|
||||
swtch(&c->context, &p->context);
|
||||
|
||||
// Process is done running for now.
|
||||
// It should have changed its p->state before coming back.
|
||||
c->proc = 0;
|
||||
}
|
||||
release(&p->lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Switch to scheduler. Must hold only p->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->noff, but that would
|
||||
// break in the few places where a lock is held but
|
||||
// there's no process.
|
||||
void sched(void);
|
||||
|
||||
// A fork child's very first scheduling by scheduler()
|
||||
// will swtch to forkret.
|
||||
void
|
||||
@ -251,11 +200,6 @@ void wakeup(void *chan)
|
||||
}
|
||||
}
|
||||
|
||||
// Kill the process with the given pid.
|
||||
// The victim won't exit until it tries to return
|
||||
// to user space (see usertrap() in trap.c).
|
||||
int kill(int pid);
|
||||
void setkilled(struct proc *p);
|
||||
int killed(struct proc *p);
|
||||
|
||||
// Copy to either a user address, or kernel address,
|
||||
|
@ -1,20 +1,20 @@
|
||||
use super::{
|
||||
context::Context,
|
||||
cpu::Cpu,
|
||||
process::{Process, ProcessState},
|
||||
process::{proc, Process, ProcessState},
|
||||
};
|
||||
use crate::{
|
||||
arch::riscv::intr_get,
|
||||
arch::riscv::{intr_get, intr_on},
|
||||
sync::spinlock::{Spinlock, SpinlockGuard},
|
||||
};
|
||||
use core::{
|
||||
ffi::c_void,
|
||||
ptr::{addr_of_mut, null_mut},
|
||||
ptr::{addr_of, addr_of_mut, null_mut},
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
pub fn wakeup(chan: *const c_void);
|
||||
pub fn scheduler() -> !;
|
||||
// pub fn scheduler() -> !;
|
||||
pub fn swtch(a: *mut Context, b: *mut Context);
|
||||
}
|
||||
|
||||
@ -26,6 +26,41 @@ pub unsafe fn r#yield() {
|
||||
sched();
|
||||
}
|
||||
|
||||
// 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.
|
||||
pub unsafe fn scheduler() -> ! {
|
||||
let cpu = Cpu::current();
|
||||
cpu.proc = null_mut();
|
||||
|
||||
loop {
|
||||
// Avoid deadlock by ensuring that devices can interrupt.
|
||||
intr_on();
|
||||
|
||||
for p in &mut proc {
|
||||
let _guard = p.lock.lock();
|
||||
if p.state == ProcessState::Runnable {
|
||||
// Switch to the chosen process. It's the process's job
|
||||
// to release its lock and then reacquire it before
|
||||
// jumping back to us.
|
||||
p.state = ProcessState::Running;
|
||||
cpu.proc = addr_of!(*p).cast_mut();
|
||||
|
||||
// Run the process.
|
||||
swtch(addr_of_mut!(cpu.context), addr_of_mut!(p.context));
|
||||
|
||||
// Process is done running for now.
|
||||
// It should have changed its state before coming back.
|
||||
cpu.proc = null_mut();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Switch to scheduler. Must hold only p->lock
|
||||
/// and have changed proc->state. Saves and restores
|
||||
/// previous_interrupts_enabled because previous_interrupts_enabled is a property of this
|
||||
@ -33,8 +68,7 @@ pub unsafe fn r#yield() {
|
||||
/// be proc->previous_interrupts_enabled and proc->interrupt_disable_layers, but that would
|
||||
/// break in the few places where a lock is held but
|
||||
/// there's no process.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sched() {
|
||||
pub unsafe fn sched() {
|
||||
let p = Process::current().unwrap();
|
||||
let cpu = Cpu::current();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user