summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrsc <rsc>2006-09-07 14:12:30 +0000
committerrsc <rsc>2006-09-07 14:12:30 +0000
commit31085bb4166c18b3dee059160d64b4edd7c5e2f4 (patch)
treed3b166a2c39f77e06e7104659b537521282f9260
parent7e019461c8bf0afbe73f959ca3394cce832501fd (diff)
downloadxv6-labs-31085bb4166c18b3dee059160d64b4edd7c5e2f4.tar.gz
xv6-labs-31085bb4166c18b3dee059160d64b4edd7c5e2f4.tar.bz2
xv6-labs-31085bb4166c18b3dee059160d64b4edd7c5e2f4.zip
more comments
-rw-r--r--elf.h6
-rw-r--r--fs.h53
-rw-r--r--kalloc.c4
-rw-r--r--mkdir.c1
-rw-r--r--proc.c5
-rw-r--r--proc.h76
-rw-r--r--setjmp.S27
-rw-r--r--spinlock.c16
-rw-r--r--spinlock.h12
-rw-r--r--stat.h10
-rw-r--r--trap.c14
-rw-r--r--traps.h4
-rw-r--r--x86.h4
13 files changed, 151 insertions, 81 deletions
diff --git a/elf.h b/elf.h
index da18dca..da852a9 100644
--- a/elf.h
+++ b/elf.h
@@ -1,9 +1,8 @@
-//
-// format of an ELF executable file
-//
+// Format of an ELF executable file
#define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian
+// File header
struct elfhdr {
uint magic; // must equal ELF_MAGIC
uchar elf[12];
@@ -22,6 +21,7 @@ struct elfhdr {
ushort shstrndx;
};
+// Program section header
struct proghdr {
uint type;
uint offset;
diff --git a/fs.h b/fs.h
index 04e0b67..8687d16 100644
--- a/fs.h
+++ b/fs.h
@@ -1,12 +1,17 @@
-// on-disk file system format
+// On-disk file system format.
+// This header is shared between kernel and user space.
+
+// Block 0 is unused.
+// Block 1 is super block.
+// Inodes start at block 2.
#define BSIZE 512 // block size
-// sector 1 (2nd sector)
-struct superblock{
- uint size;
- uint nblocks;
- uint ninodes;
+// File system super block
+struct superblock {
+ uint size; // Size of file system (bytes???) xxx
+ uint nblocks; // Number of blocks
+ uint ninodes; // Number of inodes.
};
#define NADDRS (NDIRECT+1)
@@ -15,24 +20,31 @@ struct superblock{
#define NINDIRECT (BSIZE / sizeof(uint))
#define MAXFILE (NDIRECT + NINDIRECT)
+// On-disk inode structure
struct dinode {
- short type;
- short major;
- short minor;
- short nlink;
- uint size;
- uint addrs[NADDRS];
+ short type; // File type
+ short major; // Major device number (T_DEV only)
+ short minor; // Minor device number (T_DEV only)
+ short nlink; // Number of links to inode in file system
+ uint size; // Size of file (bytes)
+ uint addrs[NADDRS]; // Data block addresses
};
-#define T_DIR 1
-#define T_FILE 2
-#define T_DEV 3
+#define T_DIR 1 // Directory
+#define T_FILE 2 // File
+#define T_DEV 3 // Special device
+
+// Inodes per block.
+#define IPB (BSIZE / sizeof(struct dinode))
+
+// Block containing inode i
+#define IBLOCK(i) ((i) / IPB + 2)
+
+// Bitmap bits per block
+#define BPB (BSIZE*8)
-// sector 0 is unused, sector 1 is superblock, inodes start at sector 2
-#define IPB (BSIZE / sizeof(struct dinode))
-#define IBLOCK(inum) (inum / IPB + 2) // start of inode
-#define BPB (BSIZE*8)
-#define BBLOCK(b,ninodes) (b/BPB + (ninodes/IPB) + 3) // start of bitmap
+// Block containing bit for block b
+#define BBLOCK(b, ninodes) (b/BPB + (ninodes)/IPB + 3)
#define DIRSIZ 14
@@ -41,4 +53,5 @@ struct dirent {
char name[DIRSIZ];
};
+extern uint rootdev; // Device number of root file system
diff --git a/kalloc.c b/kalloc.c
index 34a55eb..7d3ca0c 100644
--- a/kalloc.c
+++ b/kalloc.c
@@ -40,6 +40,10 @@ kinit(void)
kfree(start, mem * PAGE);
}
+// Free the len bytes of memory pointed at by cp,
+// which normally should have been returned by a
+// call to kalloc(cp). (The exception is when
+// initializing the allocator; see kinit above.)
void
kfree(char *cp, int len)
{
diff --git a/mkdir.c b/mkdir.c
index ece7691..ac2c7a6 100644
--- a/mkdir.c
+++ b/mkdir.c
@@ -2,6 +2,7 @@
#include "stat.h"
#include "user.h"
+int
main(int argc, char *argv[])
{
int i;
diff --git a/proc.c b/proc.c
index 06ee2fd..3b7843f 100644
--- a/proc.c
+++ b/proc.c
@@ -136,7 +136,9 @@ copyproc(struct proc *p)
return np;
}
-uint
+// Grow current process's memory by n bytes.
+// Return old size on success, -1 on failure.
+int
growproc(int n)
{
struct proc *cp = curproc[cpu()];
@@ -154,6 +156,7 @@ growproc(int n)
return cp->sz - n;
}
+//PAGEBREAK: 42
// Per-CPU process scheduler.
// Each CPU calls scheduler() after setting itself up.
// Scheduler never returns. It loops, doing:
diff --git a/proc.h b/proc.h
index d29f765..3f0c006 100644
--- a/proc.h
+++ b/proc.h
@@ -1,18 +1,19 @@
-// segments in proc->gdt
-#define SEG_KCODE 1 // kernel code
-#define SEG_KDATA 2 // kernel data+stack
+// Segments in proc->gdt
+#define SEG_KCODE 1 // kernel code
+#define SEG_KDATA 2 // kernel data+stack
#define SEG_UCODE 3
#define SEG_UDATA 4
-#define SEG_TSS 5 // this process's task state
+#define SEG_TSS 5 // this process's task state
#define NSEGS 6
+// Saved registers for kernel context switches.
+// Don't need to save all the %fs etc. segment registers,
+// because they are constant across kernel contexts.
+// Save all the regular registers so we don't need to care
+// which are caller save.
+// Don't save %eax, because that's the return register.
+// The layout of jmpbuf is known to setjmp.S.
struct jmpbuf {
- // saved registers for kernel context switches
- // don't need to save all the fs etc. registers because
- // they are constant across kernel contexts
- // save all the regular registers so we don't care which are caller save
- // don't save eax because that's the return register
- // layout known to setjmp.S
int ebx;
int ecx;
int edx;
@@ -25,39 +26,42 @@ struct jmpbuf {
enum proc_state { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
-struct proc{
- char *mem; // start of process's memory (a kernel address)
- // process memory is laid out contiguously:
- // text
- // original data and bss
- // fixed-size stack
- // expandable heap
- uint sz; // user memory size
- char *kstack; // kernel stack
- enum proc_state state;
- int pid;
- int ppid;
- void *chan; // sleep
- int killed;
- struct file *ofile[NOFILE];
- struct inode *cwd;
- struct jmpbuf jmpbuf;
- struct trapframe *tf; // points into kstack, used to find user regs
+// Per-process state
+struct proc {
+ char *mem; // Start of process memory (kernel address)
+ uint sz; // Size of process memory (bytes)
+ char *kstack; // Bottom of kernel stack for this process
+ enum proc_state state; // Process state
+ int pid; // Process ID
+ int ppid; // Parent pid
+ 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
+ struct jmpbuf jmpbuf; // Jump here to run process
+ struct trapframe *tf; // Trap frame for current interrupt
};
+// Process memory is laid out contiguously:
+// text
+// original data and bss
+// fixed-size stack
+// expandable heap
+
extern struct proc proc[];
-extern struct proc *curproc[NCPU]; // can be NULL if no proc running.
+extern struct proc *curproc[NCPU]; // Current (running) process per CPU
#define MPSTACK 512
+// Per-CPU state
struct cpu {
- uchar apicid; // Local APIC ID
- struct jmpbuf jmpbuf;
- struct taskstate ts; // only to give cpu address of kernel stack
- struct segdesc gdt[NSEGS];
- char mpstack[MPSTACK]; // per-cpu start-up stack
- volatile int booted;
- int nlock; // # of locks currently held
+ uchar apicid; // Local APIC ID
+ struct jmpbuf jmpbuf; // Jump here to enter scheduler
+ struct taskstate ts; // Used by x86 to find stack for interrupt
+ struct segdesc gdt[NSEGS]; // x86 global descriptor table
+ char mpstack[MPSTACK]; // Per-CPU startup stack
+ volatile int booted; // Has the CPU started?
+ int nlock; // Number of locks currently held
};
extern struct cpu cpus[NCPU];
diff --git a/setjmp.S b/setjmp.S
index aee5590..64c587a 100644
--- a/setjmp.S
+++ b/setjmp.S
@@ -1,3 +1,20 @@
+# int setjmp(struct jmpbuf *jmp);
+# void longjmp(struct jmpbuf *jmp);
+#
+# Setjmp saves its stack environment in jmp
+# for later use by longjmp. It returns 0.
+#
+# Longjmp restores the environment saved by
+# the last call of setjmp. It then causes
+# execution to continue as if the call of setjmp
+# had just returned 1.
+#
+# The caller of setjmp must not itself have
+# returned in the interim. All accessible data
+# have values as of the time longjmp was called.
+#
+# [Description, but not code, borrowed from Plan 9.]
+
.globl setjmp
setjmp:
movl 4(%esp), %eax
@@ -9,10 +26,10 @@ setjmp:
movl %edi, 16(%eax)
movl %esp, 20(%eax)
movl %ebp, 24(%eax)
- pushl 0(%esp) /* %eip */
+ pushl 0(%esp) # %eip
popl 28(%eax)
- movl $0, %eax /* return value */
+ movl $0, %eax # return value
ret
.globl longjmp
@@ -27,8 +44,8 @@ longjmp:
movl 20(%eax), %esp
movl 24(%eax), %ebp
- addl $4, %esp /* pop %eip into thin air */
- pushl 28(%eax) /* push new %eip */
+ addl $4, %esp # pop and discard %eip
+ pushl 28(%eax) # push new %eip
- movl $1, %eax /* return value (appears to come from setjmp!) */
+ movl $1, %eax # return value (appears to come from setjmp!)
ret
diff --git a/spinlock.c b/spinlock.c
index 1e68ae4..486c217 100644
--- a/spinlock.c
+++ b/spinlock.c
@@ -1,3 +1,5 @@
+// Mutual exclusion spin locks.
+
#include "types.h"
#include "defs.h"
#include "x86.h"
@@ -16,6 +18,7 @@ initlock(struct spinlock *lock, char *name)
lock->cpu = 0xffffffff;
}
+// Record the current call stack in pcs[] by following the %ebp chain.
void
getcallerpcs(void *v, uint pcs[])
{
@@ -31,6 +34,10 @@ getcallerpcs(void *v, uint pcs[])
pcs[i] = 0;
}
+// Acquire the lock.
+// Loops (spins) until the lock is acquired.
+// (Because contention is handled by spinning, must not
+// go to sleep holding any locks.)
void
acquire(struct spinlock *lock)
{
@@ -44,10 +51,16 @@ acquire(struct spinlock *lock)
while(cmpxchg(0, 1, &lock->locked) == 1)
;
cpuid(0, 0, 0, 0, 0); // memory barrier
- getcallerpcs(&lock, lock->pcs);
+
+ // Record info about lock acquisition for debugging.
+ // The +10 is only so that we can tell the difference
+ // between forgetting to initialize lock->cpu
+ // and holding a lock on cpu 0.
lock->cpu = cpu() + 10;
+ getcallerpcs(&lock, lock->pcs);
}
+// Release the lock.
void
release(struct spinlock *lock)
{
@@ -63,6 +76,7 @@ release(struct spinlock *lock)
sti();
}
+// Check whether this cpu is holding the lock.
int
holding(struct spinlock *lock)
{
diff --git a/spinlock.h b/spinlock.h
index ae5ad1f..1a706cf 100644
--- a/spinlock.h
+++ b/spinlock.h
@@ -1,6 +1,10 @@
+// Mutual exclusion lock.
struct spinlock {
- char *name;
- uint locked;
- int cpu;
- uint pcs[10];
+ uint locked; // Is the lock held?
+
+ // For debugging:
+ char *name; // Name of lock.
+ int cpu; // The number of the cpu holding the lock.
+ uint pcs[10]; // The call stack (an array of program counters)
+ // that locked the lock.
};
diff --git a/stat.h b/stat.h
index 57a018c..bc3a06c 100644
--- a/stat.h
+++ b/stat.h
@@ -1,7 +1,7 @@
struct stat {
- int dev;
- uint ino;
- short type;
- short nlink;
- uint size;
+ int dev; // Device number
+ uint ino; // Inode number on device
+ short type; // Type of file
+ short nlink; // Number of links to file
+ uint size; // Size of file in bytes
};
diff --git a/trap.c b/trap.c
index 4fb3039..b35107f 100644
--- a/trap.c
+++ b/trap.c
@@ -7,11 +7,11 @@
#include "traps.h"
#include "syscall.h"
+// Interrupt descriptor table (shared by all CPUs).
struct gatedesc idt[256];
+
extern uint vectors[]; // in vectors.S: array of 256 entry pointers
-extern void trapenter(void);
-extern void trapenter1(void);
void
tvinit(void)
@@ -65,30 +65,34 @@ trap(struct trapframe *tf)
return;
}
- if(v == (IRQ_OFFSET + IRQ_IDE)){
+ if(v == IRQ_OFFSET + IRQ_IDE){
ide_intr();
cli(); // prevent a waiting interrupt from overflowing stack
lapic_eoi();
return;
}
- if(v == (IRQ_OFFSET + IRQ_KBD)){
+ if(v == IRQ_OFFSET + IRQ_KBD){
kbd_intr();
cli(); // prevent a waiting interrupt from overflowing stack
lapic_eoi();
return;
}
- if(v == (IRQ_OFFSET + IRQ_SPURIOUS)){
+ if(v == IRQ_OFFSET + IRQ_SPURIOUS){
cprintf("spurious interrupt from cpu %d eip %x\n", cpu(), tf->eip);
return; // no eoi for this one.
}
if(curproc[cpu()]) {
+ // assume process caused unexpected trap,
+ // for example by dividing by zero or dereferencing a bad pointer
cprintf("pid %d: unhandled trap %d on cpu %d eip %x -- kill proc\n",
curproc[cpu()]->pid, v, cpu(), tf->eip);
proc_exit();
}
+
+ // otherwise it's our mistake
cprintf("unexpected trap %d from cpu %d eip %x\n", v, cpu(), tf->eip);
panic("trap");
}
diff --git a/traps.h b/traps.h
index 732d8e0..d4a6a3a 100644
--- a/traps.h
+++ b/traps.h
@@ -1,4 +1,6 @@
-// system defined:
+// x86 trap and interrupt constants.
+
+// Processor-defined:
#define T_DIVIDE 0 // divide error
#define T_DEBUG 1 // debug exception
#define T_NMI 2 // non-maskable interrupt
diff --git a/x86.h b/x86.h
index bb79d3e..ab7882a 100644
--- a/x86.h
+++ b/x86.h
@@ -1,3 +1,6 @@
+// Special assembly routines to access x86-specific
+// hardware instructions.
+
static __inline uchar
inb(int port)
{
@@ -124,6 +127,7 @@ sti(void)
__asm__ volatile("sti");
}
+// Layout of the trap frame on the stack upon entry to trap.
struct trapframe {
// registers as pushed by pusha
uint edi;