CS3210 Design Operating Systems

Taesoo Kim





Process and Scheduling

Taesoo Kim

Administrivia

Grading policy (old)

Grading policy (seeking better/appropriate one)

About Quiz 2

Q&A

Given that it would be impossible for group members to meet in-person to handle final project matters, would expectations for the final project adapt, and if so, how would changes occur?

→ Short answer: we can! The bigger open-source projects like Linux have been developed and maintained (~30y) in that way.

Q&A

In Lab4, once a process is done running, how does it switch to State::Dead?

What do real-time operating systems’ schedulers offer and how do they compare to these mentioned in this excerpt?

Is there a way we can compute how the runtime of a process?

Agenda

Summary: Exception level / Execution states

Summary: Interrupt handling

Interrupt handling routines

#[no_mangle]
pub extern "C" fn handle_exception( ... ) {
    match info.kind {
        Kind::Synchronous => {
            let syndrome = Syndrome::from(esr);
            match syndrome {
                Syndrome::Brk(_) => { ... }
                Syndrome::Svc(n) => { ... }
        }
        Kind::Irq => {
            let ic = Controller::new();
            for v in Interrupt::iter() {
                if ic.is_pending(v) {
                    crate::IRQ.invoke(v, tf);
                }
            }
        }
        ...
}

Abstraction: “process” (ref)

→ How to provide the illusion of owning the hardware?

Abstraction: “process” (ref)

Process in RustOS

  1. Stack/Heap/Code: data associated with the process
  2. Virtual address space: keeping data structure to maintain address space
  3. States: scheduling state / execution context

Process in RustOS

/// A structure that represents the complete state of a process.
#[derive(Debug)]
pub struct Process {
    /// The saved trap frame of a process.
    pub context: Box<TrapFrame>,
    /// The memory allocation used for the process's stack.
    pub stack: Stack,
    /// The page table describing the Virtual Memory of the process
    pub vmap: Box<UserPageTable>,
    /// The scheduling state of the process.
    pub state: State,
}

Scheduling states of process (in RustOS)

/// The scheduling state of a process.
pub enum State {
    /// The process is ready to be scheduled.
    Ready,
    /// The process is waiting on an event to occur before it can
    /// be scheduled.
    Waiting(EventPollFn),
    /// The process is currently running.
    Running,
    /// The process is currently dead (ready to be reclaimed).
    Dead,
}

Scheduling states of process (in RustOS)

/// Type of a function used to determine if a process is ready to
/// be scheduled again. The scheduler calls this function when it
/// is the process's turn to execute. If the function returns
/// `true`, the process is scheduled. If it returns `false`, the
/// process is not scheduled, and this function will be called on
/// the next time slice.
pub type EventPollFn = Box<dyn FnMut(&mut Process) -> bool + Send>;

Scheduling processes

Thinking of scheduling

→ Average execution time: (10+20+30)/3 = 20

Thinking of scheduling

→ Average execution time: (100+110+120)/3 = 110

Shortest Job First

→ Average execution time: (10+20+120)/3 = 50

Thinking of scheduling: online process

→ Average execution time: (100 + 100 + 110)/3 = 103.3

Shortest Time-to-Completion First

→ Average execution time: (120 + 10 + 20)/3 = 50

Thinking of scheduling: response time

Thinking of scheduling: no prior knowledge

Preemptive multitasking (ref)

Lots of scheduling policy

Ref. Scheduling: Proportional Share

Example: round robin in RustOS

Example: round robin in RustOS

Example: Scheduler in RustOS

pub struct Scheduler {
    processes: VecDeque<Process>,
    last_id: Option<Id>,
}

Example: Scheduler in RustOS

fn switch_to(&mut self, tf: &mut TrapFrame) -> Option<Id> {
    for i in 0..self.processes.len() {
        if self.processes[i].is_ready() {
            // push the selected one to the front
            let mut next = self.processes.remove(i).unwrap();
            next.state = State::Running;
            *tf = *next.context;
            self.processes.push_front(next);
            return Some(tf.tpidr);
        }
    }
    return None;
}

Incorporating I/O in scheduling

References