sched: fair share by virtual runtime, with nice
The scheduler was xv6's round-robin: run everything RUNNABLE in slot order and yield on every timer tick. Slot order is not fairness, a process alone on a CPU paid a full context switch a hundred times a second to be handed straight back to itself, and there was no way to say that one thing mattered more than another. Every process now carries vruntime, the CPU time it has used divided by its weight, and the scheduler runs the runnable process with the smallest. Fairness and interactivity both fall out of that one rule; nice is a weight, 1.25x per level as UNIX has always had it. A slice is 20 ms shared among the runnable processes, never below 2 ms, and the timer tick preempts only once it is spent. A process waking from a long sleep is brought up to min_vruntime less one period, so it is scheduled promptly without being owed everything it slept through; fork inherits vruntime, so forking does not reset a debt. getpriority/setpriority are real, with Linux's offset of 20 on the return; /proc/<pid>/schedstat and the ctxt_switches lines of status report what the scheduler did. docs/architecture/scheduler.md has the reasoning, including why the run queue is still a scan of ptable. This was written in an earlier session and left uncommitted. Finished here: a signal waking a sleeper goes through the same vruntime floor as wakeup() does, and sched_yield() yields -- it returned 0 doing nothing, harmless while every tick was a yield and a spin of a whole slice once ticks stopped being one. Checked under QEMU on 1 and 4 CPUs: a nice 10 loop beside a nice 0 one gets about a tenth of a shared CPU, and a command typed meanwhile answers in 26 ms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
parent
b70e36e0a2
commit
a2d987db5f
11 changed files with 666 additions and 35 deletions
|
|
@ -545,6 +545,11 @@ int wait(void);
|
|||
int waitpid(int, int*, int, uint64*, uint64*);
|
||||
void wakeup(void*);
|
||||
void yield(void);
|
||||
int sched_slice_expired(void);
|
||||
void sched_init_proc(struct proc*, int);
|
||||
void sched_set_nice(struct proc*, int);
|
||||
int proc_setnice(int, int);
|
||||
int proc_getnice(int, int*);
|
||||
void sinit(void);
|
||||
void kstack_check_canary(const char *where);
|
||||
|
||||
|
|
|
|||
|
|
@ -169,6 +169,9 @@ struct procinfo {
|
|||
int ctty; // controlling terminal, 1-based; 0 = none
|
||||
uint64 utime, stime; // CPU time in ticks, this process
|
||||
uint64 cutime, cstime; // and its reaped children
|
||||
int nice; // scheduling priority, -20..19
|
||||
uint64 vruntime; // weighted CPU nanoseconds, for `top` and debugging
|
||||
uint64 nvcsw, nivcsw; // voluntary / involuntary context switches
|
||||
char name[16];
|
||||
char exe[64]; // full path, for /proc/<pid>/exe
|
||||
};
|
||||
|
|
@ -292,9 +295,23 @@ struct proc {
|
|||
// are tracked honestly so getuid()/setuid() stop lying to userland.
|
||||
uint uid, euid, suid;
|
||||
uint gid, egid, sgid;
|
||||
|
||||
// --- Fair-share scheduling --------------------------------------------
|
||||
// The whole of the scheduler's per-process state. What each field means,
|
||||
// and why the scheduler is shaped this way, is in kernel/proc/proc.c above
|
||||
// scheduler(); this is deliberately only the declaration.
|
||||
int nice; // -20..19, UNIX convention: lower means more CPU
|
||||
uint32 weight; // nice_weight[nice + 20], cached
|
||||
uint64 vruntime; // weighted CPU time consumed, in nanoseconds
|
||||
uint64 ran_at; // TSC when this process last entered RUNNING
|
||||
uint64 slice_ns; // how long the current slice is allowed to be
|
||||
uint64 slice_used; // how much of it has been spent, in nanoseconds
|
||||
uint64 nivcsw, nvcsw; // preempted / voluntary context switches
|
||||
|
||||
};
|
||||
#define FD_CLOEXEC 1
|
||||
|
||||
|
||||
// wait(2) status encoding, as understood by musl's WIFEXITED/WEXITSTATUS/
|
||||
// WIFSIGNALED/WTERMSIG macros:
|
||||
// normal exit -> (code & 0xff) << 8
|
||||
|
|
|
|||
Loading…
Reference in a new issue