This is not the current version of the class.

# Synchronization invariants

• A CPU’s run queue, which is implemented by members in cpustate and proc (cpustate::current_, cpustate::runq_, and proc::runq_links_), is protected by cpustate::runq_lock_. Reading or writing a CPU’s run queue requires that lock.

• cpustate::current_ is read-only, except that cpustate::schedule can modify it.

• A process may be the current process for some CPU, and simultaneously on the run queue for that same CPU.

• The proc::yields_ member may be accessed only by proc::yield and proc::resume.

• A newly-initialized user process has a nonnull proc::regs_ pointer. It is safe to access that member and modify its contents, but only up to the point that the process is scheduled.

• Running processes must not access their proc::regs_ members, except that if interrupts are disabled, the current process may set regs_ and call proc::yield_return. (See proc::exception’s timer interrupt case.)

• proc::yield must be called with no spinlocks held.

• proc::yield_noreturn must be called with no spinlocks held and with interrupts disabled.

• cpustate::schedule must be called with no spinlocks held and with interrupts disabled.

• Read or write access to the process table ptable requires the ptable_lock spinlock.

• You may free a process’s page table pages only if (1) the process is not present in ptable, or (2) the process’s page table lock is locked for writing (forcing proc::lock_pagetable_read to block).