提交 0aef8914 创建 作者: Russ Cox's avatar Russ Cox

shuffle and tweak for formatting.

pdf has very good page breaks now. would be a good copy for fall 2009.
上级 b3bebfce
...@@ -128,6 +128,7 @@ PRINT = runoff.list $(FILES) ...@@ -128,6 +128,7 @@ PRINT = runoff.list $(FILES)
xv6.pdf: $(PRINT) xv6.pdf: $(PRINT)
./runoff ./runoff
ls -l xv6.pdf
print: xv6.pdf print: xv6.pdf
......
...@@ -38,7 +38,7 @@ start: ...@@ -38,7 +38,7 @@ start:
//PAGEBREAK! //PAGEBREAK!
# Switch from real to protected mode, using a bootstrap GDT # Switch from real to protected mode, using a bootstrap GDT
# and segment translation that makes virtual addresses # and segment translation that makes virtual addresses
# identical to their physical addresses, so that the # identical to physical addresses, so that the
# effective memory map does not change during the switch. # effective memory map does not change during the switch.
lgdt gdtdesc lgdt gdtdesc
movl %cr0, %eax movl %cr0, %eax
...@@ -47,10 +47,10 @@ start: ...@@ -47,10 +47,10 @@ start:
# Jump to next instruction, but in 32-bit code segment. # Jump to next instruction, but in 32-bit code segment.
# Switches processor into 32-bit mode. # Switches processor into 32-bit mode.
ljmp $(SEG_KCODE<<3), $protcseg ljmp $(SEG_KCODE<<3), $start32
.code32 # Assemble for 32-bit mode .code32 # Assemble for 32-bit mode
protcseg: start32:
# Set up the protected-mode data segment registers # Set up the protected-mode data segment registers
movw $(SEG_KDATA<<3), %ax # Our data segment selector movw $(SEG_KDATA<<3), %ax # Our data segment selector
movw %ax, %ds # -> DS: Data Segment movw %ax, %ds # -> DS: Data Segment
...@@ -60,11 +60,11 @@ protcseg: ...@@ -60,11 +60,11 @@ protcseg:
movw %ax, %fs # -> FS movw %ax, %fs # -> FS
movw %ax, %gs # -> GS movw %ax, %gs # -> GS
# Set up the stack pointer and call into C.
movl start-4, %esp movl start-4, %esp
movl start-8, %eax call *(start-8)
call *%eax
# If bootmain returns (it shouldn't), trigger a Bochs # If the call returns (it shouldn't), trigger a Bochs
# breakpoint if running under Bochs, then loop. # breakpoint if running under Bochs, then loop.
movw $0x8a00, %ax # 0x8a00 -> port 0x8a00 movw $0x8a00, %ax # 0x8a00 -> port 0x8a00
movw %ax, %dx movw %ax, %dx
......
...@@ -7,69 +7,22 @@ ...@@ -7,69 +7,22 @@
#include "param.h" #include "param.h"
#include "traps.h" #include "traps.h"
#include "spinlock.h" #include "spinlock.h"
#include "dev.h" #include "fs.h"
#include "file.h"
#include "mmu.h" #include "mmu.h"
#include "proc.h" #include "proc.h"
#include "x86.h" #include "x86.h"
#define CRTPORT 0x3d4 static void consputc(int);
#define BACKSPACE 0x100
static ushort *crt = (ushort*)0xb8000; // CGA memory static int panicked = 0;
static struct { static struct {
struct spinlock lock; struct spinlock lock;
int locking; int locking;
} cons; } cons;
static int panicked = 0;
static void static void
cgaputc(int c)
{
int pos;
// Cursor position: col + 80*row.
outb(CRTPORT, 14);
pos = inb(CRTPORT+1) << 8;
outb(CRTPORT, 15);
pos |= inb(CRTPORT+1);
if(c == '\n')
pos += 80 - pos%80;
else if(c == BACKSPACE){
if(pos > 0)
crt[--pos] = ' ' | 0x0700;
} else
crt[pos++] = (c&0xff) | 0x0700; // black on white
if((pos/80) >= 24){ // Scroll up.
memmove(crt, crt+80, sizeof(crt[0])*23*80);
pos -= 80;
memset(crt+pos, 0, sizeof(crt[0])*(24*80 - pos));
}
outb(CRTPORT, 14);
outb(CRTPORT+1, pos>>8);
outb(CRTPORT, 15);
outb(CRTPORT+1, pos);
crt[pos] = ' ' | 0x0700;
}
void
consputc(int c)
{
if(panicked){
cli();
for(;;)
;
}
uartputc(c);
cgaputc(c);
}
void
printint(int xx, int base, int sgn) printint(int xx, int base, int sgn)
{ {
static char digits[] = "0123456789abcdef"; static char digits[] = "0123456789abcdef";
...@@ -79,10 +32,9 @@ printint(int xx, int base, int sgn) ...@@ -79,10 +32,9 @@ printint(int xx, int base, int sgn)
if(sgn && xx < 0){ if(sgn && xx < 0){
neg = 1; neg = 1;
x = 0 - xx; x = -xx;
} else { } else
x = xx; x = xx;
}
do{ do{
buf[i++] = digits[x % base]; buf[i++] = digits[x % base];
...@@ -94,6 +46,7 @@ printint(int xx, int base, int sgn) ...@@ -94,6 +46,7 @@ printint(int xx, int base, int sgn)
consputc(buf[i]); consputc(buf[i]);
} }
//PAGEBREAK: 50
// Print to the console. only understands %d, %x, %p, %s. // Print to the console. only understands %d, %x, %p, %s.
void void
cprintf(char *fmt, ...) cprintf(char *fmt, ...)
...@@ -108,17 +61,14 @@ cprintf(char *fmt, ...) ...@@ -108,17 +61,14 @@ cprintf(char *fmt, ...)
argp = (uint*)(void*)&fmt + 1; argp = (uint*)(void*)&fmt + 1;
state = 0; state = 0;
for(i = 0; fmt[i]; i++){ for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
c = fmt[i] & 0xff; if(c != '%'){
switch(state){
case 0:
if(c == '%')
state = '%';
else
consputc(c); consputc(c);
continue;
}
c = fmt[++i] & 0xff;
if(c == 0)
break; break;
case '%':
switch(c){ switch(c){
case 'd': case 'd':
printint(*argp++, 10, 1); printint(*argp++, 10, 1);
...@@ -128,8 +78,7 @@ cprintf(char *fmt, ...) ...@@ -128,8 +78,7 @@ cprintf(char *fmt, ...)
printint(*argp++, 16, 0); printint(*argp++, 16, 0);
break; break;
case 's': case 's':
s = (char*)*argp++; if((s = (char*)*argp++) == 0)
if(s == 0)
s = "(null)"; s = "(null)";
for(; *s; s++) for(; *s; s++)
consputc(*s); consputc(*s);
...@@ -143,30 +92,82 @@ cprintf(char *fmt, ...) ...@@ -143,30 +92,82 @@ cprintf(char *fmt, ...)
consputc(c); consputc(c);
break; break;
} }
state = 0;
break;
}
} }
if(locking) if(locking)
release(&cons.lock); release(&cons.lock);
} }
int void
consolewrite(struct inode *ip, char *buf, int n) panic(char *s)
{ {
int i; int i;
uint pcs[10];
iunlock(ip); cli();
acquire(&cons.lock); cons.locking = 0;
for(i = 0; i < n; i++) cprintf("cpu%d: panic: ", cpu());
consputc(buf[i] & 0xff); cprintf(s);
release(&cons.lock); cprintf("\n");
ilock(ip); getcallerpcs(&s, pcs);
for(i=0; i<10; i++)
cprintf(" %p", pcs[i]);
panicked = 1; // freeze other CPU
for(;;)
;
}
return n; //PAGEBREAK: 50
#define BACKSPACE 0x100
#define CRTPORT 0x3d4
static ushort *crt = (ushort*)0xb8000; // CGA memory
static void
cgaputc(int c)
{
int pos;
// Cursor position: col + 80*row.
outb(CRTPORT, 14);
pos = inb(CRTPORT+1) << 8;
outb(CRTPORT, 15);
pos |= inb(CRTPORT+1);
if(c == '\n')
pos += 80 - pos%80;
else if(c == BACKSPACE){
if(pos > 0)
crt[--pos] = ' ' | 0x0700;
} else
crt[pos++] = (c&0xff) | 0x0700; // black on white
if((pos/80) >= 24){ // Scroll up.
memmove(crt, crt+80, sizeof(crt[0])*23*80);
pos -= 80;
memset(crt+pos, 0, sizeof(crt[0])*(24*80 - pos));
}
outb(CRTPORT, 14);
outb(CRTPORT+1, pos>>8);
outb(CRTPORT, 15);
outb(CRTPORT+1, pos);
crt[pos] = ' ' | 0x0700;
}
void
consputc(int c)
{
if(panicked){
cli();
for(;;)
;
}
uartputc(c);
cgaputc(c);
} }
//PAGEBREAK: 50
#define INPUT_BUF 128 #define INPUT_BUF 128
struct { struct {
struct spinlock lock; struct spinlock lock;
...@@ -255,6 +256,21 @@ consoleread(struct inode *ip, char *dst, int n) ...@@ -255,6 +256,21 @@ consoleread(struct inode *ip, char *dst, int n)
return target - n; return target - n;
} }
int
consolewrite(struct inode *ip, char *buf, int n)
{
int i;
iunlock(ip);
acquire(&cons.lock);
for(i = 0; i < n; i++)
consputc(buf[i] & 0xff);
release(&cons.lock);
ilock(ip);
return n;
}
void void
consoleinit(void) consoleinit(void)
{ {
...@@ -269,22 +285,3 @@ consoleinit(void) ...@@ -269,22 +285,3 @@ consoleinit(void)
ioapicenable(IRQ_KBD, 0); ioapicenable(IRQ_KBD, 0);
} }
void
panic(char *s)
{
int i;
uint pcs[10];
cli();
cons.locking = 0;
cprintf("cpu%d: panic: ", cpu());
cprintf(s);
cprintf("\n");
getcallerpcs(&s, pcs);
for(i=0; i<10; i++)
cprintf(" %p", pcs[i]);
panicked = 1; // freeze other CPU
for(;;)
;
}
...@@ -91,6 +91,7 @@ void pipeclose(struct pipe*, int); ...@@ -91,6 +91,7 @@ void pipeclose(struct pipe*, int);
int piperead(struct pipe*, char*, int); int piperead(struct pipe*, char*, int);
int pipewrite(struct pipe*, char*, int); int pipewrite(struct pipe*, char*, int);
//PAGEBREAK: 16
// proc.c // proc.c
struct proc* copyproc(struct proc*); struct proc* copyproc(struct proc*);
void exit(void); void exit(void);
......
struct devsw {
int (*read)(struct inode*, char*, int);
int (*write)(struct inode*, char*, int);
};
extern struct devsw devsw[];
#define CONSOLE 1
...@@ -40,21 +40,3 @@ struct proghdr { ...@@ -40,21 +40,3 @@ struct proghdr {
#define ELF_PROG_FLAG_EXEC 1 #define ELF_PROG_FLAG_EXEC 1
#define ELF_PROG_FLAG_WRITE 2 #define ELF_PROG_FLAG_WRITE 2
#define ELF_PROG_FLAG_READ 4 #define ELF_PROG_FLAG_READ 4
// Blank page.
...@@ -11,7 +11,7 @@ exec(char *path, char **argv) ...@@ -11,7 +11,7 @@ exec(char *path, char **argv)
{ {
char *mem, *s, *last; char *mem, *s, *last;
int i, argc, arglen, len, off; int i, argc, arglen, len, off;
uint sz, sp, argp; uint sz, sp, argp, x;
struct elfhdr elf; struct elfhdr elf;
struct inode *ip; struct inode *ip;
struct proghdr ph; struct proghdr ph;
...@@ -67,7 +67,9 @@ exec(char *path, char **argv) ...@@ -67,7 +67,9 @@ exec(char *path, char **argv)
goto bad; goto bad;
if(ph.type != ELF_PROG_LOAD) if(ph.type != ELF_PROG_LOAD)
continue; continue;
if(ph.va + ph.memsz < ph.va || ph.va + ph.memsz > sz || ph.memsz < ph.filesz) if(ph.va + ph.memsz < ph.va || ph.va + ph.memsz > sz)
goto bad;
if(ph.memsz < ph.filesz)
goto bad; goto bad;
if(readi(ip, mem + ph.va, ph.offset, ph.filesz) != ph.filesz) if(readi(ip, mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
goto bad; goto bad;
......
#include "types.h" #include "types.h"
#include "defs.h" #include "defs.h"
#include "param.h" #include "param.h"
#include "fs.h"
#include "file.h" #include "file.h"
#include "spinlock.h" #include "spinlock.h"
#include "dev.h"
struct devsw devsw[NDEV]; struct devsw devsw[NDEV];
struct { struct {
......
...@@ -7,3 +7,35 @@ struct file { ...@@ -7,3 +7,35 @@ struct file {
struct inode *ip; struct inode *ip;
uint off; uint off;
}; };
// in-core file system types
struct inode {
uint dev; // Device number
uint inum; // Inode number
int ref; // Reference count
int flags; // I_BUSY, I_VALID
short type; // copy of disk inode
short major;
short minor;
short nlink;
uint size;
uint addrs[NDIRECT+1];
};
#define I_BUSY 0x1
#define I_VALID 0x2
// device implementations
struct devsw {
int (*read)(struct inode*, char*, int);
int (*write)(struct inode*, char*, int);
};
extern struct devsw devsw[];
#define CONSOLE 1
...@@ -19,8 +19,7 @@ ...@@ -19,8 +19,7 @@
#include "spinlock.h" #include "spinlock.h"
#include "buf.h" #include "buf.h"
#include "fs.h" #include "fs.h"
#include "fsvar.h" #include "file.h"
#include "dev.h"
#define min(a, b) ((a) < (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b))
static void itrunc(struct inode*); static void itrunc(struct inode*);
......
// in-core file system types
struct inode {
uint dev; // Device number
uint inum; // Inode number
int ref; // Reference count
int flags; // I_BUSY, I_VALID
short type; // copy of disk inode
short major;
short minor;
short nlink;
uint size;
uint addrs[NDIRECT+1];
};
#define I_BUSY 0x1
#define I_VALID 0x2
...@@ -82,3 +82,32 @@ picinit(void) ...@@ -82,3 +82,32 @@ picinit(void)
if(irqmask != 0xFFFF) if(irqmask != 0xFFFF)
picsetmask(irqmask); picsetmask(irqmask);
} }
// Blank page.
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "param.h" #include "param.h"
#include "mmu.h" #include "mmu.h"
#include "proc.h" #include "proc.h"
#include "fs.h"
#include "file.h" #include "file.h"
#include "spinlock.h" #include "spinlock.h"
...@@ -72,7 +73,7 @@ pipeclose(struct pipe *p, int writable) ...@@ -72,7 +73,7 @@ pipeclose(struct pipe *p, int writable)
release(&p->lock); release(&p->lock);
} }
//PAGEBREAK: 30 //PAGEBREAK: 40
int int
pipewrite(struct pipe *p, char *addr, int n) pipewrite(struct pipe *p, char *addr, int n)
{ {
......
...@@ -23,6 +23,79 @@ pinit(void) ...@@ -23,6 +23,79 @@ pinit(void)
initlock(&ptable.lock, "ptable"); initlock(&ptable.lock, "ptable");
} }
//PAGEBREAK: 36
// Print a process listing to console. For debugging.
// Runs when user types ^P on console.
// No lock to avoid wedging a stuck machine further.
void
procdump(void)
{
static char *states[] = {
[UNUSED] "unused",
[EMBRYO] "embryo",
[SLEEPING] "sleep ",
[RUNNABLE] "runble",
[RUNNING] "run ",
[ZOMBIE] "zombie"
};
int i;
struct proc *p;
char *state;
uint pc[10];
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
if(p->state == UNUSED)
continue;
if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
state = states[p->state];
else
state = "???";
cprintf("%d %s %s", p->pid, state, p->name);
if(p->state == SLEEPING){
getcallerpcs((uint*)p->context->ebp+2, pc);
for(i=0; i<10 && pc[i] != 0; i++)
cprintf(" %p", pc[i]);
}
cprintf("\n");
}
}
// Set up CPU's kernel segment descriptors.
// Run once at boot time on each CPU.
void
ksegment(void)
{
struct cpu *c1;
c1 = &cpus[cpu()];
c1->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0x100000 + 64*1024-1, 0);
c1->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
c1->gdt[SEG_KCPU] = SEG(STA_W, (uint)(&c1->tls+1), 0xffffffff, 0);
lgdt(c1->gdt, sizeof(c1->gdt));
loadfsgs(SEG_KCPU << 3);
// Initialize cpu-local variables.
c = c1;
cp = 0;
}
// Set up CPU's segment descriptors and current process task state.
// If cp==0, set up for "idle" state for when scheduler() is running.
void
usegment(void)
{
pushcli();
c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, (uint)cp->mem, cp->sz-1, DPL_USER);
c->gdt[SEG_UDATA] = SEG(STA_W, (uint)cp->mem, cp->sz-1, DPL_USER);
c->gdt[SEG_TSS] = SEG16(STS_T32A, (uint)&c->ts, sizeof(c->ts)-1, 0);
c->gdt[SEG_TSS].s = 0;
c->ts.ss0 = SEG_KDATA << 3;
c->ts.esp0 = (uint)cp->kstack + KSTACKSIZE;
ltr(SEG_TSS << 3);
popcli();
}
//PAGEBREAK: 15
// Look in the process table for an UNUSED proc. // Look in the process table for an UNUSED proc.
// If found, change state to EMBRYO and return it. // If found, change state to EMBRYO and return it.
// Otherwise return 0. // Otherwise return 0.
...@@ -67,6 +140,37 @@ found: ...@@ -67,6 +140,37 @@ found:
return p; return p;
} }
// Set up first user process.
void
userinit(void)
{
struct proc *p;
extern char _binary_initcode_start[], _binary_initcode_size[];
p = allocproc();
initproc = p;
// Initialize memory from initcode.S
p->sz = PAGE;
p->mem = kalloc(p->sz);
memset(p->mem, 0, p->sz);
memmove(p->mem, _binary_initcode_start, (int)_binary_initcode_size);
memset(p->tf, 0, sizeof(*p->tf));
p->tf->cs = (SEG_UCODE << 3) | DPL_USER;
p->tf->ds = (SEG_UDATA << 3) | DPL_USER;
p->tf->es = p->tf->ds;
p->tf->ss = p->tf->ds;
p->tf->eflags = FL_IF;
p->tf->esp = p->sz;
p->tf->eip = 0; // beginning of initcode.S
safestrcpy(p->name, "initcode", sizeof(p->name));
p->cwd = namei("/");
p->state = RUNNABLE;
}
// Grow current process's memory by n bytes. // Grow current process's memory by n bytes.
// Return 0 on success, -1 on failure. // Return 0 on success, -1 on failure.
int int
...@@ -86,41 +190,6 @@ growproc(int n) ...@@ -86,41 +190,6 @@ growproc(int n)
return 0; return 0;
} }
// Set up CPU's kernel segment descriptors.
// Run once at boot time on each CPU.
void
ksegment(void)
{
struct cpu *c1;
c1 = &cpus[cpu()];
c1->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0x100000 + 64*1024-1, 0);
c1->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
c1->gdt[SEG_KCPU] = SEG(STA_W, (uint)(&c1->tls+1), 0xffffffff, 0);
lgdt(c1->gdt, sizeof(c1->gdt));
loadfsgs(SEG_KCPU << 3);
// Initialize cpu-local variables.
c = c1;
cp = 0;
}
// Set up CPU's segment descriptors and task state for the current process.
// If cp==0, set up for "idle" state for when scheduler() is running.
void
usegment(void)
{
pushcli();
c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, (uint)cp->mem, cp->sz-1, DPL_USER);
c->gdt[SEG_UDATA] = SEG(STA_W, (uint)cp->mem, cp->sz-1, DPL_USER);
c->gdt[SEG_TSS] = SEG16(STS_T32A, (uint)&c->ts, sizeof(c->ts)-1, 0);
c->gdt[SEG_TSS].s = 0;
c->ts.ss0 = SEG_KDATA << 3;
c->ts.esp0 = (uint)cp->kstack + KSTACKSIZE;
ltr(SEG_TSS << 3);
popcli();
}
// Create a new process copying p as the parent. // Create a new process copying p as the parent.
// Sets up stack to return as if from system call. // Sets up stack to return as if from system call.
// Caller must set state of returned proc to RUNNABLE. // Caller must set state of returned proc to RUNNABLE.
...@@ -160,37 +229,6 @@ fork(void) ...@@ -160,37 +229,6 @@ fork(void)
return pid; return pid;
} }
// Set up first user process.
void
userinit(void)
{
struct proc *p;
extern char _binary_initcode_start[], _binary_initcode_size[];
p = allocproc();
initproc = p;
// Initialize memory from initcode.S
p->sz = PAGE;
p->mem = kalloc(p->sz);
memset(p->mem, 0, p->sz);
memmove(p->mem, _binary_initcode_start, (int)_binary_initcode_size);
memset(p->tf, 0, sizeof(*p->tf));
p->tf->cs = (SEG_UCODE << 3) | DPL_USER;
p->tf->ds = (SEG_UDATA << 3) | DPL_USER;
p->tf->es = p->tf->ds;
p->tf->ss = p->tf->ds;
p->tf->eflags = FL_IF;
p->tf->esp = p->sz;
p->tf->eip = 0; // beginning of initcode.S
safestrcpy(p->name, "initcode", sizeof(p->name));
p->cwd = namei("/");
p->state = RUNNABLE;
}
//PAGEBREAK: 42 //PAGEBREAK: 42
// Per-CPU process scheduler. // Per-CPU process scheduler.
// Each CPU calls scheduler() after setting itself up. // Each CPU calls scheduler() after setting itself up.
...@@ -440,39 +478,3 @@ wait(void) ...@@ -440,39 +478,3 @@ wait(void)
} }
} }
// Print a process listing to console. For debugging.
// Runs when user types ^P on console.
// No lock to avoid wedging a stuck machine further.
void
procdump(void)
{
static char *states[] = {
[UNUSED] "unused",
[EMBRYO] "embryo",
[SLEEPING] "sleep ",
[RUNNABLE] "runble",
[RUNNING] "run ",
[ZOMBIE] "zombie"
};
int i;
struct proc *p;
char *state;
uint pc[10];
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
if(p->state == UNUSED)
continue;
if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
state = states[p->state];
else
state = "???";
cprintf("%d %s %s", p->pid, state, p->name);
if(p->state == SLEEPING){
getcallerpcs((uint*)p->context->ebp+2, pc);
for(i=0; i<10 && pc[i] != 0; i++)
cprintf(" %p", pc[i]);
}
cprintf("\n");
}
}
...@@ -45,6 +45,7 @@ cat toc.ftr >>fmt/toc ...@@ -45,6 +45,7 @@ cat toc.ftr >>fmt/toc
# check for bad alignments # check for bad alignments
perl -e ' perl -e '
$leftwarn = 0;
while(<>){ while(<>){
chomp; chomp;
s!#.*!!; s!#.*!!;
...@@ -75,12 +76,35 @@ perl -e ' ...@@ -75,12 +76,35 @@ perl -e '
print STDERR "Have no toc for $file\n"; print STDERR "Have no toc for $file\n";
next; next;
} }
if($toc{$file} =~ /^\d\d[^5]/){ if($toc{$file} !~ /^\d\d5/){
print STDERR "$file does not start on a second half page.\n"; print STDERR "$file does not start on a second half page.\n";
} }
next; next;
} }
if(/(left|right): (.*)/){
$what = $1;
$file = $2;
if(!defined($toc{$file})){
print STDERR "Have no toc for $file\n";
next;
}
# this assumes that sheet 1 of code is a left page
# double-check the PDF
if(!$leftwarn++) {
print STDERR "assuming that sheet 1 is a left page. double-check!\n";
}
if($what eq "left" && !($toc{$file} =~ /^\d[13579]0/)){
print STDERR "$file does not start on a fresh left page [$toc{$file}]\n";
}
# why does this not work if I inline $x in the if?
$x = ($toc{$file} =~ /^\d[02468]0/);
if($what eq "right" && !$x){
print STDERR "$file does not start on a fresh right page [$toc{$file}] [$x]\n";
}
next;
}
print STDERR "Unknown spec: $_\n"; print STDERR "Unknown spec: $_\n";
} }
' fmt/tocdata runoff.spec ' fmt/tocdata runoff.spec
......
...@@ -34,12 +34,10 @@ sysproc.c ...@@ -34,12 +34,10 @@ sysproc.c
# file system # file system
buf.h buf.h
dev.h
fcntl.h fcntl.h
stat.h stat.h
file.h
fs.h fs.h
fsvar.h file.h
ide.c ide.c
bio.c bio.c
fs.c fs.c
......
...@@ -12,20 +12,27 @@ even: bootother.S # mild preference ...@@ -12,20 +12,27 @@ even: bootother.S # mild preference
# bootmain.c either # bootmain.c either
even: main.c even: main.c
# mp.c don't care at all # mp.c don't care at all
even: initcode.S # even: initcode.S
odd: init.c # odd: init.c
# spinlock.h either # spinlock.h either
# spinlock.c either # spinlock.c either
even: proc.h # mild preference even: proc.h # mild preference
even: proc.c # VERY important
# goal is to have two action-packed 2-page spreads,
# one with
# ksegment usegment allocproc userinit growproc fork
# and another with
# scheduler sched yield forkret sleep wakeup1 wakeup
right: proc.c # VERY important
# setjmp.S either # setjmp.S either
# kalloc.c either # kalloc.c either
# syscall.h either # syscall.h either
# trapasm.S either # trapasm.S either
# traps.h either # traps.h either
even: trap.c # important # even: trap.c
# vectors.pl either # vectors.pl either
# syscall.c either # syscall.c either
# sysproc.c either # sysproc.c either
...@@ -37,7 +44,7 @@ even: trap.c # important ...@@ -37,7 +44,7 @@ even: trap.c # important
# file.h either # file.h either
# fs.h either # fs.h either
# fsvar.h either # fsvar.h either
# even: ide.c left: ide.c
# odd: bio.c # odd: bio.c
odd: fs.c # VERY important odd: fs.c # VERY important
# file.c either # file.c either
...@@ -46,5 +53,6 @@ odd: fs.c # VERY important ...@@ -46,5 +53,6 @@ odd: fs.c # VERY important
# even: pipe.c # mild preference # even: pipe.c # mild preference
# string.c either # string.c either
left: kbd.h
even: console.c even: console.c
odd: sh.c odd: sh.c
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#include "mmu.h" #include "mmu.h"
#include "proc.h" #include "proc.h"
#include "fs.h" #include "fs.h"
#include "fsvar.h"
#include "file.h" #include "file.h"
#include "fcntl.h" #include "fcntl.h"
......
...@@ -30,36 +30,3 @@ timerinit(void) ...@@ -30,36 +30,3 @@ timerinit(void)
outb(IO_TIMER1, TIMER_DIV(100) / 256); outb(IO_TIMER1, TIMER_DIV(100) / 256);
picenable(IRQ_TIMER); picenable(IRQ_TIMER);
} }
// Blank page
...@@ -31,6 +31,7 @@ idtinit(void) ...@@ -31,6 +31,7 @@ idtinit(void)
lidt(idt, sizeof(idt)); lidt(idt, sizeof(idt));
} }
//PAGEBREAK: 41
void void
trap(struct trapframe *tf) trap(struct trapframe *tf)
{ {
......
...@@ -5,7 +5,8 @@ ...@@ -5,7 +5,8 @@
#include "param.h" #include "param.h"
#include "traps.h" #include "traps.h"
#include "spinlock.h" #include "spinlock.h"
#include "dev.h" #include "fs.h"
#include "file.h"
#include "mmu.h" #include "mmu.h"
#include "proc.h" #include "proc.h"
#include "x86.h" #include "x86.h"
......
...@@ -122,6 +122,7 @@ sti(void) ...@@ -122,6 +122,7 @@ sti(void)
asm volatile("sti"); asm volatile("sti");
} }
//PAGEBREAK: 36
// Layout of the trap frame built on the stack by the // Layout of the trap frame built on the stack by the
// hardware and by trapasm.S, and passed to trap(). // hardware and by trapasm.S, and passed to trap().
struct trapframe { struct trapframe {
......
没有这种文件类型的预览
这个 源代码变更 因为 太大 而不能显示。 你可以 浏览blob
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论