1 // Segments in proc->gdt. 2 // Also known to bootasm.S and trapasm.S 3 #define SEG_KCODE 1 // kernel code 4 #define SEG_KDATA 2 // kernel data+stack 5 #define SEG_KCPU 3 // kernel per-cpu data 6 #define SEG_UCODE 4 // user code 7 #define SEG_UDATA 5 // user data+stack 8 #define SEG_TSS 6 // this process's task state 9 #define NSEGS 7 10 11 // Per-CPU state 12 struct cpu { 13 uchar id; // Local APIC ID; index into cpus[] below 14 struct context *scheduler; // swtch() here to enter scheduler 15 struct taskstate ts; // Used by x86 to find stack for interrupt 16 struct segdesc gdt[NSEGS]; // x86 global descriptor table 17 volatile uint booted; // Has the CPU started? 18 int ncli; // Depth of pushcli nesting. 19 int intena; // Were interrupts enabled before pushcli? 20 21 // Cpu-local storage variables; see below 22 struct cpu *cpu; 23 struct proc *proc; // The currently-running process. 24 }; 25 26 extern struct cpu cpus[NCPU]; 27 extern int ncpu; 28 29 // Per-CPU variables, holding pointers to the 30 // current cpu and to the current process. 31 // The asm suffix tells gcc to use "%gs:0" to refer to cpu 32 // and "%gs:4" to refer to proc. seginit sets up the 33 // %gs segment register so that %gs refers to the memory 34 // holding those two variables in the local cpu's struct cpu. 35 // This is similar to how thread-local variables are implemented 36 // in thread libraries such as Linux pthreads. 37 extern struct cpu *cpu asm("%gs:0"); // &cpus[cpunum()] 38 extern struct proc *proc asm("%gs:4"); // cpus[cpunum()].proc 39 40 //PAGEBREAK: 17 41 // Saved registers for kernel context switches. 42 // Don't need to save all the segment registers (%cs, etc), 43 // because they are constant across kernel contexts. 44 // Don't need to save %eax, %ecx, %edx, because the 45 // x86 convention is that the caller has saved them. 46 // Contexts are stored at the bottom of the stack they 47 // describe; the stack pointer is the address of the context. 48 // The layout of the context matches the layout of the stack in swtch.S 49 // at the "Switch stacks" comment. Switch doesn't save eip explicitly, 50 // but it is on the stack and allocproc() manipulates it. 51 struct context { 52 uint edi; 53 uint esi; 54 uint ebx; 55 uint ebp; 56 uint eip; 57 }; 58 59 enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE }; 60 61 // Per-process state 62 struct proc { 63 uint sz; // Size of process memory (bytes) 64 pde_t* pgdir; // Page table 65 char *kstack; // Bottom of kernel stack for this process 66 enum procstate state; // Process state 67 volatile int pid; // Process ID 68 struct proc *parent; // Parent process 69 struct trapframe *tf; // Trap frame for current syscall 70 struct context *context; // swtch() here to run process 71 void *chan; // If non-zero, sleeping on chan 72 int killed; // If non-zero, have been killed 73 struct file *ofile[NOFILE]; // Open files 74 struct inode *cwd; // Current directory 75 char name[16]; // Process name (debugging) 76 }; 77 78 // Process memory is laid out contiguously, low addresses first: 79 // text 80 // original data and bss 81 // fixed-size stack 82 // expandable heap 83