xv6-65oo2/proc.h
Frans Kaashoek fbb4c09444 Read curproc from cpu structure, but be careful because after a schedule event
myproc() points to a different thread.

   myproc();
   sched();
   myproc();  // this proc maybe different than the one before sched

Thus, in a function that operates on one thread better to retrieve the
current process once at the start of the function.
2017-01-31 20:21:14 -05:00

87 lines
3.1 KiB
C

// Per-CPU state
struct cpu {
uchar apicid; // Local APIC ID
struct context *scheduler; // swtch() here to enter scheduler
struct taskstate ts; // Used by x86 to find stack for interrupt
struct segdesc gdt[NSEGS]; // x86 global descriptor table
volatile uint started; // Has the CPU started?
int ncli; // Depth of pushcli nesting.
int intena; // Were interrupts enabled before pushcli?
// Per-CPU variables, holding pointers to the current cpu and to the current
// process (see cpu() and proc() in proc.c)
struct cpu *cpu; // On cpu 0, cpu = &cpus[0]; on cpu 1, cpu=&cpus[1], etc.
struct proc *proc; // The currently-running process on this cpu
};
extern struct cpu cpus[NCPU];
extern int ncpu;
// The asm suffix tells gcc to use "%gs:0" to refer to cpu
// and "%gs:4" to refer to proc. seginit sets up the
// %gs segment register so that %gs refers to the memory
// holding those two variables in the local cpu's struct cpu.
// This is similar to how thread-local variables are implemented
// in thread libraries such as Linux pthreads.
static inline struct cpu*
mycpu(void) {
struct cpu *cpu;
asm("movl %%gs:0, %0" : "=r"(cpu));
return cpu;
}
#if 0
static inline struct proc*
myproc(void) {
struct proc *proc;
asm("movl %%gs:4, %0" : "=r"(proc));
return proc;
}
#endif
//PAGEBREAK: 17
// Saved registers for kernel context switches.
// Don't need to save all the segment registers (%cs, etc),
// because they are constant across kernel contexts.
// Don't need to save %eax, %ecx, %edx, because the
// x86 convention is that the caller has saved them.
// Contexts are stored at the bottom of the stack they
// describe; the stack pointer is the address of the context.
// The layout of the context matches the layout of the stack in swtch.S
// at the "Switch stacks" comment. Switch doesn't save eip explicitly,
// but it is on the stack and allocproc() manipulates it.
struct context {
uint edi;
uint esi;
uint ebx;
uint ebp;
uint eip;
};
enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
// Per-process state
struct proc {
uint sz; // Size of process memory (bytes)
pde_t* pgdir; // Page table
char *kstack; // Bottom of kernel stack for this process
enum procstate state; // Process state
int pid; // Process ID
struct proc *parent; // Parent process
struct trapframe *tf; // Trap frame for current syscall
struct context *context; // swtch() here to run process
void *chan; // If non-zero, sleeping on chan
int killed; // If non-zero, have been killed
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
char name[16]; // Process name (debugging)
struct cpu *cpu; // If running, which cpu.
};
// Process memory is laid out contiguously, low addresses first:
// text
// original data and bss
// fixed-size stack
// expandable heap