2024-08-07 06:35:06 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "types.h"
|
|
|
|
#include "param.h"
|
|
|
|
#include "riscv.h"
|
|
|
|
#include "spinlock.h"
|
|
|
|
|
2024-08-07 15:37:55 +02:00
|
|
|
/** Saved registers for kernel context switches. */
|
2019-05-31 15:45:59 +02:00
|
|
|
struct context {
|
2024-05-24 11:26:40 +02:00
|
|
|
u64 ra;
|
|
|
|
u64 sp;
|
2019-05-31 15:45:59 +02:00
|
|
|
|
|
|
|
// callee-saved
|
2024-05-24 11:26:40 +02:00
|
|
|
u64 s0;
|
|
|
|
u64 s1;
|
|
|
|
u64 s2;
|
|
|
|
u64 s3;
|
|
|
|
u64 s4;
|
|
|
|
u64 s5;
|
|
|
|
u64 s6;
|
|
|
|
u64 s7;
|
|
|
|
u64 s8;
|
|
|
|
u64 s9;
|
|
|
|
u64 s10;
|
|
|
|
u64 s11;
|
2019-05-31 15:45:59 +02:00
|
|
|
};
|
|
|
|
|
2024-08-07 15:37:55 +02:00
|
|
|
/** Per-CPU state. */
|
2010-09-02 10:15:17 +02:00
|
|
|
struct cpu {
|
2024-06-15 16:55:06 +02:00
|
|
|
struct proc *proc; // The process running on this cpu, or null.
|
|
|
|
struct context context; // swtch() here to enter scheduler().
|
|
|
|
int noff; // Depth of push_off() nesting.
|
|
|
|
int intena; // Were interrupts enabled before push_off()?
|
2010-09-02 10:15:17 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
extern struct cpu cpus[NCPU];
|
|
|
|
|
2019-07-10 14:57:51 +02:00
|
|
|
// per-process data for the trap handling code in trampoline.S.
|
2019-05-31 15:45:59 +02:00
|
|
|
// sits in a page by itself just under the trampoline page in the
|
|
|
|
// user page table. not specially mapped in the kernel page table.
|
2019-07-26 10:53:46 +02:00
|
|
|
// uservec in trampoline.S saves user registers in the trapframe,
|
2019-07-10 14:57:51 +02:00
|
|
|
// then initializes registers from the trapframe's
|
|
|
|
// kernel_sp, kernel_hartid, kernel_satp, and jumps to kernel_trap.
|
2019-07-26 10:53:46 +02:00
|
|
|
// usertrapret() and userret in trampoline.S set up
|
2019-07-10 14:57:51 +02:00
|
|
|
// the trapframe's kernel_*, restore user registers from the
|
|
|
|
// trapframe, switch to the user page table, and enter user space.
|
|
|
|
// the trapframe includes callee-saved user registers like s0-s11 because the
|
2019-06-01 11:33:38 +02:00
|
|
|
// return-to-user path via usertrapret() doesn't return through
|
|
|
|
// the entire kernel call stack.
|
2019-05-31 15:45:59 +02:00
|
|
|
struct trapframe {
|
2024-05-24 11:26:40 +02:00
|
|
|
/* 0 */ u64 kernel_satp; // kernel page table
|
|
|
|
/* 8 */ u64 kernel_sp; // top of process's kernel stack
|
|
|
|
/* 16 */ u64 kernel_trap; // usertrap()
|
|
|
|
/* 24 */ u64 epc; // saved user program counter
|
|
|
|
/* 32 */ u64 kernel_hartid; // saved kernel tp
|
|
|
|
/* 40 */ u64 ra;
|
|
|
|
/* 48 */ u64 sp;
|
|
|
|
/* 56 */ u64 gp;
|
|
|
|
/* 64 */ u64 tp;
|
|
|
|
/* 72 */ u64 t0;
|
|
|
|
/* 80 */ u64 t1;
|
|
|
|
/* 88 */ u64 t2;
|
|
|
|
/* 96 */ u64 s0;
|
|
|
|
/* 104 */ u64 s1;
|
|
|
|
/* 112 */ u64 a0;
|
|
|
|
/* 120 */ u64 a1;
|
|
|
|
/* 128 */ u64 a2;
|
|
|
|
/* 136 */ u64 a3;
|
|
|
|
/* 144 */ u64 a4;
|
|
|
|
/* 152 */ u64 a5;
|
|
|
|
/* 160 */ u64 a6;
|
|
|
|
/* 168 */ u64 a7;
|
|
|
|
/* 176 */ u64 s2;
|
|
|
|
/* 184 */ u64 s3;
|
|
|
|
/* 192 */ u64 s4;
|
|
|
|
/* 200 */ u64 s5;
|
|
|
|
/* 208 */ u64 s6;
|
|
|
|
/* 216 */ u64 s7;
|
|
|
|
/* 224 */ u64 s8;
|
|
|
|
/* 232 */ u64 s9;
|
|
|
|
/* 240 */ u64 s10;
|
|
|
|
/* 248 */ u64 s11;
|
|
|
|
/* 256 */ u64 t3;
|
|
|
|
/* 264 */ u64 t4;
|
|
|
|
/* 272 */ u64 t5;
|
|
|
|
/* 280 */ u64 t6;
|
Changes to allow use of native x86 ELF compilers, which on my
Linux 2.4 box using gcc 3.4.6 don't seem to follow the same
conventions as the i386-jos-elf-gcc compilers.
Can run make 'TOOLPREFIX=' or edit the Makefile.
curproc[cpu()] can now be NULL, indicating that no proc is running.
This seemed safer to me than having curproc[0] and curproc[1]
both pointing at proc[0] potentially.
The old implementation of swtch depended on the stack frame layout
used inside swtch being okay to return from on the other stack
(exactly the V6 you are not expected to understand this).
It also could be called in two contexts: at boot time, to schedule
the very first process, and later, on behalf of a process, to sleep
or schedule some other process.
I split this into two functions: scheduler and swtch.
The scheduler is now a separate never-returning function, invoked
by each cpu once set up. The scheduler looks like:
scheduler() {
setjmp(cpu.context);
pick proc to schedule
blah blah blah
longjmp(proc.context)
}
The new swtch is intended to be called only when curproc[cpu()] is not NULL,
that is, only on behalf of a user proc. It does:
swtch() {
if(setjmp(proc.context) == 0)
longjmp(cpu.context)
}
to save the current proc context and then jump over to the scheduler,
running on the cpu stack.
Similarly the system call stubs are now in assembly in usys.S to avoid
needing to know the details of stack frame layout used by the compiler.
Also various changes in the debugging prints.
2006-07-11 03:07:40 +02:00
|
|
|
};
|
|
|
|
|
2020-11-03 21:02:08 +01:00
|
|
|
enum procstate { UNUSED, USED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
|
2006-07-12 03:48:35 +02:00
|
|
|
|
2024-08-07 15:37:55 +02:00
|
|
|
/** Per-process state */
|
2006-09-07 16:12:30 +02:00
|
|
|
struct proc {
|
2019-07-02 15:14:47 +02:00
|
|
|
struct spinlock lock;
|
2019-07-10 15:28:00 +02:00
|
|
|
|
|
|
|
// p->lock must be held when using these:
|
2024-06-15 16:55:06 +02:00
|
|
|
enum procstate state; // Process state
|
|
|
|
void *chan; // If non-zero, sleeping on chan
|
|
|
|
int killed; // If non-zero, have been killed
|
|
|
|
int xstate; // Exit status to be returned to parent's wait
|
|
|
|
int pid; // Process ID
|
2019-07-10 15:28:00 +02:00
|
|
|
|
2020-11-08 07:56:57 +01:00
|
|
|
// wait_lock must be held when using this:
|
2024-06-15 16:55:06 +02:00
|
|
|
struct proc *parent; // Parent process
|
2020-11-05 13:32:10 +01:00
|
|
|
|
2019-07-10 15:28:00 +02:00
|
|
|
// these are private to the process, so p->lock need not be held.
|
2024-06-15 16:55:06 +02:00
|
|
|
u64 kstack; // Virtual address of kernel stack
|
|
|
|
u64 sz; // Size of process memory (bytes)
|
|
|
|
pagetable_t pagetable; // User page table
|
|
|
|
struct trapframe *trapframe; // data page for trampoline.S
|
|
|
|
struct context context; // swtch() here to run process
|
|
|
|
struct file *ofile[NOFILE]; // Open files
|
|
|
|
struct inode *cwd; // Current directory
|
|
|
|
char name[16]; // Process name (debugging)
|
2024-08-07 06:39:09 +02:00
|
|
|
int mask; // Process mask
|
2006-06-12 17:22:12 +02:00
|
|
|
};
|