├── .gitignore ├── 1 - Scheduler - RR ├── .cvsignore ├── .dir-locals.el ├── .gdbinit.tmpl ├── .gitignore ├── BUGS ├── LICENSE ├── Makefile ├── Notes ├── README ├── TRICKS ├── asm.h ├── bio.c ├── bootasm.S ├── bootmain.c ├── buf.h ├── cat.c ├── console.c ├── cuth ├── defs.h ├── dot-bochsrc ├── echo.c ├── elf.h ├── entry.S ├── entryother.S ├── exec.c ├── fcntl.h ├── file.c ├── file.h ├── forktest.c ├── fs.c ├── fs.h ├── gcd.c ├── gdbutil ├── grep.c ├── ide.c ├── init.c ├── initcode.S ├── ioapic.c ├── kalloc.c ├── kbd.c ├── kbd.h ├── kernel.ld ├── kill.c ├── lapic.c ├── ln.c ├── log.c ├── ls.c ├── main.c ├── memide.c ├── memlayout.h ├── mkdir.c ├── mkfs.c ├── mmu.h ├── mp.c ├── mp.h ├── param.h ├── picirq.c ├── pipe.c ├── pr.pl ├── printf.c ├── printpcs ├── proc.c ├── proc.h ├── rm.c ├── runoff ├── runoff.list ├── runoff.spec ├── runoff1 ├── sh.c ├── show1 ├── sign.pl ├── sleep1.p ├── spinlock.c ├── spinlock.h ├── spinp ├── stat.h ├── stressfs.c ├── string.c ├── swtch.S ├── symlink.patch ├── syscall.c ├── syscall.h ├── sysfile.c ├── sysproc.c ├── tags ├── timer.c ├── toc.ftr ├── toc.hdr ├── trap.c ├── trapasm.S ├── traps.h ├── types.h ├── uart.c ├── ulib.c ├── umalloc.c ├── user.h ├── usertests.c ├── usys.S ├── vectors.pl ├── vm.c ├── wc.c ├── x86.h └── zombie.c ├── 2 - Scheduler - FCFS ├── .cvsignore ├── .dir-locals.el ├── .gdbinit.tmpl ├── .gitignore ├── BUGS ├── LICENSE ├── Makefile ├── Notes ├── README ├── TRICKS ├── asm.h ├── bio.c ├── bootasm.S ├── bootmain.c ├── buf.h ├── cat.c ├── console.c ├── cuth ├── defs.h ├── dot-bochsrc ├── echo.c ├── elf.h ├── entry.S ├── entryother.S ├── exec.c ├── fcntl.h ├── file.c ├── file.h ├── forktest.c ├── fs.c ├── fs.h ├── gdbutil ├── grep.c ├── ide.c ├── init.c ├── initcode.S ├── ioapic.c ├── kalloc.c ├── kbd.c ├── kbd.h ├── kernel.ld ├── kill.c ├── lapic.c ├── ln.c ├── log.c ├── ls.c ├── main.c ├── memide.c ├── memlayout.h ├── mkdir.c ├── mkfs.c ├── mmu.h ├── mp.c ├── mp.h ├── param.h ├── picirq.c ├── pipe.c ├── pr.pl ├── prime.c ├── printf.c ├── printpcs ├── proc.c ├── proc.h ├── ps.c ├── rm.c ├── runoff ├── runoff.list ├── runoff.spec ├── runoff1 ├── sh.c ├── show1 ├── sign.pl ├── sleep1.p ├── spinlock.c ├── spinlock.h ├── spinp ├── stat.h ├── stressfs.c ├── string.c ├── swtch.S ├── symlink.patch ├── syscall.c ├── syscall.h ├── sysfile.c ├── sysproc.c ├── tags ├── timer.c ├── toc.ftr ├── toc.hdr ├── trap.c ├── trapasm.S ├── traps.h ├── types.h ├── uart.c ├── ulib.c ├── umalloc.c ├── user.h ├── usertests.c ├── usys.S ├── vectors.pl ├── vm.c ├── wc.c ├── x86.h └── zombie.c ├── 3 - Scheduler - Priority ├── .cvsignore ├── .dir-locals.el ├── .gdbinit.tmpl ├── .gitignore ├── BUGS ├── LICENSE ├── Makefile ├── Notes ├── README ├── TRICKS ├── asm.h ├── bio.c ├── bootasm.S ├── bootmain.c ├── buf.h ├── cat.c ├── console.c ├── cuth ├── defs.h ├── dot-bochsrc ├── echo.c ├── elf.h ├── entry.S ├── entryother.S ├── exec.c ├── fcntl.h ├── file.c ├── file.h ├── forktest.c ├── fs.c ├── fs.h ├── gdbutil ├── grep.c ├── ide.c ├── init.c ├── initcode.S ├── ioapic.c ├── kalloc.c ├── kbd.c ├── kbd.h ├── kernel.ld ├── kill.c ├── lapic.c ├── ln.c ├── log.c ├── ls.c ├── main.c ├── memide.c ├── memlayout.h ├── mkdir.c ├── mkfs.c ├── mmu.h ├── mp.c ├── mp.h ├── param.h ├── picirq.c ├── pipe.c ├── pr.pl ├── prime.c ├── printf.c ├── printpcs ├── proc.c ├── proc.h ├── ps.c ├── rm.c ├── runoff ├── runoff.list ├── runoff.spec ├── runoff1 ├── sh.c ├── show1 ├── sign.pl ├── sleep1.p ├── spinlock.c ├── spinlock.h ├── spinp ├── stat.h ├── stressfs.c ├── string.c ├── swtch.S ├── symlink.patch ├── syscall.c ├── syscall.h ├── sysfile.c ├── sysproc.c ├── tags ├── timer.c ├── toc.ftr ├── toc.hdr ├── trap.c ├── trapasm.S ├── traps.h ├── types.h ├── uart.c ├── ulib.c ├── umalloc.c ├── user.h ├── usertests.c ├── usys.S ├── vectors.pl ├── vm.c ├── wc.c ├── x86.h └── zombie.c ├── 4 - Scheduler - CFS ├── .cvsignore ├── .dir-locals.el ├── .gdbinit.tmpl ├── .gitignore ├── BUGS ├── LICENSE ├── Makefile ├── Notes ├── README ├── TRICKS ├── asm.h ├── bio.c ├── bootasm.S ├── bootmain.c ├── buf.h ├── cat.c ├── console.c ├── cuth ├── defs.h ├── dot-bochsrc ├── echo.c ├── elf.h ├── entry.S ├── entryother.S ├── exec.c ├── fcntl.h ├── file.c ├── file.h ├── forktest.c ├── fs.c ├── fs.h ├── gdbutil ├── grep.c ├── ide.c ├── init.c ├── initcode.S ├── ioapic.c ├── kalloc.c ├── kbd.c ├── kbd.h ├── kernel.ld ├── kill.c ├── lapic.c ├── ln.c ├── log.c ├── ls.c ├── main.c ├── memide.c ├── memlayout.h ├── mkdir.c ├── mkfs.c ├── mmu.h ├── mp.c ├── mp.h ├── param.h ├── picirq.c ├── pipe.c ├── pr.pl ├── prime.c ├── printf.c ├── printpcs ├── proc.c ├── proc.h ├── ps.c ├── rm.c ├── runoff ├── runoff.list ├── runoff.spec ├── runoff1 ├── sh.c ├── show1 ├── sign.pl ├── sleep1.p ├── spinlock.c ├── spinlock.h ├── spinp ├── stat.h ├── stressfs.c ├── string.c ├── swtch.S ├── symlink.patch ├── syscall.c ├── syscall.h ├── sysfile.c ├── sysproc.c ├── tags ├── timer.c ├── toc.ftr ├── toc.hdr ├── trap.c ├── trapasm.S ├── traps.h ├── types.h ├── uart.c ├── ulib.c ├── umalloc.c ├── user.h ├── usertests.c ├── usys.S ├── vectors.pl ├── vm.c ├── wc.c ├── x86.h └── zombie.c ├── 5 - Filesystem - Doubly Indirect ├── .cvsignore ├── .dir-locals.el ├── .gdbinit.tmpl ├── .gitignore ├── BUGS ├── LICENSE ├── Makefile ├── Notes ├── README ├── TRICKS ├── asm.h ├── big.c ├── bio.c ├── bootasm.S ├── bootmain.c ├── buf.h ├── cat.c ├── console.c ├── cuth ├── defs.h ├── dot-bochsrc ├── echo.c ├── elf.h ├── entry.S ├── entryother.S ├── exec.c ├── fcntl.h ├── file.c ├── file.h ├── forktest.c ├── fs-time.c ├── fs.c ├── fs.h ├── gcd.c ├── gdbutil ├── grep.c ├── ide.c ├── init.c ├── initcode.S ├── ioapic.c ├── kalloc.c ├── kbd.c ├── kbd.h ├── kernel.ld ├── kill.c ├── lapic.c ├── ln.c ├── log.c ├── ls.c ├── main.c ├── memide.c ├── memlayout.h ├── mkdir.c ├── mkfs.c ├── mmu.h ├── mp.c ├── mp.h ├── param.h ├── picirq.c ├── pipe.c ├── pr.pl ├── printf.c ├── printpcs ├── proc.c ├── proc.h ├── ps.c ├── rm.c ├── runoff ├── runoff.list ├── runoff.spec ├── runoff1 ├── sh.c ├── show1 ├── sign.pl ├── sleep1.p ├── spinlock.c ├── spinlock.h ├── spinp ├── stat.h ├── stressfs.c ├── string.c ├── swtch.S ├── symlink.patch ├── syscall.c ├── syscall.h ├── sysfile.c ├── sysproc.c ├── tags ├── timer.c ├── toc.ftr ├── toc.hdr ├── trap.c ├── trapasm.S ├── traps.h ├── types.h ├── uart.c ├── ulib.c ├── umalloc.c ├── user.h ├── usertests.c ├── usys.S ├── vectors.pl ├── vm.c ├── wc.c ├── x86.h └── zombie.c ├── 6 - Filesystem - Triply Indirect ├── BUGS ├── LICENSE ├── Makefile ├── Notes ├── README ├── TRICKS ├── asm.h ├── big.c ├── bio.c ├── bootasm.S ├── bootmain.c ├── buf.h ├── cat.c ├── console.c ├── cuth ├── defs.h ├── dot-bochsrc ├── echo.c ├── elf.h ├── entry.S ├── entryother.S ├── exec.c ├── fcntl.h ├── file.c ├── file.h ├── forktest.c ├── fs.c ├── fs.h ├── gdbutil ├── grep.c ├── ide.c ├── init.c ├── initcode.S ├── ioapic.c ├── kalloc.c ├── kbd.c ├── kbd.h ├── kernel.ld ├── kill.c ├── lapic.c ├── ln.c ├── log.c ├── ls.c ├── main.c ├── memide.c ├── memlayout.h ├── mkdir.c ├── mkfs.c ├── mmu.h ├── mp.c ├── mp.h ├── param.h ├── picirq.c ├── pipe.c ├── pr.pl ├── printf.c ├── printpcs ├── proc.c ├── proc.h ├── rm.c ├── runoff ├── runoff.list ├── runoff.spec ├── runoff1 ├── sh.c ├── show1 ├── sign.pl ├── sleep1.p ├── spinlock.c ├── spinlock.h ├── spinp ├── stat.h ├── stressfs.c ├── string.c ├── swtch.S ├── symlink.patch ├── syscall.c ├── syscall.h ├── sysfile.c ├── sysproc.c ├── tags ├── timer.c ├── toc.ftr ├── toc.hdr ├── trap.c ├── trapasm.S ├── traps.h ├── types.h ├── uart.c ├── ulib.c ├── umalloc.c ├── user.h ├── usertests.c ├── usys.S ├── vectors.pl ├── vm.c ├── wc.c ├── x86.h └── zombie.c ├── 7 - Filesystem - Fast File System ├── BUGS ├── LICENSE ├── Makefile ├── Notes ├── README ├── README.md ├── TRICKS ├── asm.h ├── bio.c ├── bootasm.S ├── bootmain.c ├── buf.h ├── cat.c ├── console.c ├── cuth ├── defs.h ├── dot-bochsrc ├── echo.c ├── elf.h ├── entry.S ├── entryother.S ├── exec.c ├── fcntl.h ├── file.c ├── file.h ├── forktest.c ├── fs-time.c ├── fs.c ├── fs.h ├── gcd.c ├── gdbutil ├── grep.c ├── ide.c ├── init.c ├── initcode.S ├── ioapic.c ├── kalloc.c ├── kbd.c ├── kbd.h ├── kernel.ld ├── kill.c ├── lapic.c ├── ln.c ├── log.c ├── ls.c ├── main.c ├── memide.c ├── memlayout.h ├── mkdir.c ├── mkfs.c ├── mmu.h ├── mp.c ├── mp.h ├── param.h ├── picirq.c ├── pipe.c ├── pr.pl ├── printf.c ├── printpcs ├── proc.c ├── proc.h ├── rm.c ├── runoff ├── runoff.list ├── runoff.spec ├── runoff1 ├── sh.c ├── show1 ├── sign.pl ├── sleep1.p ├── spinlock.c ├── spinlock.h ├── spinp ├── stat.h ├── stressfs.c ├── string.c ├── swtch.S ├── symlink.patch ├── syscall.c ├── syscall.h ├── sysfile.c ├── sysproc.c ├── tags ├── timer.c ├── toc.ftr ├── toc.hdr ├── trap.c ├── trapasm.S ├── traps.h ├── types.h ├── uart.c ├── ulib.c ├── umalloc.c ├── user.h ├── usertests.c ├── usys.S ├── vectors.pl ├── vm.c ├── wc.c ├── x86.h └── zombie.c ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.DS_Store 3 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/.cvsignore: -------------------------------------------------------------------------------- 1 | *.asm 2 | *.d 3 | *.sym 4 | _* 5 | kernel 6 | user1 7 | userfs 8 | usertests 9 | xv6.img 10 | vectors.S 11 | bochsout.txt 12 | bootblock 13 | bootother 14 | bootother.out 15 | parport.out 16 | fmt 17 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((c-mode 2 | (indent-tabs-mode . nil) 3 | (c-file-style . "bsd") 4 | (c-basic-offset . 2))) 5 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/.gdbinit.tmpl: -------------------------------------------------------------------------------- 1 | set $lastcs = -1 2 | 3 | define hook-stop 4 | # There doesn't seem to be a good way to detect if we're in 16- or 5 | # 32-bit mode, but in 32-bit mode we always run with CS == 8 in the 6 | # kernel and CS == 35 in user space 7 | if $cs == 8 || $cs == 35 8 | if $lastcs != 8 && $lastcs != 35 9 | set architecture i386 10 | end 11 | x/i $pc 12 | else 13 | if $lastcs == -1 || $lastcs == 8 || $lastcs == 35 14 | set architecture i8086 15 | end 16 | # Translate the segment:offset into a physical address 17 | printf "[%4x:%4x] ", $cs, $eip 18 | x/i $cs*16+$eip 19 | end 20 | set $lastcs = $cs 21 | end 22 | 23 | echo + target remote localhost:1234\n 24 | target remote localhost:1234 25 | 26 | echo + symbol-file kernel\n 27 | symbol-file kernel 28 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | _* 3 | *.o 4 | *.d 5 | *.asm 6 | *.sym 7 | *.img 8 | vectors.S 9 | bootblock 10 | entryother 11 | initcode 12 | initcode.out 13 | kernel 14 | kernelmemfs 15 | mkfs 16 | .gdbinit 17 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/BUGS: -------------------------------------------------------------------------------- 1 | formatting: 2 | need to fix PAGEBREAK mechanism 3 | 4 | sh: 5 | can't always runcmd in child -- breaks cd. 6 | maybe should hard-code PATH=/ ? 7 | 8 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/asm.h: -------------------------------------------------------------------------------- 1 | // 2 | // assembler macros to create x86 segments 3 | // 4 | 5 | #define SEG_NULLASM \ 6 | .word 0, 0; \ 7 | .byte 0, 0, 0, 0 8 | 9 | // The 0xC0 means the limit is in 4096-byte units 10 | // and (for executable segments) 32-bit mode. 11 | #define SEG_ASM(type,base,lim) \ 12 | .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ 13 | .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ 14 | (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) 15 | 16 | #define STA_X 0x8 // Executable segment 17 | #define STA_E 0x4 // Expand down (non-executable segments) 18 | #define STA_C 0x4 // Conforming code segment (executable only) 19 | #define STA_W 0x2 // Writeable (non-executable segments) 20 | #define STA_R 0x2 // Readable (executable segments) 21 | #define STA_A 0x1 // Accessed 22 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/buf.h: -------------------------------------------------------------------------------- 1 | struct buf { 2 | int flags; 3 | uint dev; 4 | uint sector; 5 | struct buf *prev; // LRU cache list 6 | struct buf *next; 7 | struct buf *qnext; // disk queue 8 | uchar data[512]; 9 | }; 10 | #define B_BUSY 0x1 // buffer is locked by some process 11 | #define B_VALID 0x2 // buffer has been read from disk 12 | #define B_DIRTY 0x4 // buffer needs to be written to disk 13 | 14 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/cat.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | cat(int fd) 9 | { 10 | int n; 11 | 12 | while((n = read(fd, buf, sizeof(buf))) > 0) 13 | write(1, buf, n); 14 | if(n < 0){ 15 | printf(1, "cat: read error\n"); 16 | exit(); 17 | } 18 | } 19 | 20 | int 21 | main(int argc, char *argv[]) 22 | { 23 | int fd, i; 24 | 25 | if(argc <= 1){ 26 | cat(0); 27 | exit(); 28 | } 29 | 30 | for(i = 1; i < argc; i++){ 31 | if((fd = open(argv[i], 0)) < 0){ 32 | printf(1, "cat: cannot open %s\n", argv[i]); 33 | exit(); 34 | } 35 | cat(fd); 36 | close(fd); 37 | } 38 | exit(); 39 | } 40 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/cuth: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | $| = 1; 4 | 5 | sub writefile($@){ 6 | my ($file, @lines) = @_; 7 | 8 | sleep(1); 9 | open(F, ">$file") || die "open >$file: $!"; 10 | print F @lines; 11 | close(F); 12 | } 13 | 14 | # Cut out #include lines that don't contribute anything. 15 | for($i=0; $i<@ARGV; $i++){ 16 | $file = $ARGV[$i]; 17 | if(!open(F, $file)){ 18 | print STDERR "open $file: $!\n"; 19 | next; 20 | } 21 | @lines = ; 22 | close(F); 23 | 24 | $obj = "$file.o"; 25 | $obj =~ s/\.c\.o$/.o/; 26 | system("touch $file"); 27 | 28 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 29 | print STDERR "make $obj failed: $rv\n"; 30 | next; 31 | } 32 | 33 | system("cp $file =$file"); 34 | for($j=@lines-1; $j>=0; $j--){ 35 | if($lines[$j] =~ /^#include/){ 36 | $old = $lines[$j]; 37 | $lines[$j] = "/* CUT-H */\n"; 38 | writefile($file, @lines); 39 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 40 | $lines[$j] = $old; 41 | }else{ 42 | print STDERR "$file $old"; 43 | } 44 | } 45 | } 46 | writefile($file, grep {!/CUT-H/} @lines); 47 | system("rm =$file"); 48 | } 49 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/echo.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | for(i = 1; i < argc; i++) 11 | printf(1, "%s%s", argv[i], i+1 < argc ? " " : "\n"); 12 | exit(); 13 | } 14 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/elf.h: -------------------------------------------------------------------------------- 1 | // Format of an ELF executable file 2 | 3 | #define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian 4 | 5 | // File header 6 | struct elfhdr { 7 | uint magic; // must equal ELF_MAGIC 8 | uchar elf[12]; 9 | ushort type; 10 | ushort machine; 11 | uint version; 12 | uint entry; 13 | uint phoff; 14 | uint shoff; 15 | uint flags; 16 | ushort ehsize; 17 | ushort phentsize; 18 | ushort phnum; 19 | ushort shentsize; 20 | ushort shnum; 21 | ushort shstrndx; 22 | }; 23 | 24 | // Program section header 25 | struct proghdr { 26 | uint type; 27 | uint off; 28 | uint vaddr; 29 | uint paddr; 30 | uint filesz; 31 | uint memsz; 32 | uint flags; 33 | uint align; 34 | }; 35 | 36 | // Values for Proghdr type 37 | #define ELF_PROG_LOAD 1 38 | 39 | // Flag bits for Proghdr flags 40 | #define ELF_PROG_FLAG_EXEC 1 41 | #define ELF_PROG_FLAG_WRITE 2 42 | #define ELF_PROG_FLAG_READ 4 43 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/fcntl.h: -------------------------------------------------------------------------------- 1 | #define O_RDONLY 0x000 2 | #define O_WRONLY 0x001 3 | #define O_RDWR 0x002 4 | #define O_CREATE 0x200 5 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/file.h: -------------------------------------------------------------------------------- 1 | struct file { 2 | enum { FD_NONE, FD_PIPE, FD_INODE } type; 3 | int ref; // reference count 4 | char readable; 5 | char writable; 6 | struct pipe *pipe; 7 | struct inode *ip; 8 | uint off; 9 | }; 10 | 11 | 12 | // in-memory copy of an inode 13 | struct inode { 14 | uint dev; // Device number 15 | uint inum; // Inode number 16 | int ref; // Reference count 17 | int flags; // I_BUSY, I_VALID 18 | 19 | short type; // copy of disk inode 20 | short major; 21 | short minor; 22 | short nlink; 23 | uint size; 24 | uint addrs[NDIRECT+1]; 25 | }; 26 | #define I_BUSY 0x1 27 | #define I_VALID 0x2 28 | 29 | // table mapping major device number to 30 | // device functions 31 | struct devsw { 32 | int (*read)(struct inode*, char*, int); 33 | int (*write)(struct inode*, char*, int); 34 | }; 35 | 36 | extern struct devsw devsw[]; 37 | 38 | #define CONSOLE 1 39 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/forktest.c: -------------------------------------------------------------------------------- 1 | // Test that fork fails gracefully. 2 | // Tiny executable so that the limit can be filling the proc table. 3 | 4 | #include "types.h" 5 | #include "stat.h" 6 | #include "user.h" 7 | 8 | #define N 1000 9 | 10 | void 11 | printf(int fd, char *s, ...) 12 | { 13 | write(fd, s, strlen(s)); 14 | } 15 | 16 | void 17 | forktest(void) 18 | { 19 | int n, pid; 20 | 21 | printf(1, "fork test\n"); 22 | 23 | for(n=0; n 0; n--){ 37 | if(wait() < 0){ 38 | printf(1, "wait stopped early\n"); 39 | exit(); 40 | } 41 | } 42 | 43 | if(wait() != -1){ 44 | printf(1, "wait got too many\n"); 45 | exit(); 46 | } 47 | 48 | printf(1, "fork test OK\n"); 49 | } 50 | 51 | int 52 | main(void) 53 | { 54 | forktest(); 55 | exit(); 56 | } 57 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/init.c: -------------------------------------------------------------------------------- 1 | // init: The initial user-level program 2 | 3 | #include "types.h" 4 | #include "stat.h" 5 | #include "user.h" 6 | #include "fcntl.h" 7 | 8 | char *argv[] = { "sh", 0 }; 9 | 10 | int 11 | main(void) 12 | { 13 | int pid, wpid; 14 | 15 | if(open("console", O_RDWR) < 0){ 16 | mknod("console", 1, 1); 17 | open("console", O_RDWR); 18 | } 19 | dup(0); // stdout 20 | dup(0); // stderr 21 | 22 | for(;;){ 23 | printf(1, "init: starting sh\n"); 24 | pid = fork(); 25 | if(pid < 0){ 26 | printf(1, "init: fork failed\n"); 27 | exit(); 28 | } 29 | if(pid == 0){ 30 | exec("sh", argv); 31 | printf(1, "init: exec sh failed\n"); 32 | exit(); 33 | } 34 | while((wpid=wait()) >= 0 && wpid != pid) 35 | printf(1, "zombie!\n"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/initcode.S: -------------------------------------------------------------------------------- 1 | # Initial process execs /init. 2 | 3 | #include "syscall.h" 4 | #include "traps.h" 5 | 6 | 7 | # exec(init, argv) 8 | .globl start 9 | start: 10 | pushl $argv 11 | pushl $init 12 | pushl $0 // where caller pc would be 13 | movl $SYS_exec, %eax 14 | int $T_SYSCALL 15 | 16 | # for(;;) exit(); 17 | exit: 18 | movl $SYS_exit, %eax 19 | int $T_SYSCALL 20 | jmp exit 21 | 22 | # char init[] = "/init\0"; 23 | init: 24 | .string "/init\0" 25 | 26 | # char *argv[] = { init, 0 }; 27 | .p2align 2 28 | argv: 29 | .long init 30 | .long 0 31 | 32 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/kbd.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "x86.h" 3 | #include "defs.h" 4 | #include "kbd.h" 5 | 6 | int 7 | kbdgetc(void) 8 | { 9 | static uint shift; 10 | static uchar *charcode[4] = { 11 | normalmap, shiftmap, ctlmap, ctlmap 12 | }; 13 | uint st, data, c; 14 | 15 | st = inb(KBSTATP); 16 | if((st & KBS_DIB) == 0) 17 | return -1; 18 | data = inb(KBDATAP); 19 | 20 | if(data == 0xE0){ 21 | shift |= E0ESC; 22 | return 0; 23 | } else if(data & 0x80){ 24 | // Key released 25 | data = (shift & E0ESC ? data : data & 0x7F); 26 | shift &= ~(shiftcode[data] | E0ESC); 27 | return 0; 28 | } else if(shift & E0ESC){ 29 | // Last character was an E0 escape; or with 0x80 30 | data |= 0x80; 31 | shift &= ~E0ESC; 32 | } 33 | 34 | shift |= shiftcode[data]; 35 | shift ^= togglecode[data]; 36 | c = charcode[shift & (CTL | SHIFT)][data]; 37 | if(shift & CAPSLOCK){ 38 | if('a' <= c && c <= 'z') 39 | c += 'A' - 'a'; 40 | else if('A' <= c && c <= 'Z') 41 | c += 'a' - 'A'; 42 | } 43 | return c; 44 | } 45 | 46 | void 47 | kbdintr(void) 48 | { 49 | consoleintr(kbdgetc); 50 | } 51 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/kill.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char **argv) 7 | { 8 | int i; 9 | 10 | if(argc < 1){ 11 | printf(2, "usage: kill pid...\n"); 12 | exit(); 13 | } 14 | for(i=1; i; 17 | for($i=0; $i<@lines; $i+=50){ 18 | print "\n\n"; 19 | ++$page; 20 | print "$now $h Page $page\n"; 21 | print "\n\n"; 22 | for($j=$i; $j<@lines && $j<$i +50; $j++){ 23 | $lines[$j] =~ s!//DOC.*!!; 24 | print $lines[$j]; 25 | } 26 | for(; $j<$i+50; $j++){ 27 | print "\n"; 28 | } 29 | $sheet = ""; 30 | if($lines[$i] =~ /^([0-9][0-9])[0-9][0-9] /){ 31 | $sheet = "Sheet $1"; 32 | } 33 | print "\n\n"; 34 | print "$sheet\n"; 35 | print "\n\n"; 36 | } 37 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/printpcs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Decode the symbols from a panic EIP list 4 | 5 | # Find a working addr2line 6 | for p in i386-jos-elf-addr2line addr2line; do 7 | if which $p 2>&1 >/dev/null && \ 8 | $p -h 2>&1 | grep -q '\belf32-i386\b'; then 9 | break 10 | fi 11 | done 12 | 13 | # Enable as much pretty-printing as this addr2line can do 14 | $p $($p -h | grep ' -[aipsf] ' | awk '{print $1}') -e kernel "$@" 15 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/rm.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | if(argc < 2){ 11 | printf(2, "Usage: rm files...\n"); 12 | exit(); 13 | } 14 | 15 | for(i = 1; i < argc; i++){ 16 | if(unlink(argv[i]) < 0){ 17 | printf(2, "rm: %s failed to delete\n", argv[i]); 18 | break; 19 | } 20 | } 21 | 22 | exit(); 23 | } 24 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/runoff.list: -------------------------------------------------------------------------------- 1 | # basic headers 2 | types.h 3 | param.h 4 | memlayout.h 5 | defs.h 6 | x86.h 7 | asm.h 8 | mmu.h 9 | elf.h 10 | 11 | # entering xv6 12 | entry.S 13 | entryother.S 14 | main.c 15 | 16 | # locks 17 | spinlock.h 18 | spinlock.c 19 | 20 | # processes 21 | vm.c 22 | proc.h 23 | proc.c 24 | swtch.S 25 | kalloc.c 26 | 27 | # system calls 28 | traps.h 29 | vectors.pl 30 | trapasm.S 31 | trap.c 32 | syscall.h 33 | syscall.c 34 | sysproc.c 35 | 36 | # file system 37 | buf.h 38 | fcntl.h 39 | stat.h 40 | fs.h 41 | file.h 42 | ide.c 43 | bio.c 44 | log.c 45 | fs.c 46 | file.c 47 | sysfile.c 48 | exec.c 49 | 50 | # pipes 51 | pipe.c 52 | 53 | # string operations 54 | string.c 55 | 56 | # low-level hardware 57 | mp.h 58 | mp.c 59 | lapic.c 60 | ioapic.c 61 | picirq.c 62 | kbd.h 63 | kbd.c 64 | console.c 65 | timer.c 66 | uart.c 67 | 68 | # user-level 69 | initcode.S 70 | usys.S 71 | init.c 72 | sh.c 73 | 74 | # bootloader 75 | bootasm.S 76 | bootmain.c 77 | 78 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/show1: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | runoff1 "$@" | pr.pl -h "xv6/$@" | mpage -m50t50b -o -bLetter -T -t -2 -FLucidaSans-Typewriter83 -L60 >x.ps; gv --swap x.ps 4 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/sign.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; 4 | 5 | $n = sysread(SIG, $buf, 1000); 6 | 7 | if($n > 510){ 8 | print STDERR "boot block too large: $n bytes (max 510)\n"; 9 | exit 1; 10 | } 11 | 12 | print STDERR "boot block is $n bytes (max 510)\n"; 13 | 14 | $buf .= "\0" x (510-$n); 15 | $buf .= "\x55\xAA"; 16 | 17 | open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; 18 | print SIG $buf; 19 | close SIG; 20 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/spinlock.h: -------------------------------------------------------------------------------- 1 | // Mutual exclusion lock. 2 | struct spinlock { 3 | uint locked; // Is the lock held? 4 | 5 | // For debugging: 6 | char *name; // Name of lock. 7 | struct cpu *cpu; // The cpu holding the lock. 8 | uint pcs[10]; // The call stack (an array of program counters) 9 | // that locked the lock. 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/spinp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# != 1 ] || [ ! -f "$1" ]; then 4 | echo 'usage: spinp file.p' 1>&2 5 | exit 1 6 | fi 7 | 8 | rm -f $1.trail 9 | spin -a $1 || exit 1 10 | cc -DSAFETY -DREACH -DMEMLIM=500 -o pan pan.c 11 | pan -i 12 | rm pan.* pan 13 | if [ -f $1.trail ]; then 14 | spin -t -p $1 15 | fi 16 | 17 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/stat.h: -------------------------------------------------------------------------------- 1 | #define T_DIR 1 // Directory 2 | #define T_FILE 2 // File 3 | #define T_DEV 3 // Device 4 | 5 | struct stat { 6 | short type; // Type of file 7 | int dev; // File system's disk device 8 | uint ino; // Inode number 9 | short nlink; // Number of links to file 10 | uint size; // Size of file in bytes 11 | }; 12 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/stressfs.c: -------------------------------------------------------------------------------- 1 | // Demonstrate that moving the "acquire" in iderw after the loop that 2 | // appends to the idequeue results in a race. 3 | 4 | // For this to work, you should also add a spin within iderw's 5 | // idequeue traversal loop. Adding the following demonstrated a panic 6 | // after about 5 runs of stressfs in QEMU on a 2.1GHz CPU: 7 | // for (i = 0; i < 40000; i++) 8 | // asm volatile(""); 9 | 10 | #include "types.h" 11 | #include "stat.h" 12 | #include "user.h" 13 | #include "fs.h" 14 | #include "fcntl.h" 15 | 16 | int 17 | main(int argc, char *argv[]) 18 | { 19 | int fd, i; 20 | char path[] = "stressfs0"; 21 | char data[512]; 22 | 23 | printf(1, "stressfs starting\n"); 24 | memset(data, 'a', sizeof(data)); 25 | 26 | for(i = 0; i < 4; i++) 27 | if(fork() > 0) 28 | break; 29 | 30 | printf(1, "write %d\n", i); 31 | 32 | path[8] += i; 33 | fd = open(path, O_CREATE | O_RDWR); 34 | for(i = 0; i < 20; i++) 35 | // printf(fd, "%d\n", i); 36 | write(fd, data, sizeof(data)); 37 | close(fd); 38 | 39 | printf(1, "read\n"); 40 | 41 | fd = open(path, O_RDONLY); 42 | for (i = 0; i < 20; i++) 43 | read(fd, data, sizeof(data)); 44 | close(fd); 45 | 46 | wait(); 47 | 48 | exit(); 49 | } 50 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/swtch.S: -------------------------------------------------------------------------------- 1 | # Context switch 2 | # 3 | # void swtch(struct context **old, struct context *new); 4 | # 5 | # Save current register context in old 6 | # and then load register context from new. 7 | 8 | .globl swtch 9 | swtch: 10 | movl 4(%esp), %eax 11 | movl 8(%esp), %edx 12 | 13 | # Save old callee-save registers 14 | pushl %ebp 15 | pushl %ebx 16 | pushl %esi 17 | pushl %edi 18 | 19 | # Switch stacks 20 | movl %esp, (%eax) 21 | movl %edx, %esp 22 | 23 | # Load new callee-save registers 24 | popl %edi 25 | popl %esi 26 | popl %ebx 27 | popl %ebp 28 | ret 29 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/syscall.h: -------------------------------------------------------------------------------- 1 | // System call numbers 2 | #define SYS_fork 1 3 | #define SYS_exit 2 4 | #define SYS_wait 3 5 | #define SYS_pipe 4 6 | #define SYS_read 5 7 | #define SYS_kill 6 8 | #define SYS_exec 7 9 | #define SYS_fstat 8 10 | #define SYS_chdir 9 11 | #define SYS_dup 10 12 | #define SYS_getpid 11 13 | #define SYS_sbrk 12 14 | #define SYS_sleep 13 15 | #define SYS_uptime 14 16 | #define SYS_open 15 17 | #define SYS_write 16 18 | #define SYS_mknod 17 19 | #define SYS_unlink 18 20 | #define SYS_link 19 21 | #define SYS_mkdir 20 22 | #define SYS_close 21 23 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/timer.c: -------------------------------------------------------------------------------- 1 | // Intel 8253/8254/82C54 Programmable Interval Timer (PIT). 2 | // Only used on uniprocessors; 3 | // SMP machines use the local APIC timer. 4 | 5 | #include "types.h" 6 | #include "defs.h" 7 | #include "traps.h" 8 | #include "x86.h" 9 | 10 | #define IO_TIMER1 0x040 // 8253 Timer #1 11 | 12 | // Frequency of all three count-down timers; 13 | // (TIMER_FREQ/freq) is the appropriate count 14 | // to generate a frequency of freq Hz. 15 | 16 | #define TIMER_FREQ 1193182 17 | #define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) 18 | 19 | #define TIMER_MODE (IO_TIMER1 + 3) // timer mode port 20 | #define TIMER_SEL0 0x00 // select counter 0 21 | #define TIMER_RATEGEN 0x04 // mode 2, rate generator 22 | #define TIMER_16BIT 0x30 // r/w counter 16 bits, LSB first 23 | 24 | void 25 | timerinit(void) 26 | { 27 | // Interrupt 100 times/sec. 28 | outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 29 | outb(IO_TIMER1, TIMER_DIV(100) % 256); 30 | outb(IO_TIMER1, TIMER_DIV(100) / 256); 31 | picenable(IRQ_TIMER); 32 | } 33 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/toc.ftr: -------------------------------------------------------------------------------- 1 | 2 | 3 | The source listing is preceded by a cross-reference that lists every defined 4 | constant, struct, global variable, and function in xv6. Each entry gives, 5 | on the same line as the name, the line number (or, in a few cases, numbers) 6 | where the name is defined. Successive lines in an entry list the line 7 | numbers where the name is used. For example, this entry: 8 | 9 | swtch 2658 10 | 0374 2428 2466 2657 2658 11 | 12 | indicates that swtch is defined on line 2658 and is mentioned on five lines 13 | on sheets 03, 24, and 26. 14 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/toc.hdr: -------------------------------------------------------------------------------- 1 | The numbers to the left of the file names in the table are sheet numbers. 2 | The source code has been printed in a double column format with fifty 3 | lines per column, giving one hundred lines per sheet (or page). 4 | Thus there is a convenient relationship between line numbers and sheet numbers. 5 | 6 | 7 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/trapasm.S: -------------------------------------------------------------------------------- 1 | #include "mmu.h" 2 | 3 | # vectors.S sends all traps here. 4 | .globl alltraps 5 | alltraps: 6 | # Build trap frame. 7 | pushl %ds 8 | pushl %es 9 | pushl %fs 10 | pushl %gs 11 | pushal 12 | 13 | # Set up data and per-cpu segments. 14 | movw $(SEG_KDATA<<3), %ax 15 | movw %ax, %ds 16 | movw %ax, %es 17 | movw $(SEG_KCPU<<3), %ax 18 | movw %ax, %fs 19 | movw %ax, %gs 20 | 21 | # Call trap(tf), where tf=%esp 22 | pushl %esp 23 | call trap 24 | addl $4, %esp 25 | 26 | # Return falls through to trapret... 27 | .globl trapret 28 | trapret: 29 | popal 30 | popl %gs 31 | popl %fs 32 | popl %es 33 | popl %ds 34 | addl $0x8, %esp # trapno and errcode 35 | iret 36 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/types.h: -------------------------------------------------------------------------------- 1 | typedef unsigned int uint; 2 | typedef unsigned short ushort; 3 | typedef unsigned char uchar; 4 | typedef uint pde_t; 5 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/user.h: -------------------------------------------------------------------------------- 1 | struct stat; 2 | 3 | // system calls 4 | int fork(void); 5 | int exit(void) __attribute__((noreturn)); 6 | int wait(void); 7 | int pipe(int*); 8 | int write(int, void*, int); 9 | int read(int, void*, int); 10 | int close(int); 11 | int kill(int); 12 | int exec(char*, char**); 13 | int open(char*, int); 14 | int mknod(char*, short, short); 15 | int unlink(char*); 16 | int fstat(int fd, struct stat*); 17 | int link(char*, char*); 18 | int mkdir(char*); 19 | int chdir(char*); 20 | int dup(int); 21 | int getpid(void); 22 | char* sbrk(int); 23 | int sleep(int); 24 | int uptime(void); 25 | 26 | // ulib.c 27 | int stat(char*, struct stat*); 28 | char* strcpy(char*, char*); 29 | void *memmove(void*, void*, int); 30 | char* strchr(const char*, char c); 31 | int strcmp(const char*, const char*); 32 | void printf(int, char*, ...); 33 | char* gets(char*, int max); 34 | uint strlen(char*); 35 | void* memset(void*, int, uint); 36 | void* malloc(uint); 37 | void free(void*); 38 | int atoi(const char*); 39 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/usys.S: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | #include "traps.h" 3 | 4 | #define SYSCALL(name) \ 5 | .globl name; \ 6 | name: \ 7 | movl $SYS_ ## name, %eax; \ 8 | int $T_SYSCALL; \ 9 | ret 10 | 11 | SYSCALL(fork) 12 | SYSCALL(exit) 13 | SYSCALL(wait) 14 | SYSCALL(pipe) 15 | SYSCALL(read) 16 | SYSCALL(write) 17 | SYSCALL(close) 18 | SYSCALL(kill) 19 | SYSCALL(exec) 20 | SYSCALL(open) 21 | SYSCALL(mknod) 22 | SYSCALL(unlink) 23 | SYSCALL(fstat) 24 | SYSCALL(link) 25 | SYSCALL(mkdir) 26 | SYSCALL(chdir) 27 | SYSCALL(dup) 28 | SYSCALL(getpid) 29 | SYSCALL(sbrk) 30 | SYSCALL(sleep) 31 | SYSCALL(uptime) 32 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/vectors.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # Generate vectors.S, the trap/interrupt entry points. 4 | # There has to be one entry point per interrupt number 5 | # since otherwise there's no way for trap() to discover 6 | # the interrupt number. 7 | 8 | print "# generated by vectors.pl - do not edit\n"; 9 | print "# handlers\n"; 10 | print ".globl alltraps\n"; 11 | for(my $i = 0; $i < 256; $i++){ 12 | print ".globl vector$i\n"; 13 | print "vector$i:\n"; 14 | if(!($i == 8 || ($i >= 10 && $i <= 14) || $i == 17)){ 15 | print " pushl \$0\n"; 16 | } 17 | print " pushl \$$i\n"; 18 | print " jmp alltraps\n"; 19 | } 20 | 21 | print "\n# vector table\n"; 22 | print ".data\n"; 23 | print ".globl vectors\n"; 24 | print "vectors:\n"; 25 | for(my $i = 0; $i < 256; $i++){ 26 | print " .long vector$i\n"; 27 | } 28 | 29 | # sample output: 30 | # # handlers 31 | # .globl alltraps 32 | # .globl vector0 33 | # vector0: 34 | # pushl $0 35 | # pushl $0 36 | # jmp alltraps 37 | # ... 38 | # 39 | # # vector table 40 | # .data 41 | # .globl vectors 42 | # vectors: 43 | # .long vector0 44 | # .long vector1 45 | # .long vector2 46 | # ... 47 | 48 | -------------------------------------------------------------------------------- /1 - Scheduler - RR/wc.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | wc(int fd, char *name) 9 | { 10 | int i, n; 11 | int l, w, c, inword; 12 | 13 | l = w = c = 0; 14 | inword = 0; 15 | while((n = read(fd, buf, sizeof(buf))) > 0){ 16 | for(i=0; i 0) 12 | sleep(5); // Let child exit before parent. 13 | exit(); 14 | } 15 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/.cvsignore: -------------------------------------------------------------------------------- 1 | *.asm 2 | *.d 3 | *.sym 4 | _* 5 | kernel 6 | user1 7 | userfs 8 | usertests 9 | xv6.img 10 | vectors.S 11 | bochsout.txt 12 | bootblock 13 | bootother 14 | bootother.out 15 | parport.out 16 | fmt 17 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((c-mode 2 | (indent-tabs-mode . nil) 3 | (c-file-style . "bsd") 4 | (c-basic-offset . 2))) 5 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/.gdbinit.tmpl: -------------------------------------------------------------------------------- 1 | set $lastcs = -1 2 | 3 | define hook-stop 4 | # There doesn't seem to be a good way to detect if we're in 16- or 5 | # 32-bit mode, but in 32-bit mode we always run with CS == 8 in the 6 | # kernel and CS == 35 in user space 7 | if $cs == 8 || $cs == 35 8 | if $lastcs != 8 && $lastcs != 35 9 | set architecture i386 10 | end 11 | x/i $pc 12 | else 13 | if $lastcs == -1 || $lastcs == 8 || $lastcs == 35 14 | set architecture i8086 15 | end 16 | # Translate the segment:offset into a physical address 17 | printf "[%4x:%4x] ", $cs, $eip 18 | x/i $cs*16+$eip 19 | end 20 | set $lastcs = $cs 21 | end 22 | 23 | echo + target remote localhost:1234\n 24 | target remote localhost:1234 25 | 26 | echo + symbol-file kernel\n 27 | symbol-file kernel 28 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | _* 3 | *.o 4 | *.d 5 | *.asm 6 | *.sym 7 | *.img 8 | vectors.S 9 | bootblock 10 | entryother 11 | initcode 12 | initcode.out 13 | kernel 14 | kernelmemfs 15 | mkfs 16 | .gdbinit 17 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/BUGS: -------------------------------------------------------------------------------- 1 | formatting: 2 | need to fix PAGEBREAK mechanism 3 | 4 | sh: 5 | can't always runcmd in child -- breaks cd. 6 | maybe should hard-code PATH=/ ? 7 | 8 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/asm.h: -------------------------------------------------------------------------------- 1 | // 2 | // assembler macros to create x86 segments 3 | // 4 | 5 | #define SEG_NULLASM \ 6 | .word 0, 0; \ 7 | .byte 0, 0, 0, 0 8 | 9 | // The 0xC0 means the limit is in 4096-byte units 10 | // and (for executable segments) 32-bit mode. 11 | #define SEG_ASM(type,base,lim) \ 12 | .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ 13 | .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ 14 | (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) 15 | 16 | #define STA_X 0x8 // Executable segment 17 | #define STA_E 0x4 // Expand down (non-executable segments) 18 | #define STA_C 0x4 // Conforming code segment (executable only) 19 | #define STA_W 0x2 // Writeable (non-executable segments) 20 | #define STA_R 0x2 // Readable (executable segments) 21 | #define STA_A 0x1 // Accessed 22 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/buf.h: -------------------------------------------------------------------------------- 1 | struct buf { 2 | int flags; 3 | uint dev; 4 | uint sector; 5 | struct buf *prev; // LRU cache list 6 | struct buf *next; 7 | struct buf *qnext; // disk queue 8 | uchar data[512]; 9 | }; 10 | #define B_BUSY 0x1 // buffer is locked by some process 11 | #define B_VALID 0x2 // buffer has been read from disk 12 | #define B_DIRTY 0x4 // buffer needs to be written to disk 13 | 14 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/cat.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | cat(int fd) 9 | { 10 | int n; 11 | 12 | while((n = read(fd, buf, sizeof(buf))) > 0) 13 | write(1, buf, n); 14 | if(n < 0){ 15 | printf(1, "cat: read error\n"); 16 | exit(); 17 | } 18 | } 19 | 20 | int 21 | main(int argc, char *argv[]) 22 | { 23 | int fd, i; 24 | 25 | if(argc <= 1){ 26 | cat(0); 27 | exit(); 28 | } 29 | 30 | for(i = 1; i < argc; i++){ 31 | if((fd = open(argv[i], 0)) < 0){ 32 | printf(1, "cat: cannot open %s\n", argv[i]); 33 | exit(); 34 | } 35 | cat(fd); 36 | close(fd); 37 | } 38 | exit(); 39 | } 40 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/cuth: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | $| = 1; 4 | 5 | sub writefile($@){ 6 | my ($file, @lines) = @_; 7 | 8 | sleep(1); 9 | open(F, ">$file") || die "open >$file: $!"; 10 | print F @lines; 11 | close(F); 12 | } 13 | 14 | # Cut out #include lines that don't contribute anything. 15 | for($i=0; $i<@ARGV; $i++){ 16 | $file = $ARGV[$i]; 17 | if(!open(F, $file)){ 18 | print STDERR "open $file: $!\n"; 19 | next; 20 | } 21 | @lines = ; 22 | close(F); 23 | 24 | $obj = "$file.o"; 25 | $obj =~ s/\.c\.o$/.o/; 26 | system("touch $file"); 27 | 28 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 29 | print STDERR "make $obj failed: $rv\n"; 30 | next; 31 | } 32 | 33 | system("cp $file =$file"); 34 | for($j=@lines-1; $j>=0; $j--){ 35 | if($lines[$j] =~ /^#include/){ 36 | $old = $lines[$j]; 37 | $lines[$j] = "/* CUT-H */\n"; 38 | writefile($file, @lines); 39 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 40 | $lines[$j] = $old; 41 | }else{ 42 | print STDERR "$file $old"; 43 | } 44 | } 45 | } 46 | writefile($file, grep {!/CUT-H/} @lines); 47 | system("rm =$file"); 48 | } 49 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/echo.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | for(i = 1; i < argc; i++) 11 | printf(1, "%s%s", argv[i], i+1 < argc ? " " : "\n"); 12 | exit(); 13 | } 14 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/elf.h: -------------------------------------------------------------------------------- 1 | // Format of an ELF executable file 2 | 3 | #define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian 4 | 5 | // File header 6 | struct elfhdr { 7 | uint magic; // must equal ELF_MAGIC 8 | uchar elf[12]; 9 | ushort type; 10 | ushort machine; 11 | uint version; 12 | uint entry; 13 | uint phoff; 14 | uint shoff; 15 | uint flags; 16 | ushort ehsize; 17 | ushort phentsize; 18 | ushort phnum; 19 | ushort shentsize; 20 | ushort shnum; 21 | ushort shstrndx; 22 | }; 23 | 24 | // Program section header 25 | struct proghdr { 26 | uint type; 27 | uint off; 28 | uint vaddr; 29 | uint paddr; 30 | uint filesz; 31 | uint memsz; 32 | uint flags; 33 | uint align; 34 | }; 35 | 36 | // Values for Proghdr type 37 | #define ELF_PROG_LOAD 1 38 | 39 | // Flag bits for Proghdr flags 40 | #define ELF_PROG_FLAG_EXEC 1 41 | #define ELF_PROG_FLAG_WRITE 2 42 | #define ELF_PROG_FLAG_READ 4 43 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/fcntl.h: -------------------------------------------------------------------------------- 1 | #define O_RDONLY 0x000 2 | #define O_WRONLY 0x001 3 | #define O_RDWR 0x002 4 | #define O_CREATE 0x200 5 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/file.h: -------------------------------------------------------------------------------- 1 | struct file { 2 | enum { FD_NONE, FD_PIPE, FD_INODE } type; 3 | int ref; // reference count 4 | char readable; 5 | char writable; 6 | struct pipe *pipe; 7 | struct inode *ip; 8 | uint off; 9 | }; 10 | 11 | 12 | // in-memory copy of an inode 13 | struct inode { 14 | uint dev; // Device number 15 | uint inum; // Inode number 16 | int ref; // Reference count 17 | int flags; // I_BUSY, I_VALID 18 | 19 | short type; // copy of disk inode 20 | short major; 21 | short minor; 22 | short nlink; 23 | uint size; 24 | uint addrs[NDIRECT+1]; 25 | }; 26 | #define I_BUSY 0x1 27 | #define I_VALID 0x2 28 | 29 | // table mapping major device number to 30 | // device functions 31 | struct devsw { 32 | int (*read)(struct inode*, char*, int); 33 | int (*write)(struct inode*, char*, int); 34 | }; 35 | 36 | extern struct devsw devsw[]; 37 | 38 | #define CONSOLE 1 39 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/forktest.c: -------------------------------------------------------------------------------- 1 | // Test that fork fails gracefully. 2 | // Tiny executable so that the limit can be filling the proc table. 3 | 4 | #include "types.h" 5 | #include "stat.h" 6 | #include "user.h" 7 | 8 | #define N 1000 9 | 10 | void 11 | printf(int fd, char *s, ...) 12 | { 13 | write(fd, s, strlen(s)); 14 | } 15 | 16 | void 17 | forktest(void) 18 | { 19 | int n, pid; 20 | 21 | printf(1, "fork test\n"); 22 | 23 | for(n=0; n 0; n--){ 37 | if(wait() < 0){ 38 | printf(1, "wait stopped early\n"); 39 | exit(); 40 | } 41 | } 42 | 43 | if(wait() != -1){ 44 | printf(1, "wait got too many\n"); 45 | exit(); 46 | } 47 | 48 | printf(1, "fork test OK\n"); 49 | } 50 | 51 | int 52 | main(void) 53 | { 54 | forktest(); 55 | exit(); 56 | } 57 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/init.c: -------------------------------------------------------------------------------- 1 | // init: The initial user-level program 2 | 3 | #include "types.h" 4 | #include "stat.h" 5 | #include "user.h" 6 | #include "fcntl.h" 7 | 8 | char *argv[] = { "sh", 0 }; 9 | 10 | int 11 | main(void) 12 | { 13 | int pid, wpid; 14 | 15 | if(open("console", O_RDWR) < 0){ 16 | mknod("console", 1, 1); 17 | open("console", O_RDWR); 18 | } 19 | dup(0); // stdout 20 | dup(0); // stderr 21 | 22 | for(;;){ 23 | printf(1, "init: starting sh\n"); 24 | pid = fork(); 25 | if(pid < 0){ 26 | printf(1, "init: fork failed\n"); 27 | exit(); 28 | } 29 | if(pid == 0){ 30 | exec("sh", argv); 31 | printf(1, "init: exec sh failed\n"); 32 | exit(); 33 | } 34 | while((wpid=wait()) >= 0 && wpid != pid) 35 | printf(1, "zombie!\n"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/initcode.S: -------------------------------------------------------------------------------- 1 | # Initial process execs /init. 2 | 3 | #include "syscall.h" 4 | #include "traps.h" 5 | 6 | 7 | # exec(init, argv) 8 | .globl start 9 | start: 10 | pushl $argv 11 | pushl $init 12 | pushl $0 // where caller pc would be 13 | movl $SYS_exec, %eax 14 | int $T_SYSCALL 15 | 16 | # for(;;) exit(); 17 | exit: 18 | movl $SYS_exit, %eax 19 | int $T_SYSCALL 20 | jmp exit 21 | 22 | # char init[] = "/init\0"; 23 | init: 24 | .string "/init\0" 25 | 26 | # char *argv[] = { init, 0 }; 27 | .p2align 2 28 | argv: 29 | .long init 30 | .long 0 31 | 32 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/kbd.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "x86.h" 3 | #include "defs.h" 4 | #include "kbd.h" 5 | 6 | int 7 | kbdgetc(void) 8 | { 9 | static uint shift; 10 | static uchar *charcode[4] = { 11 | normalmap, shiftmap, ctlmap, ctlmap 12 | }; 13 | uint st, data, c; 14 | 15 | st = inb(KBSTATP); 16 | if((st & KBS_DIB) == 0) 17 | return -1; 18 | data = inb(KBDATAP); 19 | 20 | if(data == 0xE0){ 21 | shift |= E0ESC; 22 | return 0; 23 | } else if(data & 0x80){ 24 | // Key released 25 | data = (shift & E0ESC ? data : data & 0x7F); 26 | shift &= ~(shiftcode[data] | E0ESC); 27 | return 0; 28 | } else if(shift & E0ESC){ 29 | // Last character was an E0 escape; or with 0x80 30 | data |= 0x80; 31 | shift &= ~E0ESC; 32 | } 33 | 34 | shift |= shiftcode[data]; 35 | shift ^= togglecode[data]; 36 | c = charcode[shift & (CTL | SHIFT)][data]; 37 | if(shift & CAPSLOCK){ 38 | if('a' <= c && c <= 'z') 39 | c += 'A' - 'a'; 40 | else if('A' <= c && c <= 'Z') 41 | c += 'a' - 'A'; 42 | } 43 | return c; 44 | } 45 | 46 | void 47 | kbdintr(void) 48 | { 49 | consoleintr(kbdgetc); 50 | } 51 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/kill.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char **argv) 7 | { 8 | int i; 9 | 10 | if(argc < 1){ 11 | printf(2, "usage: kill pid...\n"); 12 | exit(); 13 | } 14 | for(i=1; i; 17 | for($i=0; $i<@lines; $i+=50){ 18 | print "\n\n"; 19 | ++$page; 20 | print "$now $h Page $page\n"; 21 | print "\n\n"; 22 | for($j=$i; $j<@lines && $j<$i +50; $j++){ 23 | $lines[$j] =~ s!//DOC.*!!; 24 | print $lines[$j]; 25 | } 26 | for(; $j<$i+50; $j++){ 27 | print "\n"; 28 | } 29 | $sheet = ""; 30 | if($lines[$i] =~ /^([0-9][0-9])[0-9][0-9] /){ 31 | $sheet = "Sheet $1"; 32 | } 33 | print "\n\n"; 34 | print "$sheet\n"; 35 | print "\n\n"; 36 | } 37 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/printpcs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Decode the symbols from a panic EIP list 4 | 5 | # Find a working addr2line 6 | for p in i386-jos-elf-addr2line addr2line; do 7 | if which $p 2>&1 >/dev/null && \ 8 | $p -h 2>&1 | grep -q '\belf32-i386\b'; then 9 | break 10 | fi 11 | done 12 | 13 | # Enable as much pretty-printing as this addr2line can do 14 | $p $($p -h | grep ' -[aipsf] ' | awk '{print $1}') -e kernel "$@" 15 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/ps.c: -------------------------------------------------------------------------------- 1 | 2 | #include "types.h" 3 | #include "stat.h" 4 | #include "user.h" 5 | 6 | int main(int argc, const char * argv[]) 7 | { 8 | ps(); 9 | exit(); 10 | } -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/rm.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | if(argc < 2){ 11 | printf(2, "Usage: rm files...\n"); 12 | exit(); 13 | } 14 | 15 | for(i = 1; i < argc; i++){ 16 | if(unlink(argv[i]) < 0){ 17 | printf(2, "rm: %s failed to delete\n", argv[i]); 18 | break; 19 | } 20 | } 21 | 22 | exit(); 23 | } 24 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/runoff.list: -------------------------------------------------------------------------------- 1 | # basic headers 2 | types.h 3 | param.h 4 | memlayout.h 5 | defs.h 6 | x86.h 7 | asm.h 8 | mmu.h 9 | elf.h 10 | 11 | # entering xv6 12 | entry.S 13 | entryother.S 14 | main.c 15 | 16 | # locks 17 | spinlock.h 18 | spinlock.c 19 | 20 | # processes 21 | vm.c 22 | proc.h 23 | proc.c 24 | swtch.S 25 | kalloc.c 26 | 27 | # system calls 28 | traps.h 29 | vectors.pl 30 | trapasm.S 31 | trap.c 32 | syscall.h 33 | syscall.c 34 | sysproc.c 35 | 36 | # file system 37 | buf.h 38 | fcntl.h 39 | stat.h 40 | fs.h 41 | file.h 42 | ide.c 43 | bio.c 44 | log.c 45 | fs.c 46 | file.c 47 | sysfile.c 48 | exec.c 49 | 50 | # pipes 51 | pipe.c 52 | 53 | # string operations 54 | string.c 55 | 56 | # low-level hardware 57 | mp.h 58 | mp.c 59 | lapic.c 60 | ioapic.c 61 | picirq.c 62 | kbd.h 63 | kbd.c 64 | console.c 65 | timer.c 66 | uart.c 67 | 68 | # user-level 69 | initcode.S 70 | usys.S 71 | init.c 72 | sh.c 73 | 74 | # bootloader 75 | bootasm.S 76 | bootmain.c 77 | 78 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/show1: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | runoff1 "$@" | pr.pl -h "xv6/$@" | mpage -m50t50b -o -bLetter -T -t -2 -FLucidaSans-Typewriter83 -L60 >x.ps; gv --swap x.ps 4 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/sign.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; 4 | 5 | $n = sysread(SIG, $buf, 1000); 6 | 7 | if($n > 510){ 8 | print STDERR "boot block too large: $n bytes (max 510)\n"; 9 | exit 1; 10 | } 11 | 12 | print STDERR "boot block is $n bytes (max 510)\n"; 13 | 14 | $buf .= "\0" x (510-$n); 15 | $buf .= "\x55\xAA"; 16 | 17 | open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; 18 | print SIG $buf; 19 | close SIG; 20 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/spinlock.h: -------------------------------------------------------------------------------- 1 | // Mutual exclusion lock. 2 | struct spinlock { 3 | uint locked; // Is the lock held? 4 | 5 | // For debugging: 6 | char *name; // Name of lock. 7 | struct cpu *cpu; // The cpu holding the lock. 8 | uint pcs[10]; // The call stack (an array of program counters) 9 | // that locked the lock. 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/spinp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# != 1 ] || [ ! -f "$1" ]; then 4 | echo 'usage: spinp file.p' 1>&2 5 | exit 1 6 | fi 7 | 8 | rm -f $1.trail 9 | spin -a $1 || exit 1 10 | cc -DSAFETY -DREACH -DMEMLIM=500 -o pan pan.c 11 | pan -i 12 | rm pan.* pan 13 | if [ -f $1.trail ]; then 14 | spin -t -p $1 15 | fi 16 | 17 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/stat.h: -------------------------------------------------------------------------------- 1 | #define T_DIR 1 // Directory 2 | #define T_FILE 2 // File 3 | #define T_DEV 3 // Device 4 | 5 | struct stat { 6 | short type; // Type of file 7 | int dev; // File system's disk device 8 | uint ino; // Inode number 9 | short nlink; // Number of links to file 10 | uint size; // Size of file in bytes 11 | }; 12 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/stressfs.c: -------------------------------------------------------------------------------- 1 | // Demonstrate that moving the "acquire" in iderw after the loop that 2 | // appends to the idequeue results in a race. 3 | 4 | // For this to work, you should also add a spin within iderw's 5 | // idequeue traversal loop. Adding the following demonstrated a panic 6 | // after about 5 runs of stressfs in QEMU on a 2.1GHz CPU: 7 | // for (i = 0; i < 40000; i++) 8 | // asm volatile(""); 9 | 10 | #include "types.h" 11 | #include "stat.h" 12 | #include "user.h" 13 | #include "fs.h" 14 | #include "fcntl.h" 15 | 16 | int 17 | main(int argc, char *argv[]) 18 | { 19 | int fd, i; 20 | char path[] = "stressfs0"; 21 | char data[512]; 22 | 23 | printf(1, "stressfs starting\n"); 24 | memset(data, 'a', sizeof(data)); 25 | 26 | for(i = 0; i < 4; i++) 27 | if(fork() > 0) 28 | break; 29 | 30 | printf(1, "write %d\n", i); 31 | 32 | path[8] += i; 33 | fd = open(path, O_CREATE | O_RDWR); 34 | for(i = 0; i < 20; i++) 35 | // printf(fd, "%d\n", i); 36 | write(fd, data, sizeof(data)); 37 | close(fd); 38 | 39 | printf(1, "read\n"); 40 | 41 | fd = open(path, O_RDONLY); 42 | for (i = 0; i < 20; i++) 43 | read(fd, data, sizeof(data)); 44 | close(fd); 45 | 46 | wait(); 47 | 48 | exit(); 49 | } 50 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/swtch.S: -------------------------------------------------------------------------------- 1 | # Context switch 2 | # 3 | # void swtch(struct context **old, struct context *new); 4 | # 5 | # Save current register context in old 6 | # and then load register context from new. 7 | 8 | .globl swtch 9 | swtch: 10 | movl 4(%esp), %eax 11 | movl 8(%esp), %edx 12 | 13 | # Save old callee-save registers 14 | pushl %ebp 15 | pushl %ebx 16 | pushl %esi 17 | pushl %edi 18 | 19 | # Switch stacks 20 | movl %esp, (%eax) 21 | movl %edx, %esp 22 | 23 | # Load new callee-save registers 24 | popl %edi 25 | popl %esi 26 | popl %ebx 27 | popl %ebp 28 | ret 29 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/syscall.h: -------------------------------------------------------------------------------- 1 | // System call numbers 2 | #define SYS_fork 1 3 | #define SYS_exit 2 4 | #define SYS_wait 3 5 | #define SYS_pipe 4 6 | #define SYS_read 5 7 | #define SYS_kill 6 8 | #define SYS_exec 7 9 | #define SYS_fstat 8 10 | #define SYS_chdir 9 11 | #define SYS_dup 10 12 | #define SYS_getpid 11 13 | #define SYS_sbrk 12 14 | #define SYS_sleep 13 15 | #define SYS_uptime 14 16 | #define SYS_open 15 17 | #define SYS_write 16 18 | #define SYS_mknod 17 19 | #define SYS_unlink 18 20 | #define SYS_link 19 21 | #define SYS_mkdir 20 22 | #define SYS_close 21 23 | #define SYS_ps 22 -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/timer.c: -------------------------------------------------------------------------------- 1 | // Intel 8253/8254/82C54 Programmable Interval Timer (PIT). 2 | // Only used on uniprocessors; 3 | // SMP machines use the local APIC timer. 4 | 5 | #include "types.h" 6 | #include "defs.h" 7 | #include "traps.h" 8 | #include "x86.h" 9 | 10 | #define IO_TIMER1 0x040 // 8253 Timer #1 11 | 12 | // Frequency of all three count-down timers; 13 | // (TIMER_FREQ/freq) is the appropriate count 14 | // to generate a frequency of freq Hz. 15 | 16 | #define TIMER_FREQ 1193182 17 | #define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) 18 | 19 | #define TIMER_MODE (IO_TIMER1 + 3) // timer mode port 20 | #define TIMER_SEL0 0x00 // select counter 0 21 | #define TIMER_RATEGEN 0x04 // mode 2, rate generator 22 | #define TIMER_16BIT 0x30 // r/w counter 16 bits, LSB first 23 | 24 | void 25 | timerinit(void) 26 | { 27 | // Interrupt 100 times/sec. 28 | outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 29 | outb(IO_TIMER1, TIMER_DIV(100) % 256); 30 | outb(IO_TIMER1, TIMER_DIV(100) / 256); 31 | picenable(IRQ_TIMER); 32 | } 33 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/toc.ftr: -------------------------------------------------------------------------------- 1 | 2 | 3 | The source listing is preceded by a cross-reference that lists every defined 4 | constant, struct, global variable, and function in xv6. Each entry gives, 5 | on the same line as the name, the line number (or, in a few cases, numbers) 6 | where the name is defined. Successive lines in an entry list the line 7 | numbers where the name is used. For example, this entry: 8 | 9 | swtch 2658 10 | 0374 2428 2466 2657 2658 11 | 12 | indicates that swtch is defined on line 2658 and is mentioned on five lines 13 | on sheets 03, 24, and 26. 14 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/toc.hdr: -------------------------------------------------------------------------------- 1 | The numbers to the left of the file names in the table are sheet numbers. 2 | The source code has been printed in a double column format with fifty 3 | lines per column, giving one hundred lines per sheet (or page). 4 | Thus there is a convenient relationship between line numbers and sheet numbers. 5 | 6 | 7 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/trapasm.S: -------------------------------------------------------------------------------- 1 | #include "mmu.h" 2 | 3 | # vectors.S sends all traps here. 4 | .globl alltraps 5 | alltraps: 6 | # Build trap frame. 7 | pushl %ds 8 | pushl %es 9 | pushl %fs 10 | pushl %gs 11 | pushal 12 | 13 | # Set up data and per-cpu segments. 14 | movw $(SEG_KDATA<<3), %ax 15 | movw %ax, %ds 16 | movw %ax, %es 17 | movw $(SEG_KCPU<<3), %ax 18 | movw %ax, %fs 19 | movw %ax, %gs 20 | 21 | # Call trap(tf), where tf=%esp 22 | pushl %esp 23 | call trap 24 | addl $4, %esp 25 | 26 | # Return falls through to trapret... 27 | .globl trapret 28 | trapret: 29 | popal 30 | popl %gs 31 | popl %fs 32 | popl %es 33 | popl %ds 34 | addl $0x8, %esp # trapno and errcode 35 | iret 36 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/types.h: -------------------------------------------------------------------------------- 1 | typedef unsigned int uint; 2 | typedef unsigned short ushort; 3 | typedef unsigned char uchar; 4 | typedef uint pde_t; 5 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/user.h: -------------------------------------------------------------------------------- 1 | struct stat; 2 | 3 | // system calls 4 | int fork(void); 5 | int exit(void) __attribute__((noreturn)); 6 | int wait(void); 7 | int pipe(int*); 8 | int write(int, void*, int); 9 | int read(int, void*, int); 10 | int close(int); 11 | int kill(int); 12 | int exec(char*, char**); 13 | int open(char*, int); 14 | int mknod(char*, short, short); 15 | int unlink(char*); 16 | int fstat(int fd, struct stat*); 17 | int link(char*, char*); 18 | int mkdir(char*); 19 | int chdir(char*); 20 | int dup(int); 21 | int getpid(void); 22 | char* sbrk(int); 23 | int sleep(int); 24 | int uptime(void); 25 | int ps(void); 26 | 27 | // ulib.c 28 | int stat(char*, struct stat*); 29 | char* strcpy(char*, char*); 30 | void *memmove(void*, void*, int); 31 | char* strchr(const char*, char c); 32 | int strcmp(const char*, const char*); 33 | void printf(int, char*, ...); 34 | char* gets(char*, int max); 35 | uint strlen(char*); 36 | void* memset(void*, int, uint); 37 | void* malloc(uint); 38 | void free(void*); 39 | int atoi(const char*); 40 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/usys.S: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | #include "traps.h" 3 | 4 | #define SYSCALL(name) \ 5 | .globl name; \ 6 | name: \ 7 | movl $SYS_ ## name, %eax; \ 8 | int $T_SYSCALL; \ 9 | ret 10 | 11 | SYSCALL(fork) 12 | SYSCALL(exit) 13 | SYSCALL(wait) 14 | SYSCALL(pipe) 15 | SYSCALL(read) 16 | SYSCALL(write) 17 | SYSCALL(close) 18 | SYSCALL(kill) 19 | SYSCALL(exec) 20 | SYSCALL(open) 21 | SYSCALL(mknod) 22 | SYSCALL(unlink) 23 | SYSCALL(fstat) 24 | SYSCALL(link) 25 | SYSCALL(mkdir) 26 | SYSCALL(chdir) 27 | SYSCALL(dup) 28 | SYSCALL(getpid) 29 | SYSCALL(sbrk) 30 | SYSCALL(sleep) 31 | SYSCALL(uptime) 32 | SYSCALL(ps) -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/vectors.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # Generate vectors.S, the trap/interrupt entry points. 4 | # There has to be one entry point per interrupt number 5 | # since otherwise there's no way for trap() to discover 6 | # the interrupt number. 7 | 8 | print "# generated by vectors.pl - do not edit\n"; 9 | print "# handlers\n"; 10 | print ".globl alltraps\n"; 11 | for(my $i = 0; $i < 256; $i++){ 12 | print ".globl vector$i\n"; 13 | print "vector$i:\n"; 14 | if(!($i == 8 || ($i >= 10 && $i <= 14) || $i == 17)){ 15 | print " pushl \$0\n"; 16 | } 17 | print " pushl \$$i\n"; 18 | print " jmp alltraps\n"; 19 | } 20 | 21 | print "\n# vector table\n"; 22 | print ".data\n"; 23 | print ".globl vectors\n"; 24 | print "vectors:\n"; 25 | for(my $i = 0; $i < 256; $i++){ 26 | print " .long vector$i\n"; 27 | } 28 | 29 | # sample output: 30 | # # handlers 31 | # .globl alltraps 32 | # .globl vector0 33 | # vector0: 34 | # pushl $0 35 | # pushl $0 36 | # jmp alltraps 37 | # ... 38 | # 39 | # # vector table 40 | # .data 41 | # .globl vectors 42 | # vectors: 43 | # .long vector0 44 | # .long vector1 45 | # .long vector2 46 | # ... 47 | 48 | -------------------------------------------------------------------------------- /2 - Scheduler - FCFS/wc.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | wc(int fd, char *name) 9 | { 10 | int i, n; 11 | int l, w, c, inword; 12 | 13 | l = w = c = 0; 14 | inword = 0; 15 | while((n = read(fd, buf, sizeof(buf))) > 0){ 16 | for(i=0; i 0) 12 | sleep(5); // Let child exit before parent. 13 | exit(); 14 | } 15 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/.cvsignore: -------------------------------------------------------------------------------- 1 | *.asm 2 | *.d 3 | *.sym 4 | _* 5 | kernel 6 | user1 7 | userfs 8 | usertests 9 | xv6.img 10 | vectors.S 11 | bochsout.txt 12 | bootblock 13 | bootother 14 | bootother.out 15 | parport.out 16 | fmt 17 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((c-mode 2 | (indent-tabs-mode . nil) 3 | (c-file-style . "bsd") 4 | (c-basic-offset . 2))) 5 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/.gdbinit.tmpl: -------------------------------------------------------------------------------- 1 | set $lastcs = -1 2 | 3 | define hook-stop 4 | # There doesn't seem to be a good way to detect if we're in 16- or 5 | # 32-bit mode, but in 32-bit mode we always run with CS == 8 in the 6 | # kernel and CS == 35 in user space 7 | if $cs == 8 || $cs == 35 8 | if $lastcs != 8 && $lastcs != 35 9 | set architecture i386 10 | end 11 | x/i $pc 12 | else 13 | if $lastcs == -1 || $lastcs == 8 || $lastcs == 35 14 | set architecture i8086 15 | end 16 | # Translate the segment:offset into a physical address 17 | printf "[%4x:%4x] ", $cs, $eip 18 | x/i $cs*16+$eip 19 | end 20 | set $lastcs = $cs 21 | end 22 | 23 | echo + target remote localhost:1234\n 24 | target remote localhost:1234 25 | 26 | echo + symbol-file kernel\n 27 | symbol-file kernel 28 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | _* 3 | *.o 4 | *.d 5 | *.asm 6 | *.sym 7 | *.img 8 | vectors.S 9 | bootblock 10 | entryother 11 | initcode 12 | initcode.out 13 | kernel 14 | kernelmemfs 15 | mkfs 16 | .gdbinit 17 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/BUGS: -------------------------------------------------------------------------------- 1 | formatting: 2 | need to fix PAGEBREAK mechanism 3 | 4 | sh: 5 | can't always runcmd in child -- breaks cd. 6 | maybe should hard-code PATH=/ ? 7 | 8 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/asm.h: -------------------------------------------------------------------------------- 1 | // 2 | // assembler macros to create x86 segments 3 | // 4 | 5 | #define SEG_NULLASM \ 6 | .word 0, 0; \ 7 | .byte 0, 0, 0, 0 8 | 9 | // The 0xC0 means the limit is in 4096-byte units 10 | // and (for executable segments) 32-bit mode. 11 | #define SEG_ASM(type,base,lim) \ 12 | .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ 13 | .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ 14 | (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) 15 | 16 | #define STA_X 0x8 // Executable segment 17 | #define STA_E 0x4 // Expand down (non-executable segments) 18 | #define STA_C 0x4 // Conforming code segment (executable only) 19 | #define STA_W 0x2 // Writeable (non-executable segments) 20 | #define STA_R 0x2 // Readable (executable segments) 21 | #define STA_A 0x1 // Accessed 22 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/buf.h: -------------------------------------------------------------------------------- 1 | struct buf { 2 | int flags; 3 | uint dev; 4 | uint sector; 5 | struct buf *prev; // LRU cache list 6 | struct buf *next; 7 | struct buf *qnext; // disk queue 8 | uchar data[512]; 9 | }; 10 | #define B_BUSY 0x1 // buffer is locked by some process 11 | #define B_VALID 0x2 // buffer has been read from disk 12 | #define B_DIRTY 0x4 // buffer needs to be written to disk 13 | 14 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/cat.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | cat(int fd) 9 | { 10 | int n; 11 | 12 | while((n = read(fd, buf, sizeof(buf))) > 0) 13 | write(1, buf, n); 14 | if(n < 0){ 15 | printf(1, "cat: read error\n"); 16 | exit(); 17 | } 18 | } 19 | 20 | int 21 | main(int argc, char *argv[]) 22 | { 23 | int fd, i; 24 | 25 | if(argc <= 1){ 26 | cat(0); 27 | exit(); 28 | } 29 | 30 | for(i = 1; i < argc; i++){ 31 | if((fd = open(argv[i], 0)) < 0){ 32 | printf(1, "cat: cannot open %s\n", argv[i]); 33 | exit(); 34 | } 35 | cat(fd); 36 | close(fd); 37 | } 38 | exit(); 39 | } 40 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/cuth: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | $| = 1; 4 | 5 | sub writefile($@){ 6 | my ($file, @lines) = @_; 7 | 8 | sleep(1); 9 | open(F, ">$file") || die "open >$file: $!"; 10 | print F @lines; 11 | close(F); 12 | } 13 | 14 | # Cut out #include lines that don't contribute anything. 15 | for($i=0; $i<@ARGV; $i++){ 16 | $file = $ARGV[$i]; 17 | if(!open(F, $file)){ 18 | print STDERR "open $file: $!\n"; 19 | next; 20 | } 21 | @lines = ; 22 | close(F); 23 | 24 | $obj = "$file.o"; 25 | $obj =~ s/\.c\.o$/.o/; 26 | system("touch $file"); 27 | 28 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 29 | print STDERR "make $obj failed: $rv\n"; 30 | next; 31 | } 32 | 33 | system("cp $file =$file"); 34 | for($j=@lines-1; $j>=0; $j--){ 35 | if($lines[$j] =~ /^#include/){ 36 | $old = $lines[$j]; 37 | $lines[$j] = "/* CUT-H */\n"; 38 | writefile($file, @lines); 39 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 40 | $lines[$j] = $old; 41 | }else{ 42 | print STDERR "$file $old"; 43 | } 44 | } 45 | } 46 | writefile($file, grep {!/CUT-H/} @lines); 47 | system("rm =$file"); 48 | } 49 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/echo.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | for(i = 1; i < argc; i++) 11 | printf(1, "%s%s", argv[i], i+1 < argc ? " " : "\n"); 12 | exit(); 13 | } 14 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/elf.h: -------------------------------------------------------------------------------- 1 | // Format of an ELF executable file 2 | 3 | #define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian 4 | 5 | // File header 6 | struct elfhdr { 7 | uint magic; // must equal ELF_MAGIC 8 | uchar elf[12]; 9 | ushort type; 10 | ushort machine; 11 | uint version; 12 | uint entry; 13 | uint phoff; 14 | uint shoff; 15 | uint flags; 16 | ushort ehsize; 17 | ushort phentsize; 18 | ushort phnum; 19 | ushort shentsize; 20 | ushort shnum; 21 | ushort shstrndx; 22 | }; 23 | 24 | // Program section header 25 | struct proghdr { 26 | uint type; 27 | uint off; 28 | uint vaddr; 29 | uint paddr; 30 | uint filesz; 31 | uint memsz; 32 | uint flags; 33 | uint align; 34 | }; 35 | 36 | // Values for Proghdr type 37 | #define ELF_PROG_LOAD 1 38 | 39 | // Flag bits for Proghdr flags 40 | #define ELF_PROG_FLAG_EXEC 1 41 | #define ELF_PROG_FLAG_WRITE 2 42 | #define ELF_PROG_FLAG_READ 4 43 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/fcntl.h: -------------------------------------------------------------------------------- 1 | #define O_RDONLY 0x000 2 | #define O_WRONLY 0x001 3 | #define O_RDWR 0x002 4 | #define O_CREATE 0x200 5 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/file.h: -------------------------------------------------------------------------------- 1 | struct file { 2 | enum { FD_NONE, FD_PIPE, FD_INODE } type; 3 | int ref; // reference count 4 | char readable; 5 | char writable; 6 | struct pipe *pipe; 7 | struct inode *ip; 8 | uint off; 9 | }; 10 | 11 | 12 | // in-memory copy of an inode 13 | struct inode { 14 | uint dev; // Device number 15 | uint inum; // Inode number 16 | int ref; // Reference count 17 | int flags; // I_BUSY, I_VALID 18 | 19 | short type; // copy of disk inode 20 | short major; 21 | short minor; 22 | short nlink; 23 | uint size; 24 | uint addrs[NDIRECT+1]; 25 | }; 26 | #define I_BUSY 0x1 27 | #define I_VALID 0x2 28 | 29 | // table mapping major device number to 30 | // device functions 31 | struct devsw { 32 | int (*read)(struct inode*, char*, int); 33 | int (*write)(struct inode*, char*, int); 34 | }; 35 | 36 | extern struct devsw devsw[]; 37 | 38 | #define CONSOLE 1 39 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/forktest.c: -------------------------------------------------------------------------------- 1 | // Test that fork fails gracefully. 2 | // Tiny executable so that the limit can be filling the proc table. 3 | 4 | #include "types.h" 5 | #include "stat.h" 6 | #include "user.h" 7 | 8 | #define N 1000 9 | 10 | void 11 | printf(int fd, char *s, ...) 12 | { 13 | write(fd, s, strlen(s)); 14 | } 15 | 16 | void 17 | forktest(void) 18 | { 19 | int n, pid; 20 | 21 | printf(1, "fork test\n"); 22 | 23 | for(n=0; n 0; n--){ 37 | if(wait() < 0){ 38 | printf(1, "wait stopped early\n"); 39 | exit(); 40 | } 41 | } 42 | 43 | if(wait() != -1){ 44 | printf(1, "wait got too many\n"); 45 | exit(); 46 | } 47 | 48 | printf(1, "fork test OK\n"); 49 | } 50 | 51 | int 52 | main(void) 53 | { 54 | forktest(); 55 | exit(); 56 | } 57 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/init.c: -------------------------------------------------------------------------------- 1 | // init: The initial user-level program 2 | 3 | #include "types.h" 4 | #include "stat.h" 5 | #include "user.h" 6 | #include "fcntl.h" 7 | 8 | char *argv[] = { "sh", 0 }; 9 | 10 | int 11 | main(void) 12 | { 13 | int pid, wpid; 14 | 15 | if(open("console", O_RDWR) < 0){ 16 | mknod("console", 1, 1); 17 | open("console", O_RDWR); 18 | } 19 | dup(0); // stdout 20 | dup(0); // stderr 21 | 22 | for(;;){ 23 | printf(1, "init: starting sh\n"); 24 | pid = fork(); 25 | if(pid < 0){ 26 | printf(1, "init: fork failed\n"); 27 | exit(); 28 | } 29 | if(pid == 0){ 30 | exec("sh", argv); 31 | printf(1, "init: exec sh failed\n"); 32 | exit(); 33 | } 34 | while((wpid=wait()) >= 0 && wpid != pid) 35 | printf(1, "zombie!\n"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/initcode.S: -------------------------------------------------------------------------------- 1 | # Initial process execs /init. 2 | 3 | #include "syscall.h" 4 | #include "traps.h" 5 | 6 | 7 | # exec(init, argv) 8 | .globl start 9 | start: 10 | pushl $argv 11 | pushl $init 12 | pushl $0 // where caller pc would be 13 | movl $SYS_exec, %eax 14 | int $T_SYSCALL 15 | 16 | # for(;;) exit(); 17 | exit: 18 | movl $SYS_exit, %eax 19 | int $T_SYSCALL 20 | jmp exit 21 | 22 | # char init[] = "/init\0"; 23 | init: 24 | .string "/init\0" 25 | 26 | # char *argv[] = { init, 0 }; 27 | .p2align 2 28 | argv: 29 | .long init 30 | .long 0 31 | 32 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/kbd.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "x86.h" 3 | #include "defs.h" 4 | #include "kbd.h" 5 | 6 | int 7 | kbdgetc(void) 8 | { 9 | static uint shift; 10 | static uchar *charcode[4] = { 11 | normalmap, shiftmap, ctlmap, ctlmap 12 | }; 13 | uint st, data, c; 14 | 15 | st = inb(KBSTATP); 16 | if((st & KBS_DIB) == 0) 17 | return -1; 18 | data = inb(KBDATAP); 19 | 20 | if(data == 0xE0){ 21 | shift |= E0ESC; 22 | return 0; 23 | } else if(data & 0x80){ 24 | // Key released 25 | data = (shift & E0ESC ? data : data & 0x7F); 26 | shift &= ~(shiftcode[data] | E0ESC); 27 | return 0; 28 | } else if(shift & E0ESC){ 29 | // Last character was an E0 escape; or with 0x80 30 | data |= 0x80; 31 | shift &= ~E0ESC; 32 | } 33 | 34 | shift |= shiftcode[data]; 35 | shift ^= togglecode[data]; 36 | c = charcode[shift & (CTL | SHIFT)][data]; 37 | if(shift & CAPSLOCK){ 38 | if('a' <= c && c <= 'z') 39 | c += 'A' - 'a'; 40 | else if('A' <= c && c <= 'Z') 41 | c += 'a' - 'A'; 42 | } 43 | return c; 44 | } 45 | 46 | void 47 | kbdintr(void) 48 | { 49 | consoleintr(kbdgetc); 50 | } 51 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/kill.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char **argv) 7 | { 8 | int i; 9 | 10 | if(argc < 1){ 11 | printf(2, "usage: kill pid...\n"); 12 | exit(); 13 | } 14 | for(i=1; i; 17 | for($i=0; $i<@lines; $i+=50){ 18 | print "\n\n"; 19 | ++$page; 20 | print "$now $h Page $page\n"; 21 | print "\n\n"; 22 | for($j=$i; $j<@lines && $j<$i +50; $j++){ 23 | $lines[$j] =~ s!//DOC.*!!; 24 | print $lines[$j]; 25 | } 26 | for(; $j<$i+50; $j++){ 27 | print "\n"; 28 | } 29 | $sheet = ""; 30 | if($lines[$i] =~ /^([0-9][0-9])[0-9][0-9] /){ 31 | $sheet = "Sheet $1"; 32 | } 33 | print "\n\n"; 34 | print "$sheet\n"; 35 | print "\n\n"; 36 | } 37 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/printpcs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Decode the symbols from a panic EIP list 4 | 5 | # Find a working addr2line 6 | for p in i386-jos-elf-addr2line addr2line; do 7 | if which $p 2>&1 >/dev/null && \ 8 | $p -h 2>&1 | grep -q '\belf32-i386\b'; then 9 | break 10 | fi 11 | done 12 | 13 | # Enable as much pretty-printing as this addr2line can do 14 | $p $($p -h | grep ' -[aipsf] ' | awk '{print $1}') -e kernel "$@" 15 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/ps.c: -------------------------------------------------------------------------------- 1 | 2 | #include "types.h" 3 | #include "stat.h" 4 | #include "user.h" 5 | 6 | int main(int argc, const char * argv[]) 7 | { 8 | ps(); 9 | exit(); 10 | } -------------------------------------------------------------------------------- /3 - Scheduler - Priority/rm.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | if(argc < 2){ 11 | printf(2, "Usage: rm files...\n"); 12 | exit(); 13 | } 14 | 15 | for(i = 1; i < argc; i++){ 16 | if(unlink(argv[i]) < 0){ 17 | printf(2, "rm: %s failed to delete\n", argv[i]); 18 | break; 19 | } 20 | } 21 | 22 | exit(); 23 | } 24 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/runoff.list: -------------------------------------------------------------------------------- 1 | # basic headers 2 | types.h 3 | param.h 4 | memlayout.h 5 | defs.h 6 | x86.h 7 | asm.h 8 | mmu.h 9 | elf.h 10 | 11 | # entering xv6 12 | entry.S 13 | entryother.S 14 | main.c 15 | 16 | # locks 17 | spinlock.h 18 | spinlock.c 19 | 20 | # processes 21 | vm.c 22 | proc.h 23 | proc.c 24 | swtch.S 25 | kalloc.c 26 | 27 | # system calls 28 | traps.h 29 | vectors.pl 30 | trapasm.S 31 | trap.c 32 | syscall.h 33 | syscall.c 34 | sysproc.c 35 | 36 | # file system 37 | buf.h 38 | fcntl.h 39 | stat.h 40 | fs.h 41 | file.h 42 | ide.c 43 | bio.c 44 | log.c 45 | fs.c 46 | file.c 47 | sysfile.c 48 | exec.c 49 | 50 | # pipes 51 | pipe.c 52 | 53 | # string operations 54 | string.c 55 | 56 | # low-level hardware 57 | mp.h 58 | mp.c 59 | lapic.c 60 | ioapic.c 61 | picirq.c 62 | kbd.h 63 | kbd.c 64 | console.c 65 | timer.c 66 | uart.c 67 | 68 | # user-level 69 | initcode.S 70 | usys.S 71 | init.c 72 | sh.c 73 | 74 | # bootloader 75 | bootasm.S 76 | bootmain.c 77 | 78 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/show1: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | runoff1 "$@" | pr.pl -h "xv6/$@" | mpage -m50t50b -o -bLetter -T -t -2 -FLucidaSans-Typewriter83 -L60 >x.ps; gv --swap x.ps 4 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/sign.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; 4 | 5 | $n = sysread(SIG, $buf, 1000); 6 | 7 | if($n > 510){ 8 | print STDERR "boot block too large: $n bytes (max 510)\n"; 9 | exit 1; 10 | } 11 | 12 | print STDERR "boot block is $n bytes (max 510)\n"; 13 | 14 | $buf .= "\0" x (510-$n); 15 | $buf .= "\x55\xAA"; 16 | 17 | open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; 18 | print SIG $buf; 19 | close SIG; 20 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/spinlock.h: -------------------------------------------------------------------------------- 1 | // Mutual exclusion lock. 2 | struct spinlock { 3 | uint locked; // Is the lock held? 4 | 5 | // For debugging: 6 | char *name; // Name of lock. 7 | struct cpu *cpu; // The cpu holding the lock. 8 | uint pcs[10]; // The call stack (an array of program counters) 9 | // that locked the lock. 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/spinp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# != 1 ] || [ ! -f "$1" ]; then 4 | echo 'usage: spinp file.p' 1>&2 5 | exit 1 6 | fi 7 | 8 | rm -f $1.trail 9 | spin -a $1 || exit 1 10 | cc -DSAFETY -DREACH -DMEMLIM=500 -o pan pan.c 11 | pan -i 12 | rm pan.* pan 13 | if [ -f $1.trail ]; then 14 | spin -t -p $1 15 | fi 16 | 17 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/stat.h: -------------------------------------------------------------------------------- 1 | #define T_DIR 1 // Directory 2 | #define T_FILE 2 // File 3 | #define T_DEV 3 // Device 4 | 5 | struct stat { 6 | short type; // Type of file 7 | int dev; // File system's disk device 8 | uint ino; // Inode number 9 | short nlink; // Number of links to file 10 | uint size; // Size of file in bytes 11 | }; 12 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/swtch.S: -------------------------------------------------------------------------------- 1 | # Context switch 2 | # 3 | # void swtch(struct context **old, struct context *new); 4 | # 5 | # Save current register context in old 6 | # and then load register context from new. 7 | 8 | .globl swtch 9 | swtch: 10 | movl 4(%esp), %eax 11 | movl 8(%esp), %edx 12 | 13 | # Save old callee-save registers 14 | pushl %ebp 15 | pushl %ebx 16 | pushl %esi 17 | pushl %edi 18 | 19 | # Switch stacks 20 | movl %esp, (%eax) 21 | movl %edx, %esp 22 | 23 | # Load new callee-save registers 24 | popl %edi 25 | popl %esi 26 | popl %ebx 27 | popl %ebp 28 | ret 29 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/syscall.h: -------------------------------------------------------------------------------- 1 | // System call numbers 2 | #define SYS_fork 1 3 | #define SYS_exit 2 4 | #define SYS_wait 3 5 | #define SYS_pipe 4 6 | #define SYS_read 5 7 | #define SYS_kill 6 8 | #define SYS_exec 7 9 | #define SYS_fstat 8 10 | #define SYS_chdir 9 11 | #define SYS_dup 10 12 | #define SYS_getpid 11 13 | #define SYS_sbrk 12 14 | #define SYS_sleep 13 15 | #define SYS_uptime 14 16 | #define SYS_open 15 17 | #define SYS_write 16 18 | #define SYS_mknod 17 19 | #define SYS_unlink 18 20 | #define SYS_link 19 21 | #define SYS_mkdir 20 22 | #define SYS_close 21 23 | #define SYS_setpriority 22 24 | #define SYS_getpriority 23 25 | #define SYS_ps 24 26 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/timer.c: -------------------------------------------------------------------------------- 1 | // Intel 8253/8254/82C54 Programmable Interval Timer (PIT). 2 | // Only used on uniprocessors; 3 | // SMP machines use the local APIC timer. 4 | 5 | #include "types.h" 6 | #include "defs.h" 7 | #include "traps.h" 8 | #include "x86.h" 9 | 10 | #define IO_TIMER1 0x040 // 8253 Timer #1 11 | 12 | // Frequency of all three count-down timers; 13 | // (TIMER_FREQ/freq) is the appropriate count 14 | // to generate a frequency of freq Hz. 15 | 16 | #define TIMER_FREQ 1193182 17 | #define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) 18 | 19 | #define TIMER_MODE (IO_TIMER1 + 3) // timer mode port 20 | #define TIMER_SEL0 0x00 // select counter 0 21 | #define TIMER_RATEGEN 0x04 // mode 2, rate generator 22 | #define TIMER_16BIT 0x30 // r/w counter 16 bits, LSB first 23 | 24 | void 25 | timerinit(void) 26 | { 27 | // Interrupt 100 times/sec. 28 | outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 29 | outb(IO_TIMER1, TIMER_DIV(100) % 256); 30 | outb(IO_TIMER1, TIMER_DIV(100) / 256); 31 | picenable(IRQ_TIMER); 32 | } 33 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/toc.ftr: -------------------------------------------------------------------------------- 1 | 2 | 3 | The source listing is preceded by a cross-reference that lists every defined 4 | constant, struct, global variable, and function in xv6. Each entry gives, 5 | on the same line as the name, the line number (or, in a few cases, numbers) 6 | where the name is defined. Successive lines in an entry list the line 7 | numbers where the name is used. For example, this entry: 8 | 9 | swtch 2658 10 | 0374 2428 2466 2657 2658 11 | 12 | indicates that swtch is defined on line 2658 and is mentioned on five lines 13 | on sheets 03, 24, and 26. 14 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/toc.hdr: -------------------------------------------------------------------------------- 1 | The numbers to the left of the file names in the table are sheet numbers. 2 | The source code has been printed in a double column format with fifty 3 | lines per column, giving one hundred lines per sheet (or page). 4 | Thus there is a convenient relationship between line numbers and sheet numbers. 5 | 6 | 7 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/trapasm.S: -------------------------------------------------------------------------------- 1 | #include "mmu.h" 2 | 3 | # vectors.S sends all traps here. 4 | .globl alltraps 5 | alltraps: 6 | # Build trap frame. 7 | pushl %ds 8 | pushl %es 9 | pushl %fs 10 | pushl %gs 11 | pushal 12 | 13 | # Set up data and per-cpu segments. 14 | movw $(SEG_KDATA<<3), %ax 15 | movw %ax, %ds 16 | movw %ax, %es 17 | movw $(SEG_KCPU<<3), %ax 18 | movw %ax, %fs 19 | movw %ax, %gs 20 | 21 | # Call trap(tf), where tf=%esp 22 | pushl %esp 23 | call trap 24 | addl $4, %esp 25 | 26 | # Return falls through to trapret... 27 | .globl trapret 28 | trapret: 29 | popal 30 | popl %gs 31 | popl %fs 32 | popl %es 33 | popl %ds 34 | addl $0x8, %esp # trapno and errcode 35 | iret 36 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/types.h: -------------------------------------------------------------------------------- 1 | typedef unsigned int uint; 2 | typedef unsigned short ushort; 3 | typedef unsigned char uchar; 4 | typedef uint pde_t; 5 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/user.h: -------------------------------------------------------------------------------- 1 | struct stat; 2 | 3 | // system calls 4 | int fork(void); 5 | int exit(void) __attribute__((noreturn)); 6 | int wait(void); 7 | int pipe(int*); 8 | int write(int, void*, int); 9 | int read(int, void*, int); 10 | int close(int); 11 | int kill(int); 12 | int exec(char*, char**); 13 | int open(char*, int); 14 | int mknod(char*, short, short); 15 | int unlink(char*); 16 | int fstat(int fd, struct stat*); 17 | int link(char*, char*); 18 | int mkdir(char*); 19 | int chdir(char*); 20 | int dup(int); 21 | int getpid(void); 22 | char* sbrk(int); 23 | int sleep(int); 24 | int uptime(void); 25 | int setpriority(int); 26 | int getpriority(void); 27 | int ps(void); 28 | 29 | // ulib.c 30 | int stat(char*, struct stat*); 31 | char* strcpy(char*, char*); 32 | void *memmove(void*, void*, int); 33 | char* strchr(const char*, char c); 34 | int strcmp(const char*, const char*); 35 | void printf(int, char*, ...); 36 | char* gets(char*, int max); 37 | uint strlen(char*); 38 | void* memset(void*, int, uint); 39 | void* malloc(uint); 40 | void free(void*); 41 | int atoi(const char*); 42 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/usys.S: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | #include "traps.h" 3 | 4 | #define SYSCALL(name) \ 5 | .globl name; \ 6 | name: \ 7 | movl $SYS_ ## name, %eax; \ 8 | int $T_SYSCALL; \ 9 | ret 10 | 11 | SYSCALL(fork) 12 | SYSCALL(exit) 13 | SYSCALL(wait) 14 | SYSCALL(pipe) 15 | SYSCALL(read) 16 | SYSCALL(write) 17 | SYSCALL(close) 18 | SYSCALL(kill) 19 | SYSCALL(exec) 20 | SYSCALL(open) 21 | SYSCALL(mknod) 22 | SYSCALL(unlink) 23 | SYSCALL(fstat) 24 | SYSCALL(link) 25 | SYSCALL(mkdir) 26 | SYSCALL(chdir) 27 | SYSCALL(dup) 28 | SYSCALL(getpid) 29 | SYSCALL(sbrk) 30 | SYSCALL(sleep) 31 | SYSCALL(uptime) 32 | SYSCALL(setpriority) 33 | SYSCALL(getpriority) 34 | SYSCALL(ps) 35 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/vectors.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # Generate vectors.S, the trap/interrupt entry points. 4 | # There has to be one entry point per interrupt number 5 | # since otherwise there's no way for trap() to discover 6 | # the interrupt number. 7 | 8 | print "# generated by vectors.pl - do not edit\n"; 9 | print "# handlers\n"; 10 | print ".globl alltraps\n"; 11 | for(my $i = 0; $i < 256; $i++){ 12 | print ".globl vector$i\n"; 13 | print "vector$i:\n"; 14 | if(!($i == 8 || ($i >= 10 && $i <= 14) || $i == 17)){ 15 | print " pushl \$0\n"; 16 | } 17 | print " pushl \$$i\n"; 18 | print " jmp alltraps\n"; 19 | } 20 | 21 | print "\n# vector table\n"; 22 | print ".data\n"; 23 | print ".globl vectors\n"; 24 | print "vectors:\n"; 25 | for(my $i = 0; $i < 256; $i++){ 26 | print " .long vector$i\n"; 27 | } 28 | 29 | # sample output: 30 | # # handlers 31 | # .globl alltraps 32 | # .globl vector0 33 | # vector0: 34 | # pushl $0 35 | # pushl $0 36 | # jmp alltraps 37 | # ... 38 | # 39 | # # vector table 40 | # .data 41 | # .globl vectors 42 | # vectors: 43 | # .long vector0 44 | # .long vector1 45 | # .long vector2 46 | # ... 47 | 48 | -------------------------------------------------------------------------------- /3 - Scheduler - Priority/wc.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | wc(int fd, char *name) 9 | { 10 | int i, n; 11 | int l, w, c, inword; 12 | 13 | l = w = c = 0; 14 | inword = 0; 15 | while((n = read(fd, buf, sizeof(buf))) > 0){ 16 | for(i=0; i 0) 12 | sleep(5); // Let child exit before parent. 13 | exit(); 14 | } 15 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/.cvsignore: -------------------------------------------------------------------------------- 1 | *.asm 2 | *.d 3 | *.sym 4 | _* 5 | kernel 6 | user1 7 | userfs 8 | usertests 9 | xv6.img 10 | vectors.S 11 | bochsout.txt 12 | bootblock 13 | bootother 14 | bootother.out 15 | parport.out 16 | fmt 17 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((c-mode 2 | (indent-tabs-mode . nil) 3 | (c-file-style . "bsd") 4 | (c-basic-offset . 2))) 5 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/.gdbinit.tmpl: -------------------------------------------------------------------------------- 1 | set $lastcs = -1 2 | 3 | define hook-stop 4 | # There doesn't seem to be a good way to detect if we're in 16- or 5 | # 32-bit mode, but in 32-bit mode we always run with CS == 8 in the 6 | # kernel and CS == 35 in user space 7 | if $cs == 8 || $cs == 35 8 | if $lastcs != 8 && $lastcs != 35 9 | set architecture i386 10 | end 11 | x/i $pc 12 | else 13 | if $lastcs == -1 || $lastcs == 8 || $lastcs == 35 14 | set architecture i8086 15 | end 16 | # Translate the segment:offset into a physical address 17 | printf "[%4x:%4x] ", $cs, $eip 18 | x/i $cs*16+$eip 19 | end 20 | set $lastcs = $cs 21 | end 22 | 23 | echo + target remote localhost:1234\n 24 | target remote localhost:1234 25 | 26 | echo + symbol-file kernel\n 27 | symbol-file kernel 28 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | _* 3 | *.o 4 | *.d 5 | *.asm 6 | *.sym 7 | *.img 8 | vectors.S 9 | bootblock 10 | entryother 11 | initcode 12 | initcode.out 13 | kernel 14 | kernelmemfs 15 | mkfs 16 | .gdbinit 17 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/BUGS: -------------------------------------------------------------------------------- 1 | formatting: 2 | need to fix PAGEBREAK mechanism 3 | 4 | sh: 5 | can't always runcmd in child -- breaks cd. 6 | maybe should hard-code PATH=/ ? 7 | 8 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/asm.h: -------------------------------------------------------------------------------- 1 | // 2 | // assembler macros to create x86 segments 3 | // 4 | 5 | #define SEG_NULLASM \ 6 | .word 0, 0; \ 7 | .byte 0, 0, 0, 0 8 | 9 | // The 0xC0 means the limit is in 4096-byte units 10 | // and (for executable segments) 32-bit mode. 11 | #define SEG_ASM(type,base,lim) \ 12 | .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ 13 | .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ 14 | (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) 15 | 16 | #define STA_X 0x8 // Executable segment 17 | #define STA_E 0x4 // Expand down (non-executable segments) 18 | #define STA_C 0x4 // Conforming code segment (executable only) 19 | #define STA_W 0x2 // Writeable (non-executable segments) 20 | #define STA_R 0x2 // Readable (executable segments) 21 | #define STA_A 0x1 // Accessed 22 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/buf.h: -------------------------------------------------------------------------------- 1 | struct buf { 2 | int flags; 3 | uint dev; 4 | uint sector; 5 | struct buf *prev; // LRU cache list 6 | struct buf *next; 7 | struct buf *qnext; // disk queue 8 | uchar data[512]; 9 | }; 10 | #define B_BUSY 0x1 // buffer is locked by some process 11 | #define B_VALID 0x2 // buffer has been read from disk 12 | #define B_DIRTY 0x4 // buffer needs to be written to disk 13 | 14 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/cat.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | cat(int fd) 9 | { 10 | int n; 11 | 12 | while((n = read(fd, buf, sizeof(buf))) > 0) 13 | write(1, buf, n); 14 | if(n < 0){ 15 | printf(1, "cat: read error\n"); 16 | exit(); 17 | } 18 | } 19 | 20 | int 21 | main(int argc, char *argv[]) 22 | { 23 | int fd, i; 24 | 25 | if(argc <= 1){ 26 | cat(0); 27 | exit(); 28 | } 29 | 30 | for(i = 1; i < argc; i++){ 31 | if((fd = open(argv[i], 0)) < 0){ 32 | printf(1, "cat: cannot open %s\n", argv[i]); 33 | exit(); 34 | } 35 | cat(fd); 36 | close(fd); 37 | } 38 | exit(); 39 | } 40 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/cuth: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | $| = 1; 4 | 5 | sub writefile($@){ 6 | my ($file, @lines) = @_; 7 | 8 | sleep(1); 9 | open(F, ">$file") || die "open >$file: $!"; 10 | print F @lines; 11 | close(F); 12 | } 13 | 14 | # Cut out #include lines that don't contribute anything. 15 | for($i=0; $i<@ARGV; $i++){ 16 | $file = $ARGV[$i]; 17 | if(!open(F, $file)){ 18 | print STDERR "open $file: $!\n"; 19 | next; 20 | } 21 | @lines = ; 22 | close(F); 23 | 24 | $obj = "$file.o"; 25 | $obj =~ s/\.c\.o$/.o/; 26 | system("touch $file"); 27 | 28 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 29 | print STDERR "make $obj failed: $rv\n"; 30 | next; 31 | } 32 | 33 | system("cp $file =$file"); 34 | for($j=@lines-1; $j>=0; $j--){ 35 | if($lines[$j] =~ /^#include/){ 36 | $old = $lines[$j]; 37 | $lines[$j] = "/* CUT-H */\n"; 38 | writefile($file, @lines); 39 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 40 | $lines[$j] = $old; 41 | }else{ 42 | print STDERR "$file $old"; 43 | } 44 | } 45 | } 46 | writefile($file, grep {!/CUT-H/} @lines); 47 | system("rm =$file"); 48 | } 49 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/echo.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | for(i = 1; i < argc; i++) 11 | printf(1, "%s%s", argv[i], i+1 < argc ? " " : "\n"); 12 | exit(); 13 | } 14 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/elf.h: -------------------------------------------------------------------------------- 1 | // Format of an ELF executable file 2 | 3 | #define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian 4 | 5 | // File header 6 | struct elfhdr { 7 | uint magic; // must equal ELF_MAGIC 8 | uchar elf[12]; 9 | ushort type; 10 | ushort machine; 11 | uint version; 12 | uint entry; 13 | uint phoff; 14 | uint shoff; 15 | uint flags; 16 | ushort ehsize; 17 | ushort phentsize; 18 | ushort phnum; 19 | ushort shentsize; 20 | ushort shnum; 21 | ushort shstrndx; 22 | }; 23 | 24 | // Program section header 25 | struct proghdr { 26 | uint type; 27 | uint off; 28 | uint vaddr; 29 | uint paddr; 30 | uint filesz; 31 | uint memsz; 32 | uint flags; 33 | uint align; 34 | }; 35 | 36 | // Values for Proghdr type 37 | #define ELF_PROG_LOAD 1 38 | 39 | // Flag bits for Proghdr flags 40 | #define ELF_PROG_FLAG_EXEC 1 41 | #define ELF_PROG_FLAG_WRITE 2 42 | #define ELF_PROG_FLAG_READ 4 43 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/fcntl.h: -------------------------------------------------------------------------------- 1 | #define O_RDONLY 0x000 2 | #define O_WRONLY 0x001 3 | #define O_RDWR 0x002 4 | #define O_CREATE 0x200 5 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/file.h: -------------------------------------------------------------------------------- 1 | struct file { 2 | enum { FD_NONE, FD_PIPE, FD_INODE } type; 3 | int ref; // reference count 4 | char readable; 5 | char writable; 6 | struct pipe *pipe; 7 | struct inode *ip; 8 | uint off; 9 | }; 10 | 11 | 12 | // in-memory copy of an inode 13 | struct inode { 14 | uint dev; // Device number 15 | uint inum; // Inode number 16 | int ref; // Reference count 17 | int flags; // I_BUSY, I_VALID 18 | 19 | short type; // copy of disk inode 20 | short major; 21 | short minor; 22 | short nlink; 23 | uint size; 24 | uint addrs[NDIRECT+1]; 25 | }; 26 | #define I_BUSY 0x1 27 | #define I_VALID 0x2 28 | 29 | // table mapping major device number to 30 | // device functions 31 | struct devsw { 32 | int (*read)(struct inode*, char*, int); 33 | int (*write)(struct inode*, char*, int); 34 | }; 35 | 36 | extern struct devsw devsw[]; 37 | 38 | #define CONSOLE 1 39 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/forktest.c: -------------------------------------------------------------------------------- 1 | // Test that fork fails gracefully. 2 | // Tiny executable so that the limit can be filling the proc table. 3 | 4 | #include "types.h" 5 | #include "stat.h" 6 | #include "user.h" 7 | 8 | #define N 1000 9 | 10 | void 11 | printf(int fd, char *s, ...) 12 | { 13 | write(fd, s, strlen(s)); 14 | } 15 | 16 | void 17 | forktest(void) 18 | { 19 | int n, pid; 20 | 21 | printf(1, "fork test\n"); 22 | 23 | for(n=0; n 0; n--){ 37 | if(wait() < 0){ 38 | printf(1, "wait stopped early\n"); 39 | exit(); 40 | } 41 | } 42 | 43 | if(wait() != -1){ 44 | printf(1, "wait got too many\n"); 45 | exit(); 46 | } 47 | 48 | printf(1, "fork test OK\n"); 49 | } 50 | 51 | int 52 | main(void) 53 | { 54 | forktest(); 55 | exit(); 56 | } 57 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/init.c: -------------------------------------------------------------------------------- 1 | // init: The initial user-level program 2 | 3 | #include "types.h" 4 | #include "stat.h" 5 | #include "user.h" 6 | #include "fcntl.h" 7 | 8 | char *argv[] = { "sh", 0 }; 9 | 10 | int 11 | main(void) 12 | { 13 | int pid, wpid; 14 | 15 | if(open("console", O_RDWR) < 0){ 16 | mknod("console", 1, 1); 17 | open("console", O_RDWR); 18 | } 19 | dup(0); // stdout 20 | dup(0); // stderr 21 | 22 | for(;;){ 23 | printf(1, "init: starting sh\n"); 24 | pid = fork(); 25 | if(pid < 0){ 26 | printf(1, "init: fork failed\n"); 27 | exit(); 28 | } 29 | if(pid == 0){ 30 | exec("sh", argv); 31 | printf(1, "init: exec sh failed\n"); 32 | exit(); 33 | } 34 | while((wpid=wait()) >= 0 && wpid != pid) 35 | printf(1, "zombie!\n"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/initcode.S: -------------------------------------------------------------------------------- 1 | # Initial process execs /init. 2 | 3 | #include "syscall.h" 4 | #include "traps.h" 5 | 6 | 7 | # exec(init, argv) 8 | .globl start 9 | start: 10 | pushl $argv 11 | pushl $init 12 | pushl $0 // where caller pc would be 13 | movl $SYS_exec, %eax 14 | int $T_SYSCALL 15 | 16 | # for(;;) exit(); 17 | exit: 18 | movl $SYS_exit, %eax 19 | int $T_SYSCALL 20 | jmp exit 21 | 22 | # char init[] = "/init\0"; 23 | init: 24 | .string "/init\0" 25 | 26 | # char *argv[] = { init, 0 }; 27 | .p2align 2 28 | argv: 29 | .long init 30 | .long 0 31 | 32 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/kbd.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "x86.h" 3 | #include "defs.h" 4 | #include "kbd.h" 5 | 6 | int 7 | kbdgetc(void) 8 | { 9 | static uint shift; 10 | static uchar *charcode[4] = { 11 | normalmap, shiftmap, ctlmap, ctlmap 12 | }; 13 | uint st, data, c; 14 | 15 | st = inb(KBSTATP); 16 | if((st & KBS_DIB) == 0) 17 | return -1; 18 | data = inb(KBDATAP); 19 | 20 | if(data == 0xE0){ 21 | shift |= E0ESC; 22 | return 0; 23 | } else if(data & 0x80){ 24 | // Key released 25 | data = (shift & E0ESC ? data : data & 0x7F); 26 | shift &= ~(shiftcode[data] | E0ESC); 27 | return 0; 28 | } else if(shift & E0ESC){ 29 | // Last character was an E0 escape; or with 0x80 30 | data |= 0x80; 31 | shift &= ~E0ESC; 32 | } 33 | 34 | shift |= shiftcode[data]; 35 | shift ^= togglecode[data]; 36 | c = charcode[shift & (CTL | SHIFT)][data]; 37 | if(shift & CAPSLOCK){ 38 | if('a' <= c && c <= 'z') 39 | c += 'A' - 'a'; 40 | else if('A' <= c && c <= 'Z') 41 | c += 'a' - 'A'; 42 | } 43 | return c; 44 | } 45 | 46 | void 47 | kbdintr(void) 48 | { 49 | consoleintr(kbdgetc); 50 | } 51 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/kill.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char **argv) 7 | { 8 | int i; 9 | 10 | if(argc < 1){ 11 | printf(2, "usage: kill pid...\n"); 12 | exit(); 13 | } 14 | for(i=1; i; 17 | for($i=0; $i<@lines; $i+=50){ 18 | print "\n\n"; 19 | ++$page; 20 | print "$now $h Page $page\n"; 21 | print "\n\n"; 22 | for($j=$i; $j<@lines && $j<$i +50; $j++){ 23 | $lines[$j] =~ s!//DOC.*!!; 24 | print $lines[$j]; 25 | } 26 | for(; $j<$i+50; $j++){ 27 | print "\n"; 28 | } 29 | $sheet = ""; 30 | if($lines[$i] =~ /^([0-9][0-9])[0-9][0-9] /){ 31 | $sheet = "Sheet $1"; 32 | } 33 | print "\n\n"; 34 | print "$sheet\n"; 35 | print "\n\n"; 36 | } 37 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/printpcs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Decode the symbols from a panic EIP list 4 | 5 | # Find a working addr2line 6 | for p in i386-jos-elf-addr2line addr2line; do 7 | if which $p 2>&1 >/dev/null && \ 8 | $p -h 2>&1 | grep -q '\belf32-i386\b'; then 9 | break 10 | fi 11 | done 12 | 13 | # Enable as much pretty-printing as this addr2line can do 14 | $p $($p -h | grep ' -[aipsf] ' | awk '{print $1}') -e kernel "$@" 15 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/ps.c: -------------------------------------------------------------------------------- 1 | 2 | #include "types.h" 3 | #include "stat.h" 4 | #include "user.h" 5 | 6 | int main(int argc, const char * argv[]) 7 | { 8 | ps(); 9 | exit(); 10 | } -------------------------------------------------------------------------------- /4 - Scheduler - CFS/rm.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | if(argc < 2){ 11 | printf(2, "Usage: rm files...\n"); 12 | exit(); 13 | } 14 | 15 | for(i = 1; i < argc; i++){ 16 | if(unlink(argv[i]) < 0){ 17 | printf(2, "rm: %s failed to delete\n", argv[i]); 18 | break; 19 | } 20 | } 21 | 22 | exit(); 23 | } 24 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/runoff.list: -------------------------------------------------------------------------------- 1 | # basic headers 2 | types.h 3 | param.h 4 | memlayout.h 5 | defs.h 6 | x86.h 7 | asm.h 8 | mmu.h 9 | elf.h 10 | 11 | # entering xv6 12 | entry.S 13 | entryother.S 14 | main.c 15 | 16 | # locks 17 | spinlock.h 18 | spinlock.c 19 | 20 | # processes 21 | vm.c 22 | proc.h 23 | proc.c 24 | swtch.S 25 | kalloc.c 26 | 27 | # system calls 28 | traps.h 29 | vectors.pl 30 | trapasm.S 31 | trap.c 32 | syscall.h 33 | syscall.c 34 | sysproc.c 35 | 36 | # file system 37 | buf.h 38 | fcntl.h 39 | stat.h 40 | fs.h 41 | file.h 42 | ide.c 43 | bio.c 44 | log.c 45 | fs.c 46 | file.c 47 | sysfile.c 48 | exec.c 49 | 50 | # pipes 51 | pipe.c 52 | 53 | # string operations 54 | string.c 55 | 56 | # low-level hardware 57 | mp.h 58 | mp.c 59 | lapic.c 60 | ioapic.c 61 | picirq.c 62 | kbd.h 63 | kbd.c 64 | console.c 65 | timer.c 66 | uart.c 67 | 68 | # user-level 69 | initcode.S 70 | usys.S 71 | init.c 72 | sh.c 73 | 74 | # bootloader 75 | bootasm.S 76 | bootmain.c 77 | 78 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/show1: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | runoff1 "$@" | pr.pl -h "xv6/$@" | mpage -m50t50b -o -bLetter -T -t -2 -FLucidaSans-Typewriter83 -L60 >x.ps; gv --swap x.ps 4 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/sign.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; 4 | 5 | $n = sysread(SIG, $buf, 1000); 6 | 7 | if($n > 510){ 8 | print STDERR "boot block too large: $n bytes (max 510)\n"; 9 | exit 1; 10 | } 11 | 12 | print STDERR "boot block is $n bytes (max 510)\n"; 13 | 14 | $buf .= "\0" x (510-$n); 15 | $buf .= "\x55\xAA"; 16 | 17 | open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; 18 | print SIG $buf; 19 | close SIG; 20 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/spinlock.h: -------------------------------------------------------------------------------- 1 | // Mutual exclusion lock. 2 | struct spinlock { 3 | uint locked; // Is the lock held? 4 | 5 | // For debugging: 6 | char *name; // Name of lock. 7 | struct cpu *cpu; // The cpu holding the lock. 8 | uint pcs[10]; // The call stack (an array of program counters) 9 | // that locked the lock. 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/spinp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# != 1 ] || [ ! -f "$1" ]; then 4 | echo 'usage: spinp file.p' 1>&2 5 | exit 1 6 | fi 7 | 8 | rm -f $1.trail 9 | spin -a $1 || exit 1 10 | cc -DSAFETY -DREACH -DMEMLIM=500 -o pan pan.c 11 | pan -i 12 | rm pan.* pan 13 | if [ -f $1.trail ]; then 14 | spin -t -p $1 15 | fi 16 | 17 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/stat.h: -------------------------------------------------------------------------------- 1 | #define T_DIR 1 // Directory 2 | #define T_FILE 2 // File 3 | #define T_DEV 3 // Device 4 | 5 | struct stat { 6 | short type; // Type of file 7 | int dev; // File system's disk device 8 | uint ino; // Inode number 9 | short nlink; // Number of links to file 10 | uint size; // Size of file in bytes 11 | }; 12 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/swtch.S: -------------------------------------------------------------------------------- 1 | # Context switch 2 | # 3 | # void swtch(struct context **old, struct context *new); 4 | # 5 | # Save current register context in old 6 | # and then load register context from new. 7 | 8 | .globl swtch 9 | swtch: 10 | movl 4(%esp), %eax 11 | movl 8(%esp), %edx 12 | 13 | # Save old callee-save registers 14 | pushl %ebp 15 | pushl %ebx 16 | pushl %esi 17 | pushl %edi 18 | 19 | # Switch stacks 20 | movl %esp, (%eax) 21 | movl %edx, %esp 22 | 23 | # Load new callee-save registers 24 | popl %edi 25 | popl %esi 26 | popl %ebx 27 | popl %ebp 28 | ret 29 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/syscall.h: -------------------------------------------------------------------------------- 1 | // System call numbers 2 | #define SYS_fork 1 3 | #define SYS_exit 2 4 | #define SYS_wait 3 5 | #define SYS_pipe 4 6 | #define SYS_read 5 7 | #define SYS_kill 6 8 | #define SYS_exec 7 9 | #define SYS_fstat 8 10 | #define SYS_chdir 9 11 | #define SYS_dup 10 12 | #define SYS_getpid 11 13 | #define SYS_sbrk 12 14 | #define SYS_sleep 13 15 | #define SYS_uptime 14 16 | #define SYS_open 15 17 | #define SYS_write 16 18 | #define SYS_mknod 17 19 | #define SYS_unlink 18 20 | #define SYS_link 19 21 | #define SYS_mkdir 20 22 | #define SYS_close 21 23 | #define SYS_ps 22 -------------------------------------------------------------------------------- /4 - Scheduler - CFS/timer.c: -------------------------------------------------------------------------------- 1 | // Intel 8253/8254/82C54 Programmable Interval Timer (PIT). 2 | // Only used on uniprocessors; 3 | // SMP machines use the local APIC timer. 4 | 5 | #include "types.h" 6 | #include "defs.h" 7 | #include "traps.h" 8 | #include "x86.h" 9 | 10 | #define IO_TIMER1 0x040 // 8253 Timer #1 11 | 12 | // Frequency of all three count-down timers; 13 | // (TIMER_FREQ/freq) is the appropriate count 14 | // to generate a frequency of freq Hz. 15 | 16 | #define TIMER_FREQ 1193182 17 | #define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) 18 | 19 | #define TIMER_MODE (IO_TIMER1 + 3) // timer mode port 20 | #define TIMER_SEL0 0x00 // select counter 0 21 | #define TIMER_RATEGEN 0x04 // mode 2, rate generator 22 | #define TIMER_16BIT 0x30 // r/w counter 16 bits, LSB first 23 | 24 | void 25 | timerinit(void) 26 | { 27 | // Interrupt 100 times/sec. 28 | outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 29 | outb(IO_TIMER1, TIMER_DIV(100) % 256); 30 | outb(IO_TIMER1, TIMER_DIV(100) / 256); 31 | picenable(IRQ_TIMER); 32 | } 33 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/toc.ftr: -------------------------------------------------------------------------------- 1 | 2 | 3 | The source listing is preceded by a cross-reference that lists every defined 4 | constant, struct, global variable, and function in xv6. Each entry gives, 5 | on the same line as the name, the line number (or, in a few cases, numbers) 6 | where the name is defined. Successive lines in an entry list the line 7 | numbers where the name is used. For example, this entry: 8 | 9 | swtch 2658 10 | 0374 2428 2466 2657 2658 11 | 12 | indicates that swtch is defined on line 2658 and is mentioned on five lines 13 | on sheets 03, 24, and 26. 14 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/toc.hdr: -------------------------------------------------------------------------------- 1 | The numbers to the left of the file names in the table are sheet numbers. 2 | The source code has been printed in a double column format with fifty 3 | lines per column, giving one hundred lines per sheet (or page). 4 | Thus there is a convenient relationship between line numbers and sheet numbers. 5 | 6 | 7 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/trapasm.S: -------------------------------------------------------------------------------- 1 | #include "mmu.h" 2 | 3 | # vectors.S sends all traps here. 4 | .globl alltraps 5 | alltraps: 6 | # Build trap frame. 7 | pushl %ds 8 | pushl %es 9 | pushl %fs 10 | pushl %gs 11 | pushal 12 | 13 | # Set up data and per-cpu segments. 14 | movw $(SEG_KDATA<<3), %ax 15 | movw %ax, %ds 16 | movw %ax, %es 17 | movw $(SEG_KCPU<<3), %ax 18 | movw %ax, %fs 19 | movw %ax, %gs 20 | 21 | # Call trap(tf), where tf=%esp 22 | pushl %esp 23 | call trap 24 | addl $4, %esp 25 | 26 | # Return falls through to trapret... 27 | .globl trapret 28 | trapret: 29 | popal 30 | popl %gs 31 | popl %fs 32 | popl %es 33 | popl %ds 34 | addl $0x8, %esp # trapno and errcode 35 | iret 36 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/types.h: -------------------------------------------------------------------------------- 1 | typedef unsigned int uint; 2 | typedef unsigned short ushort; 3 | typedef unsigned char uchar; 4 | typedef uint pde_t; 5 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/user.h: -------------------------------------------------------------------------------- 1 | struct stat; 2 | 3 | // system calls 4 | int fork(void); 5 | int exit(void) __attribute__((noreturn)); 6 | int wait(void); 7 | int pipe(int*); 8 | int write(int, void*, int); 9 | int read(int, void*, int); 10 | int close(int); 11 | int kill(int); 12 | int exec(char*, char**); 13 | int open(char*, int); 14 | int mknod(char*, short, short); 15 | int unlink(char*); 16 | int fstat(int fd, struct stat*); 17 | int link(char*, char*); 18 | int mkdir(char*); 19 | int chdir(char*); 20 | int dup(int); 21 | int getpid(void); 22 | char* sbrk(int); 23 | int sleep(int); 24 | int uptime(void); 25 | int ps(void); 26 | 27 | // ulib.c 28 | int stat(char*, struct stat*); 29 | char* strcpy(char*, char*); 30 | void *memmove(void*, void*, int); 31 | char* strchr(const char*, char c); 32 | int strcmp(const char*, const char*); 33 | void printf(int, char*, ...); 34 | char* gets(char*, int max); 35 | uint strlen(char*); 36 | void* memset(void*, int, uint); 37 | void* malloc(uint); 38 | void free(void*); 39 | int atoi(const char*); 40 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/usys.S: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | #include "traps.h" 3 | 4 | #define SYSCALL(name) \ 5 | .globl name; \ 6 | name: \ 7 | movl $SYS_ ## name, %eax; \ 8 | int $T_SYSCALL; \ 9 | ret 10 | 11 | SYSCALL(fork) 12 | SYSCALL(exit) 13 | SYSCALL(wait) 14 | SYSCALL(pipe) 15 | SYSCALL(read) 16 | SYSCALL(write) 17 | SYSCALL(close) 18 | SYSCALL(kill) 19 | SYSCALL(exec) 20 | SYSCALL(open) 21 | SYSCALL(mknod) 22 | SYSCALL(unlink) 23 | SYSCALL(fstat) 24 | SYSCALL(link) 25 | SYSCALL(mkdir) 26 | SYSCALL(chdir) 27 | SYSCALL(dup) 28 | SYSCALL(getpid) 29 | SYSCALL(sbrk) 30 | SYSCALL(sleep) 31 | SYSCALL(uptime) 32 | SYSCALL(ps) -------------------------------------------------------------------------------- /4 - Scheduler - CFS/vectors.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # Generate vectors.S, the trap/interrupt entry points. 4 | # There has to be one entry point per interrupt number 5 | # since otherwise there's no way for trap() to discover 6 | # the interrupt number. 7 | 8 | print "# generated by vectors.pl - do not edit\n"; 9 | print "# handlers\n"; 10 | print ".globl alltraps\n"; 11 | for(my $i = 0; $i < 256; $i++){ 12 | print ".globl vector$i\n"; 13 | print "vector$i:\n"; 14 | if(!($i == 8 || ($i >= 10 && $i <= 14) || $i == 17)){ 15 | print " pushl \$0\n"; 16 | } 17 | print " pushl \$$i\n"; 18 | print " jmp alltraps\n"; 19 | } 20 | 21 | print "\n# vector table\n"; 22 | print ".data\n"; 23 | print ".globl vectors\n"; 24 | print "vectors:\n"; 25 | for(my $i = 0; $i < 256; $i++){ 26 | print " .long vector$i\n"; 27 | } 28 | 29 | # sample output: 30 | # # handlers 31 | # .globl alltraps 32 | # .globl vector0 33 | # vector0: 34 | # pushl $0 35 | # pushl $0 36 | # jmp alltraps 37 | # ... 38 | # 39 | # # vector table 40 | # .data 41 | # .globl vectors 42 | # vectors: 43 | # .long vector0 44 | # .long vector1 45 | # .long vector2 46 | # ... 47 | 48 | -------------------------------------------------------------------------------- /4 - Scheduler - CFS/wc.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | wc(int fd, char *name) 9 | { 10 | int i, n; 11 | int l, w, c, inword; 12 | 13 | l = w = c = 0; 14 | inword = 0; 15 | while((n = read(fd, buf, sizeof(buf))) > 0){ 16 | for(i=0; i 0) 12 | sleep(5); // Let child exit before parent. 13 | exit(); 14 | } 15 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/.cvsignore: -------------------------------------------------------------------------------- 1 | *.asm 2 | *.d 3 | *.sym 4 | _* 5 | kernel 6 | user1 7 | userfs 8 | usertests 9 | xv6.img 10 | vectors.S 11 | bochsout.txt 12 | bootblock 13 | bootother 14 | bootother.out 15 | parport.out 16 | fmt 17 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((c-mode 2 | (indent-tabs-mode . nil) 3 | (c-file-style . "bsd") 4 | (c-basic-offset . 2))) 5 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/.gdbinit.tmpl: -------------------------------------------------------------------------------- 1 | set $lastcs = -1 2 | 3 | define hook-stop 4 | # There doesn't seem to be a good way to detect if we're in 16- or 5 | # 32-bit mode, but in 32-bit mode we always run with CS == 8 in the 6 | # kernel and CS == 35 in user space 7 | if $cs == 8 || $cs == 35 8 | if $lastcs != 8 && $lastcs != 35 9 | set architecture i386 10 | end 11 | x/i $pc 12 | else 13 | if $lastcs == -1 || $lastcs == 8 || $lastcs == 35 14 | set architecture i8086 15 | end 16 | # Translate the segment:offset into a physical address 17 | printf "[%4x:%4x] ", $cs, $eip 18 | x/i $cs*16+$eip 19 | end 20 | set $lastcs = $cs 21 | end 22 | 23 | echo + target remote localhost:1234\n 24 | target remote localhost:1234 25 | 26 | echo + symbol-file kernel\n 27 | symbol-file kernel 28 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | _* 3 | *.o 4 | *.d 5 | *.asm 6 | *.sym 7 | *.img 8 | vectors.S 9 | bootblock 10 | entryother 11 | initcode 12 | initcode.out 13 | kernel 14 | kernelmemfs 15 | mkfs 16 | .gdbinit 17 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/BUGS: -------------------------------------------------------------------------------- 1 | formatting: 2 | need to fix PAGEBREAK mechanism 3 | 4 | sh: 5 | can't always runcmd in child -- breaks cd. 6 | maybe should hard-code PATH=/ ? 7 | 8 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/asm.h: -------------------------------------------------------------------------------- 1 | // 2 | // assembler macros to create x86 segments 3 | // 4 | 5 | #define SEG_NULLASM \ 6 | .word 0, 0; \ 7 | .byte 0, 0, 0, 0 8 | 9 | // The 0xC0 means the limit is in 4096-byte units 10 | // and (for executable segments) 32-bit mode. 11 | #define SEG_ASM(type,base,lim) \ 12 | .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ 13 | .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ 14 | (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) 15 | 16 | #define STA_X 0x8 // Executable segment 17 | #define STA_E 0x4 // Expand down (non-executable segments) 18 | #define STA_C 0x4 // Conforming code segment (executable only) 19 | #define STA_W 0x2 // Writeable (non-executable segments) 20 | #define STA_R 0x2 // Readable (executable segments) 21 | #define STA_A 0x1 // Accessed 22 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/big.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | #include "fcntl.h" 5 | 6 | int 7 | main() 8 | { 9 | char buf[512]; 10 | int fd, i, sectors; 11 | 12 | fd = open("big.file", O_CREATE | O_WRONLY); 13 | if(fd < 0){ 14 | printf(2, "big: cannot open big.file for writing\n"); 15 | exit(); 16 | } 17 | 18 | sectors = 0; 19 | while(1){ 20 | *(int*)buf = sectors; 21 | int cc = write(fd, buf, sizeof(buf)); 22 | if(cc <= 0) 23 | break; 24 | sectors++; 25 | if (sectors % 100 == 0) 26 | printf(2, "."); 27 | } 28 | 29 | printf(1, "\nwrote %d sectors\n", sectors); 30 | 31 | close(fd); 32 | fd = open("big.file", O_RDONLY); 33 | if(fd < 0){ 34 | printf(2, "big: cannot re-open big.file for reading\n"); 35 | exit(); 36 | } 37 | for(i = 0; i < sectors; i++){ 38 | int cc = read(fd, buf, sizeof(buf)); 39 | if(cc <= 0){ 40 | printf(2, "big: read error at sector %d\n", i); 41 | exit(); 42 | } 43 | if(*(int*)buf != i){ 44 | printf(2, "big: read the wrong data (%d) for sector %d\n", 45 | *(int*)buf, i); 46 | exit(); 47 | } 48 | } 49 | 50 | exit(); 51 | } 52 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/buf.h: -------------------------------------------------------------------------------- 1 | struct buf { 2 | int flags; 3 | uint dev; 4 | uint sector; 5 | struct buf *prev; // LRU cache list 6 | struct buf *next; 7 | struct buf *qnext; // disk queue 8 | uchar data[512]; 9 | }; 10 | #define B_BUSY 0x1 // buffer is locked by some process 11 | #define B_VALID 0x2 // buffer has been read from disk 12 | #define B_DIRTY 0x4 // buffer needs to be written to disk 13 | 14 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/cat.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | cat(int fd) 9 | { 10 | int n; 11 | 12 | while((n = read(fd, buf, sizeof(buf))) > 0) 13 | write(1, buf, n); 14 | if(n < 0){ 15 | printf(1, "cat: read error\n"); 16 | exit(); 17 | } 18 | } 19 | 20 | int 21 | main(int argc, char *argv[]) 22 | { 23 | int fd, i; 24 | 25 | if(argc <= 1){ 26 | cat(0); 27 | exit(); 28 | } 29 | 30 | for(i = 1; i < argc; i++){ 31 | if((fd = open(argv[i], 0)) < 0){ 32 | printf(1, "cat: cannot open %s\n", argv[i]); 33 | exit(); 34 | } 35 | cat(fd); 36 | close(fd); 37 | } 38 | exit(); 39 | } 40 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/cuth: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | $| = 1; 4 | 5 | sub writefile($@){ 6 | my ($file, @lines) = @_; 7 | 8 | sleep(1); 9 | open(F, ">$file") || die "open >$file: $!"; 10 | print F @lines; 11 | close(F); 12 | } 13 | 14 | # Cut out #include lines that don't contribute anything. 15 | for($i=0; $i<@ARGV; $i++){ 16 | $file = $ARGV[$i]; 17 | if(!open(F, $file)){ 18 | print STDERR "open $file: $!\n"; 19 | next; 20 | } 21 | @lines = ; 22 | close(F); 23 | 24 | $obj = "$file.o"; 25 | $obj =~ s/\.c\.o$/.o/; 26 | system("touch $file"); 27 | 28 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 29 | print STDERR "make $obj failed: $rv\n"; 30 | next; 31 | } 32 | 33 | system("cp $file =$file"); 34 | for($j=@lines-1; $j>=0; $j--){ 35 | if($lines[$j] =~ /^#include/){ 36 | $old = $lines[$j]; 37 | $lines[$j] = "/* CUT-H */\n"; 38 | writefile($file, @lines); 39 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 40 | $lines[$j] = $old; 41 | }else{ 42 | print STDERR "$file $old"; 43 | } 44 | } 45 | } 46 | writefile($file, grep {!/CUT-H/} @lines); 47 | system("rm =$file"); 48 | } 49 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/echo.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | for(i = 1; i < argc; i++) 11 | printf(1, "%s%s", argv[i], i+1 < argc ? " " : "\n"); 12 | exit(); 13 | } 14 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/elf.h: -------------------------------------------------------------------------------- 1 | // Format of an ELF executable file 2 | 3 | #define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian 4 | 5 | // File header 6 | struct elfhdr { 7 | uint magic; // must equal ELF_MAGIC 8 | uchar elf[12]; 9 | ushort type; 10 | ushort machine; 11 | uint version; 12 | uint entry; 13 | uint phoff; 14 | uint shoff; 15 | uint flags; 16 | ushort ehsize; 17 | ushort phentsize; 18 | ushort phnum; 19 | ushort shentsize; 20 | ushort shnum; 21 | ushort shstrndx; 22 | }; 23 | 24 | // Program section header 25 | struct proghdr { 26 | uint type; 27 | uint off; 28 | uint vaddr; 29 | uint paddr; 30 | uint filesz; 31 | uint memsz; 32 | uint flags; 33 | uint align; 34 | }; 35 | 36 | // Values for Proghdr type 37 | #define ELF_PROG_LOAD 1 38 | 39 | // Flag bits for Proghdr flags 40 | #define ELF_PROG_FLAG_EXEC 1 41 | #define ELF_PROG_FLAG_WRITE 2 42 | #define ELF_PROG_FLAG_READ 4 43 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/fcntl.h: -------------------------------------------------------------------------------- 1 | #define O_RDONLY 0x000 2 | #define O_WRONLY 0x001 3 | #define O_RDWR 0x002 4 | #define O_CREATE 0x200 5 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/file.h: -------------------------------------------------------------------------------- 1 | struct file { 2 | enum { FD_NONE, FD_PIPE, FD_INODE } type; 3 | int ref; // reference count 4 | char readable; 5 | char writable; 6 | struct pipe *pipe; 7 | struct inode *ip; 8 | uint off; 9 | }; 10 | 11 | 12 | // in-memory copy of an inode 13 | struct inode { 14 | uint dev; // Device number 15 | uint inum; // Inode number 16 | int ref; // Reference count 17 | int flags; // I_BUSY, I_VALID 18 | 19 | short type; // copy of disk inode 20 | short major; 21 | short minor; 22 | short nlink; 23 | uint size; 24 | uint addrs[NDIRECT+1]; 25 | }; 26 | #define I_BUSY 0x1 27 | #define I_VALID 0x2 28 | 29 | // table mapping major device number to 30 | // device functions 31 | struct devsw { 32 | int (*read)(struct inode*, char*, int); 33 | int (*write)(struct inode*, char*, int); 34 | }; 35 | 36 | extern struct devsw devsw[]; 37 | 38 | #define CONSOLE 1 39 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/forktest.c: -------------------------------------------------------------------------------- 1 | // Test that fork fails gracefully. 2 | // Tiny executable so that the limit can be filling the proc table. 3 | 4 | #include "types.h" 5 | #include "stat.h" 6 | #include "user.h" 7 | 8 | #define N 1000 9 | 10 | void 11 | printf(int fd, char *s, ...) 12 | { 13 | write(fd, s, strlen(s)); 14 | } 15 | 16 | void 17 | forktest(void) 18 | { 19 | int n, pid; 20 | 21 | printf(1, "fork test\n"); 22 | 23 | for(n=0; n 0; n--){ 37 | if(wait() < 0){ 38 | printf(1, "wait stopped early\n"); 39 | exit(); 40 | } 41 | } 42 | 43 | if(wait() != -1){ 44 | printf(1, "wait got too many\n"); 45 | exit(); 46 | } 47 | 48 | printf(1, "fork test OK\n"); 49 | } 50 | 51 | int 52 | main(void) 53 | { 54 | forktest(); 55 | exit(); 56 | } 57 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/init.c: -------------------------------------------------------------------------------- 1 | // init: The initial user-level program 2 | 3 | #include "types.h" 4 | #include "stat.h" 5 | #include "user.h" 6 | #include "fcntl.h" 7 | 8 | char *argv[] = { "sh", 0 }; 9 | 10 | int 11 | main(void) 12 | { 13 | int pid, wpid; 14 | 15 | if(open("console", O_RDWR) < 0){ 16 | mknod("console", 1, 1); 17 | open("console", O_RDWR); 18 | } 19 | dup(0); // stdout 20 | dup(0); // stderr 21 | 22 | for(;;){ 23 | printf(1, "init: starting sh\n"); 24 | pid = fork(); 25 | if(pid < 0){ 26 | printf(1, "init: fork failed\n"); 27 | exit(); 28 | } 29 | if(pid == 0){ 30 | exec("sh", argv); 31 | printf(1, "init: exec sh failed\n"); 32 | exit(); 33 | } 34 | while((wpid=wait()) >= 0 && wpid != pid) 35 | printf(1, "zombie!\n"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/initcode.S: -------------------------------------------------------------------------------- 1 | # Initial process execs /init. 2 | 3 | #include "syscall.h" 4 | #include "traps.h" 5 | 6 | 7 | # exec(init, argv) 8 | .globl start 9 | start: 10 | pushl $argv 11 | pushl $init 12 | pushl $0 // where caller pc would be 13 | movl $SYS_exec, %eax 14 | int $T_SYSCALL 15 | 16 | # for(;;) exit(); 17 | exit: 18 | movl $SYS_exit, %eax 19 | int $T_SYSCALL 20 | jmp exit 21 | 22 | # char init[] = "/init\0"; 23 | init: 24 | .string "/init\0" 25 | 26 | # char *argv[] = { init, 0 }; 27 | .p2align 2 28 | argv: 29 | .long init 30 | .long 0 31 | 32 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/kbd.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "x86.h" 3 | #include "defs.h" 4 | #include "kbd.h" 5 | 6 | int 7 | kbdgetc(void) 8 | { 9 | static uint shift; 10 | static uchar *charcode[4] = { 11 | normalmap, shiftmap, ctlmap, ctlmap 12 | }; 13 | uint st, data, c; 14 | 15 | st = inb(KBSTATP); 16 | if((st & KBS_DIB) == 0) 17 | return -1; 18 | data = inb(KBDATAP); 19 | 20 | if(data == 0xE0){ 21 | shift |= E0ESC; 22 | return 0; 23 | } else if(data & 0x80){ 24 | // Key released 25 | data = (shift & E0ESC ? data : data & 0x7F); 26 | shift &= ~(shiftcode[data] | E0ESC); 27 | return 0; 28 | } else if(shift & E0ESC){ 29 | // Last character was an E0 escape; or with 0x80 30 | data |= 0x80; 31 | shift &= ~E0ESC; 32 | } 33 | 34 | shift |= shiftcode[data]; 35 | shift ^= togglecode[data]; 36 | c = charcode[shift & (CTL | SHIFT)][data]; 37 | if(shift & CAPSLOCK){ 38 | if('a' <= c && c <= 'z') 39 | c += 'A' - 'a'; 40 | else if('A' <= c && c <= 'Z') 41 | c += 'a' - 'A'; 42 | } 43 | return c; 44 | } 45 | 46 | void 47 | kbdintr(void) 48 | { 49 | consoleintr(kbdgetc); 50 | } 51 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/kill.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char **argv) 7 | { 8 | int i; 9 | 10 | if(argc < 1){ 11 | printf(2, "usage: kill pid...\n"); 12 | exit(); 13 | } 14 | for(i=1; i; 17 | for($i=0; $i<@lines; $i+=50){ 18 | print "\n\n"; 19 | ++$page; 20 | print "$now $h Page $page\n"; 21 | print "\n\n"; 22 | for($j=$i; $j<@lines && $j<$i +50; $j++){ 23 | $lines[$j] =~ s!//DOC.*!!; 24 | print $lines[$j]; 25 | } 26 | for(; $j<$i+50; $j++){ 27 | print "\n"; 28 | } 29 | $sheet = ""; 30 | if($lines[$i] =~ /^([0-9][0-9])[0-9][0-9] /){ 31 | $sheet = "Sheet $1"; 32 | } 33 | print "\n\n"; 34 | print "$sheet\n"; 35 | print "\n\n"; 36 | } 37 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/printpcs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Decode the symbols from a panic EIP list 4 | 5 | # Find a working addr2line 6 | for p in i386-jos-elf-addr2line addr2line; do 7 | if which $p 2>&1 >/dev/null && \ 8 | $p -h 2>&1 | grep -q '\belf32-i386\b'; then 9 | break 10 | fi 11 | done 12 | 13 | # Enable as much pretty-printing as this addr2line can do 14 | $p $($p -h | grep ' -[aipsf] ' | awk '{print $1}') -e kernel "$@" 15 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/ps.c: -------------------------------------------------------------------------------- 1 | 2 | #include "types.h" 3 | #include "stat.h" 4 | #include "user.h" 5 | 6 | int main(int argc, const char * argv[]) 7 | { 8 | ps(); 9 | exit(); 10 | } -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/rm.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | if(argc < 2){ 11 | printf(2, "Usage: rm files...\n"); 12 | exit(); 13 | } 14 | 15 | for(i = 1; i < argc; i++){ 16 | if(unlink(argv[i]) < 0){ 17 | printf(2, "rm: %s failed to delete\n", argv[i]); 18 | break; 19 | } 20 | } 21 | 22 | exit(); 23 | } 24 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/runoff.list: -------------------------------------------------------------------------------- 1 | # basic headers 2 | types.h 3 | param.h 4 | memlayout.h 5 | defs.h 6 | x86.h 7 | asm.h 8 | mmu.h 9 | elf.h 10 | 11 | # entering xv6 12 | entry.S 13 | entryother.S 14 | main.c 15 | 16 | # locks 17 | spinlock.h 18 | spinlock.c 19 | 20 | # processes 21 | vm.c 22 | proc.h 23 | proc.c 24 | swtch.S 25 | kalloc.c 26 | 27 | # system calls 28 | traps.h 29 | vectors.pl 30 | trapasm.S 31 | trap.c 32 | syscall.h 33 | syscall.c 34 | sysproc.c 35 | 36 | # file system 37 | buf.h 38 | fcntl.h 39 | stat.h 40 | fs.h 41 | file.h 42 | ide.c 43 | bio.c 44 | log.c 45 | fs.c 46 | file.c 47 | sysfile.c 48 | exec.c 49 | 50 | # pipes 51 | pipe.c 52 | 53 | # string operations 54 | string.c 55 | 56 | # low-level hardware 57 | mp.h 58 | mp.c 59 | lapic.c 60 | ioapic.c 61 | picirq.c 62 | kbd.h 63 | kbd.c 64 | console.c 65 | timer.c 66 | uart.c 67 | 68 | # user-level 69 | initcode.S 70 | usys.S 71 | init.c 72 | sh.c 73 | 74 | # bootloader 75 | bootasm.S 76 | bootmain.c 77 | 78 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/show1: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | runoff1 "$@" | pr.pl -h "xv6/$@" | mpage -m50t50b -o -bLetter -T -t -2 -FLucidaSans-Typewriter83 -L60 >x.ps; gv --swap x.ps 4 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/sign.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; 4 | 5 | $n = sysread(SIG, $buf, 1000); 6 | 7 | if($n > 510){ 8 | print STDERR "boot block too large: $n bytes (max 510)\n"; 9 | exit 1; 10 | } 11 | 12 | print STDERR "boot block is $n bytes (max 510)\n"; 13 | 14 | $buf .= "\0" x (510-$n); 15 | $buf .= "\x55\xAA"; 16 | 17 | open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; 18 | print SIG $buf; 19 | close SIG; 20 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/spinlock.h: -------------------------------------------------------------------------------- 1 | // Mutual exclusion lock. 2 | struct spinlock { 3 | uint locked; // Is the lock held? 4 | 5 | // For debugging: 6 | char *name; // Name of lock. 7 | struct cpu *cpu; // The cpu holding the lock. 8 | uint pcs[10]; // The call stack (an array of program counters) 9 | // that locked the lock. 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/spinp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# != 1 ] || [ ! -f "$1" ]; then 4 | echo 'usage: spinp file.p' 1>&2 5 | exit 1 6 | fi 7 | 8 | rm -f $1.trail 9 | spin -a $1 || exit 1 10 | cc -DSAFETY -DREACH -DMEMLIM=500 -o pan pan.c 11 | pan -i 12 | rm pan.* pan 13 | if [ -f $1.trail ]; then 14 | spin -t -p $1 15 | fi 16 | 17 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/stat.h: -------------------------------------------------------------------------------- 1 | #define T_DIR 1 // Directory 2 | #define T_FILE 2 // File 3 | #define T_DEV 3 // Device 4 | 5 | struct stat { 6 | short type; // Type of file 7 | int dev; // File system's disk device 8 | uint ino; // Inode number 9 | short nlink; // Number of links to file 10 | uint size; // Size of file in bytes 11 | }; 12 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/swtch.S: -------------------------------------------------------------------------------- 1 | # Context switch 2 | # 3 | # void swtch(struct context **old, struct context *new); 4 | # 5 | # Save current register context in old 6 | # and then load register context from new. 7 | 8 | .globl swtch 9 | swtch: 10 | movl 4(%esp), %eax 11 | movl 8(%esp), %edx 12 | 13 | # Save old callee-save registers 14 | pushl %ebp 15 | pushl %ebx 16 | pushl %esi 17 | pushl %edi 18 | 19 | # Switch stacks 20 | movl %esp, (%eax) 21 | movl %edx, %esp 22 | 23 | # Load new callee-save registers 24 | popl %edi 25 | popl %esi 26 | popl %ebx 27 | popl %ebp 28 | ret 29 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/syscall.h: -------------------------------------------------------------------------------- 1 | // System call numbers 2 | #define SYS_fork 1 3 | #define SYS_exit 2 4 | #define SYS_wait 3 5 | #define SYS_pipe 4 6 | #define SYS_read 5 7 | #define SYS_kill 6 8 | #define SYS_exec 7 9 | #define SYS_fstat 8 10 | #define SYS_chdir 9 11 | #define SYS_dup 10 12 | #define SYS_getpid 11 13 | #define SYS_sbrk 12 14 | #define SYS_sleep 13 15 | #define SYS_uptime 14 16 | #define SYS_open 15 17 | #define SYS_write 16 18 | #define SYS_mknod 17 19 | #define SYS_unlink 18 20 | #define SYS_link 19 21 | #define SYS_mkdir 20 22 | #define SYS_close 21 23 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/timer.c: -------------------------------------------------------------------------------- 1 | // Intel 8253/8254/82C54 Programmable Interval Timer (PIT). 2 | // Only used on uniprocessors; 3 | // SMP machines use the local APIC timer. 4 | 5 | #include "types.h" 6 | #include "defs.h" 7 | #include "traps.h" 8 | #include "x86.h" 9 | 10 | #define IO_TIMER1 0x040 // 8253 Timer #1 11 | 12 | // Frequency of all three count-down timers; 13 | // (TIMER_FREQ/freq) is the appropriate count 14 | // to generate a frequency of freq Hz. 15 | 16 | #define TIMER_FREQ 1193182 17 | #define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) 18 | 19 | #define TIMER_MODE (IO_TIMER1 + 3) // timer mode port 20 | #define TIMER_SEL0 0x00 // select counter 0 21 | #define TIMER_RATEGEN 0x04 // mode 2, rate generator 22 | #define TIMER_16BIT 0x30 // r/w counter 16 bits, LSB first 23 | 24 | void 25 | timerinit(void) 26 | { 27 | // Interrupt 100 times/sec. 28 | outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 29 | outb(IO_TIMER1, TIMER_DIV(100) % 256); 30 | outb(IO_TIMER1, TIMER_DIV(100) / 256); 31 | picenable(IRQ_TIMER); 32 | } 33 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/toc.ftr: -------------------------------------------------------------------------------- 1 | 2 | 3 | The source listing is preceded by a cross-reference that lists every defined 4 | constant, struct, global variable, and function in xv6. Each entry gives, 5 | on the same line as the name, the line number (or, in a few cases, numbers) 6 | where the name is defined. Successive lines in an entry list the line 7 | numbers where the name is used. For example, this entry: 8 | 9 | swtch 2658 10 | 0374 2428 2466 2657 2658 11 | 12 | indicates that swtch is defined on line 2658 and is mentioned on five lines 13 | on sheets 03, 24, and 26. 14 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/toc.hdr: -------------------------------------------------------------------------------- 1 | The numbers to the left of the file names in the table are sheet numbers. 2 | The source code has been printed in a double column format with fifty 3 | lines per column, giving one hundred lines per sheet (or page). 4 | Thus there is a convenient relationship between line numbers and sheet numbers. 5 | 6 | 7 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/trapasm.S: -------------------------------------------------------------------------------- 1 | #include "mmu.h" 2 | 3 | # vectors.S sends all traps here. 4 | .globl alltraps 5 | alltraps: 6 | # Build trap frame. 7 | pushl %ds 8 | pushl %es 9 | pushl %fs 10 | pushl %gs 11 | pushal 12 | 13 | # Set up data and per-cpu segments. 14 | movw $(SEG_KDATA<<3), %ax 15 | movw %ax, %ds 16 | movw %ax, %es 17 | movw $(SEG_KCPU<<3), %ax 18 | movw %ax, %fs 19 | movw %ax, %gs 20 | 21 | # Call trap(tf), where tf=%esp 22 | pushl %esp 23 | call trap 24 | addl $4, %esp 25 | 26 | # Return falls through to trapret... 27 | .globl trapret 28 | trapret: 29 | popal 30 | popl %gs 31 | popl %fs 32 | popl %es 33 | popl %ds 34 | addl $0x8, %esp # trapno and errcode 35 | iret 36 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/types.h: -------------------------------------------------------------------------------- 1 | typedef unsigned int uint; 2 | typedef unsigned short ushort; 3 | typedef unsigned char uchar; 4 | typedef uint pde_t; 5 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/user.h: -------------------------------------------------------------------------------- 1 | struct stat; 2 | 3 | // system calls 4 | int fork(void); 5 | int exit(void) __attribute__((noreturn)); 6 | int wait(void); 7 | int pipe(int*); 8 | int write(int, void*, int); 9 | int read(int, void*, int); 10 | int close(int); 11 | int kill(int); 12 | int exec(char*, char**); 13 | int open(char*, int); 14 | int mknod(char*, short, short); 15 | int unlink(char*); 16 | int fstat(int fd, struct stat*); 17 | int link(char*, char*); 18 | int mkdir(char*); 19 | int chdir(char*); 20 | int dup(int); 21 | int getpid(void); 22 | char* sbrk(int); 23 | int sleep(int); 24 | int uptime(void); 25 | 26 | // ulib.c 27 | int stat(char*, struct stat*); 28 | char* strcpy(char*, char*); 29 | void *memmove(void*, void*, int); 30 | char* strchr(const char*, char c); 31 | int strcmp(const char*, const char*); 32 | void printf(int, char*, ...); 33 | char* gets(char*, int max); 34 | uint strlen(char*); 35 | void* memset(void*, int, uint); 36 | void* malloc(uint); 37 | void free(void*); 38 | int atoi(const char*); 39 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/usys.S: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | #include "traps.h" 3 | 4 | #define SYSCALL(name) \ 5 | .globl name; \ 6 | name: \ 7 | movl $SYS_ ## name, %eax; \ 8 | int $T_SYSCALL; \ 9 | ret 10 | 11 | SYSCALL(fork) 12 | SYSCALL(exit) 13 | SYSCALL(wait) 14 | SYSCALL(pipe) 15 | SYSCALL(read) 16 | SYSCALL(write) 17 | SYSCALL(close) 18 | SYSCALL(kill) 19 | SYSCALL(exec) 20 | SYSCALL(open) 21 | SYSCALL(mknod) 22 | SYSCALL(unlink) 23 | SYSCALL(fstat) 24 | SYSCALL(link) 25 | SYSCALL(mkdir) 26 | SYSCALL(chdir) 27 | SYSCALL(dup) 28 | SYSCALL(getpid) 29 | SYSCALL(sbrk) 30 | SYSCALL(sleep) 31 | SYSCALL(uptime) 32 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/vectors.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # Generate vectors.S, the trap/interrupt entry points. 4 | # There has to be one entry point per interrupt number 5 | # since otherwise there's no way for trap() to discover 6 | # the interrupt number. 7 | 8 | print "# generated by vectors.pl - do not edit\n"; 9 | print "# handlers\n"; 10 | print ".globl alltraps\n"; 11 | for(my $i = 0; $i < 256; $i++){ 12 | print ".globl vector$i\n"; 13 | print "vector$i:\n"; 14 | if(!($i == 8 || ($i >= 10 && $i <= 14) || $i == 17)){ 15 | print " pushl \$0\n"; 16 | } 17 | print " pushl \$$i\n"; 18 | print " jmp alltraps\n"; 19 | } 20 | 21 | print "\n# vector table\n"; 22 | print ".data\n"; 23 | print ".globl vectors\n"; 24 | print "vectors:\n"; 25 | for(my $i = 0; $i < 256; $i++){ 26 | print " .long vector$i\n"; 27 | } 28 | 29 | # sample output: 30 | # # handlers 31 | # .globl alltraps 32 | # .globl vector0 33 | # vector0: 34 | # pushl $0 35 | # pushl $0 36 | # jmp alltraps 37 | # ... 38 | # 39 | # # vector table 40 | # .data 41 | # .globl vectors 42 | # vectors: 43 | # .long vector0 44 | # .long vector1 45 | # .long vector2 46 | # ... 47 | 48 | -------------------------------------------------------------------------------- /5 - Filesystem - Doubly Indirect/wc.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | wc(int fd, char *name) 9 | { 10 | int i, n; 11 | int l, w, c, inword; 12 | 13 | l = w = c = 0; 14 | inword = 0; 15 | while((n = read(fd, buf, sizeof(buf))) > 0){ 16 | for(i=0; i 0) 12 | sleep(5); // Let child exit before parent. 13 | exit(); 14 | } 15 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/BUGS: -------------------------------------------------------------------------------- 1 | formatting: 2 | need to fix PAGEBREAK mechanism 3 | 4 | sh: 5 | can't always runcmd in child -- breaks cd. 6 | maybe should hard-code PATH=/ ? 7 | 8 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/asm.h: -------------------------------------------------------------------------------- 1 | // 2 | // assembler macros to create x86 segments 3 | // 4 | 5 | #define SEG_NULLASM \ 6 | .word 0, 0; \ 7 | .byte 0, 0, 0, 0 8 | 9 | // The 0xC0 means the limit is in 4096-byte units 10 | // and (for executable segments) 32-bit mode. 11 | #define SEG_ASM(type,base,lim) \ 12 | .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ 13 | .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ 14 | (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) 15 | 16 | #define STA_X 0x8 // Executable segment 17 | #define STA_E 0x4 // Expand down (non-executable segments) 18 | #define STA_C 0x4 // Conforming code segment (executable only) 19 | #define STA_W 0x2 // Writeable (non-executable segments) 20 | #define STA_R 0x2 // Readable (executable segments) 21 | #define STA_A 0x1 // Accessed 22 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/buf.h: -------------------------------------------------------------------------------- 1 | struct buf { 2 | int flags; 3 | uint dev; 4 | uint sector; 5 | struct buf *prev; // LRU cache list 6 | struct buf *next; 7 | struct buf *qnext; // disk queue 8 | uchar data[512]; 9 | }; 10 | #define B_BUSY 0x1 // buffer is locked by some process 11 | #define B_VALID 0x2 // buffer has been read from disk 12 | #define B_DIRTY 0x4 // buffer needs to be written to disk 13 | 14 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/cat.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | cat(int fd) 9 | { 10 | int n; 11 | 12 | while((n = read(fd, buf, sizeof(buf))) > 0) 13 | write(1, buf, n); 14 | if(n < 0){ 15 | printf(1, "cat: read error\n"); 16 | exit(); 17 | } 18 | } 19 | 20 | int 21 | main(int argc, char *argv[]) 22 | { 23 | int fd, i; 24 | 25 | if(argc <= 1){ 26 | cat(0); 27 | exit(); 28 | } 29 | 30 | for(i = 1; i < argc; i++){ 31 | if((fd = open(argv[i], 0)) < 0){ 32 | printf(1, "cat: cannot open %s\n", argv[i]); 33 | exit(); 34 | } 35 | cat(fd); 36 | close(fd); 37 | } 38 | exit(); 39 | } 40 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/cuth: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | $| = 1; 4 | 5 | sub writefile($@){ 6 | my ($file, @lines) = @_; 7 | 8 | sleep(1); 9 | open(F, ">$file") || die "open >$file: $!"; 10 | print F @lines; 11 | close(F); 12 | } 13 | 14 | # Cut out #include lines that don't contribute anything. 15 | for($i=0; $i<@ARGV; $i++){ 16 | $file = $ARGV[$i]; 17 | if(!open(F, $file)){ 18 | print STDERR "open $file: $!\n"; 19 | next; 20 | } 21 | @lines = ; 22 | close(F); 23 | 24 | $obj = "$file.o"; 25 | $obj =~ s/\.c\.o$/.o/; 26 | system("touch $file"); 27 | 28 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 29 | print STDERR "make $obj failed: $rv\n"; 30 | next; 31 | } 32 | 33 | system("cp $file =$file"); 34 | for($j=@lines-1; $j>=0; $j--){ 35 | if($lines[$j] =~ /^#include/){ 36 | $old = $lines[$j]; 37 | $lines[$j] = "/* CUT-H */\n"; 38 | writefile($file, @lines); 39 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 40 | $lines[$j] = $old; 41 | }else{ 42 | print STDERR "$file $old"; 43 | } 44 | } 45 | } 46 | writefile($file, grep {!/CUT-H/} @lines); 47 | system("rm =$file"); 48 | } 49 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/echo.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | for(i = 1; i < argc; i++) 11 | printf(1, "%s%s", argv[i], i+1 < argc ? " " : "\n"); 12 | exit(); 13 | } 14 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/elf.h: -------------------------------------------------------------------------------- 1 | // Format of an ELF executable file 2 | 3 | #define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian 4 | 5 | // File header 6 | struct elfhdr { 7 | uint magic; // must equal ELF_MAGIC 8 | uchar elf[12]; 9 | ushort type; 10 | ushort machine; 11 | uint version; 12 | uint entry; 13 | uint phoff; 14 | uint shoff; 15 | uint flags; 16 | ushort ehsize; 17 | ushort phentsize; 18 | ushort phnum; 19 | ushort shentsize; 20 | ushort shnum; 21 | ushort shstrndx; 22 | }; 23 | 24 | // Program section header 25 | struct proghdr { 26 | uint type; 27 | uint off; 28 | uint vaddr; 29 | uint paddr; 30 | uint filesz; 31 | uint memsz; 32 | uint flags; 33 | uint align; 34 | }; 35 | 36 | // Values for Proghdr type 37 | #define ELF_PROG_LOAD 1 38 | 39 | // Flag bits for Proghdr flags 40 | #define ELF_PROG_FLAG_EXEC 1 41 | #define ELF_PROG_FLAG_WRITE 2 42 | #define ELF_PROG_FLAG_READ 4 43 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/fcntl.h: -------------------------------------------------------------------------------- 1 | #define O_RDONLY 0x000 2 | #define O_WRONLY 0x001 3 | #define O_RDWR 0x002 4 | #define O_CREATE 0x200 5 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/file.h: -------------------------------------------------------------------------------- 1 | struct file { 2 | enum { FD_NONE, FD_PIPE, FD_INODE } type; 3 | int ref; // reference count 4 | char readable; 5 | char writable; 6 | struct pipe *pipe; 7 | struct inode *ip; 8 | uint off; 9 | }; 10 | 11 | 12 | // in-memory copy of an inode 13 | struct inode { 14 | uint dev; // Device number 15 | uint inum; // Inode number 16 | int ref; // Reference count 17 | int flags; // I_BUSY, I_VALID 18 | 19 | short type; // copy of disk inode 20 | short major; 21 | short minor; 22 | short nlink; 23 | uint size; 24 | uint addrs[NDIRECT+3]; 25 | }; 26 | #define I_BUSY 0x1 27 | #define I_VALID 0x2 28 | 29 | // table mapping major device number to 30 | // device functions 31 | struct devsw { 32 | int (*read)(struct inode*, char*, int); 33 | int (*write)(struct inode*, char*, int); 34 | }; 35 | 36 | extern struct devsw devsw[]; 37 | 38 | #define CONSOLE 1 39 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/forktest.c: -------------------------------------------------------------------------------- 1 | // Test that fork fails gracefully. 2 | // Tiny executable so that the limit can be filling the proc table. 3 | 4 | #include "types.h" 5 | #include "stat.h" 6 | #include "user.h" 7 | 8 | #define N 1000 9 | 10 | void 11 | printf(int fd, char *s, ...) 12 | { 13 | write(fd, s, strlen(s)); 14 | } 15 | 16 | void 17 | forktest(void) 18 | { 19 | int n, pid; 20 | 21 | printf(1, "fork test\n"); 22 | 23 | for(n=0; n 0; n--){ 37 | if(wait() < 0){ 38 | printf(1, "wait stopped early\n"); 39 | exit(); 40 | } 41 | } 42 | 43 | if(wait() != -1){ 44 | printf(1, "wait got too many\n"); 45 | exit(); 46 | } 47 | 48 | printf(1, "fork test OK\n"); 49 | } 50 | 51 | int 52 | main(void) 53 | { 54 | forktest(); 55 | exit(); 56 | } 57 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/init.c: -------------------------------------------------------------------------------- 1 | // init: The initial user-level program 2 | 3 | #include "types.h" 4 | #include "stat.h" 5 | #include "user.h" 6 | #include "fcntl.h" 7 | 8 | char *argv[] = { "sh", 0 }; 9 | 10 | int 11 | main(void) 12 | { 13 | int pid, wpid; 14 | 15 | if(open("console", O_RDWR) < 0){ 16 | mknod("console", 1, 1); 17 | open("console", O_RDWR); 18 | } 19 | dup(0); // stdout 20 | dup(0); // stderr 21 | 22 | for(;;){ 23 | printf(1, "init: starting sh\n"); 24 | pid = fork(); 25 | if(pid < 0){ 26 | printf(1, "init: fork failed\n"); 27 | exit(); 28 | } 29 | if(pid == 0){ 30 | exec("sh", argv); 31 | printf(1, "init: exec sh failed\n"); 32 | exit(); 33 | } 34 | while((wpid=wait()) >= 0 && wpid != pid) 35 | printf(1, "zombie!\n"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/initcode.S: -------------------------------------------------------------------------------- 1 | # Initial process execs /init. 2 | 3 | #include "syscall.h" 4 | #include "traps.h" 5 | 6 | 7 | # exec(init, argv) 8 | .globl start 9 | start: 10 | pushl $argv 11 | pushl $init 12 | pushl $0 // where caller pc would be 13 | movl $SYS_exec, %eax 14 | int $T_SYSCALL 15 | 16 | # for(;;) exit(); 17 | exit: 18 | movl $SYS_exit, %eax 19 | int $T_SYSCALL 20 | jmp exit 21 | 22 | # char init[] = "/init\0"; 23 | init: 24 | .string "/init\0" 25 | 26 | # char *argv[] = { init, 0 }; 27 | .p2align 2 28 | argv: 29 | .long init 30 | .long 0 31 | 32 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/kbd.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "x86.h" 3 | #include "defs.h" 4 | #include "kbd.h" 5 | 6 | int 7 | kbdgetc(void) 8 | { 9 | static uint shift; 10 | static uchar *charcode[4] = { 11 | normalmap, shiftmap, ctlmap, ctlmap 12 | }; 13 | uint st, data, c; 14 | 15 | st = inb(KBSTATP); 16 | if((st & KBS_DIB) == 0) 17 | return -1; 18 | data = inb(KBDATAP); 19 | 20 | if(data == 0xE0){ 21 | shift |= E0ESC; 22 | return 0; 23 | } else if(data & 0x80){ 24 | // Key released 25 | data = (shift & E0ESC ? data : data & 0x7F); 26 | shift &= ~(shiftcode[data] | E0ESC); 27 | return 0; 28 | } else if(shift & E0ESC){ 29 | // Last character was an E0 escape; or with 0x80 30 | data |= 0x80; 31 | shift &= ~E0ESC; 32 | } 33 | 34 | shift |= shiftcode[data]; 35 | shift ^= togglecode[data]; 36 | c = charcode[shift & (CTL | SHIFT)][data]; 37 | if(shift & CAPSLOCK){ 38 | if('a' <= c && c <= 'z') 39 | c += 'A' - 'a'; 40 | else if('A' <= c && c <= 'Z') 41 | c += 'a' - 'A'; 42 | } 43 | return c; 44 | } 45 | 46 | void 47 | kbdintr(void) 48 | { 49 | consoleintr(kbdgetc); 50 | } 51 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/kill.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char **argv) 7 | { 8 | int i; 9 | 10 | if(argc < 1){ 11 | printf(2, "usage: kill pid...\n"); 12 | exit(); 13 | } 14 | for(i=1; i; 17 | for($i=0; $i<@lines; $i+=50){ 18 | print "\n\n"; 19 | ++$page; 20 | print "$now $h Page $page\n"; 21 | print "\n\n"; 22 | for($j=$i; $j<@lines && $j<$i +50; $j++){ 23 | $lines[$j] =~ s!//DOC.*!!; 24 | print $lines[$j]; 25 | } 26 | for(; $j<$i+50; $j++){ 27 | print "\n"; 28 | } 29 | $sheet = ""; 30 | if($lines[$i] =~ /^([0-9][0-9])[0-9][0-9] /){ 31 | $sheet = "Sheet $1"; 32 | } 33 | print "\n\n"; 34 | print "$sheet\n"; 35 | print "\n\n"; 36 | } 37 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/printpcs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Decode the symbols from a panic EIP list 4 | 5 | # Find a working addr2line 6 | for p in i386-jos-elf-addr2line addr2line; do 7 | if which $p 2>&1 >/dev/null && \ 8 | $p -h 2>&1 | grep -q '\belf32-i386\b'; then 9 | break 10 | fi 11 | done 12 | 13 | # Enable as much pretty-printing as this addr2line can do 14 | $p $($p -h | grep ' -[aipsf] ' | awk '{print $1}') -e kernel "$@" 15 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/rm.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | if(argc < 2){ 11 | printf(2, "Usage: rm files...\n"); 12 | exit(); 13 | } 14 | 15 | for(i = 1; i < argc; i++){ 16 | if(unlink(argv[i]) < 0){ 17 | printf(2, "rm: %s failed to delete\n", argv[i]); 18 | break; 19 | } 20 | } 21 | 22 | exit(); 23 | } 24 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/runoff.list: -------------------------------------------------------------------------------- 1 | # basic headers 2 | types.h 3 | param.h 4 | memlayout.h 5 | defs.h 6 | x86.h 7 | asm.h 8 | mmu.h 9 | elf.h 10 | 11 | # entering xv6 12 | entry.S 13 | entryother.S 14 | main.c 15 | 16 | # locks 17 | spinlock.h 18 | spinlock.c 19 | 20 | # processes 21 | vm.c 22 | proc.h 23 | proc.c 24 | swtch.S 25 | kalloc.c 26 | 27 | # system calls 28 | traps.h 29 | vectors.pl 30 | trapasm.S 31 | trap.c 32 | syscall.h 33 | syscall.c 34 | sysproc.c 35 | 36 | # file system 37 | buf.h 38 | fcntl.h 39 | stat.h 40 | fs.h 41 | file.h 42 | ide.c 43 | bio.c 44 | log.c 45 | fs.c 46 | file.c 47 | sysfile.c 48 | exec.c 49 | 50 | # pipes 51 | pipe.c 52 | 53 | # string operations 54 | string.c 55 | 56 | # low-level hardware 57 | mp.h 58 | mp.c 59 | lapic.c 60 | ioapic.c 61 | picirq.c 62 | kbd.h 63 | kbd.c 64 | console.c 65 | timer.c 66 | uart.c 67 | 68 | # user-level 69 | initcode.S 70 | usys.S 71 | init.c 72 | sh.c 73 | 74 | # bootloader 75 | bootasm.S 76 | bootmain.c 77 | 78 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/show1: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | runoff1 "$@" | pr.pl -h "xv6/$@" | mpage -m50t50b -o -bLetter -T -t -2 -FLucidaSans-Typewriter83 -L60 >x.ps; gv --swap x.ps 4 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/sign.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; 4 | 5 | $n = sysread(SIG, $buf, 1000); 6 | 7 | if($n > 510){ 8 | print STDERR "boot block too large: $n bytes (max 510)\n"; 9 | exit 1; 10 | } 11 | 12 | print STDERR "boot block is $n bytes (max 510)\n"; 13 | 14 | $buf .= "\0" x (510-$n); 15 | $buf .= "\x55\xAA"; 16 | 17 | open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; 18 | print SIG $buf; 19 | close SIG; 20 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/spinlock.h: -------------------------------------------------------------------------------- 1 | // Mutual exclusion lock. 2 | struct spinlock { 3 | uint locked; // Is the lock held? 4 | 5 | // For debugging: 6 | char *name; // Name of lock. 7 | struct cpu *cpu; // The cpu holding the lock. 8 | uint pcs[10]; // The call stack (an array of program counters) 9 | // that locked the lock. 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/spinp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# != 1 ] || [ ! -f "$1" ]; then 4 | echo 'usage: spinp file.p' 1>&2 5 | exit 1 6 | fi 7 | 8 | rm -f $1.trail 9 | spin -a $1 || exit 1 10 | cc -DSAFETY -DREACH -DMEMLIM=500 -o pan pan.c 11 | pan -i 12 | rm pan.* pan 13 | if [ -f $1.trail ]; then 14 | spin -t -p $1 15 | fi 16 | 17 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/stat.h: -------------------------------------------------------------------------------- 1 | #define T_DIR 1 // Directory 2 | #define T_FILE 2 // File 3 | #define T_DEV 3 // Device 4 | 5 | struct stat { 6 | short type; // Type of file 7 | int dev; // File system's disk device 8 | uint ino; // Inode number 9 | short nlink; // Number of links to file 10 | uint size; // Size of file in bytes 11 | }; 12 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/swtch.S: -------------------------------------------------------------------------------- 1 | # Context switch 2 | # 3 | # void swtch(struct context **old, struct context *new); 4 | # 5 | # Save current register context in old 6 | # and then load register context from new. 7 | 8 | .globl swtch 9 | swtch: 10 | movl 4(%esp), %eax 11 | movl 8(%esp), %edx 12 | 13 | # Save old callee-save registers 14 | pushl %ebp 15 | pushl %ebx 16 | pushl %esi 17 | pushl %edi 18 | 19 | # Switch stacks 20 | movl %esp, (%eax) 21 | movl %edx, %esp 22 | 23 | # Load new callee-save registers 24 | popl %edi 25 | popl %esi 26 | popl %ebx 27 | popl %ebp 28 | ret 29 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/syscall.h: -------------------------------------------------------------------------------- 1 | // System call numbers 2 | #define SYS_fork 1 3 | #define SYS_exit 2 4 | #define SYS_wait 3 5 | #define SYS_pipe 4 6 | #define SYS_read 5 7 | #define SYS_kill 6 8 | #define SYS_exec 7 9 | #define SYS_fstat 8 10 | #define SYS_chdir 9 11 | #define SYS_dup 10 12 | #define SYS_getpid 11 13 | #define SYS_sbrk 12 14 | #define SYS_sleep 13 15 | #define SYS_uptime 14 16 | #define SYS_open 15 17 | #define SYS_write 16 18 | #define SYS_mknod 17 19 | #define SYS_unlink 18 20 | #define SYS_link 19 21 | #define SYS_mkdir 20 22 | #define SYS_close 21 23 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/timer.c: -------------------------------------------------------------------------------- 1 | // Intel 8253/8254/82C54 Programmable Interval Timer (PIT). 2 | // Only used on uniprocessors; 3 | // SMP machines use the local APIC timer. 4 | 5 | #include "types.h" 6 | #include "defs.h" 7 | #include "traps.h" 8 | #include "x86.h" 9 | 10 | #define IO_TIMER1 0x040 // 8253 Timer #1 11 | 12 | // Frequency of all three count-down timers; 13 | // (TIMER_FREQ/freq) is the appropriate count 14 | // to generate a frequency of freq Hz. 15 | 16 | #define TIMER_FREQ 1193182 17 | #define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) 18 | 19 | #define TIMER_MODE (IO_TIMER1 + 3) // timer mode port 20 | #define TIMER_SEL0 0x00 // select counter 0 21 | #define TIMER_RATEGEN 0x04 // mode 2, rate generator 22 | #define TIMER_16BIT 0x30 // r/w counter 16 bits, LSB first 23 | 24 | void 25 | timerinit(void) 26 | { 27 | // Interrupt 100 times/sec. 28 | outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 29 | outb(IO_TIMER1, TIMER_DIV(100) % 256); 30 | outb(IO_TIMER1, TIMER_DIV(100) / 256); 31 | picenable(IRQ_TIMER); 32 | } 33 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/toc.ftr: -------------------------------------------------------------------------------- 1 | 2 | 3 | The source listing is preceded by a cross-reference that lists every defined 4 | constant, struct, global variable, and function in xv6. Each entry gives, 5 | on the same line as the name, the line number (or, in a few cases, numbers) 6 | where the name is defined. Successive lines in an entry list the line 7 | numbers where the name is used. For example, this entry: 8 | 9 | swtch 2658 10 | 0374 2428 2466 2657 2658 11 | 12 | indicates that swtch is defined on line 2658 and is mentioned on five lines 13 | on sheets 03, 24, and 26. 14 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/toc.hdr: -------------------------------------------------------------------------------- 1 | The numbers to the left of the file names in the table are sheet numbers. 2 | The source code has been printed in a double column format with fifty 3 | lines per column, giving one hundred lines per sheet (or page). 4 | Thus there is a convenient relationship between line numbers and sheet numbers. 5 | 6 | 7 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/trapasm.S: -------------------------------------------------------------------------------- 1 | #include "mmu.h" 2 | 3 | # vectors.S sends all traps here. 4 | .globl alltraps 5 | alltraps: 6 | # Build trap frame. 7 | pushl %ds 8 | pushl %es 9 | pushl %fs 10 | pushl %gs 11 | pushal 12 | 13 | # Set up data and per-cpu segments. 14 | movw $(SEG_KDATA<<3), %ax 15 | movw %ax, %ds 16 | movw %ax, %es 17 | movw $(SEG_KCPU<<3), %ax 18 | movw %ax, %fs 19 | movw %ax, %gs 20 | 21 | # Call trap(tf), where tf=%esp 22 | pushl %esp 23 | call trap 24 | addl $4, %esp 25 | 26 | # Return falls through to trapret... 27 | .globl trapret 28 | trapret: 29 | popal 30 | popl %gs 31 | popl %fs 32 | popl %es 33 | popl %ds 34 | addl $0x8, %esp # trapno and errcode 35 | iret 36 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/types.h: -------------------------------------------------------------------------------- 1 | typedef unsigned int uint; 2 | typedef unsigned short ushort; 3 | typedef unsigned char uchar; 4 | typedef uint pde_t; 5 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/user.h: -------------------------------------------------------------------------------- 1 | struct stat; 2 | 3 | // system calls 4 | int fork(void); 5 | int exit(void) __attribute__((noreturn)); 6 | int wait(void); 7 | int pipe(int*); 8 | int write(int, void*, int); 9 | int read(int, void*, int); 10 | int close(int); 11 | int kill(int); 12 | int exec(char*, char**); 13 | int open(char*, int); 14 | int mknod(char*, short, short); 15 | int unlink(char*); 16 | int fstat(int fd, struct stat*); 17 | int link(char*, char*); 18 | int mkdir(char*); 19 | int chdir(char*); 20 | int dup(int); 21 | int getpid(void); 22 | char* sbrk(int); 23 | int sleep(int); 24 | int uptime(void); 25 | 26 | // ulib.c 27 | int stat(char*, struct stat*); 28 | char* strcpy(char*, char*); 29 | void *memmove(void*, void*, int); 30 | char* strchr(const char*, char c); 31 | int strcmp(const char*, const char*); 32 | void printf(int, char*, ...); 33 | char* gets(char*, int max); 34 | uint strlen(char*); 35 | void* memset(void*, int, uint); 36 | void* malloc(uint); 37 | void free(void*); 38 | int atoi(const char*); 39 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/usys.S: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | #include "traps.h" 3 | 4 | #define SYSCALL(name) \ 5 | .globl name; \ 6 | name: \ 7 | movl $SYS_ ## name, %eax; \ 8 | int $T_SYSCALL; \ 9 | ret 10 | 11 | SYSCALL(fork) 12 | SYSCALL(exit) 13 | SYSCALL(wait) 14 | SYSCALL(pipe) 15 | SYSCALL(read) 16 | SYSCALL(write) 17 | SYSCALL(close) 18 | SYSCALL(kill) 19 | SYSCALL(exec) 20 | SYSCALL(open) 21 | SYSCALL(mknod) 22 | SYSCALL(unlink) 23 | SYSCALL(fstat) 24 | SYSCALL(link) 25 | SYSCALL(mkdir) 26 | SYSCALL(chdir) 27 | SYSCALL(dup) 28 | SYSCALL(getpid) 29 | SYSCALL(sbrk) 30 | SYSCALL(sleep) 31 | SYSCALL(uptime) 32 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/vectors.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # Generate vectors.S, the trap/interrupt entry points. 4 | # There has to be one entry point per interrupt number 5 | # since otherwise there's no way for trap() to discover 6 | # the interrupt number. 7 | 8 | print "# generated by vectors.pl - do not edit\n"; 9 | print "# handlers\n"; 10 | print ".globl alltraps\n"; 11 | for(my $i = 0; $i < 256; $i++){ 12 | print ".globl vector$i\n"; 13 | print "vector$i:\n"; 14 | if(!($i == 8 || ($i >= 10 && $i <= 14) || $i == 17)){ 15 | print " pushl \$0\n"; 16 | } 17 | print " pushl \$$i\n"; 18 | print " jmp alltraps\n"; 19 | } 20 | 21 | print "\n# vector table\n"; 22 | print ".data\n"; 23 | print ".globl vectors\n"; 24 | print "vectors:\n"; 25 | for(my $i = 0; $i < 256; $i++){ 26 | print " .long vector$i\n"; 27 | } 28 | 29 | # sample output: 30 | # # handlers 31 | # .globl alltraps 32 | # .globl vector0 33 | # vector0: 34 | # pushl $0 35 | # pushl $0 36 | # jmp alltraps 37 | # ... 38 | # 39 | # # vector table 40 | # .data 41 | # .globl vectors 42 | # vectors: 43 | # .long vector0 44 | # .long vector1 45 | # .long vector2 46 | # ... 47 | 48 | -------------------------------------------------------------------------------- /6 - Filesystem - Triply Indirect/wc.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | wc(int fd, char *name) 9 | { 10 | int i, n; 11 | int l, w, c, inword; 12 | 13 | l = w = c = 0; 14 | inword = 0; 15 | while((n = read(fd, buf, sizeof(buf))) > 0){ 16 | for(i=0; i 0) 12 | sleep(5); // Let child exit before parent. 13 | exit(); 14 | } 15 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/BUGS: -------------------------------------------------------------------------------- 1 | formatting: 2 | need to fix PAGEBREAK mechanism 3 | 4 | sh: 5 | can't always runcmd in child -- breaks cd. 6 | maybe should hard-code PATH=/ ? 7 | 8 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/asm.h: -------------------------------------------------------------------------------- 1 | // 2 | // assembler macros to create x86 segments 3 | // 4 | 5 | #define SEG_NULLASM \ 6 | .word 0, 0; \ 7 | .byte 0, 0, 0, 0 8 | 9 | // The 0xC0 means the limit is in 4096-byte units 10 | // and (for executable segments) 32-bit mode. 11 | #define SEG_ASM(type,base,lim) \ 12 | .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ 13 | .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ 14 | (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) 15 | 16 | #define STA_X 0x8 // Executable segment 17 | #define STA_E 0x4 // Expand down (non-executable segments) 18 | #define STA_C 0x4 // Conforming code segment (executable only) 19 | #define STA_W 0x2 // Writeable (non-executable segments) 20 | #define STA_R 0x2 // Readable (executable segments) 21 | #define STA_A 0x1 // Accessed 22 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/buf.h: -------------------------------------------------------------------------------- 1 | struct buf { 2 | int flags; 3 | uint dev; 4 | uint blockno; 5 | struct buf *prev; // LRU cache list 6 | struct buf *next; 7 | struct buf *qnext; // disk queue 8 | uchar data[512]; 9 | }; 10 | #define B_BUSY 0x1 // buffer is locked by some process 11 | #define B_VALID 0x2 // buffer has been read from disk 12 | #define B_DIRTY 0x4 // buffer needs to be written to disk 13 | 14 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/cat.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | cat(int fd) 9 | { 10 | int n; 11 | 12 | while((n = read(fd, buf, sizeof(buf))) > 0) 13 | write(1, buf, n); 14 | if(n < 0){ 15 | printf(1, "cat: read error\n"); 16 | exit(); 17 | } 18 | } 19 | 20 | int 21 | main(int argc, char *argv[]) 22 | { 23 | int fd, i; 24 | 25 | if(argc <= 1){ 26 | cat(0); 27 | exit(); 28 | } 29 | 30 | for(i = 1; i < argc; i++){ 31 | if((fd = open(argv[i], 0)) < 0){ 32 | printf(1, "cat: cannot open %s\n", argv[i]); 33 | exit(); 34 | } 35 | cat(fd); 36 | close(fd); 37 | } 38 | exit(); 39 | } 40 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/cuth: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | $| = 1; 4 | 5 | sub writefile($@){ 6 | my ($file, @lines) = @_; 7 | 8 | sleep(1); 9 | open(F, ">$file") || die "open >$file: $!"; 10 | print F @lines; 11 | close(F); 12 | } 13 | 14 | # Cut out #include lines that don't contribute anything. 15 | for($i=0; $i<@ARGV; $i++){ 16 | $file = $ARGV[$i]; 17 | if(!open(F, $file)){ 18 | print STDERR "open $file: $!\n"; 19 | next; 20 | } 21 | @lines = ; 22 | close(F); 23 | 24 | $obj = "$file.o"; 25 | $obj =~ s/\.c\.o$/.o/; 26 | system("touch $file"); 27 | 28 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 29 | print STDERR "make $obj failed: $rv\n"; 30 | next; 31 | } 32 | 33 | system("cp $file =$file"); 34 | for($j=@lines-1; $j>=0; $j--){ 35 | if($lines[$j] =~ /^#include/){ 36 | $old = $lines[$j]; 37 | $lines[$j] = "/* CUT-H */\n"; 38 | writefile($file, @lines); 39 | if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ 40 | $lines[$j] = $old; 41 | }else{ 42 | print STDERR "$file $old"; 43 | } 44 | } 45 | } 46 | writefile($file, grep {!/CUT-H/} @lines); 47 | system("rm =$file"); 48 | } 49 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/echo.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | for(i = 1; i < argc; i++) 11 | printf(1, "%s%s", argv[i], i+1 < argc ? " " : "\n"); 12 | exit(); 13 | } 14 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/elf.h: -------------------------------------------------------------------------------- 1 | // Format of an ELF executable file 2 | 3 | #define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian 4 | 5 | // File header 6 | struct elfhdr { 7 | uint magic; // must equal ELF_MAGIC 8 | uchar elf[12]; 9 | ushort type; 10 | ushort machine; 11 | uint version; 12 | uint entry; 13 | uint phoff; 14 | uint shoff; 15 | uint flags; 16 | ushort ehsize; 17 | ushort phentsize; 18 | ushort phnum; 19 | ushort shentsize; 20 | ushort shnum; 21 | ushort shstrndx; 22 | }; 23 | 24 | // Program section header 25 | struct proghdr { 26 | uint type; 27 | uint off; 28 | uint vaddr; 29 | uint paddr; 30 | uint filesz; 31 | uint memsz; 32 | uint flags; 33 | uint align; 34 | }; 35 | 36 | // Values for Proghdr type 37 | #define ELF_PROG_LOAD 1 38 | 39 | // Flag bits for Proghdr flags 40 | #define ELF_PROG_FLAG_EXEC 1 41 | #define ELF_PROG_FLAG_WRITE 2 42 | #define ELF_PROG_FLAG_READ 4 43 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/fcntl.h: -------------------------------------------------------------------------------- 1 | #define O_RDONLY 0x000 2 | #define O_WRONLY 0x001 3 | #define O_RDWR 0x002 4 | #define O_CREATE 0x200 5 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/file.h: -------------------------------------------------------------------------------- 1 | struct file { 2 | enum { FD_NONE, FD_PIPE, FD_INODE } type; 3 | int ref; // reference count 4 | char readable; 5 | char writable; 6 | struct pipe *pipe; 7 | struct inode *ip; 8 | uint off; 9 | }; 10 | 11 | 12 | // in-memory copy of an inode 13 | struct inode { 14 | uint dev; // Device number 15 | uint inum; // Inode number 16 | int ref; // Reference count 17 | int flags; // I_BUSY, I_VALID 18 | 19 | short type; // copy of disk inode 20 | short major; 21 | short minor; 22 | short nlink; 23 | uint size; 24 | uint addrs[NDIRECT+1]; 25 | }; 26 | #define I_BUSY 0x1 27 | #define I_VALID 0x2 28 | 29 | // table mapping major device number to 30 | // device functions 31 | struct devsw { 32 | int (*read)(struct inode*, char*, int); 33 | int (*write)(struct inode*, char*, int); 34 | }; 35 | 36 | extern struct devsw devsw[]; 37 | 38 | #define CONSOLE 1 39 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/forktest.c: -------------------------------------------------------------------------------- 1 | // Test that fork fails gracefully. 2 | // Tiny executable so that the limit can be filling the proc table. 3 | 4 | #include "types.h" 5 | #include "stat.h" 6 | #include "user.h" 7 | 8 | #define N 1000 9 | 10 | void 11 | printf(int fd, char *s, ...) 12 | { 13 | write(fd, s, strlen(s)); 14 | } 15 | 16 | void 17 | forktest(void) 18 | { 19 | int n, pid; 20 | 21 | printf(1, "fork test\n"); 22 | 23 | for(n=0; n 0; n--){ 37 | if(wait() < 0){ 38 | printf(1, "wait stopped early\n"); 39 | exit(); 40 | } 41 | } 42 | 43 | if(wait() != -1){ 44 | printf(1, "wait got too many\n"); 45 | exit(); 46 | } 47 | 48 | printf(1, "fork test OK\n"); 49 | } 50 | 51 | int 52 | main(void) 53 | { 54 | forktest(); 55 | exit(); 56 | } 57 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/init.c: -------------------------------------------------------------------------------- 1 | // init: The initial user-level program 2 | 3 | #include "types.h" 4 | #include "stat.h" 5 | #include "user.h" 6 | #include "fcntl.h" 7 | 8 | char *argv[] = { "sh", 0 }; 9 | 10 | int 11 | main(void) 12 | { 13 | int pid, wpid; 14 | 15 | if(open("console", O_RDWR) < 0){ 16 | mknod("console", 1, 1); 17 | open("console", O_RDWR); 18 | } 19 | dup(0); // stdout 20 | dup(0); // stderr 21 | 22 | for(;;){ 23 | printf(1, "init: starting sh\n"); 24 | pid = fork(); 25 | if(pid < 0){ 26 | printf(1, "init: fork failed\n"); 27 | exit(); 28 | } 29 | if(pid == 0){ 30 | exec("sh", argv); 31 | printf(1, "init: exec sh failed\n"); 32 | exit(); 33 | } 34 | while((wpid=wait()) >= 0 && wpid != pid) 35 | printf(1, "zombie!\n"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/initcode.S: -------------------------------------------------------------------------------- 1 | # Initial process execs /init. 2 | 3 | #include "syscall.h" 4 | #include "traps.h" 5 | 6 | 7 | # exec(init, argv) 8 | .globl start 9 | start: 10 | pushl $argv 11 | pushl $init 12 | pushl $0 // where caller pc would be 13 | movl $SYS_exec, %eax 14 | int $T_SYSCALL 15 | 16 | # for(;;) exit(); 17 | exit: 18 | movl $SYS_exit, %eax 19 | int $T_SYSCALL 20 | jmp exit 21 | 22 | # char init[] = "/init\0"; 23 | init: 24 | .string "/init\0" 25 | 26 | # char *argv[] = { init, 0 }; 27 | .p2align 2 28 | argv: 29 | .long init 30 | .long 0 31 | 32 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/kbd.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "x86.h" 3 | #include "defs.h" 4 | #include "kbd.h" 5 | 6 | int 7 | kbdgetc(void) 8 | { 9 | static uint shift; 10 | static uchar *charcode[4] = { 11 | normalmap, shiftmap, ctlmap, ctlmap 12 | }; 13 | uint st, data, c; 14 | 15 | st = inb(KBSTATP); 16 | if((st & KBS_DIB) == 0) 17 | return -1; 18 | data = inb(KBDATAP); 19 | 20 | if(data == 0xE0){ 21 | shift |= E0ESC; 22 | return 0; 23 | } else if(data & 0x80){ 24 | // Key released 25 | data = (shift & E0ESC ? data : data & 0x7F); 26 | shift &= ~(shiftcode[data] | E0ESC); 27 | return 0; 28 | } else if(shift & E0ESC){ 29 | // Last character was an E0 escape; or with 0x80 30 | data |= 0x80; 31 | shift &= ~E0ESC; 32 | } 33 | 34 | shift |= shiftcode[data]; 35 | shift ^= togglecode[data]; 36 | c = charcode[shift & (CTL | SHIFT)][data]; 37 | if(shift & CAPSLOCK){ 38 | if('a' <= c && c <= 'z') 39 | c += 'A' - 'a'; 40 | else if('A' <= c && c <= 'Z') 41 | c += 'a' - 'A'; 42 | } 43 | return c; 44 | } 45 | 46 | void 47 | kbdintr(void) 48 | { 49 | consoleintr(kbdgetc); 50 | } 51 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/kill.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char **argv) 7 | { 8 | int i; 9 | 10 | if(argc < 1){ 11 | printf(2, "usage: kill pid...\n"); 12 | exit(); 13 | } 14 | for(i=1; i; 17 | for($i=0; $i<@lines; $i+=50){ 18 | print "\n\n"; 19 | ++$page; 20 | print "$now $h Page $page\n"; 21 | print "\n\n"; 22 | for($j=$i; $j<@lines && $j<$i +50; $j++){ 23 | $lines[$j] =~ s!//DOC.*!!; 24 | print $lines[$j]; 25 | } 26 | for(; $j<$i+50; $j++){ 27 | print "\n"; 28 | } 29 | $sheet = ""; 30 | if($lines[$i] =~ /^([0-9][0-9])[0-9][0-9] /){ 31 | $sheet = "Sheet $1"; 32 | } 33 | print "\n\n"; 34 | print "$sheet\n"; 35 | print "\n\n"; 36 | } 37 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/printpcs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Decode the symbols from a panic EIP list 4 | 5 | # Find a working addr2line 6 | for p in i386-jos-elf-addr2line addr2line; do 7 | if which $p 2>&1 >/dev/null && \ 8 | $p -h 2>&1 | grep -q '\belf32-i386\b'; then 9 | break 10 | fi 11 | done 12 | 13 | # Enable as much pretty-printing as this addr2line can do 14 | $p $($p -h | grep ' -[aipsf] ' | awk '{print $1}') -e kernel "$@" 15 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/rm.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | int 6 | main(int argc, char *argv[]) 7 | { 8 | int i; 9 | 10 | if(argc < 2){ 11 | printf(2, "Usage: rm files...\n"); 12 | exit(); 13 | } 14 | 15 | for(i = 1; i < argc; i++){ 16 | if(unlink(argv[i]) < 0){ 17 | printf(2, "rm: %s failed to delete\n", argv[i]); 18 | break; 19 | } 20 | } 21 | 22 | exit(); 23 | } 24 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/runoff.list: -------------------------------------------------------------------------------- 1 | # basic headers 2 | types.h 3 | param.h 4 | memlayout.h 5 | defs.h 6 | x86.h 7 | asm.h 8 | mmu.h 9 | elf.h 10 | 11 | # entering xv6 12 | entry.S 13 | entryother.S 14 | main.c 15 | 16 | # locks 17 | spinlock.h 18 | spinlock.c 19 | 20 | # processes 21 | vm.c 22 | proc.h 23 | proc.c 24 | swtch.S 25 | kalloc.c 26 | 27 | # system calls 28 | traps.h 29 | vectors.pl 30 | trapasm.S 31 | trap.c 32 | syscall.h 33 | syscall.c 34 | sysproc.c 35 | 36 | # file system 37 | buf.h 38 | fcntl.h 39 | stat.h 40 | fs.h 41 | file.h 42 | ide.c 43 | bio.c 44 | log.c 45 | fs.c 46 | file.c 47 | sysfile.c 48 | exec.c 49 | 50 | # pipes 51 | pipe.c 52 | 53 | # string operations 54 | string.c 55 | 56 | # low-level hardware 57 | mp.h 58 | mp.c 59 | lapic.c 60 | ioapic.c 61 | picirq.c 62 | kbd.h 63 | kbd.c 64 | console.c 65 | timer.c 66 | uart.c 67 | 68 | # user-level 69 | initcode.S 70 | usys.S 71 | init.c 72 | sh.c 73 | 74 | # bootloader 75 | bootasm.S 76 | bootmain.c 77 | 78 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/show1: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | runoff1 "$@" | pr.pl -h "xv6/$@" | mpage -m50t50b -o -bLetter -T -t -2 -FLucidaSans-Typewriter83 -L60 >x.ps; gv --swap x.ps 4 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/sign.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; 4 | 5 | $n = sysread(SIG, $buf, 1000); 6 | 7 | if($n > 510){ 8 | print STDERR "boot block too large: $n bytes (max 510)\n"; 9 | exit 1; 10 | } 11 | 12 | print STDERR "boot block is $n bytes (max 510)\n"; 13 | 14 | $buf .= "\0" x (510-$n); 15 | $buf .= "\x55\xAA"; 16 | 17 | open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; 18 | print SIG $buf; 19 | close SIG; 20 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/spinlock.h: -------------------------------------------------------------------------------- 1 | // Mutual exclusion lock. 2 | struct spinlock { 3 | uint locked; // Is the lock held? 4 | 5 | // For debugging: 6 | char *name; // Name of lock. 7 | struct cpu *cpu; // The cpu holding the lock. 8 | uint pcs[10]; // The call stack (an array of program counters) 9 | // that locked the lock. 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/spinp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# != 1 ] || [ ! -f "$1" ]; then 4 | echo 'usage: spinp file.p' 1>&2 5 | exit 1 6 | fi 7 | 8 | rm -f $1.trail 9 | spin -a $1 || exit 1 10 | cc -DSAFETY -DREACH -DMEMLIM=500 -o pan pan.c 11 | pan -i 12 | rm pan.* pan 13 | if [ -f $1.trail ]; then 14 | spin -t -p $1 15 | fi 16 | 17 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/stat.h: -------------------------------------------------------------------------------- 1 | #define T_DIR 1 // Directory 2 | #define T_FILE 2 // File 3 | #define T_DEV 3 // Device 4 | 5 | struct stat { 6 | short type; // Type of file 7 | int dev; // File system's disk device 8 | uint ino; // Inode number 9 | short nlink; // Number of links to file 10 | uint size; // Size of file in bytes 11 | }; 12 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/swtch.S: -------------------------------------------------------------------------------- 1 | # Context switch 2 | # 3 | # void swtch(struct context **old, struct context *new); 4 | # 5 | # Save current register context in old 6 | # and then load register context from new. 7 | 8 | .globl swtch 9 | swtch: 10 | movl 4(%esp), %eax 11 | movl 8(%esp), %edx 12 | 13 | # Save old callee-save registers 14 | pushl %ebp 15 | pushl %ebx 16 | pushl %esi 17 | pushl %edi 18 | 19 | # Switch stacks 20 | movl %esp, (%eax) 21 | movl %edx, %esp 22 | 23 | # Load new callee-save registers 24 | popl %edi 25 | popl %esi 26 | popl %ebx 27 | popl %ebp 28 | ret 29 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/syscall.h: -------------------------------------------------------------------------------- 1 | // System call numbers 2 | #define SYS_fork 1 3 | #define SYS_exit 2 4 | #define SYS_wait 3 5 | #define SYS_pipe 4 6 | #define SYS_read 5 7 | #define SYS_kill 6 8 | #define SYS_exec 7 9 | #define SYS_fstat 8 10 | #define SYS_chdir 9 11 | #define SYS_dup 10 12 | #define SYS_getpid 11 13 | #define SYS_sbrk 12 14 | #define SYS_sleep 13 15 | #define SYS_uptime 14 16 | #define SYS_open 15 17 | #define SYS_write 16 18 | #define SYS_mknod 17 19 | #define SYS_unlink 18 20 | #define SYS_link 19 21 | #define SYS_mkdir 20 22 | #define SYS_close 21 23 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/timer.c: -------------------------------------------------------------------------------- 1 | // Intel 8253/8254/82C54 Programmable Interval Timer (PIT). 2 | // Only used on uniprocessors; 3 | // SMP machines use the local APIC timer. 4 | 5 | #include "types.h" 6 | #include "defs.h" 7 | #include "traps.h" 8 | #include "x86.h" 9 | 10 | #define IO_TIMER1 0x040 // 8253 Timer #1 11 | 12 | // Frequency of all three count-down timers; 13 | // (TIMER_FREQ/freq) is the appropriate count 14 | // to generate a frequency of freq Hz. 15 | 16 | #define TIMER_FREQ 1193182 17 | #define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) 18 | 19 | #define TIMER_MODE (IO_TIMER1 + 3) // timer mode port 20 | #define TIMER_SEL0 0x00 // select counter 0 21 | #define TIMER_RATEGEN 0x04 // mode 2, rate generator 22 | #define TIMER_16BIT 0x30 // r/w counter 16 bits, LSB first 23 | 24 | void 25 | timerinit(void) 26 | { 27 | // Interrupt 100 times/sec. 28 | outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); 29 | outb(IO_TIMER1, TIMER_DIV(100) % 256); 30 | outb(IO_TIMER1, TIMER_DIV(100) / 256); 31 | picenable(IRQ_TIMER); 32 | } 33 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/toc.ftr: -------------------------------------------------------------------------------- 1 | 2 | 3 | The source listing is preceded by a cross-reference that lists every defined 4 | constant, struct, global variable, and function in xv6. Each entry gives, 5 | on the same line as the name, the line number (or, in a few cases, numbers) 6 | where the name is defined. Successive lines in an entry list the line 7 | numbers where the name is used. For example, this entry: 8 | 9 | swtch 2658 10 | 0374 2428 2466 2657 2658 11 | 12 | indicates that swtch is defined on line 2658 and is mentioned on five lines 13 | on sheets 03, 24, and 26. 14 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/toc.hdr: -------------------------------------------------------------------------------- 1 | The numbers to the left of the file names in the table are sheet numbers. 2 | The source code has been printed in a double column format with fifty 3 | lines per column, giving one hundred lines per sheet (or page). 4 | Thus there is a convenient relationship between line numbers and sheet numbers. 5 | 6 | 7 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/trapasm.S: -------------------------------------------------------------------------------- 1 | #include "mmu.h" 2 | 3 | # vectors.S sends all traps here. 4 | .globl alltraps 5 | alltraps: 6 | # Build trap frame. 7 | pushl %ds 8 | pushl %es 9 | pushl %fs 10 | pushl %gs 11 | pushal 12 | 13 | # Set up data and per-cpu segments. 14 | movw $(SEG_KDATA<<3), %ax 15 | movw %ax, %ds 16 | movw %ax, %es 17 | movw $(SEG_KCPU<<3), %ax 18 | movw %ax, %fs 19 | movw %ax, %gs 20 | 21 | # Call trap(tf), where tf=%esp 22 | pushl %esp 23 | call trap 24 | addl $4, %esp 25 | 26 | # Return falls through to trapret... 27 | .globl trapret 28 | trapret: 29 | popal 30 | popl %gs 31 | popl %fs 32 | popl %es 33 | popl %ds 34 | addl $0x8, %esp # trapno and errcode 35 | iret 36 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/types.h: -------------------------------------------------------------------------------- 1 | typedef unsigned int uint; 2 | typedef unsigned short ushort; 3 | typedef unsigned char uchar; 4 | typedef uint pde_t; 5 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/user.h: -------------------------------------------------------------------------------- 1 | struct stat; 2 | 3 | // system calls 4 | int fork(void); 5 | int exit(void) __attribute__((noreturn)); 6 | int wait(void); 7 | int pipe(int*); 8 | int write(int, void*, int); 9 | int read(int, void*, int); 10 | int close(int); 11 | int kill(int); 12 | int exec(char*, char**); 13 | int open(char*, int); 14 | int mknod(char*, short, short); 15 | int unlink(char*); 16 | int fstat(int fd, struct stat*); 17 | int link(char*, char*); 18 | int mkdir(char*); 19 | int chdir(char*); 20 | int dup(int); 21 | int getpid(void); 22 | char* sbrk(int); 23 | int sleep(int); 24 | int uptime(void); 25 | 26 | // ulib.c 27 | int stat(char*, struct stat*); 28 | char* strcpy(char*, char*); 29 | void *memmove(void*, void*, int); 30 | char* strchr(const char*, char c); 31 | int strcmp(const char*, const char*); 32 | void printf(int, char*, ...); 33 | char* gets(char*, int max); 34 | uint strlen(char*); 35 | void* memset(void*, int, uint); 36 | void* malloc(uint); 37 | void free(void*); 38 | int atoi(const char*); 39 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/usys.S: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | #include "traps.h" 3 | 4 | #define SYSCALL(name) \ 5 | .globl name; \ 6 | name: \ 7 | movl $SYS_ ## name, %eax; \ 8 | int $T_SYSCALL; \ 9 | ret 10 | 11 | SYSCALL(fork) 12 | SYSCALL(exit) 13 | SYSCALL(wait) 14 | SYSCALL(pipe) 15 | SYSCALL(read) 16 | SYSCALL(write) 17 | SYSCALL(close) 18 | SYSCALL(kill) 19 | SYSCALL(exec) 20 | SYSCALL(open) 21 | SYSCALL(mknod) 22 | SYSCALL(unlink) 23 | SYSCALL(fstat) 24 | SYSCALL(link) 25 | SYSCALL(mkdir) 26 | SYSCALL(chdir) 27 | SYSCALL(dup) 28 | SYSCALL(getpid) 29 | SYSCALL(sbrk) 30 | SYSCALL(sleep) 31 | SYSCALL(uptime) 32 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/vectors.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # Generate vectors.S, the trap/interrupt entry points. 4 | # There has to be one entry point per interrupt number 5 | # since otherwise there's no way for trap() to discover 6 | # the interrupt number. 7 | 8 | print "# generated by vectors.pl - do not edit\n"; 9 | print "# handlers\n"; 10 | print ".globl alltraps\n"; 11 | for(my $i = 0; $i < 256; $i++){ 12 | print ".globl vector$i\n"; 13 | print "vector$i:\n"; 14 | if(!($i == 8 || ($i >= 10 && $i <= 14) || $i == 17)){ 15 | print " pushl \$0\n"; 16 | } 17 | print " pushl \$$i\n"; 18 | print " jmp alltraps\n"; 19 | } 20 | 21 | print "\n# vector table\n"; 22 | print ".data\n"; 23 | print ".globl vectors\n"; 24 | print "vectors:\n"; 25 | for(my $i = 0; $i < 256; $i++){ 26 | print " .long vector$i\n"; 27 | } 28 | 29 | # sample output: 30 | # # handlers 31 | # .globl alltraps 32 | # .globl vector0 33 | # vector0: 34 | # pushl $0 35 | # pushl $0 36 | # jmp alltraps 37 | # ... 38 | # 39 | # # vector table 40 | # .data 41 | # .globl vectors 42 | # vectors: 43 | # .long vector0 44 | # .long vector1 45 | # .long vector2 46 | # ... 47 | 48 | -------------------------------------------------------------------------------- /7 - Filesystem - Fast File System/wc.c: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "stat.h" 3 | #include "user.h" 4 | 5 | char buf[512]; 6 | 7 | void 8 | wc(int fd, char *name) 9 | { 10 | int i, n; 11 | int l, w, c, inword; 12 | 13 | l = w = c = 0; 14 | inword = 0; 15 | while((n = read(fd, buf, sizeof(buf))) > 0){ 16 | for(i=0; i 0) 12 | sleep(5); // Let child exit before parent. 13 | exit(); 14 | } 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Warren S. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------