From 33ebdf5cfdc0547f93e9db34f20e515f9f3389a5 Mon Sep 17 00:00:00 2001 From: ginger88895 Date: Sun, 31 Mar 2019 04:08:58 +0800 Subject: [PATCH] Init --- Makefile | 54 + README | 270 ++++ ag/AutoGrader.java | 279 ++++ ag/BoatGrader.java | 81 + ag/package.html | 3 + bin/nachos | 15 + machine/ArrayFile.java | 44 + machine/Coff.java | 151 ++ machine/CoffSection.java | 228 +++ machine/Config.java | 283 ++++ machine/ElevatorBank.java | 620 ++++++++ machine/ElevatorControllerInterface.java | 40 + machine/ElevatorControls.java | 96 ++ machine/ElevatorEvent.java | 33 + machine/ElevatorGui.java | 424 ++++++ machine/ElevatorTest.java | 158 ++ machine/FileSystem.java | 35 + machine/Interrupt.java | 253 ++++ machine/Kernel.java | 45 + machine/Lib.java | 638 ++++++++ machine/Machine.java | 489 ++++++ machine/MalformedPacketException.java | 14 + machine/NetworkLink.java | 329 ++++ machine/OpenFile.java | 141 ++ machine/OpenFileWithPosition.java | 58 + machine/Packet.java | 106 ++ machine/Processor.java | 1321 +++++++++++++++++ machine/RiderControls.java | 142 ++ machine/RiderEvent.java | 33 + machine/RiderInterface.java | 51 + machine/SerialConsole.java | 49 + machine/StandardConsole.java | 161 ++ machine/Stats.java | 100 ++ machine/StubFileSystem.java | 216 +++ machine/TCB.java | 414 ++++++ machine/Timer.java | 89 ++ machine/TranslationEntry.java | 81 + machine/package.html | 3 + network/MailMessage.java | 105 ++ network/NetKernel.java | 123 ++ network/NetProcess.java | 46 + network/PostOffice.java | 134 ++ network/package.html | 3 + proj1/Makefile | 3 + proj1/nachos.conf | 10 + proj1/nachos/ag/AutoGrader.class | Bin 0 -> 6204 bytes proj1/nachos/ag/BoatGrader.class | Bin 0 -> 1642 bytes proj1/nachos/machine/ArrayFile.class | Bin 0 -> 1070 bytes .../machine/AssertionFailureError.class | Bin 0 -> 444 bytes proj1/nachos/machine/Coff.class | Bin 0 -> 2861 bytes proj1/nachos/machine/CoffSection.class | Bin 0 -> 3855 bytes proj1/nachos/machine/Config.class | Bin 0 -> 5449 bytes proj1/nachos/machine/ElevatorBank$1.class | Bin 0 -> 620 bytes .../ElevatorBank$ElevatorManager$1.class | Bin 0 -> 934 bytes .../ElevatorBank$ElevatorManager.class | Bin 0 -> 5643 bytes .../machine/ElevatorBank$ElevatorState.class | Bin 0 -> 2906 bytes .../machine/ElevatorBank$RiderState$1.class | Bin 0 -> 894 bytes .../machine/ElevatorBank$RiderState.class | Bin 0 -> 6335 bytes proj1/nachos/machine/ElevatorBank.class | Bin 0 -> 5507 bytes .../machine/ElevatorControllerInterface.class | Bin 0 -> 407 bytes proj1/nachos/machine/ElevatorControls.class | Bin 0 -> 457 bytes proj1/nachos/machine/ElevatorEvent.class | Bin 0 -> 685 bytes .../machine/ElevatorGui$ElevatorShaft.class | Bin 0 -> 4322 bytes proj1/nachos/machine/ElevatorGui$Floor.class | Bin 0 -> 3226 bytes proj1/nachos/machine/ElevatorGui.class | Bin 0 -> 4355 bytes proj1/nachos/machine/ElevatorTest$1.class | Bin 0 -> 214 bytes .../ElevatorTest$ElevatorController$1.class | Bin 0 -> 829 bytes .../ElevatorTest$ElevatorController.class | Bin 0 -> 2499 bytes .../nachos/machine/ElevatorTest$Rider$1.class | Bin 0 -> 750 bytes proj1/nachos/machine/ElevatorTest$Rider.class | Bin 0 -> 2507 bytes proj1/nachos/machine/ElevatorTest.class | Bin 0 -> 1010 bytes proj1/nachos/machine/FileSystem.class | Bin 0 -> 221 bytes proj1/nachos/machine/Interrupt$1.class | Bin 0 -> 205 bytes .../Interrupt$InterruptPrivilege.class | Bin 0 -> 1311 bytes .../machine/Interrupt$PendingInterrupt.class | Bin 0 -> 1117 bytes proj1/nachos/machine/Interrupt.class | Bin 0 -> 5082 bytes proj1/nachos/machine/Kernel.class | Bin 0 -> 576 bytes proj1/nachos/machine/Lib.class | Bin 0 -> 9304 bytes proj1/nachos/machine/Machine$1.class | Bin 0 -> 684 bytes .../machine/Machine$MachinePrivilege.class | Bin 0 -> 913 bytes proj1/nachos/machine/Machine.class | Bin 0 -> 12258 bytes .../machine/MalformedPacketException.class | Bin 0 -> 334 bytes proj1/nachos/machine/NetworkLink$1.class | Bin 0 -> 647 bytes proj1/nachos/machine/NetworkLink$2.class | Bin 0 -> 647 bytes proj1/nachos/machine/NetworkLink$3.class | Bin 0 -> 647 bytes proj1/nachos/machine/NetworkLink$4.class | Bin 0 -> 630 bytes proj1/nachos/machine/NetworkLink.class | Bin 0 -> 6424 bytes proj1/nachos/machine/OpenFile.class | Bin 0 -> 1495 bytes .../nachos/machine/OpenFileWithPosition.class | Bin 0 -> 1188 bytes proj1/nachos/machine/Packet.class | Bin 0 -> 1288 bytes proj1/nachos/machine/Processor$1.class | Bin 0 -> 205 bytes .../machine/Processor$Instruction.class | Bin 0 -> 8426 bytes proj1/nachos/machine/Processor$Mips.class | Bin 0 -> 5751 bytes .../machine/Processor$MipsException.class | Bin 0 -> 1956 bytes .../Processor$ProcessorPrivilege.class | Bin 0 -> 922 bytes proj1/nachos/machine/Processor.class | Bin 0 -> 10477 bytes proj1/nachos/machine/RiderControls.class | Bin 0 -> 569 bytes proj1/nachos/machine/RiderEvent.class | Bin 0 -> 632 bytes proj1/nachos/machine/RiderInterface.class | Bin 0 -> 343 bytes proj1/nachos/machine/SerialConsole.class | Bin 0 -> 251 bytes proj1/nachos/machine/StandardConsole$1.class | Bin 0 -> 671 bytes proj1/nachos/machine/StandardConsole$2.class | Bin 0 -> 671 bytes proj1/nachos/machine/StandardConsole.class | Bin 0 -> 3593 bytes proj1/nachos/machine/Stats.class | Bin 0 -> 1881 bytes .../machine/StubFileSystem$FileRemover.class | Bin 0 -> 771 bytes .../StubFileSystem$StubOpenFile$1.class | Bin 0 -> 1091 bytes .../machine/StubFileSystem$StubOpenFile.class | Bin 0 -> 3050 bytes proj1/nachos/machine/StubFileSystem.class | Bin 0 -> 3724 bytes proj1/nachos/machine/TCB$1.class | Bin 0 -> 600 bytes proj1/nachos/machine/TCB$2.class | Bin 0 -> 776 bytes proj1/nachos/machine/TCB$TCBPrivilege.class | Bin 0 -> 1112 bytes proj1/nachos/machine/TCB.class | Bin 0 -> 5106 bytes proj1/nachos/machine/Timer$1.class | Bin 0 -> 611 bytes proj1/nachos/machine/Timer$2.class | Bin 0 -> 906 bytes proj1/nachos/machine/Timer.class | Bin 0 -> 2298 bytes proj1/nachos/machine/TranslationEntry.class | Bin 0 -> 866 bytes .../security/NachosSecurityManager$1.class | Bin 0 -> 755 bytes .../security/NachosSecurityManager$2.class | Bin 0 -> 848 bytes ...hosSecurityManager$PrivilegeProvider.class | Bin 0 -> 1992 bytes .../security/NachosSecurityManager.class | Bin 0 -> 7062 bytes .../Privilege$InterruptPrivilege.class | Bin 0 -> 303 bytes .../security/Privilege$MachinePrivilege.class | Bin 0 -> 270 bytes .../Privilege$ProcessorPrivilege.class | Bin 0 -> 243 bytes .../security/Privilege$TCBPrivilege.class | Bin 0 -> 288 bytes proj1/nachos/security/Privilege.class | Bin 0 -> 2304 bytes proj1/nachos/threads/Alarm$1.class | Bin 0 -> 577 bytes proj1/nachos/threads/Alarm.class | Bin 0 -> 940 bytes proj1/nachos/threads/Boat$1.class | Bin 0 -> 522 bytes proj1/nachos/threads/Boat.class | Bin 0 -> 1597 bytes proj1/nachos/threads/Communicator.class | Bin 0 -> 461 bytes proj1/nachos/threads/Condition.class | Bin 0 -> 1348 bytes proj1/nachos/threads/Condition2.class | Bin 0 -> 812 bytes proj1/nachos/threads/ElevatorController.class | Bin 0 -> 592 bytes proj1/nachos/threads/KThread$1.class | Bin 0 -> 601 bytes proj1/nachos/threads/KThread$2.class | Bin 0 -> 528 bytes proj1/nachos/threads/KThread$PingTest.class | Bin 0 -> 1066 bytes proj1/nachos/threads/KThread.class | Bin 0 -> 6255 bytes proj1/nachos/threads/Lock.class | Bin 0 -> 1591 bytes proj1/nachos/threads/LotteryScheduler.class | Bin 0 -> 465 bytes .../PriorityScheduler$PriorityQueue.class | Bin 0 -> 1654 bytes .../PriorityScheduler$ThreadState.class | Bin 0 -> 1342 bytes proj1/nachos/threads/PriorityScheduler.class | Bin 0 -> 2423 bytes proj1/nachos/threads/Rider.class | Bin 0 -> 559 bytes .../threads/RoundRobinScheduler$1.class | Bin 0 -> 235 bytes .../RoundRobinScheduler$FifoQueue.class | Bin 0 -> 2390 bytes .../nachos/threads/RoundRobinScheduler.class | Bin 0 -> 707 bytes proj1/nachos/threads/Scheduler.class | Bin 0 -> 1439 bytes proj1/nachos/threads/Semaphore$PingTest.class | Bin 0 -> 761 bytes proj1/nachos/threads/Semaphore.class | Bin 0 -> 1922 bytes proj1/nachos/threads/SynchList$PingTest.class | Bin 0 -> 816 bytes proj1/nachos/threads/SynchList.class | Bin 0 -> 1926 bytes proj1/nachos/threads/ThreadQueue.class | Bin 0 -> 426 bytes proj1/nachos/threads/ThreadedKernel.class | Bin 0 -> 2450 bytes proj2/Makefile | 3 + proj2/nachos.conf | 14 + proj3/Makefile | 3 + proj3/nachos.conf | 14 + proj4/Makefile | 3 + proj4/nachos.conf | 16 + security/NachosSecurityManager.java | 318 ++++ security/Privilege.java | 195 +++ security/package.html | 4 + test/Makefile | 59 + test/assert.c | 7 + test/assert.o | Bin 0 -> 876 bytes test/atoi.c | 15 + test/atoi.o | Bin 0 -> 776 bytes test/cat.c | 31 + test/cat.coff | Bin 0 -> 7020 bytes test/cat.o | Bin 0 -> 1212 bytes test/cp.c | 39 + test/cp.coff | Bin 0 -> 7112 bytes test/cp.o | Bin 0 -> 1376 bytes test/echo.c | 14 + test/echo.coff | Bin 0 -> 6924 bytes test/echo.o | Bin 0 -> 940 bytes test/halt.c | 20 + test/halt.coff | Bin 0 -> 2472 bytes test/halt.o | Bin 0 -> 756 bytes test/libnachos.a | Bin 0 -> 15112 bytes test/matmult.c | 36 + test/matmult.coff | Bin 0 -> 2728 bytes test/matmult.o | Bin 0 -> 1132 bytes test/memcpy.c | 10 + test/memcpy.o | Bin 0 -> 700 bytes test/memset.c | 10 + test/memset.o | Bin 0 -> 700 bytes test/mv.c | 40 + test/mv.coff | Bin 0 -> 7128 bytes test/mv.o | Bin 0 -> 1424 bytes test/printf.c | 184 +++ test/printf.o | Bin 0 -> 4584 bytes test/readline.c | 37 + test/readline.o | Bin 0 -> 1076 bytes test/rm.c | 18 + test/rm.coff | Bin 0 -> 6936 bytes test/rm.o | Bin 0 -> 992 bytes test/script | 15 + test/script_old | 12 + test/sh.c | 203 +++ test/sh.coff | Bin 0 -> 10468 bytes test/sh.o | Bin 0 -> 3440 bytes test/sort.c | 51 + test/sort.coff | Bin 0 -> 2784 bytes test/sort.o | Bin 0 -> 1136 bytes test/start.o | Bin 0 -> 2528 bytes test/start.s | 69 + test/stdarg.h | 205 +++ test/stdio.c | 18 + test/stdio.h | 40 + test/stdio.o | Bin 0 -> 1160 bytes test/stdlib.c | 1 + test/stdlib.h | 37 + test/strcat.c | 16 + test/strcat.o | Bin 0 -> 748 bytes test/strcmp.c | 14 + test/strcmp.o | Bin 0 -> 740 bytes test/strcpy.c | 15 + test/strcpy.o | Bin 0 -> 700 bytes test/strlen.c | 11 + test/strlen.o | Bin 0 -> 708 bytes test/strncmp.c | 20 + test/strncmp.o | Bin 0 -> 896 bytes test/syscall.h | 262 ++++ test/va-mips.h | 276 ++++ threads/Alarm.java | 53 + threads/Boat.java | 76 + threads/Communicator.java | 41 + threads/Condition.java | 114 ++ threads/Condition2.java | 58 + threads/ElevatorController.java | 38 + threads/KThread.java | 447 ++++++ threads/Lock.java | 79 + threads/LotteryScheduler.java | 48 + threads/PriorityScheduler.java | 261 ++++ threads/Rider.java | 52 + threads/RoundRobinScheduler.java | 84 ++ threads/Scheduler.java | 157 ++ threads/Semaphore.java | 104 ++ threads/SynchList.java | 88 ++ threads/ThreadQueue.java | 98 ++ threads/ThreadedKernel.java | 86 ++ threads/package.html | 3 + userprog/SynchConsole.java | 147 ++ userprog/UThread.java | 75 + userprog/UserKernel.java | 115 ++ userprog/UserProcess.java | 449 ++++++ userprog/package.html | 4 + vm/VMKernel.java | 51 + vm/VMProcess.java | 73 + vm/package.html | 4 + 251 files changed, 13131 insertions(+) create mode 100644 Makefile create mode 100644 README create mode 100644 ag/AutoGrader.java create mode 100644 ag/BoatGrader.java create mode 100644 ag/package.html create mode 100644 bin/nachos create mode 100644 machine/ArrayFile.java create mode 100644 machine/Coff.java create mode 100644 machine/CoffSection.java create mode 100644 machine/Config.java create mode 100644 machine/ElevatorBank.java create mode 100644 machine/ElevatorControllerInterface.java create mode 100644 machine/ElevatorControls.java create mode 100644 machine/ElevatorEvent.java create mode 100644 machine/ElevatorGui.java create mode 100644 machine/ElevatorTest.java create mode 100644 machine/FileSystem.java create mode 100644 machine/Interrupt.java create mode 100644 machine/Kernel.java create mode 100644 machine/Lib.java create mode 100644 machine/Machine.java create mode 100644 machine/MalformedPacketException.java create mode 100644 machine/NetworkLink.java create mode 100644 machine/OpenFile.java create mode 100644 machine/OpenFileWithPosition.java create mode 100644 machine/Packet.java create mode 100644 machine/Processor.java create mode 100644 machine/RiderControls.java create mode 100644 machine/RiderEvent.java create mode 100644 machine/RiderInterface.java create mode 100644 machine/SerialConsole.java create mode 100644 machine/StandardConsole.java create mode 100644 machine/Stats.java create mode 100644 machine/StubFileSystem.java create mode 100644 machine/TCB.java create mode 100644 machine/Timer.java create mode 100644 machine/TranslationEntry.java create mode 100644 machine/package.html create mode 100644 network/MailMessage.java create mode 100644 network/NetKernel.java create mode 100644 network/NetProcess.java create mode 100644 network/PostOffice.java create mode 100644 network/package.html create mode 100644 proj1/Makefile create mode 100644 proj1/nachos.conf create mode 100644 proj1/nachos/ag/AutoGrader.class create mode 100644 proj1/nachos/ag/BoatGrader.class create mode 100644 proj1/nachos/machine/ArrayFile.class create mode 100644 proj1/nachos/machine/AssertionFailureError.class create mode 100644 proj1/nachos/machine/Coff.class create mode 100644 proj1/nachos/machine/CoffSection.class create mode 100644 proj1/nachos/machine/Config.class create mode 100644 proj1/nachos/machine/ElevatorBank$1.class create mode 100644 proj1/nachos/machine/ElevatorBank$ElevatorManager$1.class create mode 100644 proj1/nachos/machine/ElevatorBank$ElevatorManager.class create mode 100644 proj1/nachos/machine/ElevatorBank$ElevatorState.class create mode 100644 proj1/nachos/machine/ElevatorBank$RiderState$1.class create mode 100644 proj1/nachos/machine/ElevatorBank$RiderState.class create mode 100644 proj1/nachos/machine/ElevatorBank.class create mode 100644 proj1/nachos/machine/ElevatorControllerInterface.class create mode 100644 proj1/nachos/machine/ElevatorControls.class create mode 100644 proj1/nachos/machine/ElevatorEvent.class create mode 100644 proj1/nachos/machine/ElevatorGui$ElevatorShaft.class create mode 100644 proj1/nachos/machine/ElevatorGui$Floor.class create mode 100644 proj1/nachos/machine/ElevatorGui.class create mode 100644 proj1/nachos/machine/ElevatorTest$1.class create mode 100644 proj1/nachos/machine/ElevatorTest$ElevatorController$1.class create mode 100644 proj1/nachos/machine/ElevatorTest$ElevatorController.class create mode 100644 proj1/nachos/machine/ElevatorTest$Rider$1.class create mode 100644 proj1/nachos/machine/ElevatorTest$Rider.class create mode 100644 proj1/nachos/machine/ElevatorTest.class create mode 100644 proj1/nachos/machine/FileSystem.class create mode 100644 proj1/nachos/machine/Interrupt$1.class create mode 100644 proj1/nachos/machine/Interrupt$InterruptPrivilege.class create mode 100644 proj1/nachos/machine/Interrupt$PendingInterrupt.class create mode 100644 proj1/nachos/machine/Interrupt.class create mode 100644 proj1/nachos/machine/Kernel.class create mode 100644 proj1/nachos/machine/Lib.class create mode 100644 proj1/nachos/machine/Machine$1.class create mode 100644 proj1/nachos/machine/Machine$MachinePrivilege.class create mode 100644 proj1/nachos/machine/Machine.class create mode 100644 proj1/nachos/machine/MalformedPacketException.class create mode 100644 proj1/nachos/machine/NetworkLink$1.class create mode 100644 proj1/nachos/machine/NetworkLink$2.class create mode 100644 proj1/nachos/machine/NetworkLink$3.class create mode 100644 proj1/nachos/machine/NetworkLink$4.class create mode 100644 proj1/nachos/machine/NetworkLink.class create mode 100644 proj1/nachos/machine/OpenFile.class create mode 100644 proj1/nachos/machine/OpenFileWithPosition.class create mode 100644 proj1/nachos/machine/Packet.class create mode 100644 proj1/nachos/machine/Processor$1.class create mode 100644 proj1/nachos/machine/Processor$Instruction.class create mode 100644 proj1/nachos/machine/Processor$Mips.class create mode 100644 proj1/nachos/machine/Processor$MipsException.class create mode 100644 proj1/nachos/machine/Processor$ProcessorPrivilege.class create mode 100644 proj1/nachos/machine/Processor.class create mode 100644 proj1/nachos/machine/RiderControls.class create mode 100644 proj1/nachos/machine/RiderEvent.class create mode 100644 proj1/nachos/machine/RiderInterface.class create mode 100644 proj1/nachos/machine/SerialConsole.class create mode 100644 proj1/nachos/machine/StandardConsole$1.class create mode 100644 proj1/nachos/machine/StandardConsole$2.class create mode 100644 proj1/nachos/machine/StandardConsole.class create mode 100644 proj1/nachos/machine/Stats.class create mode 100644 proj1/nachos/machine/StubFileSystem$FileRemover.class create mode 100644 proj1/nachos/machine/StubFileSystem$StubOpenFile$1.class create mode 100644 proj1/nachos/machine/StubFileSystem$StubOpenFile.class create mode 100644 proj1/nachos/machine/StubFileSystem.class create mode 100644 proj1/nachos/machine/TCB$1.class create mode 100644 proj1/nachos/machine/TCB$2.class create mode 100644 proj1/nachos/machine/TCB$TCBPrivilege.class create mode 100644 proj1/nachos/machine/TCB.class create mode 100644 proj1/nachos/machine/Timer$1.class create mode 100644 proj1/nachos/machine/Timer$2.class create mode 100644 proj1/nachos/machine/Timer.class create mode 100644 proj1/nachos/machine/TranslationEntry.class create mode 100644 proj1/nachos/security/NachosSecurityManager$1.class create mode 100644 proj1/nachos/security/NachosSecurityManager$2.class create mode 100644 proj1/nachos/security/NachosSecurityManager$PrivilegeProvider.class create mode 100644 proj1/nachos/security/NachosSecurityManager.class create mode 100644 proj1/nachos/security/Privilege$InterruptPrivilege.class create mode 100644 proj1/nachos/security/Privilege$MachinePrivilege.class create mode 100644 proj1/nachos/security/Privilege$ProcessorPrivilege.class create mode 100644 proj1/nachos/security/Privilege$TCBPrivilege.class create mode 100644 proj1/nachos/security/Privilege.class create mode 100644 proj1/nachos/threads/Alarm$1.class create mode 100644 proj1/nachos/threads/Alarm.class create mode 100644 proj1/nachos/threads/Boat$1.class create mode 100644 proj1/nachos/threads/Boat.class create mode 100644 proj1/nachos/threads/Communicator.class create mode 100644 proj1/nachos/threads/Condition.class create mode 100644 proj1/nachos/threads/Condition2.class create mode 100644 proj1/nachos/threads/ElevatorController.class create mode 100644 proj1/nachos/threads/KThread$1.class create mode 100644 proj1/nachos/threads/KThread$2.class create mode 100644 proj1/nachos/threads/KThread$PingTest.class create mode 100644 proj1/nachos/threads/KThread.class create mode 100644 proj1/nachos/threads/Lock.class create mode 100644 proj1/nachos/threads/LotteryScheduler.class create mode 100644 proj1/nachos/threads/PriorityScheduler$PriorityQueue.class create mode 100644 proj1/nachos/threads/PriorityScheduler$ThreadState.class create mode 100644 proj1/nachos/threads/PriorityScheduler.class create mode 100644 proj1/nachos/threads/Rider.class create mode 100644 proj1/nachos/threads/RoundRobinScheduler$1.class create mode 100644 proj1/nachos/threads/RoundRobinScheduler$FifoQueue.class create mode 100644 proj1/nachos/threads/RoundRobinScheduler.class create mode 100644 proj1/nachos/threads/Scheduler.class create mode 100644 proj1/nachos/threads/Semaphore$PingTest.class create mode 100644 proj1/nachos/threads/Semaphore.class create mode 100644 proj1/nachos/threads/SynchList$PingTest.class create mode 100644 proj1/nachos/threads/SynchList.class create mode 100644 proj1/nachos/threads/ThreadQueue.class create mode 100644 proj1/nachos/threads/ThreadedKernel.class create mode 100644 proj2/Makefile create mode 100644 proj2/nachos.conf create mode 100644 proj3/Makefile create mode 100644 proj3/nachos.conf create mode 100644 proj4/Makefile create mode 100644 proj4/nachos.conf create mode 100644 security/NachosSecurityManager.java create mode 100644 security/Privilege.java create mode 100644 security/package.html create mode 100644 test/Makefile create mode 100644 test/assert.c create mode 100644 test/assert.o create mode 100644 test/atoi.c create mode 100644 test/atoi.o create mode 100644 test/cat.c create mode 100644 test/cat.coff create mode 100644 test/cat.o create mode 100644 test/cp.c create mode 100644 test/cp.coff create mode 100644 test/cp.o create mode 100644 test/echo.c create mode 100644 test/echo.coff create mode 100644 test/echo.o create mode 100644 test/halt.c create mode 100644 test/halt.coff create mode 100644 test/halt.o create mode 100644 test/libnachos.a create mode 100644 test/matmult.c create mode 100644 test/matmult.coff create mode 100644 test/matmult.o create mode 100644 test/memcpy.c create mode 100644 test/memcpy.o create mode 100644 test/memset.c create mode 100644 test/memset.o create mode 100644 test/mv.c create mode 100644 test/mv.coff create mode 100644 test/mv.o create mode 100644 test/printf.c create mode 100644 test/printf.o create mode 100644 test/readline.c create mode 100644 test/readline.o create mode 100644 test/rm.c create mode 100644 test/rm.coff create mode 100644 test/rm.o create mode 100644 test/script create mode 100644 test/script_old create mode 100644 test/sh.c create mode 100644 test/sh.coff create mode 100644 test/sh.o create mode 100644 test/sort.c create mode 100644 test/sort.coff create mode 100644 test/sort.o create mode 100644 test/start.o create mode 100644 test/start.s create mode 100644 test/stdarg.h create mode 100644 test/stdio.c create mode 100644 test/stdio.h create mode 100644 test/stdio.o create mode 100644 test/stdlib.c create mode 100644 test/stdlib.h create mode 100644 test/strcat.c create mode 100644 test/strcat.o create mode 100644 test/strcmp.c create mode 100644 test/strcmp.o create mode 100644 test/strcpy.c create mode 100644 test/strcpy.o create mode 100644 test/strlen.c create mode 100644 test/strlen.o create mode 100644 test/strncmp.c create mode 100644 test/strncmp.o create mode 100644 test/syscall.h create mode 100644 test/va-mips.h create mode 100644 threads/Alarm.java create mode 100644 threads/Boat.java create mode 100644 threads/Communicator.java create mode 100644 threads/Condition.java create mode 100644 threads/Condition2.java create mode 100644 threads/ElevatorController.java create mode 100644 threads/KThread.java create mode 100644 threads/Lock.java create mode 100644 threads/LotteryScheduler.java create mode 100644 threads/PriorityScheduler.java create mode 100644 threads/Rider.java create mode 100644 threads/RoundRobinScheduler.java create mode 100644 threads/Scheduler.java create mode 100644 threads/Semaphore.java create mode 100644 threads/SynchList.java create mode 100644 threads/ThreadQueue.java create mode 100644 threads/ThreadedKernel.java create mode 100644 threads/package.html create mode 100644 userprog/SynchConsole.java create mode 100644 userprog/UThread.java create mode 100644 userprog/UserKernel.java create mode 100644 userprog/UserProcess.java create mode 100644 userprog/package.html create mode 100644 vm/VMKernel.java create mode 100644 vm/VMProcess.java create mode 100644 vm/package.html diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e7cf883 --- /dev/null +++ b/Makefile @@ -0,0 +1,54 @@ +JAVADOCPARAMS = -doctitle "Nachos 5.0 Java" -protected \ + -link http://java.sun.com/j2se/1.5.0/docs/api/ + +machine = Lib Config Stats Machine TCB \ + Interrupt Timer \ + Processor TranslationEntry \ + SerialConsole StandardConsole \ + OpenFile OpenFileWithPosition ArrayFile FileSystem StubFileSystem \ + ElevatorBank ElevatorTest ElevatorGui \ + ElevatorControls ElevatorEvent ElevatorControllerInterface \ + RiderControls RiderEvent RiderInterface \ + Kernel Coff CoffSection \ + NetworkLink Packet MalformedPacketException + +security = Privilege NachosSecurityManager + +ag = AutoGrader BoatGrader + +threads = ThreadedKernel KThread Alarm \ + Scheduler ThreadQueue RoundRobinScheduler \ + Semaphore Lock Condition SynchList \ + Condition2 Communicator Rider ElevatorController \ + PriorityScheduler LotteryScheduler Boat + +userprog = UserKernel UThread UserProcess SynchConsole + +vm = VMKernel VMProcess + +network = NetKernel NetProcess PostOffice MailMessage + +ALLDIRS = machine security ag threads userprog vm network + +PACKAGES := $(patsubst %,nachos.%,$(ALLDIRS)) + +CLASSFILES := $(foreach dir,$(DIRS),$(patsubst %,nachos/$(dir)/%.class,$($(dir)))) + +.PHONY: all rmtemp clean doc hwdoc swdoc + +all: $(CLASSFILES) + +nachos/%.class: ../%.java + javac -classpath . -d . -sourcepath ../.. -g $< + +clean: + rm -f */*/*.class + +doc: + mkdir -p ../doc + javadoc $(JAVADOCPARAMS) -d ../doc -sourcepath .. $(PACKAGES) + +test: + cd ../test ; gmake + +ag: $(patsubst ../ag/%.java,nachos/ag/%.class,$(wildcard ../ag/*.java)) diff --git a/README b/README new file mode 100644 index 0000000..b0902f4 --- /dev/null +++ b/README @@ -0,0 +1,270 @@ + Nachos for Java README + +Welcome to Nachos for Java. We believe that working in Java rather than +C++ will greatly simplify the development process by preventing bugs +arising from memory management errors, and improving debugging support. + +Getting Nachos: + +Download nachos-java.tar.gz from the Projects section of the class +homepage at: + + http://www-inst.EECS.Berkeley.EDU/~cs162/ + +Unpack it with these commands: + + gunzip -c nachos-java.tar.gz | tar xf - + +Additional software: + +Nachos requires the Java Devlopment Kit, version 1.5 or later. This is +installed on all instructional machines in: + /usr/sww/lang/jdk-1.5.0_05 +To use this version of the JDK, be sure that + /usr/sww/lang/jdk-1.5.0_05/bin +is on your PATH. (This should be the case for all class accounts +already.) + +If you are working at home, you will need to download the JDK. +It is available from: + http://java.sun.com/j2se/1.5/ +Please DO NOT DOWNLOAD the JDK into your class account! Use the +preinstalled version instead. + +The build process for Nachos relies on GNU make. If you are running on +one of the instructional machines, be sure you run 'gmake', as 'make' +does not support all the features used. If you are running Linux, the +two are equivalent. If you are running Windows, you will need to +download and install a port. The most popular is the Cygnus toolkit, +available at: + + http://sources.redhat.com/cygwin/mirrors.html + +The Cygnus package includes ports of most common GNU utilities to +Windows. + +For project 2, you will need a MIPS cross compiler, which is a +specially compiled GCC which will run on one architecture (e.g. +Sparc) and produce files for the MIPS processor. These compilers +are already installed on the instructional machines, and are +available in the directory specified by the $ARCHDIR environment +variable. + +If you are working at home, you will need to get a cross-compiler +for yourself. Cross-compilers for Linux and Win32 will be available +from the CS162 Projects web page. Download the cross compiler +distribution and unpack it with the following command: + + gunzip -c mips-x86-linux-xgcc.tar.gz | tar xf - + +(Substitute the appropriate file name for mips-x86.linux-xgcc in the +above command.) You need to add the mips-x86.linux-xgcc directory to +your PATH, and set an environment variable ARCHDIR to point to this +directory. (Again, this has already been done for you on the +instructional machines.) + +Compiling Nachos: + +You should now have a directory called nachos, containing a Makefile, +this README, and a number of subdirectories. + +First, put the 'nachos/bin' directory on your PATH. This directory +contains the script 'nachos', which simply runs the Nachos code. + +To compile Nachos, go to the subdirectory for the project you wish +to compile (I will assume 'proj1/' for Project 1 in my examples), +and run: + + gmake + +This will compile those portions of Nachos which are relevant to the +project, and place the compiled .class files in the proj1/nachos +directory. + +You can now test Nachos from the proj1/ directory with: + + nachos + +You should see output resembling the following: + + nachos 5.0j initializing... config interrupt timer elevators user-check grader + *** thread 0 looped 0 times + *** thread 1 looped 0 times + *** thread 0 looped 1 times + *** thread 1 looped 1 times + *** thread 0 looped 2 times + *** thread 1 looped 2 times + *** thread 0 looped 3 times + *** thread 1 looped 3 times + *** thread 0 looped 4 times + *** thread 1 looped 4 times + Machine halting! + + Ticks: total 24750, kernel 24750, user 0 + Disk I/O: reads 0, writes 0 + Console I/O: reads 0, writes 0 + Paging: page faults 0, TLB misses 0 + Network I/O: received 0, sent 0 + +This is the correct output for the "bare bones" Nachos, without any of +the features you will add during the projects. + +If you are working on a project which runs user programs (projects 2-4), +you will also need to compile the MIPS test programs with: + + gmake test + +Command Line Arguments: + +For a summary of the command line arguments, run: + + nachos -h + +The commands are: + + -d + Enable some debug flags, e.g. -d ti + + -h + Print this help message. + + -s + Specify the seed for the random number generator + + -x + Specify a program that UserKernel.run() should execute, + instead of the value of the configuration variable + Kernel.shellProgram + + -z + print the copyright message + + -- + Specify an autograder class to use, instead of + nachos.ag.AutoGrader + + -# + Specify the argument string to pass to the autograder. + + -[] + Specifiy a config file to use, instead of nachos.conf + + +Nachos offers the following debug flags: + + c: COFF loader info + i: HW interrupt controller info + p: processor info + m: disassembly + M: more disassembly + t: thread info + a: process info (formerly "address space", hence a) + +To use multiple debug flags, clump them all together. For example, to +monitor coff info and process info, run: + + nachos -d ac + +nachos.conf: + +When Nachos starts, it reads in nachos.conf from the current +directory. It contains a bunch of keys and values, in the simple +format "key = value" with one key/value pair per line. To change the +default scheduler, default shell program, to change the amount of +memory the simulator provides, or to reduce network reliability, modify +this file. + +Machine.stubFileSystem: + Specifies whether the machine should provide a stub file system. A + stub file system just provides direct access to the test directory. + Since we're not doing the file system project, this should always + be true. + +Machine.processor: + Specifies whether the machine should provide a MIPS processor. In + the first project, we only run kernel code, so this is false. In + the other projects it should be true. + +Machine.console: + Specifies whether the machine should provide a console. Again, the + first project doesn't need it, but the rest of them do. + +Machine.disk: + Specifies whether the machine should provide a simulated disk. No + file system project, so this should always be false. + +ElevatorBank.allowElevatorGUI: + Normally true. When we grade, this will be false, to prevent + malicious students from running a GUI during grading. + +NachosSecurityManager.fullySecure: + Normally false. When we grade, this will be true, to enable + additional security checks. + +Kernel.kernel: + Specifies what kernel class to dynmically load. For proj1, this is + nachos.threads.ThreadedKernel. For proj2, this should be + nachos.userprog.UserKernel. For proj3, nachos.vm.VMKernel. For + proj4, nachos.network.NetKernel. + +Processor.usingTLB: + Specifies whether the MIPS processor provides a page table + interface or a TLB interface. In page table mode (proj2), the + processor accesses an arbitrarily large kernel data structure to do + address translation. In TLB mode (proj3 and proj4), the processor + maintains a small TLB (4 entries). + +Processor.numPhysPages: + The number of pages of physical memory. Each page is 1K. This is + normally 64, but we can lower it in proj3 to see whether projects + thrash or crash. + +Documentation: + +The JDK provides a command to create a set of HTML pages showing all +classes and methods in program. We will make these pages available on +the webpage, but you can create your own for your home machine by doing +the following (from the nachos/ directory): + + mkdir ../doc + gmake doc + +Troubleshooting: + +If you receive an error about "class not found exception", it may be +because you have not set the CLASSPATH environment variable. Add the +following to your .cshrc: + + setenv CLASSPATH . + +Credits: + +Nachos was originally written by Wayne A. Christopher, Steven J. +Procter, and Thomas E. Anderson. It incorporates the SPIM simulator +written by John Ousterhout. Nachos was rewritten in Java by Daniel +Hettena. + +Copyright: + +Copyright (c) 1992-2001 The Regents of the University of California. +All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose, without fee, and without written +agreement is hereby granted, provided that the above copyright notice +and the following two paragraphs appear in all copies of this +software. + +IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF +THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE +PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF +CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, +ENHANCEMENTS, OR MODIFICATIONS. + diff --git a/ag/AutoGrader.java b/ag/AutoGrader.java new file mode 100644 index 0000000..b81279c --- /dev/null +++ b/ag/AutoGrader.java @@ -0,0 +1,279 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.ag; + +import nachos.machine.*; +import nachos.security.*; +import nachos.threads.*; + +import java.util.Hashtable; +import java.util.StringTokenizer; + +/** + * The default autograder. Loads the kernel, and then tests it using + * Kernel.selfTest(). + */ +public class AutoGrader { + /** + * Allocate a new autograder. + */ + public AutoGrader() { + } + + /** + * Start this autograder. Extract the -# arguments, call + * init(), load and initialize the kernel, and call + * run(). + * + * @param privilege encapsulates privileged access to the Nachos + * machine. + */ + public void start(Privilege privilege) { + Lib.assertTrue(this.privilege == null, + "start() called multiple times"); + this.privilege = privilege; + + String[] args = Machine.getCommandLineArguments(); + + extractArguments(args); + + System.out.print(" grader"); + + init(); + + System.out.print("\n"); + + kernel = + (Kernel) Lib.constructObject(Config.getString("Kernel.kernel")); + kernel.initialize(args); + + run(); + } + + private void extractArguments(String[] args) { + String testArgsString = Config.getString("AutoGrader.testArgs"); + if (testArgsString == null) { + testArgsString = ""; + } + + for (int i=0; i 0 && arg.charAt(0) == '-') { + if (arg.equals("-#")) { + Lib.assertTrue(i < args.length, + "-# switch missing argument"); + testArgsString = args[i++]; + } + } + } + + StringTokenizer st = new StringTokenizer(testArgsString, ",\n\t\f\r"); + + while (st.hasMoreTokens()) { + StringTokenizer pair = new StringTokenizer(st.nextToken(), "="); + + Lib.assertTrue(pair.hasMoreTokens(), + "test argument missing key"); + String key = pair.nextToken(); + + Lib.assertTrue(pair.hasMoreTokens(), + "test argument missing value"); + String value = pair.nextToken(); + + testArgs.put(key, value); + } + } + + String getStringArgument(String key) { + String value = (String) testArgs.get(key); + Lib.assertTrue(value != null, + "getStringArgument(" + key + ") failed to find key"); + return value; + } + + int getIntegerArgument(String key) { + try { + return Integer.parseInt(getStringArgument(key)); + } + catch (NumberFormatException e) { + Lib.assertNotReached("getIntegerArgument(" + key + ") failed: " + + "value is not an integer"); + return 0; + } + } + + boolean getBooleanArgument(String key) { + String value = getStringArgument(key); + + if (value.equals("1") || value.toLowerCase().equals("true")) { + return true; + } + else if (value.equals("0") || value.toLowerCase().equals("false")) { + return false; + } + else { + Lib.assertNotReached("getBooleanArgument(" + key + ") failed: " + + "value is not a boolean"); + return false; + } + } + + long getTime() { + return privilege.stats.totalTicks; + } + + void targetLevel(int targetLevel) { + this.targetLevel = targetLevel; + } + + void level(int level) { + this.level++; + Lib.assertTrue(level == this.level, + "level() advanced more than one step: test jumped ahead"); + + if (level == targetLevel) + done(); + } + + private int level = 0, targetLevel = 0; + + void done() { + System.out.print("\nsuccess\n"); + privilege.exit(162); + } + + private Hashtable testArgs = + new Hashtable(); + + void init() { + } + + void run() { + kernel.selfTest(); + kernel.run(); + kernel.terminate(); + } + + Privilege privilege = null; + Kernel kernel; + + /** + * Notify the autograder that the specified thread is the idle thread. + * KThread.createIdleThread() must call this method before + * forking the idle thread. + * + * @param idleThread the idle thread. + */ + public void setIdleThread(KThread idleThread) { + } + + /** + * Notify the autograder that the specified thread has moved to the ready + * state. KThread.ready() must call this method before + * returning. + * + * @param thread the thread that has been added to the ready set. + */ + public void readyThread(KThread thread) { + } + + /** + * Notify the autograder that the specified thread is now running. + * KThread.restoreState() must call this method before + * returning. + * + * @param thread the thread that is now running. + */ + public void runningThread(KThread thread) { + privilege.tcb.associateThread(thread); + currentThread = thread; + } + + /** + * Notify the autograder that the current thread has finished. + * KThread.finish() must call this method before putting + * the thread to sleep and scheduling its TCB to be destroyed. + */ + public void finishingCurrentThread() { + privilege.tcb.authorizeDestroy(currentThread); + } + + /** + * Notify the autograder that a timer interrupt occurred and was handled by + * software if a timer interrupt handler was installed. Called by the + * hardware timer. + * + * @param privilege proves the authenticity of this call. + * @param time the actual time at which the timer interrupt was + * issued. + */ + public void timerInterrupt(Privilege privilege, long time) { + Lib.assertTrue(privilege == this.privilege, + "security violation"); + } + + /** + * Notify the autograder that a user program executed a syscall + * instruction. + * + * @param privilege proves the authenticity of this call. + * @return true if the kernel exception handler should be called. + */ + public boolean exceptionHandler(Privilege privilege) { + Lib.assertTrue(privilege == this.privilege, + "security violation"); + return true; + } + + /** + * Notify the autograder that Processor.run() was invoked. This + * can be used to simulate user programs. + * + * @param privilege proves the authenticity of this call. + */ + public void runProcessor(Privilege privilege) { + Lib.assertTrue(privilege == this.privilege, + "security violation"); + } + + /** + * Notify the autograder that a COFF loader is being constructed for the + * specified file. The autograder can use this to provide its own COFF + * loader, or return null to use the default loader. + * + * @param file the executable file being loaded. + * @return a loader to use in loading the file, or null to use + * the default. + */ + public Coff createLoader(OpenFile file) { + return null; + } + + /** + * Request permission to send a packet. The autograder can use this to drop + * packets very selectively. + * + * @param privilege proves the authenticity of this call. + * @return true if the packet should be sent. + */ + public boolean canSendPacket(Privilege privilege) { + Lib.assertTrue(privilege == this.privilege, + "security violation"); + return true; + } + + /** + * Request permission to receive a packet. The autograder can use this to + * drop packets very selectively. + * + * @param privilege proves the authenticity of this call. + * @return true if the packet should be delivered to the kernel. + */ + public boolean canReceivePacket(Privilege privilege) { + Lib.assertTrue(privilege == this.privilege, + "security violation"); + return true; + } + + private KThread currentThread; +} diff --git a/ag/BoatGrader.java b/ag/BoatGrader.java new file mode 100644 index 0000000..e642844 --- /dev/null +++ b/ag/BoatGrader.java @@ -0,0 +1,81 @@ +package nachos.ag; + +public class BoatGrader { + + /** + * BoatGrader consists of functions to be called to show that + * your solution is properly synchronized. This version simply + * prints messages to standard out, so that you can watch it. + * You cannot submit this file, as we will be using our own + * version of it during grading. + + * Note that this file includes all possible variants of how + * someone can get from one island to another. Inclusion in + * this class does not imply that any of the indicated actions + * are a good idea or even allowed. + */ + + //NEW ADDITION FOR 2014 + //MUST BE CALLED AT THE START OF CHILDITINERARY! + public void initializeChild(){ + System.out.println("A child has forked."); + } + + //NEW ADDITION FOR 2014 + //MUST BE CALLED AT THE START OF ADULTITINERARY! + public void initializeAdult(){ + System.out.println("An adult as forked."); + } + + /* ChildRowToMolokai should be called when a child pilots the boat + from Oahu to Molokai */ + public void ChildRowToMolokai() { + System.out.println("**Child rowing to Molokai."); + } + + /* ChildRowToOahu should be called when a child pilots the boat + from Molokai to Oahu*/ + public void ChildRowToOahu() { + System.out.println("**Child rowing to Oahu."); + } + + /* ChildRideToMolokai should be called when a child not piloting + the boat disembarks on Molokai */ + public void ChildRideToMolokai() { + System.out.println("**Child arrived on Molokai as a passenger."); + } + + /* ChildRideToOahu should be called when a child not piloting + the boat disembarks on Oahu */ + public void ChildRideToOahu() { + System.out.println("**Child arrived on Oahu as a passenger."); + } + + /* AdultRowToMolokai should be called when a adult pilots the boat + from Oahu to Molokai */ + public void AdultRowToMolokai() { + System.out.println("**Adult rowing to Molokai."); + } + + /* AdultRowToOahu should be called when a adult pilots the boat + from Molokai to Oahu */ + public void AdultRowToOahu() { + System.out.println("**Adult rowing to Oahu."); + } + + /* AdultRideToMolokai should be called when an adult not piloting + the boat disembarks on Molokai */ + public void AdultRideToMolokai() { + System.out.println("**Adult arrived on Molokai as a passenger."); + } + + /* AdultRideToOahu should be called when an adult not piloting + the boat disembarks on Oahu */ + public void AdultRideToOahu() { + System.out.println("**Adult arrived on Oahu as a passenger."); + } +} + + + + diff --git a/ag/package.html b/ag/package.html new file mode 100644 index 0000000..04aa1f6 --- /dev/null +++ b/ag/package.html @@ -0,0 +1,3 @@ + +Provides classes that can be used to automatically grade Nachos projects. + diff --git a/bin/nachos b/bin/nachos new file mode 100644 index 0000000..46c6bce --- /dev/null +++ b/bin/nachos @@ -0,0 +1,15 @@ +#!/bin/sh + +# Shell-script front-end to run Nachos. +# Simply sets terminal to a minimum of one byte to complete a read and +# disables character echo. Restores original terminal state on exit. + +onexit () { + stty $OLDSTTYSTATE +} + +OLDSTTYSTATE=`stty -g` +trap onexit 0 +stty -icanon min 1 -echo +java nachos.machine.Machine $* + diff --git a/machine/ArrayFile.java b/machine/ArrayFile.java new file mode 100644 index 0000000..e2133fa --- /dev/null +++ b/machine/ArrayFile.java @@ -0,0 +1,44 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +/** + * A read-only OpenFile backed by a byte array. + */ +public class ArrayFile extends OpenFileWithPosition { + /** + * Allocate a new ArrayFile. + * + * @param array the array backing this file. + */ + public ArrayFile(byte[] array) { + this.array = array; + } + + public int length() { + return array.length; + } + + public void close() { + array = null; + } + + public int read(int position, byte[] buf, int offset, int length) { + Lib.assertTrue(offset >= 0 && length >= 0 && offset+length <= buf.length); + + if (position < 0 || position >= array.length) + return 0; + + length = Math.min(length, array.length-position); + System.arraycopy(array, position, buf, offset, length); + + return length; + } + + public int write(int position, byte[] buf, int offset, int length) { + return 0; + } + + private byte[] array; +} + diff --git a/machine/Coff.java b/machine/Coff.java new file mode 100644 index 0000000..c25fedb --- /dev/null +++ b/machine/Coff.java @@ -0,0 +1,151 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import java.io.EOFException; + +/** + * A COFF (common object file format) loader. + */ +public class Coff { + /** + * Allocate a new Coff object. + */ + protected Coff() { + file = null; + entryPoint = 0; + sections = null; + } + + /** + * Load the COFF executable in the specified file. + * + *

+ * Notes: + *

    + *
  1. If the constructor returns successfully, the file becomes the + * property of this loader, and should not be accessed any further. + *
  2. The autograder expects this loader class to be used. Do not load + * sections through any other mechanism. + *
  3. This loader will verify that the file is backed by a file system, + * by asserting that read() operations take non-zero simulated time to + * complete. Do not supply a file backed by a simulated cache (the primary + * purpose of this restriction is to prevent sections from being loaded + * instantaneously while handling page faults). + *
+ * + * @param file the file containing the executable. + * @exception EOFException if the executable is corrupt. + */ + public Coff(OpenFile file) throws EOFException { + this.file = file; + + Coff coff = Machine.autoGrader().createLoader(file); + + if (coff != null) { + this.entryPoint = coff.entryPoint; + this.sections = coff.sections; + } + else { + byte[] headers = new byte[headerLength+aoutHeaderLength]; + + if (file.length() < headers.length) { + Lib.debug(dbgCoff, "\tfile is not executable"); + throw new EOFException(); + } + + Lib.strictReadFile(file, 0, headers, 0, headers.length); + + int magic = Lib.bytesToUnsignedShort(headers, 0); + int numSections = Lib.bytesToUnsignedShort(headers, 2); + int optionalHeaderLength = Lib.bytesToUnsignedShort(headers, 16); + int flags = Lib.bytesToUnsignedShort(headers, 18); + entryPoint = Lib.bytesToInt(headers, headerLength+16); + + if (magic != 0x0162) { + Lib.debug(dbgCoff, "\tincorrect magic number"); + throw new EOFException(); + } + if (numSections < 2 || numSections > 10) { + Lib.debug(dbgCoff, "\tbad section count"); + throw new EOFException(); + } + if ((flags & 0x0003) != 0x0003) { + Lib.debug(dbgCoff, "\tbad header flags"); + throw new EOFException(); + } + + int offset = headerLength + optionalHeaderLength; + + sections = new CoffSection[numSections]; + for (int s=0; s0 through getNumSections() - + * 1. + * + * @param sectionNumber the section to select. + * @return an object that can be used to access the specified section. + */ + public CoffSection getSection(int sectionNumber) { + Lib.assertTrue(sectionNumber >= 0 && sectionNumber < sections.length); + + return sections[sectionNumber]; + } + + /** + * Return the program entry point. This is the value that to which the PC + * register should be initialized to before running the program. + * + * @return the program entry point. + */ + public int getEntryPoint() { + Lib.assertTrue(file != null); + + return entryPoint; + } + + /** + * Close the executable file and release any resources allocated by this + * loader. + */ + public void close() { + file.close(); + + sections = null; + } + + private OpenFile file; + + /** The virtual address of the first instruction of the program. */ + protected int entryPoint; + /** The sections in this COFF executable. */ + protected CoffSection sections[]; + + private static final int headerLength = 20; + private static final int aoutHeaderLength = 28; + + private static final char dbgCoff = 'c'; +} diff --git a/machine/CoffSection.java b/machine/CoffSection.java new file mode 100644 index 0000000..2fb684d --- /dev/null +++ b/machine/CoffSection.java @@ -0,0 +1,228 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import nachos.security.*; + +import java.io.EOFException; +import java.util.Arrays; + +/** + * A CoffSection manages a single section within a COFF executable. + */ +public class CoffSection { + /** + * Allocate a new COFF section with the specified parameters. + * + * @param coff the COFF object to which this section belongs. + * @param name the COFF name of this section. + * @param executable true if this section contains code. + * @param readOnly true if this section is read-only. + * @param numPages the number of virtual pages in this section. + * @param firstVPN the first virtual page number used by this. + */ + protected CoffSection(Coff coff, String name, boolean executable, + boolean readOnly, int numPages, int firstVPN) { + this.coff = coff; + this.name = name; + this.executable = executable; + this.readOnly = readOnly; + this.numPages = numPages; + this.firstVPN = firstVPN; + + file = null; + size = 0; + contentOffset = 0; + initialized = true; + } + + /** + * Load a COFF section from an executable. + * + * @param file the file containing the executable. + * @param headerOffset the offset of the section header in the + * executable. + * + * @exception EOFException if an error occurs. + */ + public CoffSection(OpenFile file, Coff coff, + int headerOffset) throws EOFException { + this.file = file; + this.coff = coff; + + Lib.assertTrue(headerOffset >= 0); + if (headerOffset+headerLength > file.length()) { + Lib.debug(dbgCoffSection, "\tsection header truncated"); + throw new EOFException(); + } + + byte[] buf = new byte[headerLength]; + Lib.strictReadFile(file, headerOffset, buf, 0, headerLength); + + name = Lib.bytesToString(buf, 0, 8); + int vaddr = Lib.bytesToInt(buf, 12); + size = Lib.bytesToInt(buf, 16); + contentOffset = Lib.bytesToInt(buf, 20); + int numRelocations = Lib.bytesToUnsignedShort(buf, 32); + int flags = Lib.bytesToInt(buf, 36); + + if (numRelocations != 0) { + Lib.debug(dbgCoffSection, "\tsection needs relocation"); + throw new EOFException(); + } + + switch (flags & 0x0FFF) { + case 0x0020: + executable = true; + readOnly = true; + initialized = true; + break; + case 0x0040: + executable = false; + readOnly = false; + initialized = true; + break; + case 0x0080: + executable = false; + readOnly = false; + initialized = false; + break; + case 0x0100: + executable = false; + readOnly = true; + initialized = true; + break; + default: + Lib.debug(dbgCoffSection, "\tinvalid section flags: " + flags); + throw new EOFException(); + } + + if (vaddr%Processor.pageSize != 0 || size < 0 || + initialized && (contentOffset < 0 || + contentOffset+size > file.length())) { + Lib.debug(dbgCoffSection, "\tinvalid section addresses: " + + "vaddr=" + vaddr + " size=" + size + + " contentOffset=" + contentOffset); + throw new EOFException(); + } + + numPages = Lib.divRoundUp(size, Processor.pageSize); + firstVPN = vaddr / Processor.pageSize; + } + + /** + * Return the COFF object used to load this executable instance. + * + * @return the COFF object corresponding to this section. + */ + public Coff getCoff() { + return coff; + } + + /** + * Return the name of this section. + * + * @return the name of this section. + */ + public String getName() { + return name; + } + + /** + * Test whether this section is read-only. + * + * @return true if this section should never be written. + */ + public boolean isReadOnly() { + return readOnly; + } + + /** + * Test whether this section is initialized. Loading a page from an + * initialized section requires a disk access, while loading a page from an + * uninitialized section requires only zero-filling the page. + * + * @return true if this section contains initialized data in the + * executable. + */ + public boolean isInitialzed() { + return initialized; + } + + /** + * Return the length of this section in pages. + * + * @return the number of pages in this section. + */ + public int getLength() { + return numPages; + } + + /** + * Return the first virtual page number used by this section. + * + * @return the first virtual page number used by this section. + */ + public int getFirstVPN() { + return firstVPN; + } + + /** + * Load a page from this segment into physical memory. + * + * @param spn the page number within this segment. + * @param ppn the physical page to load into. + */ + public void loadPage(int spn, int ppn) { + Lib.assertTrue(file != null); + + Lib.assertTrue(spn>=0 && spn=0 && ppn 0) + Lib.strictReadFile(file, faddr, memory, paddr, initlen); + + Arrays.fill(memory, paddr+initlen, paddr+pageSize, (byte) 0); + } + + /** The COFF object to which this section belongs. */ + protected Coff coff; + /** The COFF name of this section. */ + protected String name; + /** True if this section contains code. */ + protected boolean executable; + /** True if this section is read-only. */ + protected boolean readOnly; + /** True if this section contains initialized data. */ + protected boolean initialized; + + /** The number of virtual pages in this section. */ + protected int numPages; + /** The first virtual page number used by this section. */ + protected int firstVPN; + + private OpenFile file; + private int contentOffset, size; + + /** The length of a COFF section header. */ + public static final int headerLength = 40; + + private static final char dbgCoffSection = 'c'; +} diff --git a/machine/Config.java b/machine/Config.java new file mode 100644 index 0000000..60b69c9 --- /dev/null +++ b/machine/Config.java @@ -0,0 +1,283 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import java.util.HashMap; +import java.io.File; +import java.io.FileReader; +import java.io.Reader; +import java.io.StreamTokenizer; + +/** + * Provides routines to access the Nachos configuration. + */ +public final class Config { + /** + * Load configuration information from the specified file. Must be called + * before the Nachos security manager is installed. + * + * @param fileName the name of the file containing the + * configuration to use. + */ + public static void load(String fileName) { + System.out.print(" config"); + + Lib.assertTrue(!loaded); + loaded = true; + + configFile = fileName; + + try { + config = new HashMap(); + + File file = new File(configFile); + Reader reader = new FileReader(file); + StreamTokenizer s = new StreamTokenizer(reader); + + s.resetSyntax(); + s.whitespaceChars(0x00, 0x20); + s.wordChars(0x21, 0xFF); + s.eolIsSignificant(true); + s.commentChar('#'); + s.quoteChar('"'); + + int line = 1; + + s.nextToken(); + + while (true) { + if (s.ttype == StreamTokenizer.TT_EOF) + break; + + if (s.ttype == StreamTokenizer.TT_EOL) { + line++; + s.nextToken(); + continue; + } + + if (s.ttype != StreamTokenizer.TT_WORD) + loadError(line); + + String key = s.sval; + + if (s.nextToken() != StreamTokenizer.TT_WORD || + !s.sval.equals("=")) + loadError(line); + + if (s.nextToken() != StreamTokenizer.TT_WORD && s.ttype != '"') + loadError(line); + + String value = s.sval; + + // ignore everything after first string + while (s.nextToken() != StreamTokenizer.TT_EOL && + s.ttype != StreamTokenizer.TT_EOF); + + if (config.get(key) != null) + loadError(line); + + config.put(key, value); + line++; + } + } + catch (Throwable e) { + System.err.println("Error loading " + configFile); + System.exit(1); + } + } + + private static void loadError(int line) { + System.err.println("Error in " + configFile + " line " + line); + System.exit(1); + } + + private static void configError(String message) { + System.err.println(""); + System.err.println("Error in " + configFile + ": " + message); + System.exit(1); + } + + /** + * Get the value of a key in nachos.conf. + * + * @param key the key to look up. + * @return the value of the specified key, or null if it is not + * present. + */ + public static String getString(String key) { + return (String) config.get(key); + } + + /** + * Get the value of a key in nachos.conf, returning the specified + * default if the key does not exist. + * + * @param key the key to look up. + * @param defaultValue the value to return if the key does not exist. + * @return the value of the specified key, or defaultValue if it + * is not present. + */ + public static String getString(String key, String defaultValue) { + String result = getString(key); + + if (result == null) + return defaultValue; + + return result; + } + + private static Integer requestInteger(String key) { + try { + String value = getString(key); + if (value == null) + return null; + + return new Integer(value); + } + catch (NumberFormatException e) { + configError(key + " should be an integer"); + + Lib.assertNotReached(); + return null; + } + } + + /** + * Get the value of an integer key in nachos.conf. + * + * @param key the key to look up. + * @return the value of the specified key. + */ + public static int getInteger(String key) { + Integer result = requestInteger(key); + + if (result == null) + configError("missing int " + key); + + return result.intValue(); + } + + /** + * Get the value of an integer key in nachos.conf, returning the + * specified default if the key does not exist. + * + * @param key the key to look up. + * @param defaultValue the value to return if the key does not exist. + * @return the value of the specified key, or defaultValue if the + * key does not exist. + */ + public static int getInteger(String key, int defaultValue) { + Integer result = requestInteger(key); + + if (result == null) + return defaultValue; + + return result.intValue(); + } + + private static Double requestDouble(String key) { + try { + String value = getString(key); + if (value == null) + return null; + + return new Double(value); + } + catch (NumberFormatException e) { + configError(key + " should be a double"); + + Lib.assertNotReached(); + return null; + } + } + + /** + * Get the value of a double key in nachos.conf. + * + * @param key the key to look up. + * @return the value of the specified key. + */ + public static double getDouble(String key) { + Double result = requestDouble(key); + + if (result == null) + configError("missing double " + key); + + return result.doubleValue(); + } + + /** + * Get the value of a double key in nachos.conf, returning the + * specified default if the key does not exist. + * + * @param key the key to look up. + * @param defaultValue the value to return if the key does not exist. + * @return the value of the specified key, or defaultValue if the + * key does not exist. + */ + public static double getDouble(String key, double defaultValue) { + Double result = requestDouble(key); + + if (result == null) + return defaultValue; + + return result.doubleValue(); + } + + private static Boolean requestBoolean(String key) { + String value = getString(key); + + if (value == null) + return null; + + if (value.equals("1") || value.toLowerCase().equals("true")) { + return Boolean.TRUE; + } + else if (value.equals("0") || value.toLowerCase().equals("false")) { + return Boolean.FALSE; + } + else { + configError(key + " should be a boolean"); + + Lib.assertNotReached(); + return null; + } + } + + /** + * Get the value of a boolean key in nachos.conf. + * + * @param key the key to look up. + * @return the value of the specified key. + */ + public static boolean getBoolean(String key) { + Boolean result = requestBoolean(key); + + if (result == null) + configError("missing boolean " + key); + + return result.booleanValue(); + } + + /** + * Get the value of a boolean key in nachos.conf, returning the + * specified default if the key does not exist. + * + * @param key the key to look up. + * @param defaultValue the value to return if the key does not exist. + * @return the value of the specified key, or defaultValue if the + * key does not exist. + */ + public static boolean getBoolean(String key, boolean defaultValue) { + Boolean result = requestBoolean(key); + + if (result == null) + return defaultValue; + + return result.booleanValue(); + } + + private static boolean loaded = false; + private static String configFile; + private static HashMap config; +} diff --git a/machine/ElevatorBank.java b/machine/ElevatorBank.java new file mode 100644 index 0000000..4daf517 --- /dev/null +++ b/machine/ElevatorBank.java @@ -0,0 +1,620 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import nachos.security.*; +import nachos.threads.KThread; +import nachos.threads.Semaphore; + +import java.util.Vector; +import java.util.LinkedList; +import java.util.Iterator; + +/** + * A bank of elevators. + */ +public final class ElevatorBank implements Runnable { + /** Indicates an elevator intends to move down. */ + public static final int dirDown = -1; + /** Indicates an elevator intends not to move. */ + public static final int dirNeither = 0; + /** Indicates an elevator intends to move up. */ + public static final int dirUp = 1; + + /** + * Allocate a new elevator bank. + * + * @param privilege encapsulates privileged access to the Nachos + * machine. + */ + public ElevatorBank(Privilege privilege) { + System.out.print(" elevators"); + + this.privilege = privilege; + + simulationStarted = false; + } + + /** + * Initialize this elevator bank with the specified number of elevators and + * the specified number of floors. The software elevator controller must + * also be specified. This elevator must not already be running a + * simulation. + * + * @param numElevators the number of elevators in the bank. + * @param numFloors the number of floors in the bank. + * @param controller the elevator controller. + */ + public void init(int numElevators, int numFloors, + ElevatorControllerInterface controller) { + Lib.assertTrue(!simulationStarted); + + this.numElevators = numElevators; + this.numFloors = numFloors; + + manager = new ElevatorManager(controller); + + elevators = new ElevatorState[numElevators]; + for (int i=0; i(); + + enableGui = false; + gui = null; + } + + /** + * Add a rider to the simulation. This method must not be called after + * run() is called. + * + * @param rider the rider to add. + * @param floor the floor the rider will start on. + * @param stops the array to pass to the rider's initialize() + * method. + * @return the controls that will be given to the rider. + */ + public RiderControls addRider(RiderInterface rider, + int floor, int[] stops) { + Lib.assertTrue(!simulationStarted); + + RiderControls controls = new RiderState(rider, floor, stops); + ridersVector.addElement(controls); + numRiders++; + return controls; + } + + /** + * Create a GUI for this elevator bank. + */ + public void enableGui() { + Lib.assertTrue(!simulationStarted); + Lib.assertTrue(Config.getBoolean("ElevatorBank.allowElevatorGUI")); + + enableGui = true; + } + + /** + * Run a simulation. Initialize all elevators and riders, and then + * fork threads to each of their run() methods. Return when the + * simulation is finished. + */ + public void run() { + Lib.assertTrue(!simulationStarted); + simulationStarted = true; + + riders = new RiderState[numRiders]; + ridersVector.toArray(riders); + + if (enableGui) { + privilege.doPrivileged(new Runnable() { + public void run() { initGui(); } + }); + } + + for (int i=0; i= 0 && elevator < numElevators); + direction = elevators[elevator].direction; + } + + RiderEvent e = new RiderEvent(event, floor, elevator, direction); + for (int i=0; i= 0 && elevator < numElevators); + postRiderEvent(RiderEvent.eventDoorsOpened, + elevators[elevator].openDoors(), elevator); + + if (gui != null) { + if (elevators[elevator].direction == dirUp) + gui.clearUpButton(elevators[elevator].floor); + else if (elevators[elevator].direction == dirDown) + gui.clearDownButton(elevators[elevator].floor); + + gui.openDoors(elevator); + } + } + + public void closeDoors(int elevator) { + Lib.assertTrue(elevator >= 0 && elevator < numElevators); + postRiderEvent(RiderEvent.eventDoorsClosed, + elevators[elevator].closeDoors(), elevator); + + if (gui != null) + gui.closeDoors(elevator); + } + + public boolean moveTo(int floor, int elevator) { + Lib.assertTrue(floor >= 0 && floor < numFloors); + Lib.assertTrue(elevator >= 0 && elevator < numElevators); + + if (!elevators[elevator].moveTo(floor)) + return false; + + schedule(Stats.ElevatorTicks); + return true; + } + + public int getFloor(int elevator) { + Lib.assertTrue(elevator >= 0 && elevator < numElevators); + return elevators[elevator].floor; + } + + public void setDirectionDisplay(int elevator, int direction) { + Lib.assertTrue(elevator >= 0 && elevator < numElevators); + elevators[elevator].direction = direction; + + if (elevators[elevator].doorsOpen) { + postRiderEvent(RiderEvent.eventDirectionChanged, + elevators[elevator].floor, elevator); + } + + if (gui != null) { + if (elevators[elevator].doorsOpen) { + if (direction == dirUp) + gui.clearUpButton(elevators[elevator].floor); + else if (direction == dirDown) + gui.clearDownButton(elevators[elevator].floor); + } + + gui.setDirectionDisplay(elevator, direction); + } + } + + public void finish() { + finished = true; + + Lib.assertTrue(KThread.currentThread() == thread); + + done.V(); + KThread.finish(); + } + + public ElevatorEvent getNextEvent() { + if (events.isEmpty()) + return null; + else + return (ElevatorEvent) events.removeFirst(); + } + + void schedule(int when) { + privilege.interrupt.schedule(when, "elevator", interrupt); + } + + void postEvent(int event, int floor, int elevator, boolean schedule) { + events.add(new ElevatorEvent(event, floor, elevator)); + + if (schedule) + schedule(1); + } + + void interrupt() { + for (int i=0; i events = new LinkedList(); + Semaphore done = new Semaphore(0); + boolean finished = false; + } + + private class ElevatorState { + ElevatorState(int floor) { + this.floor = floor; + destination = floor; + } + + int openDoors() { + Lib.assertTrue(!doorsOpen && !moving); + doorsOpen = true; + return floor; + } + + int closeDoors() { + Lib.assertTrue(doorsOpen); + doorsOpen = false; + return floor; + } + + boolean moveTo(int newDestination) { + Lib.assertTrue(!doorsOpen); + + if (!moving) { + // can't move to current floor + if (floor == newDestination) + return false; + + destination = newDestination; + nextETA = Machine.timer().getTime() + Stats.ElevatorTicks; + + moving = true; + return true; + } + else { + // moving, shouldn't be at destination + Lib.assertTrue(floor != destination); + + // make sure it's ok to stop + if ((destination > floor && newDestination <= floor) || + (destination < floor && newDestination >= floor)) + return false; + + destination = newDestination; + return true; + } + } + + boolean enter(RiderState rider, int onFloor) { + Lib.assertTrue(!riders.contains(rider)); + + if (!doorsOpen || moving || onFloor != floor || + riders.size() == maxRiders) + return false; + + riders.addElement(rider); + return true; + } + + boolean exit(RiderState rider, int onFloor) { + Lib.assertTrue(riders.contains(rider)); + + if (!doorsOpen || moving || onFloor != floor) + return false; + + riders.removeElement(rider); + return true; + } + + boolean atNextFloor() { + if (!moving || Machine.timer().getTime() < nextETA) + return false; + + Lib.assertTrue(destination != floor); + if (destination > floor) + floor++; + else + floor--; + + for (Iterator i=riders.iterator(); i.hasNext(); ) { + RiderState rider = (RiderState) i.next(); + + rider.floor = floor; + } + + return true; + } + + boolean atDestination() { + if (!moving || destination != floor) + return false; + + moving = false; + return true; + } + + static final int maxRiders = 4; + + int floor, destination; + long nextETA; + + boolean doorsOpen = false, moving = false; + int direction = dirNeither; + public Vector riders = new Vector(); + } + + private class RiderState implements RiderControls { + RiderState(RiderInterface rider, int floor, int[] stops) { + this.rider = rider; + this.floor = floor; + this.stops = stops; + + interrupt = new Runnable() { public void run() { interrupt(); }}; + } + + public int getNumFloors() { + return numFloors; + } + + public int getNumElevators() { + return numElevators; + } + + public void setInterruptHandler(Runnable handler) { + this.handler = handler; + } + + public int getFloor() { + return floor; + } + + public int[] getFloors() { + int[] array = new int[floors.size()]; + for (int i=0; i= 0 && elevator < numElevators); + return elevators[elevator].direction; + } + + public RiderEvent getNextEvent() { + if (events.isEmpty()) + return null; + else + return (RiderEvent) events.removeFirst(); + } + + public boolean pressDirectionButton(boolean up) { + if (up) + return pressUpButton(); + else + return pressDownButton(); + } + + public boolean pressUpButton() { + Lib.assertTrue(!inElevator && floor < numFloors-1); + + for (int elevator=0; elevator 0); + + for (int elevator=0; elevator= 0 && elevator < numElevators); + if (!elevators[elevator].enter(this, floor)) + return false; + + if (gui != null) + gui.enterElevator(floor, elevator); + + inElevator = true; + this.elevator = elevator; + return true; + } + + public boolean pressFloorButton(int floor) { + Lib.assertTrue(inElevator && floor >= 0 && floor < numFloors); + + if (elevators[elevator].doorsOpen && + elevators[elevator].floor == floor) + return false; + + manager.postEvent(ElevatorEvent.eventFloorButtonPressed, + floor, elevator, true); + + if (gui != null) + gui.pressFloorButton(floor, elevator); + + return true; + } + + public boolean exitElevator(int floor) { + Lib.assertTrue(inElevator && floor >= 0 && floor < numFloors); + + if (!elevators[elevator].exit(this, floor)) + return false; + + inElevator = false; + floors.add(new Integer(floor)); + + if (gui != null) + gui.exitElevator(floor, elevator); + + return true; + } + + public void finish() { + finished = true; + + int[] floors = getFloors(); + Lib.assertTrue(floors.length == stops.length); + for (int i=0; i events = new LinkedList(); + Vector floors = new Vector(); + Semaphore done = new Semaphore(0); + KThread thread; + } + + private int numFloors, numElevators; + private ElevatorManager manager; + private ElevatorState[] elevators; + + private int numRiders; + private Vector ridersVector; + private RiderState[] riders; + + private boolean simulationStarted, enableGui; + private Privilege privilege; + private ElevatorGui gui; +} diff --git a/machine/ElevatorControllerInterface.java b/machine/ElevatorControllerInterface.java new file mode 100644 index 0000000..d64d954 --- /dev/null +++ b/machine/ElevatorControllerInterface.java @@ -0,0 +1,40 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +/** + * A controller for all the elevators in an elevator bank. The controller + * accesses the elevator bank through an instance of ElevatorControls. + */ +public interface ElevatorControllerInterface extends Runnable { + /** + * Initialize this elevator controller. The controller will access the + * elevator bank through controls. This constructor should return + * immediately after this controller is initialized, but not until the + * interupt handler is set. The controller will start receiving events + * after this method returns, but potentially before run() is + * called. + * + * @param controls the controller's interface to the elevator + * bank. The controller must not attempt to access + * the elevator bank in any other way. + */ + public void initialize(ElevatorControls controls); + + /** + * Cause the controller to use the provided controls to receive and process + * requests from riders. This method should not return, but instead should + * call controls.finish() when the controller is finished. + */ + public void run(); + + /** The number of ticks doors should be held open before closing them. */ + public static final int timeDoorsOpen = 500; + + /** Indicates an elevator intends to move down. */ + public static final int dirDown = -1; + /** Indicates an elevator intends not to move. */ + public static final int dirNeither = 0; + /** Indicates an elevator intends to move up. */ + public static final int dirUp = 1; +} diff --git a/machine/ElevatorControls.java b/machine/ElevatorControls.java new file mode 100644 index 0000000..1aa3d4b --- /dev/null +++ b/machine/ElevatorControls.java @@ -0,0 +1,96 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +/** + * A set of controls that can be used by an elevator controller. + */ +public interface ElevatorControls { + /** + * Return the number of floors in the elevator bank. If n is the + * number of floors in the bank, then the floors are numbered 0 + * (the ground floor) through n - 1 (the top floor). + * + * @return the number of floors in the bank. + */ + public int getNumFloors(); + + /** + * Return the number of elevators in the elevator bank. If n is the + * number of elevators in the bank, then the elevators are numbered + * 0 through n - 1. + * + * @return the numbe rof elevators in the bank. + */ + public int getNumElevators(); + + /** + * Set the elevator interrupt handler. This handler will be called when an + * elevator event occurs, and when all the riders have reaced their + * destinations. + * + * @param handler the elevator interrupt handler. + */ + public void setInterruptHandler(Runnable handler); + + /** + * Open an elevator's doors. + * + * @param elevator which elevator's doors to open. + */ + public void openDoors(int elevator); + + /** + * Close an elevator's doors. + * + * @param elevator which elevator's doors to close. + */ + public void closeDoors(int elevator); + + /** + * Move an elevator to another floor. The elevator's doors must be closed. + * If the elevator is already moving and cannot safely stop at the + * specified floor because it has already passed or is about to pass the + * floor, fails and returns false. If the elevator is already + * stopped at the specified floor, returns false. + * + * @param floor the floor to move to. + * @param elevator the elevator to move. + * @return true if the elevator's destination was changed. + */ + public boolean moveTo(int floor, int elevator); + + /** + * Return the current location of the elevator. If the elevator is in + * motion, the returned value will be within one of the exact location. + * + * @param elevator the elevator to locate. + * @return the floor the elevator is on. + */ + public int getFloor(int elevator); + + /** + * Set which direction the elevator bank will show for this elevator's + * display. The direction argument should be one of the dir* + * constants in the ElevatorBank class. + * + * @param elevator the elevator whose direction display to set. + * @param direction the direction to show (up, down, or neither). + */ + public void setDirectionDisplay(int elevator, int direction); + + /** + * Call when the elevator controller is finished. + */ + public void finish(); + + /** + * Return the next event in the event queue. Note that there may be + * multiple events pending when an elevator interrupt occurs, so this + * method should be called repeatedly until it returns null. + * + * @return the next event, or null if no further events are + * currently pending. + */ + public ElevatorEvent getNextEvent(); +} diff --git a/machine/ElevatorEvent.java b/machine/ElevatorEvent.java new file mode 100644 index 0000000..302cc43 --- /dev/null +++ b/machine/ElevatorEvent.java @@ -0,0 +1,33 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +/** + * An event that affects elevator software. + */ +public final class ElevatorEvent { + public ElevatorEvent(int event, int floor, int elevator) { + this.event = event; + this.floor = floor; + this.elevator = elevator; + } + + /** The event identifier. Refer to the event* constants. */ + public final int event; + /** The floor pertaining to the event, or -1 if not applicable. */ + public final int floor; + /** The elevator pertaining to the event, or -1 if not applicable. */ + public final int elevator; + + /** An up button was pressed. */ + public static final int eventUpButtonPressed = 0; + /** A down button was pressed. */ + public static final int eventDownButtonPressed = 1; + /** A floor button was pressed inside an elevator. */ + public static final int eventFloorButtonPressed = 2; + /** An elevator has arrived and stopped at its destination floor. */ + public static final int eventElevatorArrived = 3; + /** All riders have finished; the elevator controller should terminate. */ + public static final int eventRidersDone = 4; +} + diff --git a/machine/ElevatorGui.java b/machine/ElevatorGui.java new file mode 100644 index 0000000..27176f4 --- /dev/null +++ b/machine/ElevatorGui.java @@ -0,0 +1,424 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import java.awt.Frame; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Panel; +import java.awt.ScrollPane; +import java.awt.Canvas; + +import java.awt.GridLayout; +import java.awt.FlowLayout; +import java.awt.Insets; + +import java.awt.Rectangle; +import java.awt.Graphics; +import java.awt.Color; + +/** + * A graphical visualization for the ElevatorBank class. + */ +public final class ElevatorGui extends Frame { + private final static int w=90, h=75; + + private int numFloors, numElevators; + + private ElevatorShaft[] elevators; + private Floor[] floors; + + private int totalWidth, totalHeight; + + ElevatorGui(int numFloors, int numElevators, int[] numRidersPerFloor) { + this.numFloors = numFloors; + this.numElevators = numElevators; + + totalWidth = w*(numElevators+1); + totalHeight = h*numFloors; + + setTitle("Elevator Bank"); + + Panel floorPanel = new Panel(new GridLayout(numFloors, 1, 0, 0)); + + floors = new Floor[numFloors]; + for (int i=numFloors-1; i>=0; i--) { + floors[i] = new Floor(i, numRidersPerFloor[i]); + floorPanel.add(floors[i]); + } + + Panel panel = new Panel(new GridLayout(1, numElevators+1, 0, 0)); + + panel.add(floorPanel); + + elevators = new ElevatorShaft[numElevators]; + for (int i=0; i 0) + paintRider(g, x0 + i*t, y0 - j*t, r); + } + } + } + + private class Floor extends Canvas { + int floor, numRiders; + + boolean upSet = false; + boolean downSet = false; + + Floor(int floor, int numRiders) { + this.floor = floor; + this.numRiders = numRiders; + + setBackground(Color.black); + } + + public Dimension getPreferredSize() { + return new Dimension(w, h); + } + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + public Dimension getMaximumSize() { + return getPreferredSize(); + } + + public void repaint() { + super.repaint(); + + if (TCB.isNachosThread()) { + try { + Thread.sleep(100); + } + catch (InterruptedException e) { + } + } + } + + void pressUpButton() { + if (!upSet) { + upSet = true; + repaint(); + } + } + + void pressDownButton() { + if (!downSet) { + downSet = true; + repaint(); + } + } + + void clearUpButton() { + if (upSet) { + upSet = false; + repaint(); + } + } + + void clearDownButton() { + if (downSet) { + downSet = false; + repaint(); + } + } + + void addRider() { + numRiders++; + + repaint(); + } + + void removeRider() { + numRiders--; + + repaint(); + } + + public void paint(Graphics g) { + g.setColor(Color.lightGray); + g.drawLine(0, 0, w, 0); + + paintRiders(g, 0, 5, 3*w/4, h-10, numRiders); + + paintButtons(g); + } + + private void paintButtons(Graphics g) { + int s = 3*w/4; + + int x1 = s+w/32; + int x2 = w-w/32; + int y1 = h/8; + int y2 = h-h/8; + + g.setColor(Color.darkGray); + g.drawRect(x1, y1, x2-x1, y2-y1); + g.setColor(Color.lightGray); + g.fillRect(x1+1, y1+1, x2-x1-2, y2-y1-2); + + int r = Math.min((x2-x1)/3, (y2-y1)/6); + int xc = (x1+x2)/2; + int yc1 = (y1+y2)/2 - (3*r/2); + int yc2 = (y1+y2)/2 + (3*r/2); + + g.setColor(Color.red); + + if (floor < numFloors-1) { + if (upSet) + g.fillOval(xc-r, yc1-r, 2*r, 2*r); + else + g.drawOval(xc-r, yc1-r, 2*r, 2*r); + } + + if (floor > 0) { + if (downSet) + g.fillOval(xc-r, yc2-r, 2*r, 2*r); + else + g.drawOval(xc-r, yc2-r, 2*r, 2*r); + } + } + } + + private class ElevatorShaft extends Canvas { + ElevatorShaft(int elevator) { + this.elevator = elevator; + + floorsSet = new boolean[numFloors]; + for (int i=0; iElevatorBank module, using a single elevator and a single + * rider. + */ +public final class ElevatorTest { + /** + * Allocate a new ElevatorTest object. + */ + public ElevatorTest() { + } + + /** + * Run a test on Machine.bank(). + */ + public void run() { + Machine.bank().init(1, 2, new ElevatorController()); + + int[] stops = { 1 }; + + Machine.bank().addRider(new Rider(), 0, stops); + + Machine.bank().run(); + } + + private class ElevatorController implements ElevatorControllerInterface { + public void initialize(ElevatorControls controls) { + this.controls = controls; + + eventWait = new Semaphore(0); + + controls.setInterruptHandler(new Runnable() { + public void run() { interrupt(); } + }); + } + + public void run() { + ElevatorEvent e; + + Lib.assertTrue(controls.getFloor(0) == 0); + + e = getNextEvent(); + Lib.assertTrue(e.event == ElevatorEvent.eventUpButtonPressed && + e.floor == 0); + + controls.setDirectionDisplay(0, dirUp); + controls.openDoors(0); + + e = getNextEvent(); + Lib.assertTrue(e.event == ElevatorEvent.eventFloorButtonPressed && + e.floor == 1); + + controls.closeDoors(0); + controls.moveTo(1, 0); + + e = getNextEvent(); + Lib.assertTrue(e.event == ElevatorEvent.eventElevatorArrived && + e.floor == 1 && + e.elevator == 0); + + controls.openDoors(0); + + e = getNextEvent(); + Lib.assertTrue(e.event == ElevatorEvent.eventRidersDone); + + controls.finish(); + Lib.assertNotReached(); + } + + private void interrupt() { + eventWait.V(); + } + + private ElevatorEvent getNextEvent() { + ElevatorEvent event; + while (true) { + if ((event = controls.getNextEvent()) != null) + break; + + eventWait.P(); + } + return event; + } + + private ElevatorControls controls; + private Semaphore eventWait; + } + + private class Rider implements RiderInterface { + public void initialize(RiderControls controls, int[] stops) { + this.controls = controls; + Lib.assertTrue(stops.length == 1 && stops[0] == 1); + + eventWait = new Semaphore(0); + + controls.setInterruptHandler(new Runnable() { + public void run() { interrupt(); } + }); + } + + public void run() { + RiderEvent e; + + Lib.assertTrue(controls.getFloor() == 0); + + controls.pressUpButton(); + + e = getNextEvent(); + Lib.assertTrue(e.event == RiderEvent.eventDoorsOpened && + e.floor == 0 && + e.elevator == 0); + Lib.assertTrue(controls.getDirectionDisplay(0) == dirUp); + + Lib.assertTrue(controls.enterElevator(0)); + controls.pressFloorButton(1); + + e = getNextEvent(); + Lib.assertTrue(e.event == RiderEvent.eventDoorsClosed && + e.floor == 0 && + e.elevator == 0); + + e = getNextEvent(); + Lib.assertTrue(e.event == RiderEvent.eventDoorsOpened && + e.floor == 1 && + e.elevator == 0); + + Lib.assertTrue(controls.exitElevator(1)); + + controls.finish(); + Lib.assertNotReached(); + } + + private void interrupt() { + eventWait.V(); + } + + private RiderEvent getNextEvent() { + RiderEvent event; + while (true) { + if ((event = controls.getNextEvent()) != null) + break; + + eventWait.P(); + } + return event; + } + + private RiderControls controls; + private Semaphore eventWait; + } +} diff --git a/machine/FileSystem.java b/machine/FileSystem.java new file mode 100644 index 0000000..dbdaa31 --- /dev/null +++ b/machine/FileSystem.java @@ -0,0 +1,35 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +/** + * A file system that allows the user to create, open, and delete files. + */ +public interface FileSystem { + /** + * Atomically open a file, optionally creating it if it does not + * already exist. If the file does not + * already exist and create is false, returns + * null. If the file does not already exist and create + * is true, creates the file with zero length. If the file already + * exists, opens the file without changing it in any way. + * + * @param name the name of the file to open. + * @param create true to create the file if it does not + * already exist. + * @return an OpenFile representing a new instance of the opened + * file, or null if the file could not be opened. + */ + public OpenFile open(String name, boolean create); + + /** + * Atomically remove an existing file. After a file is removed, it cannot + * be opened until it is created again with open. If the file is + * already open, it is up to the implementation to decide whether the file + * can still be accessed or if it is deleted immediately. + * + * @param name the name of the file to remove. + * @return true if the file was successfully removed. + */ + public boolean remove(String name); +} diff --git a/machine/Interrupt.java b/machine/Interrupt.java new file mode 100644 index 0000000..8b4663f --- /dev/null +++ b/machine/Interrupt.java @@ -0,0 +1,253 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import nachos.security.*; + +import java.util.TreeSet; +import java.util.Iterator; +import java.util.SortedSet; + +/** + * The Interrupt class emulates low-level interrupt hardware. The + * hardware provides a method (setStatus()) to enable or disable + * interrupts. + * + *

+ * In order to emulate the hardware, we need to keep track of all pending + * interrupts the hardware devices would cause, and when they are supposed to + * occur. + * + *

+ * This module also keeps track of simulated time. Time advances only when the + * following occur: + *

    + *
  • interrupts are enabled, when they were previously disabled + *
  • a MIPS instruction is executed + *
+ * + *

+ * As a result, unlike real hardware, interrupts (including time-slice context + * switches) cannot occur just anywhere in the code where interrupts are + * enabled, but rather only at those places in the code where simulated time + * advances (so that it becomes time for the hardware simulation to invoke an + * interrupt handler). + * + *

+ * This means that incorrectly synchronized code may work fine on this hardware + * simulation (even with randomized time slices), but it wouldn't work on real + * hardware. But even though Nachos can't always detect when your program + * would fail in real life, you should still write properly synchronized code. + */ +public final class Interrupt { + /** + * Allocate a new interrupt controller. + * + * @param privilege encapsulates privileged access to the Nachos + * machine. + */ + public Interrupt(Privilege privilege) { + System.out.print(" interrupt"); + + this.privilege = privilege; + privilege.interrupt = new InterruptPrivilege(); + + enabled = false; + pending = new TreeSet(); + } + + /** + * Enable interrupts. This method has the same effect as + * setStatus(true). + */ + public void enable() { + setStatus(true); + } + + /** + * Disable interrupts and return the old interrupt state. This method has + * the same effect as setStatus(false). + * + * @return true if interrupts were enabled. + */ + public boolean disable() { + return setStatus(false); + } + + /** + * Restore interrupts to the specified status. This method has the same + * effect as setStatus(status). + * + * @param status true to enable interrupts. + */ + public void restore(boolean status) { + setStatus(status); + } + + /** + * Set the interrupt status to be enabled (true) or disabled + * (false) and return the previous status. If the interrupt + * status changes from disabled to enabled, the simulated time is advanced. + * + * @param status true to enable interrupts. + * @return true if interrupts were enabled. + */ + public boolean setStatus(boolean status) { + boolean oldStatus = enabled; + enabled = status; + + if (oldStatus == false && status == true) + tick(true); + + return oldStatus; + } + + /** + * Tests whether interrupts are enabled. + * + * @return true if interrupts are enabled. + */ + public boolean enabled() { + return enabled; + } + + /** + * Tests whether interrupts are disabled. + * + * @return true if interrupts are disabled. + */ + public boolean disabled() { + return !enabled; + } + + private void schedule(long when, String type, Runnable handler) { + Lib.assertTrue(when>0); + + long time = privilege.stats.totalTicks + when; + PendingInterrupt toOccur = new PendingInterrupt(time, type, handler); + + Lib.debug(dbgInt, + "Scheduling the " + type + + " interrupt handler at time = " + time); + + pending.add(toOccur); + } + + private void tick(boolean inKernelMode) { + Stats stats = privilege.stats; + + if (inKernelMode) { + stats.kernelTicks += Stats.KernelTick; + stats.totalTicks += Stats.KernelTick; + } + else { + stats.userTicks += Stats.UserTick; + stats.totalTicks += Stats.UserTick; + } + + if (Lib.test(dbgInt)) + System.out.println("== Tick " + stats.totalTicks + " =="); + + enabled = false; + checkIfDue(); + enabled = true; + } + + private void checkIfDue() { + long time = privilege.stats.totalTicks; + + Lib.assertTrue(disabled()); + + if (Lib.test(dbgInt)) + print(); + + if (pending.isEmpty()) + return; + + if (((PendingInterrupt) pending.first()).time > time) + return; + + Lib.debug(dbgInt, "Invoking interrupt handlers at time = " + time); + + while (!pending.isEmpty() && + ((PendingInterrupt) pending.first()).time <= time) { + PendingInterrupt next = (PendingInterrupt) pending.first(); + pending.remove(next); + + Lib.assertTrue(next.time <= time); + + if (privilege.processor != null) + privilege.processor.flushPipe(); + + Lib.debug(dbgInt, " " + next.type); + + next.handler.run(); + } + + Lib.debug(dbgInt, " (end of list)"); + } + + private void print() { + System.out.println("Time: " + privilege.stats.totalTicks + + ", interrupts " + (enabled ? "on" : "off")); + System.out.println("Pending interrupts:"); + + for (Iterator i=pending.iterator(); i.hasNext(); ) { + PendingInterrupt toOccur = (PendingInterrupt) i.next(); + System.out.println(" " + toOccur.type + + ", scheduled at " + toOccur.time); + } + + System.out.println(" (end of list)"); + } + + private class PendingInterrupt implements Comparable { + PendingInterrupt(long time, String type, Runnable handler) { + this.time = time; + this.type = type; + this.handler = handler; + this.id = numPendingInterruptsCreated++; + } + + public int compareTo(Object o) { + PendingInterrupt toOccur = (PendingInterrupt) o; + + // can't return 0 for unequal objects, so check all fields + if (time < toOccur.time) + return -1; + else if (time > toOccur.time) + return 1; + else if (id < toOccur.id) + return -1; + else if (id > toOccur.id) + return 1; + else + return 0; + } + + long time; + String type; + Runnable handler; + + private long id; + } + + private long numPendingInterruptsCreated = 0; + + private Privilege privilege; + + private boolean enabled; + private TreeSet pending; + + private static final char dbgInt = 'i'; + + private class InterruptPrivilege implements Privilege.InterruptPrivilege { + public void schedule(long when, String type, Runnable handler) { + Interrupt.this.schedule(when, type, handler); + } + + public void tick(boolean inKernelMode) { + Interrupt.this.tick(inKernelMode); + } + } +} diff --git a/machine/Kernel.java b/machine/Kernel.java new file mode 100644 index 0000000..d1260e6 --- /dev/null +++ b/machine/Kernel.java @@ -0,0 +1,45 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +/** + * An OS kernel. + */ +public abstract class Kernel { + /** Globally accessible reference to the kernel. */ + public static Kernel kernel = null; + + /** + * Allocate a new kernel. + */ + public Kernel() { + // make sure only one kernel is created + Lib.assertTrue(kernel == null); + kernel = this; + } + + /** + * Initialize this kernel. + */ + public abstract void initialize(String[] args); + + /** + * Test that this module works. + * + * Warning: this method will not be invoked by the autograder when + * we grade your projects. You should perform all initialization in + * initialize(). + */ + public abstract void selfTest(); + + /** + * Begin executing user programs, if applicable. + */ + public abstract void run(); + + /** + * Terminate this kernel. Never returns. + */ + public abstract void terminate(); +} + diff --git a/machine/Lib.java b/machine/Lib.java new file mode 100644 index 0000000..62ada71 --- /dev/null +++ b/machine/Lib.java @@ -0,0 +1,638 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.security.PrivilegedAction; +import java.util.Random; + +/** + * Thrown when an assertion fails. + */ +class AssertionFailureError extends Error { + AssertionFailureError() { + super(); + } + + AssertionFailureError(String message) { + super(message); + } +} + +/** + * Provides miscellaneous library routines. + */ +public final class Lib { + /** + * Prevent instantiation. + */ + private Lib() { + } + + private static Random random = null; + + /** + * Seed the random number generater. May only be called once. + * + * @param randomSeed the seed for the random number generator. + */ + public static void seedRandom(long randomSeed) { + assertTrue(random == null); + random = new Random(randomSeed); + } + + /** + * Return a random integer between 0 and range - 1. Must not be + * called before seedRandom() seeds the random number generator. + * + * @param range a positive value specifying the number of possible + * return values. + * @return a random integer in the specified range. + */ + public static int random(int range) { + assertTrue(range > 0); + return random.nextInt(range); + } + + /** + * Return a random double between 0.0 (inclusive) and 1.0 (exclusive). + * + * @return a random double between 0.0 and 1.0. + */ + public static double random() { + return random.nextDouble(); + } + + /** + * Asserts that expression is true. If not, then Nachos + * exits with an error message. + * + * @param expression the expression to assert. + */ + public static void assertTrue(boolean expression) { + if (!expression) + throw new AssertionFailureError(); + } + + /** + * Asserts that expression is true. If not, then Nachos + * exits with the specified error message. + * + * @param expression the expression to assert. + * @param message the error message. + */ + public static void assertTrue(boolean expression, String message) { + if (!expression) + throw new AssertionFailureError(message); + } + + /** + * Asserts that this call is never made. Same as assertTrue(false). + */ + public static void assertNotReached() { + assertTrue(false); + } + + /** + * Asserts that this call is never made, with the specified error messsage. + * Same as assertTrue(false, message). + * + * @param message the error message. + */ + public static void assertNotReached(String message) { + assertTrue(false, message); + } + + /** + * Print message if flag was enabled on the command line. To + * specify which flags to enable, use the -d command line option. For + * example, to enable flags a, c, and e, do the following: + * + *

+ *

nachos -d ace
+ * + *

+ * Nachos uses several debugging flags already, but you are encouraged to + * add your own. + * + * @param flag the debug flag that must be set to print this message. + * @param message the debug message. + */ + public static void debug(char flag, String message) { + if (test(flag)) + System.out.println(message); + } + + /** + * Tests if flag was enabled on the command line. + * + * @param flag the debug flag to test. + * + * @return true if this flag was enabled on the command line. + */ + public static boolean test(char flag) { + if (debugFlags == null) + return false; + else if (debugFlags[(int) '+']) + return true; + else if (flag >= 0 && flag < 0x80 && debugFlags[(int) flag]) + return true; + else + return false; + } + + /** + * Enable all the debug flags in flagsString. + * + * @param flagsString the flags to enable. + */ + public static void enableDebugFlags(String flagsString) { + if (debugFlags == null) + debugFlags = new boolean[0x80]; + + char[] newFlags = flagsString.toCharArray(); + for (int i=0; i= 0 && c < 0x80) + debugFlags[(int) c] = true; + } + } + + /** Debug flags specified on the command line. */ + private static boolean debugFlags[]; + + /** + * Read a file, verifying that the requested number of bytes is read, and + * verifying that the read operation took a non-zero amount of time. + * + * @param file the file to read. + * @param position the file offset at which to start reading. + * @param buf the buffer in which to store the data. + * @param offset the buffer offset at which storing begins. + * @param length the number of bytes to read. + */ + public static void strictReadFile(OpenFile file, int position, + byte[] buf, int offset, int length) { + long startTime = Machine.timer().getTime(); + assertTrue(file.read(position, buf, offset, length) == length); + long finishTime = Machine.timer().getTime(); + assertTrue(finishTime>startTime); + } + + /** + * Load an entire file into memory. + * + * @param file the file to load. + * @return an array containing the contents of the entire file, or + * null if an error occurred. + */ + public static byte[] loadFile(OpenFile file) { + int startOffset = file.tell(); + + int length = file.length(); + if (length < 0) + return null; + + byte[] data = new byte[length]; + + file.seek(0); + int amount = file.read(data, 0, length); + file.seek(startOffset); + + if (amount == length) + return data; + else + return null; + } + + /** + * Take a read-only snapshot of a file. + * + * @param file the file to take a snapshot of. + * @return a read-only snapshot of the file. + */ + public static OpenFile cloneFile(OpenFile file) { + OpenFile clone = new ArrayFile(loadFile(file)); + + clone.seek(file.tell()); + + return clone; + } + + /** + * Convert a short into its little-endian byte string representation. + * + * @param array the array in which to store the byte string. + * @param offset the offset in the array where the string will start. + * @param value the value to convert. + */ + public static void bytesFromShort(byte[] array, int offset, short value) { + array[offset+0] = (byte) ((value>>0)&0xFF); + array[offset+1] = (byte) ((value>>8)&0xFF); + } + + /** + * Convert an int into its little-endian byte string representation. + * + * @param array the array in which to store the byte string. + * @param offset the offset in the array where the string will start. + * @param value the value to convert. + */ + public static void bytesFromInt(byte[] array, int offset, int value) { + array[offset+0] = (byte) ((value>>0) &0xFF); + array[offset+1] = (byte) ((value>>8) &0xFF); + array[offset+2] = (byte) ((value>>16)&0xFF); + array[offset+3] = (byte) ((value>>24)&0xFF); + } + + /** + * Convert an int into its little-endian byte string representation, and + * return an array containing it. + * + * @param value the value to convert. + * @return an array containing the byte string. + */ + public static byte[] bytesFromInt(int value) { + byte[] array = new byte[4]; + bytesFromInt(array, 0, value); + return array; + } + + /** + * Convert an int into a little-endian byte string representation of the + * specified length. + * + * @param array the array in which to store the byte string. + * @param offset the offset in the array where the string will start. + * @param length the number of bytes to store (must be 1, 2, or 4). + * @param value the value to convert. + */ + public static void bytesFromInt(byte[] array, int offset, + int length, int value) { + assertTrue(length==1 || length==2 || length==4); + + switch (length) { + case 1: + array[offset] = (byte) value; + break; + case 2: + bytesFromShort(array, offset, (short) value); + break; + case 4: + bytesFromInt(array, offset, value); + break; + } + } + + /** + * Convert to a short from its little-endian byte string representation. + * + * @param array the array containing the byte string. + * @param offset the offset of the byte string in the array. + * @return the corresponding short value. + */ + public static short bytesToShort(byte[] array, int offset) { + return (short) ((((short) array[offset+0] & 0xFF) << 0) | + (((short) array[offset+1] & 0xFF) << 8)); + } + + /** + * Convert to an unsigned short from its little-endian byte string + * representation. + * + * @param array the array containing the byte string. + * @param offset the offset of the byte string in the array. + * @return the corresponding short value. + */ + public static int bytesToUnsignedShort(byte[] array, int offset) { + return (((int) bytesToShort(array, offset)) & 0xFFFF); + } + + /** + * Convert to an int from its little-endian byte string representation. + * + * @param array the array containing the byte string. + * @param offset the offset of the byte string in the array. + * @return the corresponding int value. + */ + public static int bytesToInt(byte[] array, int offset) { + return (int) ((((int) array[offset+0] & 0xFF) << 0) | + (((int) array[offset+1] & 0xFF) << 8) | + (((int) array[offset+2] & 0xFF) << 16) | + (((int) array[offset+3] & 0xFF) << 24)); + } + + /** + * Convert to an int from a little-endian byte string representation of the + * specified length. + * + * @param array the array containing the byte string. + * @param offset the offset of the byte string in the array. + * @param length the length of the byte string. + * @return the corresponding value. + */ + public static int bytesToInt(byte[] array, int offset, int length) { + assertTrue(length==1 || length==2 || length==4); + + switch (length) { + case 1: + return array[offset]; + case 2: + return bytesToShort(array, offset); + case 4: + return bytesToInt(array, offset); + default: + return -1; + } + } + + /** + * Convert to a string from a possibly null-terminated array of bytes. + * + * @param array the array containing the byte string. + * @param offset the offset of the byte string in the array. + * @param length the maximum length of the byte string. + * @return a string containing the specified bytes, up to and not + * including the null-terminator (if present). + */ + public static String bytesToString(byte[] array, int offset, int length) { + int i; + for (i=0; i> lowest); + else + return ((bits >> lowest) & ((1<> lowest); + else + return ((bits >> lowest) & ((1L<> extra); + } + + /** Test if a bit is set in a bit string. + * + * @param flag the flag to test. + * @param bits the bit string. + * @return true if (bits & flag) is non-zero. + */ + public static boolean test(long flag, long bits) { + return ((bits & flag) != 0); + } + + /** + * Creates a padded upper-case string representation of the integer + * argument in base 16. + * + * @param i an integer. + * @return a padded upper-case string representation in base 16. + */ + public static String toHexString(int i) { + return toHexString(i, 8); + } + + /** + * Creates a padded upper-case string representation of the integer + * argument in base 16, padding to at most the specified number of digits. + * + * @param i an integer. + * @param pad the minimum number of hex digits to pad to. + * @return a padded upper-case string representation in base 16. + */ + public static String toHexString(int i, int pad) { + String result = Integer.toHexString(i).toUpperCase(); + while (result.length() < pad) + result = "0" + result; + return result; + } + + /** + * Divide two non-negative integers, round the quotient up to the nearest + * integer, and return it. + * + * @param a the numerator. + * @param b the denominator. + * @return ceiling(a / b). + */ + public static int divRoundUp(int a, int b) { + assertTrue(a >= 0 && b > 0); + + return ((a + (b-1)) / b); + } + + /** + * Load and return the named class, or return null if the class + * could not be loaded. + * + * @param className the name of the class to load. + * @return the loaded class, or null if an error occurred. + */ + public static Class tryLoadClass(String className) { + try { + return ClassLoader.getSystemClassLoader().loadClass(className); + } + catch (Throwable e) { + return null; + } + } + + /** + * Load and return the named class, terminating Nachos on any error. + * + * @param className the name of the class to load. + * @return the loaded class. + */ + public static Class loadClass(String className) { + try { + return ClassLoader.getSystemClassLoader().loadClass(className); + } + catch (Throwable e) { + Machine.terminate(e); + return null; + } + } + + /** + * Create and return a new instance of the named class, using the + * constructor that takes no arguments. + * + * @param className the name of the class to instantiate. + * @return a new instance of the class. + */ + public static Object constructObject(String className) { + try { + // kamil - workaround for Java 1.4 + // Thanks to Ka-Hing Cheung for the suggestion. + // Fixed for Java 1.5 by geels + Class[] param_types = new Class[0]; + Object[] params = new Object[0]; + return loadClass(className).getConstructor(param_types).newInstance(params); + } + catch (Throwable e) { + Machine.terminate(e); + return null; + } + } + + /** + * Verify that the specified class extends or implements the specified + * superclass. + * + * @param cls the descendant class. + * @param superCls the ancestor class. + */ + public static void checkDerivation(Class cls, Class superCls) { + Lib.assertTrue(superCls.isAssignableFrom(cls)); + } + + /** + * Verifies that the specified class is public and not abstract, and that a + * constructor with the specified signature exists and is public. + * + * @param cls the class containing the constructor. + * @param parameterTypes the list of parameters. + */ + public static void checkConstructor(Class cls, Class[] parameterTypes) { + try { + Lib.assertTrue(Modifier.isPublic(cls.getModifiers()) && + !Modifier.isAbstract(cls.getModifiers())); + Constructor constructor = cls.getConstructor(parameterTypes); + Lib.assertTrue(Modifier.isPublic(constructor.getModifiers())); + } + catch (Exception e) { + Lib.assertNotReached(); + } + } + + /** + * Verifies that the specified class is public, and that a non-static + * method with the specified name and signature exists, is public, and + * returns the specified type. + * + * @param cls the class containing the non-static method. + * @param methodName the name of the non-static method. + * @param parameterTypes the list of parameters. + * @param returnType the required return type. + */ + public static void checkMethod(Class cls, String methodName, + Class[] parameterTypes, Class returnType) { + try { + Lib.assertTrue(Modifier.isPublic(cls.getModifiers())); + Method method = cls.getMethod(methodName, parameterTypes); + Lib.assertTrue(Modifier.isPublic(method.getModifiers()) && + !Modifier.isStatic(method.getModifiers())); + Lib.assertTrue(method.getReturnType() == returnType); + } + catch (Exception e) { + Lib.assertNotReached(); + } + } + + /** + * Verifies that the specified class is public, and that a static method + * with the specified name and signature exists, is public, and returns the + * specified type. + * + * @param cls the class containing the static method. + * @param methodName the name of the static method. + * @param parameterTypes the list of parameters. + * @param returnType the required return type. + */ + public static void checkStaticMethod(Class cls, String methodName, + Class[] parameterTypes, + Class returnType) { + try { + Lib.assertTrue(Modifier.isPublic(cls.getModifiers())); + Method method = cls.getMethod(methodName, parameterTypes); + Lib.assertTrue(Modifier.isPublic(method.getModifiers()) && + Modifier.isStatic(method.getModifiers())); + Lib.assertTrue(method.getReturnType() == returnType); + } + catch (Exception e) { + Lib.assertNotReached(); + } + } + + /** + * Verifies that the specified class is public, and that a non-static field + * with the specified name and type exists, is public, and is not final. + * + * @param cls the class containing the field. + * @param fieldName the name of the field. + * @param fieldType the required type. + */ + public static void checkField(Class cls, String fieldName, + Class fieldType) { + try { + Lib.assertTrue(Modifier.isPublic(cls.getModifiers())); + Field field = cls.getField(fieldName); + Lib.assertTrue(field.getType() == fieldType); + Lib.assertTrue(Modifier.isPublic(field.getModifiers()) && + !Modifier.isStatic(field.getModifiers()) && + !Modifier.isFinal(field.getModifiers())); + } + catch (Exception e) { + Lib.assertNotReached(); + } + } + + /** + * Verifies that the specified class is public, and that a static field + * with the specified name and type exists and is public. + * + * @param cls the class containing the static field. + * @param fieldName the name of the static field. + * @param fieldType the required type. + */ + public static void checkStaticField(Class cls, String fieldName, + Class fieldType) { + try { + Lib.assertTrue(Modifier.isPublic(cls.getModifiers())); + Field field = cls.getField(fieldName); + Lib.assertTrue(field.getType() == fieldType); + Lib.assertTrue(Modifier.isPublic(field.getModifiers()) && + Modifier.isStatic(field.getModifiers())); + } + catch (Exception e) { + Lib.assertNotReached(); + } + } +} diff --git a/machine/Machine.java b/machine/Machine.java new file mode 100644 index 0000000..7463ac5 --- /dev/null +++ b/machine/Machine.java @@ -0,0 +1,489 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import nachos.security.*; +import nachos.ag.*; + +import java.io.File; + +/** + * The master class of the simulated machine. Processes command line arguments, + * constructs all simulated hardware devices, and starts the grader. + */ +public final class Machine { + /** + * Nachos main entry point. + * + * @param args the command line arguments. + */ + public static void main(final String[] args) { + System.out.print("nachos 5.0j initializing..."); + + Lib.assertTrue(Machine.args == null); + Machine.args = args; + + processArgs(); + + Config.load(configFileName); + + // get the current directory (.) + baseDirectory = new File(new File("").getAbsolutePath()); + // get the nachos directory (./nachos) + nachosDirectory = new File(baseDirectory, "nachos"); + + String testDirectoryName = + Config.getString("FileSystem.testDirectory"); + + // get the test directory + if (testDirectoryName != null) { + testDirectory = new File(testDirectoryName); + } + else { + // use ../test + testDirectory = new File(baseDirectory.getParentFile(), "test"); + } + + securityManager = new NachosSecurityManager(testDirectory); + privilege = securityManager.getPrivilege(); + + privilege.machine = new MachinePrivilege(); + + TCB.givePrivilege(privilege); + privilege.stats = stats; + + securityManager.enable(); + createDevices(); + checkUserClasses(); + + autoGrader = (AutoGrader) Lib.constructObject(autoGraderClassName); + + new TCB().start(new Runnable() { + public void run() { autoGrader.start(privilege); } + }); + } + + /** + * Yield to non-Nachos threads. Use in non-preemptive JVM's to give + * non-Nachos threads a chance to run. + */ + public static void yield() { + Thread.yield(); + } + + /** + * Terminate Nachos. Same as TCB.die(). + */ + public static void terminate() { + TCB.die(); + } + + /** + * Terminate Nachos as the result of an unhandled exception or error. + * + * @param e the exception or error. + */ + public static void terminate(Throwable e) { + if (e instanceof ThreadDeath) + throw (ThreadDeath) e; + + e.printStackTrace(); + terminate(); + } + + /** + * Print stats, and terminate Nachos. + */ + public static void halt() { + System.out.print("Machine halting!\n\n"); + stats.print(); + terminate(); + } + + /** + * Return an array containing all command line arguments. + * + * @return the command line arguments passed to Nachos. + */ + public static String[] getCommandLineArguments() { + String[] result = new String[args.length]; + + System.arraycopy(args, 0, result, 0, args.length); + + return result; + } + + private static void processArgs() { + for (int i=0; i 0 && arg.charAt(0) == '-') { + if (arg.equals("-d")) { + Lib.assertTrue(i < args.length, "switch without argument"); + Lib.enableDebugFlags(args[i++]); + } + else if (arg.equals("-h")) { + System.out.print(help); + System.exit(1); + } + else if (arg.equals("-m")) { + Lib.assertTrue(i < args.length, "switch without argument"); + try { + numPhysPages = Integer.parseInt(args[i++]); + } + catch (NumberFormatException e) { + Lib.assertNotReached("bad value for -m switch"); + } + } + else if (arg.equals("-s")) { + Lib.assertTrue(i < args.length, "switch without argument"); + try { + randomSeed = Long.parseLong(args[i++]); + } + catch (NumberFormatException e) { + Lib.assertNotReached("bad value for -s switch"); + } + } + else if (arg.equals("-x")) { + Lib.assertTrue(i < args.length, "switch without argument"); + shellProgramName = args[i++]; + } + else if (arg.equals("-z")) { + System.out.print(copyright); + System.exit(1); + } + // these switches are reserved for the autograder + else if (arg.equals("-[]")) { + Lib.assertTrue(i < args.length, "switch without argument"); + configFileName = args[i++]; + } + else if (arg.equals("--")) { + Lib.assertTrue(i < args.length, "switch without argument"); + autoGraderClassName = args[i++]; + } + } + } + + Lib.seedRandom(randomSeed); + } + + private static void createDevices() { + interrupt = new Interrupt(privilege); + timer = new Timer(privilege); + + if (Config.getBoolean("Machine.bank")) + bank = new ElevatorBank(privilege); + + if (Config.getBoolean("Machine.processor")) { + if (numPhysPages == -1) + numPhysPages = Config.getInteger("Processor.numPhysPages"); + processor = new Processor(privilege, numPhysPages); + } + + if (Config.getBoolean("Machine.console")) + console = new StandardConsole(privilege); + + if (Config.getBoolean("Machine.stubFileSystem")) + stubFileSystem = new StubFileSystem(privilege, testDirectory); + + if (Config.getBoolean("Machine.networkLink")) + networkLink = new NetworkLink(privilege); + } + + private static void checkUserClasses() { + System.out.print(" user-check"); + + Class aclsInt = (new int[0]).getClass(); + Class clsObject = Lib.loadClass("java.lang.Object"); + Class clsRunnable = Lib.loadClass("java.lang.Runnable"); + Class clsString = Lib.loadClass("java.lang.String"); + + Class clsKernel = Lib.loadClass("nachos.machine.Kernel"); + Class clsFileSystem = Lib.loadClass("nachos.machine.FileSystem"); + Class clsRiderControls = Lib.loadClass("nachos.machine.RiderControls"); + Class clsElevatorControls = + Lib.loadClass("nachos.machine.ElevatorControls"); + Class clsRiderInterface = + Lib.loadClass("nachos.machine.RiderInterface"); + Class clsElevatorControllerInterface = + Lib.loadClass("nachos.machine.ElevatorControllerInterface"); + + Class clsAlarm = Lib.loadClass("nachos.threads.Alarm"); + Class clsThreadedKernel = + Lib.loadClass("nachos.threads.ThreadedKernel"); + Class clsKThread = Lib.loadClass("nachos.threads.KThread"); + Class clsCommunicator = Lib.loadClass("nachos.threads.Communicator"); + Class clsSemaphore = Lib.loadClass("nachos.threads.Semaphore"); + Class clsLock = Lib.loadClass("nachos.threads.Lock"); + Class clsCondition = Lib.loadClass("nachos.threads.Condition"); + Class clsCondition2 = Lib.loadClass("nachos.threads.Condition2"); + Class clsRider = Lib.loadClass("nachos.threads.Rider"); + Class clsElevatorController = + Lib.loadClass("nachos.threads.ElevatorController"); + + Lib.checkDerivation(clsThreadedKernel, clsKernel); + + Lib.checkStaticField(clsThreadedKernel, "alarm", clsAlarm); + Lib.checkStaticField(clsThreadedKernel, "fileSystem", clsFileSystem); + + Lib.checkMethod(clsAlarm, "waitUntil", new Class[] { long.class }, + void.class); + + Lib.checkConstructor(clsKThread, new Class[] { }); + Lib.checkConstructor(clsKThread, new Class[] { clsRunnable }); + + Lib.checkStaticMethod(clsKThread, "currentThread", new Class[] {}, + clsKThread); + Lib.checkStaticMethod(clsKThread, "finish", new Class[] {}, + void.class); + Lib.checkStaticMethod(clsKThread, "yield", new Class[] {}, void.class); + Lib.checkStaticMethod(clsKThread, "sleep", new Class[] {}, void.class); + + Lib.checkMethod(clsKThread, "setTarget", new Class[]{ clsRunnable }, + clsKThread); + Lib.checkMethod(clsKThread, "setName", new Class[] { clsString }, + clsKThread); + Lib.checkMethod(clsKThread, "getName", new Class[] { }, clsString); + Lib.checkMethod(clsKThread, "fork", new Class[] { }, void.class); + Lib.checkMethod(clsKThread, "ready", new Class[] { }, void.class); + Lib.checkMethod(clsKThread, "join", new Class[] { }, void.class); + + Lib.checkField(clsKThread, "schedulingState", clsObject); + + Lib.checkConstructor(clsCommunicator, new Class[] {}); + Lib.checkMethod(clsCommunicator, "speak", new Class[] { int.class }, + void.class); + Lib.checkMethod(clsCommunicator, "listen", new Class[] { }, int.class); + + Lib.checkConstructor(clsSemaphore, new Class[] { int.class }); + Lib.checkMethod(clsSemaphore, "P", new Class[] { }, void.class); + Lib.checkMethod(clsSemaphore, "V", new Class[] { }, void.class); + + Lib.checkConstructor(clsLock, new Class[] { }); + Lib.checkMethod(clsLock, "acquire", new Class[] { }, void.class); + Lib.checkMethod(clsLock, "release", new Class[] { }, void.class); + Lib.checkMethod(clsLock, "isHeldByCurrentThread", new Class[]{ }, + boolean.class); + + Lib.checkConstructor(clsCondition, new Class[] { clsLock }); + Lib.checkConstructor(clsCondition2, new Class[] { clsLock }); + + Lib.checkMethod(clsCondition, "sleep", new Class[] { }, void.class); + Lib.checkMethod(clsCondition, "wake", new Class[] { }, void.class); + Lib.checkMethod(clsCondition, "wakeAll", new Class[] { }, void.class); + Lib.checkMethod(clsCondition2, "sleep", new Class[] { }, void.class); + Lib.checkMethod(clsCondition2, "wake", new Class[] { }, void.class); + Lib.checkMethod(clsCondition2, "wakeAll", new Class[] { }, void.class); + + Lib.checkDerivation(clsRider, clsRiderInterface); + + Lib.checkConstructor(clsRider, new Class[] { }); + Lib.checkMethod(clsRider, "initialize", + new Class[] { clsRiderControls, aclsInt }, void.class); + + Lib.checkDerivation(clsElevatorController, + clsElevatorControllerInterface); + + Lib.checkConstructor(clsElevatorController, new Class[] { }); + Lib.checkMethod(clsElevatorController, "initialize", + new Class[] { clsElevatorControls }, void.class); + } + + /** + * Prevent instantiation. + */ + private Machine() { + } + + /** + * Return the hardware interrupt manager. + * + * @return the hardware interrupt manager. + */ + public static Interrupt interrupt() { return interrupt; } + + /** + * Return the hardware timer. + * + * @return the hardware timer. + */ + public static Timer timer() { return timer; } + + /** + * Return the hardware elevator bank. + * + * @return the hardware elevator bank, or null if it is not + * present. + */ + public static ElevatorBank bank() { return bank; } + + /** + * Return the MIPS processor. + * + * @return the MIPS processor, or null if it is not present. + */ + public static Processor processor() { return processor; } + + /** + * Return the hardware console. + * + * @return the hardware console, or null if it is not present. + */ + public static SerialConsole console() { return console; } + + /** + * Return the stub filesystem. + * + * @return the stub file system, or null if it is not present. + */ + public static FileSystem stubFileSystem() { return stubFileSystem; } + + /** + * Return the network link. + * + * @return the network link, or null if it is not present. + */ + public static NetworkLink networkLink() { return networkLink; } + + /** + * Return the autograder. + * + * @return the autograder. + */ + public static AutoGrader autoGrader() { return autoGrader; } + + private static Interrupt interrupt = null; + private static Timer timer = null; + private static ElevatorBank bank = null; + private static Processor processor = null; + private static SerialConsole console = null; + private static FileSystem stubFileSystem = null; + private static NetworkLink networkLink = null; + private static AutoGrader autoGrader = null; + + private static String autoGraderClassName = "nachos.ag.AutoGrader"; + + /** + * Return the name of the shell program that a user-programming kernel + * must run. Make sure UserKernel.run() always uses this + * method to decide which program to run. + * + * @return the name of the shell program to run. + */ + public static String getShellProgramName() { + if (shellProgramName == null) + shellProgramName = Config.getString("Kernel.shellProgram"); + + Lib.assertTrue(shellProgramName != null); + return shellProgramName; + } + + private static String shellProgramName = null; + + /** + * Return the name of the process class that the kernel should use. In + * the multi-programming project, returns + * nachos.userprog.UserProcess. In the VM project, returns + * nachos.vm.VMProcess. In the networking project, returns + * nachos.network.NetProcess. + * + * @return the name of the process class that the kernel should use. + * + * @see nachos.userprog.UserKernel#run + * @see nachos.userprog.UserProcess + * @see nachos.vm.VMProcess + * @see nachos.network.NetProcess + */ + public static String getProcessClassName() { + if (processClassName == null) + processClassName = Config.getString("Kernel.processClassName"); + + Lib.assertTrue(processClassName != null); + return processClassName; + } + + private static String processClassName = null; + + private static NachosSecurityManager securityManager; + private static Privilege privilege; + + private static String[] args = null; + + private static Stats stats = new Stats(); + + private static int numPhysPages = -1; + private static long randomSeed = 0; + + private static File baseDirectory, nachosDirectory, testDirectory; + private static String configFileName = "nachos.conf"; + + private static final String help = + "\n" + + "Options:\n" + + "\n" + + "\t-d \n" + + "\t\tEnable some debug flags, e.g. -d ti\n" + + "\n" + + "\t-h\n" + + "\t\tPrint this help message.\n" + + "\n" + + "\t-m \n" + + "\t\tSpecify how many physical pages of memory to simulate.\n" + + "\n" + + "\t-s \n" + + "\t\tSpecify the seed for the random number generator (seed is a\n" + + "\t\tlong).\n" + + "\n" + + "\t-x \n" + + "\t\tSpecify a program that UserKernel.run() should execute,\n" + + "\t\tinstead of the value of the configuration variable\n" + + "\t\tKernel.shellProgram\n" + + "\n" + + "\t-z\n" + + "\t\tprint the copyright message\n" + + "\n" + + "\t-- \n" + + "\t\tSpecify an autograder class to use, instead of\n" + + "\t\tnachos.ag.AutoGrader\n" + + "\n" + + "\t-# \n" + + "\t\tSpecify the argument string to pass to the autograder.\n" + + "\n" + + "\t-[] \n" + + "\t\tSpecifiy a config file to use, instead of nachos.conf\n" + + "" + ; + + private static final String copyright = "\n" + + "Copyright 1992-2001 The Regents of the University of California.\n" + + "All rights reserved.\n" + + "\n" + + "Permission to use, copy, modify, and distribute this software and\n" + + "its documentation for any purpose, without fee, and without\n" + + "written agreement is hereby granted, provided that the above\n" + + "copyright notice and the following two paragraphs appear in all\n" + + "copies of this software.\n" + + "\n" + + "IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY\n" + + "PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL\n" + + "DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS\n" + + "DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN\n" + + "ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" + + "\n" + + "THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY\n" + + "WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n" + + "OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE\n" + + "SOFTWARE PROVIDED HEREUNDER IS ON AN \"AS IS\" BASIS, AND THE\n" + + "UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE\n" + + "MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\n" + ; + + private static class MachinePrivilege + implements Privilege.MachinePrivilege { + public void setConsole(SerialConsole console) { + Machine.console = console; + } + } + + // dummy variables to make javac smarter + private static Coff dummy1 = null; +} diff --git a/machine/MalformedPacketException.java b/machine/MalformedPacketException.java new file mode 100644 index 0000000..c468bd8 --- /dev/null +++ b/machine/MalformedPacketException.java @@ -0,0 +1,14 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +/** + * Thrown when a malformed packet is processed. + */ +public class MalformedPacketException extends Exception { + /** + * Allocate a new MalformedPacketException. + */ + public MalformedPacketException() { + } +} diff --git a/machine/NetworkLink.java b/machine/NetworkLink.java new file mode 100644 index 0000000..dbcfcb3 --- /dev/null +++ b/machine/NetworkLink.java @@ -0,0 +1,329 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import nachos.security.*; + +import java.io.IOException; +import java.net.DatagramSocket; +import java.net.DatagramPacket; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.net.SocketException; + +/** + * A full-duplex network link. Provides ordered, unreliable delivery of + * limited-size packets to other machines on the network. Packets are + * guaranteed to be uncorrupted as well. + * + *

+ * Recall the general layering of network protocols: + *

    + *
  • Session/Transport + *
  • Network + *
  • Link + *
  • Physical + *
+ * + *

+ * The physical layer provides a bit stream interface to the link layer. This + * layer is very hardware-dependent. + * + *

+ * The link layer uses the physical layer to provide a packet interface to the + * network layer. The link layer generally provides unreliable delivery of + * limited-size packets, but guarantees that packets will not arrive out of + * order. Some links protect against packet corruption as well. The ethernet + * protocol is an example of a link layer. + * + *

+ * The network layer exists to connect multiple networks together into an + * internet. The network layer provides globally unique addresses. Routers + * (a.k.a. gateways) move packets across networks at this layer. The network + * layer provides unordered, unreliable delivery of limited-size uncorrupted + * packets to any machine on the same internet. The most commonly used network + * layer protocol is IP (Internet Protocol), which is used to connect the + * Internet. + * + *

+ * The session/transport layer provides a byte-stream interface to the + * application. This means that the transport layer must deliver uncorrupted + * bytes to the application, in the same order they were sent. Byte-streams + * must be connected and disconnected, and exist between ports, not machines. + * + *

+ * This class provides a link layer abstraction. Since we do not allow + * different Nachos networks to communicate with one another, there is no need + * for a network layer in Nachos. This should simplify your design for the + * session/transport layer, since you can assume packets never arrive out of + * order. + */ +public class NetworkLink { + /** + * Allocate a new network link. + * + *

+ * nachos.conf specifies the reliability of the network. The + * reliability, between 0 and 1, is the probability that any particular + * packet will not get dropped by the network. + * + * @param privilege encapsulates privileged access to the Nachos + * machine. + */ + public NetworkLink(Privilege privilege) { + System.out.print(" network"); + + this.privilege = privilege; + + try { + localHost = InetAddress.getLocalHost(); + } + catch (UnknownHostException e) { + localHost = null; + } + + Lib.assertTrue(localHost != null); + + reliability = Config.getDouble("NetworkLink.reliability"); + Lib.assertTrue(reliability > 0 && reliability <= 1.0); + + socket = null; + + for (linkAddress=0;linkAddress + * The receive interrupt handler is called every time a packet arrives + * and can be read using receive(). + * + *

+ * The send interrupt handler is called every time a packet sent with + * send() is finished being sent. This means that another + * packet can be sent. + * + * @param receiveInterruptHandler the callback to call when a packet + * arrives. + * @param sendInterruptHandler the callback to call when another + * packet can be sent. + */ + public void setInterruptHandlers(Runnable receiveInterruptHandler, + Runnable sendInterruptHandler) { + this.receiveInterruptHandler = receiveInterruptHandler; + this.sendInterruptHandler = sendInterruptHandler; + } + + private void scheduleReceiveInterrupt() { + privilege.interrupt.schedule(Stats.NetworkTime, "network recv", + receiveInterrupt); + } + + private synchronized void receiveInterrupt() { + Lib.assertTrue(incomingPacket == null); + + if (incomingBytes != null) { + if (Machine.autoGrader().canReceivePacket(privilege)) { + try { + incomingPacket = new Packet(incomingBytes); + + privilege.stats.numPacketsReceived++; + } + catch (MalformedPacketException e) { + } + } + + incomingBytes = null; + notify(); + + if (incomingPacket == null) + scheduleReceiveInterrupt(); + else if (receiveInterruptHandler != null) + receiveInterruptHandler.run(); + } + else { + scheduleReceiveInterrupt(); + } + } + + /** + * Return the next packet received. + * + * @return the next packet received, or null if no packet is + * available. + */ + public Packet receive() { + Packet p = incomingPacket; + + if (incomingPacket != null) { + incomingPacket = null; + scheduleReceiveInterrupt(); + } + + return p; + } + + private void receiveLoop() { + while (true) { + synchronized(this) { + while (incomingBytes != null) { + try { + wait(); + } + catch (InterruptedException e) { + } + } + } + + byte[] packetBytes; + + try { + byte[] buffer = new byte[Packet.maxPacketLength]; + + DatagramPacket dp = new DatagramPacket(buffer, buffer.length); + + socket.receive(dp); + + packetBytes = new byte[dp.getLength()]; + + System.arraycopy(buffer,0, packetBytes,0, packetBytes.length); + } + catch (IOException e) { + return; + } + + synchronized(this) { + incomingBytes = packetBytes; + } + } + } + + private void scheduleSendInterrupt() { + privilege.interrupt.schedule(Stats.NetworkTime, "network send", + sendInterrupt); + } + + private void sendInterrupt() { + Lib.assertTrue(outgoingPacket != null); + + // randomly drop packets, according to its reliability + if (Machine.autoGrader().canSendPacket(privilege) && + Lib.random() <= reliability) { + // ok, no drop + privilege.doPrivileged(new Runnable() { + public void run() { sendPacket(); } + }); + } + else { + outgoingPacket = null; + } + + if (sendInterruptHandler != null) + sendInterruptHandler.run(); + } + + private void sendPacket() { + Packet p = outgoingPacket; + outgoingPacket = null; + + try { + socket.send(new DatagramPacket(p.packetBytes, p.packetBytes.length, + localHost, portBase+p.dstLink)); + + privilege.stats.numPacketsSent++; + } + catch (IOException e) { + } + } + + /** + * Send another packet. If a packet is already being sent, the result is + * not defined. + * + * @param pkt the packet to send. + */ + public void send(Packet pkt) { + if (outgoingPacket == null) + scheduleSendInterrupt(); + + outgoingPacket = pkt; + } + + private static final int hash; + private static final int portBase; + + /** + * The address of the network to which are attached all network links in + * this JVM. This is a hash on the account name of the JVM running this + * Nachos instance. It is used to help prevent packets from other users + * from accidentally interfering with this network. + */ + public static final byte networkID; + + static { + hash = System.getProperty("user.name").hashCode(); + portBase = 0x4E41 + Math.abs(hash%0x4E41); + networkID = (byte) (hash/0x4E41); + } + + private Privilege privilege; + + private Runnable receiveInterrupt; + private Runnable sendInterrupt; + + private Runnable receiveInterruptHandler = null; + private Runnable sendInterruptHandler = null; + + private InetAddress localHost; + private DatagramSocket socket; + + private byte linkAddress; + private double reliability; + + private byte[] incomingBytes = null; + private Packet incomingPacket = null; + private Packet outgoingPacket = null; + + private boolean sendBusy = false; +} diff --git a/machine/OpenFile.java b/machine/OpenFile.java new file mode 100644 index 0000000..18a2942 --- /dev/null +++ b/machine/OpenFile.java @@ -0,0 +1,141 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import java.io.EOFException; + +/** + * A file that supports reading, writing, and seeking. + */ +public class OpenFile { + /** + * Allocate a new OpenFile object with the specified name on the + * specified file system. + * + * @param fileSystem the file system to which this file belongs. + * @param name the name of the file, on that file system. + */ + public OpenFile(FileSystem fileSystem, String name) { + this.fileSystem = fileSystem; + this.name = name; + } + + /** + * Allocate a new unnamed OpenFile that is not associated with any + * file system. + */ + public OpenFile() { + this(null, "unnamed"); + } + + /** + * Get the file system to which this file belongs. + * + * @return the file system to which this file belongs. + */ + public FileSystem getFileSystem() { + return fileSystem; + } + + /** + * Get the name of this open file. + * + * @return the name of this open file. + */ + public String getName() { + return name; + } + + /** + * Read this file starting at the specified position and return the number + * of bytes successfully read. If no bytes were read because of a fatal + * error, returns -1 + * + * @param pos the offset in the file at which to start reading. + * @param buf the buffer to store the bytes in. + * @param offset the offset in the buffer to start storing bytes. + * @param length the number of bytes to read. + * @return the actual number of bytes successfully read, or -1 on failure. + */ + public int read(int pos, byte[] buf, int offset, int length) { + return -1; + } + + /** + * Write this file starting at the specified position and return the number + * of bytes successfully written. If no bytes were written because of a + * fatal error, returns -1. + * + * @param pos the offset in the file at which to start writing. + * @param buf the buffer to get the bytes from. + * @param offset the offset in the buffer to start getting. + * @param length the number of bytes to write. + * @return the actual number of bytes successfully written, or -1 on + * failure. + */ + public int write(int pos, byte[] buf, int offset, int length) { + return -1; + } + + /** + * Get the length of this file. + * + * @return the length of this file, or -1 if this file has no length. + */ + public int length() { + return -1; + } + + /** + * Close this file and release any associated system resources. + */ + public void close() { + } + + /** + * Set the value of the current file pointer. + */ + public void seek(int pos) { + } + + /** + * Get the value of the current file pointer, or -1 if this file has no + * pointer. + */ + public int tell() { + return -1; + } + + /** + * Read this file starting at the current file pointer and return the + * number of bytes successfully read. Advances the file pointer by this + * amount. If no bytes could be* read because of a fatal error, returns -1. + * + * @param buf the buffer to store the bytes in. + * @param offset the offset in the buffer to start storing bytes. + * @param length the number of bytes to read. + * @return the actual number of bytes successfully read, or -1 on failure. + */ + public int read(byte[] buf, int offset, int length) { + return -1; + } + + /** + * Write this file starting at the current file pointer and return the + * number of bytes successfully written. Advances the file pointer by this + * amount. If no bytes could be written because of a fatal error, returns + * -1. + * + * @param buf the buffer to get the bytes from. + * @param offset the offset in the buffer to start getting. + * @param length the number of bytes to write. + * @return the actual number of bytes successfully written, or -1 on + * failure. + */ + public int write(byte[] buf, int offset, int length) { + return -1; + } + + private FileSystem fileSystem; + private String name; +} diff --git a/machine/OpenFileWithPosition.java b/machine/OpenFileWithPosition.java new file mode 100644 index 0000000..514c3c4 --- /dev/null +++ b/machine/OpenFileWithPosition.java @@ -0,0 +1,58 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +/** + * An OpenFile that maintains a current file position. + */ +public abstract class OpenFileWithPosition extends OpenFile { + /** + * Allocate a new OpenFileWithPosition with the specified name on + * the specified file system. + * + * @param fileSystem the file system to which this file belongs. + * @param name the name of the file, on that file system. + */ + public OpenFileWithPosition(FileSystem fileSystem, String name) { + super(fileSystem, name); + } + + /** + * Allocate a new unnamed OpenFileWithPosition that is not + * associated with any file system. + */ + public OpenFileWithPosition() { + super(); + } + + public void seek(int position) { + this.position = position; + } + + public int tell() { + return position; + } + + public int read(byte[] buf, int offset, int length) { + int amount = read(position, buf, offset, length); + if (amount == -1) + return -1; + + position += amount; + return amount; + } + + public int write(byte[] buf, int offset, int length) { + int amount = write(position, buf, offset, length); + if (amount == -1) + return -1; + + position += amount; + return amount; + } + + /** + * The current value of the file pointer. + */ + protected int position = 0; +} diff --git a/machine/Packet.java b/machine/Packet.java new file mode 100644 index 0000000..688e0cf --- /dev/null +++ b/machine/Packet.java @@ -0,0 +1,106 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +/** + * A link-layer packet. + * + * @see nachos.machine.NetworkLink + */ +public class Packet { + /** + * Allocate a new packet to be sent, using the specified parameters. + * + * @param dstLink the destination link address. + * @param srcLink the source link address. + * @param contents the contents of the packet. + */ + public Packet(int dstLink, int srcLink, byte[] contents) + throws MalformedPacketException { + // make sure the paramters are valid + if (dstLink < 0 || dstLink >= linkAddressLimit || + srcLink < 0 || srcLink >= linkAddressLimit || + contents.length > maxContentsLength) + throw new MalformedPacketException(); + + this.dstLink = dstLink; + this.srcLink = srcLink; + this.contents = contents; + + packetBytes = new byte[headerLength + contents.length]; + + packetBytes[0] = NetworkLink.networkID; + packetBytes[1] = (byte) dstLink; + packetBytes[2] = (byte) srcLink; + packetBytes[3] = (byte) contents.length; + + // if java had subarrays, i'd use them. but System.arraycopy is ok... + System.arraycopy(contents, 0, packetBytes, headerLength, + contents.length); + } + + /** + * Allocate a new packet using the specified array of bytes received from + * the network. + * + * @param packetBytes the bytes making up this packet. + */ + public Packet(byte[] packetBytes) throws MalformedPacketException { + this.packetBytes = packetBytes; + + // make sure we have a valid header + if (packetBytes.length < headerLength || + packetBytes[0] != NetworkLink.networkID || + packetBytes[1] < 0 || packetBytes[1] >= linkAddressLimit || + packetBytes[2] < 0 || packetBytes[2] >= linkAddressLimit || + packetBytes[3] < 0 || packetBytes[3] > packetBytes.length-4) + throw new MalformedPacketException(); + + dstLink = packetBytes[1]; + srcLink = packetBytes[2]; + + contents = new byte[packetBytes[3]]; + System.arraycopy(packetBytes, headerLength, contents, 0, + contents.length); + } + + /** This packet, as an array of bytes that can be sent on a network. */ + public byte[] packetBytes; + /** The address of the destination link of this packet. */ + public int dstLink; + /** The address of the source link of this packet. */ + public int srcLink; + /** The contents of this packet, excluding the link-layer header. */ + public byte[] contents; + + /** + * The number of bytes in a link-layer packet header. The header is + * formatted as follows: + * + * + * + * + * + * + * + *
offsetsizevalue
01network ID (collision detecting)
11destination link address
21source link address
31length of contents
+ */ + public static final int headerLength = 4; + /** + * The maximum length, in bytes, of a packet that can be sent or received + * on the network. + */ + public static final int maxPacketLength = 32; + /** + * The maximum number of content bytes (not including the header). Note + * that this is just maxPacketLength - headerLength. + */ + public static final int maxContentsLength = maxPacketLength - headerLength; + + /** + * The upper limit on Nachos link addresses. All link addresses fall + * between 0 and linkAddressLimit - 1. + */ + public static final int linkAddressLimit = 128; +} + diff --git a/machine/Processor.java b/machine/Processor.java new file mode 100644 index 0000000..b170e7d --- /dev/null +++ b/machine/Processor.java @@ -0,0 +1,1321 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import nachos.security.*; + +/** + * The Processor class simulates a MIPS processor that supports a + * subset of the R3000 instruction set. Specifically, the processor lacks all + * coprocessor support, and can only execute in user mode. Address translation + * information is accessed via the API. The API also allows a kernel to set an + * exception handler to be called on any user mode exception. + * + *

+ * The Processor API is re-entrant, so a single simulated processor + * can be shared by multiple user threads. + * + *

+ * An instance of a Processor also includes pages of physical memory + * accessible to user programs, the size of which is fixed by the constructor. + */ +public final class Processor { + /** + * Allocate a new MIPS processor, with the specified amount of memory. + * + * @param privilege encapsulates privileged access to the Nachos + * machine. + * @param numPhysPages the number of pages of physical memory to + * attach. + */ + public Processor(Privilege privilege, int numPhysPages) { + System.out.print(" processor"); + + this.privilege = privilege; + privilege.processor = new ProcessorPrivilege(); + + Class clsKernel = Lib.loadClass(Config.getString("Kernel.kernel")); + Class clsVMKernel = Lib.tryLoadClass("nachos.vm.VMKernel"); + + usingTLB = + (clsVMKernel != null && clsVMKernel.isAssignableFrom(clsKernel)); + + this.numPhysPages = numPhysPages; + + for (int i=0; i + * When the exception handler is called, interrupts will be enabled, and + * the CPU cause register will specify the cause of the exception (see the + * exception* constants). + * + * @param exceptionHandler the kernel exception handler. + */ + public void setExceptionHandler(Runnable exceptionHandler) { + this.exceptionHandler = exceptionHandler; + } + + /** + * Get the exception handler, set by the last call to + * setExceptionHandler(). + * + * @return the exception handler. + */ + public Runnable getExceptionHandler() { + return exceptionHandler; + } + + /** + * Start executing instructions at the current PC. Never returns. + */ + public void run() { + Lib.debug(dbgProcessor, "starting program in current thread"); + + registers[regNextPC] = registers[regPC] + 4; + + Machine.autoGrader().runProcessor(privilege); + + Instruction inst = new Instruction(); + + while (true) { + try { + inst.run(); + } + catch (MipsException e) { + e.handle(); + } + + privilege.interrupt.tick(false); + } + } + + /** + * Read and return the contents of the specified CPU register. + * + * @param number the register to read. + * @return the value of the register. + */ + public int readRegister(int number) { + Lib.assertTrue(number >= 0 && number < numUserRegisters); + + return registers[number]; + } + + /** + * Write the specified value into the specified CPU register. + * + * @param number the register to write. + * @param value the value to write. + */ + public void writeRegister(int number, int value) { + Lib.assertTrue(number >= 0 && number < numUserRegisters); + + if (number != 0) + registers[number] = value; + } + + /** + * Test whether this processor uses a software-managed TLB, or single-level + * paging. + * + *

+ * If false, this processor directly supports single-level paging; + * use setPageTable(). + * + *

+ * If true, this processor has a software-managed TLB; + * use getTLBSize(), readTLBEntry(), and + * writeTLBEntry(). + * + *

+ * Using a method associated with the wrong address translation mechanism + * will result in an assertion failure. + * + * @return true if this processor has a software-managed TLB. + */ + public boolean hasTLB() { + return usingTLB; + } + + /** + * Get the current page table, set by the last call to setPageTable(). + * + * @return the current page table. + */ + public TranslationEntry[] getPageTable() { + Lib.assertTrue(!usingTLB); + + return translations; + } + + /** + * Set the page table pointer. All further address translations will use + * the specified page table. The size of the current address space will be + * determined from the length of the page table array. + * + * @param pageTable the page table to use. + */ + public void setPageTable(TranslationEntry[] pageTable) { + Lib.assertTrue(!usingTLB); + + this.translations = pageTable; + } + + /** + * Return the number of entries in this processor's TLB. + * + * @return the number of entries in this processor's TLB. + */ + public int getTLBSize() { + Lib.assertTrue(usingTLB); + + return tlbSize; + } + + /** + * Returns the specified TLB entry. + * + * @param number the index into the TLB. + * @return the contents of the specified TLB entry. + */ + public TranslationEntry readTLBEntry(int number) { + Lib.assertTrue(usingTLB); + Lib.assertTrue(number >= 0 && number < tlbSize); + + return new TranslationEntry(translations[number]); + } + + /** + * Fill the specified TLB entry. + * + *

+ * The TLB is fully associative, so the location of an entry within the TLB + * does not affect anything. + * + * @param number the index into the TLB. + * @param entry the new contents of the TLB entry. + */ + public void writeTLBEntry(int number, TranslationEntry entry) { + Lib.assertTrue(usingTLB); + Lib.assertTrue(number >= 0 && number < tlbSize); + + translations[number] = new TranslationEntry(entry); + } + + /** + * Return the number of pages of physical memory attached to this simulated + * processor. + * + * @return the number of pages of physical memory. + */ + public int getNumPhysPages() { + return numPhysPages; + } + + /** + * Return a reference to the physical memory array. The size of this array + * is pageSize * getNumPhysPages(). + * + * @return the main memory array. + */ + public byte[] getMemory() { + return mainMemory; + } + + /** + * Concatenate a page number and an offset into an address. + * + * @param page the page number. Must be between 0 and + * (232 / pageSize) - 1. + * @param offset the offset within the page. Must be between 0 + * and + * pageSize - 1. + * @return a 32-bit address consisting of the specified page and offset. + */ + public static int makeAddress(int page, int offset) { + Lib.assertTrue(page >= 0 && page < maxPages); + Lib.assertTrue(offset >= 0 && offset < pageSize); + + return (page * pageSize) | offset; + } + + /** + * Extract the page number component from a 32-bit address. + * + * @param address the 32-bit address. + * @return the page number component of the address. + */ + public static int pageFromAddress(int address) { + return (int) (((long) address & 0xFFFFFFFFL) / pageSize); + } + + /** + * Extract the offset component from an address. + * + * @param address the 32-bit address. + * @return the offset component of the address. + */ + public static int offsetFromAddress(int address) { + return (int) (((long) address & 0xFFFFFFFFL) % pageSize); + } + + private void finishLoad() { + delayedLoad(0, 0, 0); + } + + /** + * Translate a virtual address into a physical address, using either a + * page table or a TLB. Check for alignment, make sure the virtual page is + * valid, make sure a read-only page is not being written, make sure the + * resulting physical page is valid, and then return the resulting physical + * address. + * + * @param vaddr the virtual address to translate. + * @param size the size of the memory reference (must be 1, 2, or 4). + * @param writing true if the memory reference is a write. + * @return the physical address. + * @exception MipsException if a translation error occurred. + */ + private int translate(int vaddr, int size, boolean writing) + throws MipsException { + if (Lib.test(dbgProcessor)) + System.out.println("\ttranslate vaddr=0x" + Lib.toHexString(vaddr) + + (writing ? ", write" : ", read...")); + + // check alignment + if ((vaddr & (size-1)) != 0) { + Lib.debug(dbgProcessor, "\t\talignment error"); + throw new MipsException(exceptionAddressError, vaddr); + } + + // calculate virtual page number and offset from the virtual address + int vpn = pageFromAddress(vaddr); + int offset = offsetFromAddress(vaddr); + + TranslationEntry entry = null; + + // if not using a TLB, then the vpn is an index into the table + if (!usingTLB) { + if (translations == null || vpn >= translations.length || + translations[vpn] == null || + !translations[vpn].valid) { + privilege.stats.numPageFaults++; + Lib.debug(dbgProcessor, "\t\tpage fault"); + throw new MipsException(exceptionPageFault, vaddr); + } + + entry = translations[vpn]; + } + // else, look through all TLB entries for matching vpn + else { + for (int i=0; i= numPhysPages) { + Lib.debug(dbgProcessor, "\t\tbad ppn"); + throw new MipsException(exceptionBusError, vaddr); + } + + // set used and dirty bits as appropriate + entry.used = true; + if (writing) + entry.dirty = true; + + int paddr = (ppn*pageSize) + offset; + + if (Lib.test(dbgProcessor)) + System.out.println("\t\tpaddr=0x" + Lib.toHexString(paddr)); + return paddr; + } + + /** + * Read size (1, 2, or 4) bytes of virtual memory at vaddr, + * and return the result. + * + * @param vaddr the virtual address to read from. + * @param size the number of bytes to read (1, 2, or 4). + * @return the value read. + * @exception MipsException if a translation error occurred. + */ + private int readMem(int vaddr, int size) throws MipsException { + if (Lib.test(dbgProcessor)) + System.out.println("\treadMem vaddr=0x" + Lib.toHexString(vaddr) + + ", size=" + size); + + Lib.assertTrue(size==1 || size==2 || size==4); + + int value = Lib.bytesToInt(mainMemory, translate(vaddr, size, false), + size); + + if (Lib.test(dbgProcessor)) + System.out.println("\t\tvalue read=0x" + + Lib.toHexString(value, size*2)); + + return value; + } + + /** + * Write value to size (1, 2, or 4) bytes of virtual memory + * starting at vaddr. + * + * @param vaddr the virtual address to write to. + * @param size the number of bytes to write (1, 2, or 4). + * @param value the value to store. + * @exception MipsException if a translation error occurred. + */ + private void writeMem(int vaddr, int size, int value) + throws MipsException { + if (Lib.test(dbgProcessor)) + System.out.println("\twriteMem vaddr=0x" + Lib.toHexString(vaddr) + + ", size=" + size + ", value=0x" + + Lib.toHexString(value, size*2)); + + Lib.assertTrue(size==1 || size==2 || size==4); + + Lib.bytesFromInt(mainMemory, translate(vaddr, size, true), size, + value); + } + + /** + * Complete the in progress delayed load and scheduled a new one. + * + * @param nextLoadTarget the target register of the new load. + * @param nextLoadValue the value to be loaded into the new target. + * @param nextLoadMask the mask specifying which bits in the new + * target are to be overwritten. If a bit in + * nextLoadMask is 0, then the + * corresponding bit of register + * nextLoadTarget will not be written. + */ + private void delayedLoad(int nextLoadTarget, int nextLoadValue, + int nextLoadMask) { + // complete previous delayed load, if not modifying r0 + if (loadTarget != 0) { + int savedBits = registers[loadTarget] & ~loadMask; + int newBits = loadValue & loadMask; + registers[loadTarget] = savedBits | newBits; + } + + // schedule next load + loadTarget = nextLoadTarget; + loadValue = nextLoadValue; + loadMask = nextLoadMask; + } + + /** + * Advance the PC to the next instruction. + * + *

+ * Transfer the contents of the nextPC register into the PC register, and + * then add 4 to the value in the nextPC register. Same as + * advancePC(readRegister(regNextPC)+4). + * + *

+ * Use after handling a syscall exception so that the processor will move + * on to the next instruction. + */ + public void advancePC() { + advancePC(registers[regNextPC]+4); + } + + /** + * Transfer the contents of the nextPC register into the PC register, and + * then write the nextPC register. + * + * @param nextPC the new value of the nextPC register. + */ + private void advancePC(int nextPC) { + registers[regPC] = registers[regNextPC]; + registers[regNextPC] = nextPC; + } + + /** Caused by a syscall instruction. */ + public static final int exceptionSyscall = 0; + /** Caused by an access to an invalid virtual page. */ + public static final int exceptionPageFault = 1; + /** Caused by an access to a virtual page not mapped by any TLB entry. */ + public static final int exceptionTLBMiss = 2; + /** Caused by a write access to a read-only virtual page. */ + public static final int exceptionReadOnly = 3; + /** Caused by an access to an invalid physical page. */ + public static final int exceptionBusError = 4; + /** Caused by an access to a misaligned virtual address. */ + public static final int exceptionAddressError = 5; + /** Caused by an overflow by a signed operation. */ + public static final int exceptionOverflow = 6; + /** Caused by an attempt to execute an illegal instruction. */ + public static final int exceptionIllegalInstruction = 7; + + /** The names of the CPU exceptions. */ + public static final String exceptionNames[] = { + "syscall ", + "page fault ", + "TLB miss ", + "read-only ", + "bus error ", + "address error", + "overflow ", + "illegal inst " + }; + + /** Index of return value register 0. */ + public static final int regV0 = 2; + /** Index of return value register 1. */ + public static final int regV1 = 3; + /** Index of argument register 0. */ + public static final int regA0 = 4; + /** Index of argument register 1. */ + public static final int regA1 = 5; + /** Index of argument register 2. */ + public static final int regA2 = 6; + /** Index of argument register 3. */ + public static final int regA3 = 7; + /** Index of the stack pointer register. */ + public static final int regSP = 29; + /** Index of the return address register. */ + public static final int regRA = 31; + /** Index of the low register, used for multiplication and division. */ + public static final int regLo = 32; + /** Index of the high register, used for multiplication and division. */ + public static final int regHi = 33; + /** Index of the program counter register. */ + public static final int regPC = 34; + /** Index of the next program counter register. */ + public static final int regNextPC = 35; + /** Index of the exception cause register. */ + public static final int regCause = 36; + /** Index of the exception bad virtual address register. */ + public static final int regBadVAddr = 37; + + /** The total number of software-accessible CPU registers. */ + public static final int numUserRegisters = 38; + + /** Provides privilege to this processor. */ + private Privilege privilege; + + /** MIPS registers accessible to the kernel. */ + private int registers[] = new int[numUserRegisters]; + + /** The registered target of the delayed load currently in progress. */ + private int loadTarget = 0; + /** The bits to be modified by the delayed load currently in progress. */ + private int loadMask; + /** The value to be loaded by the delayed load currently in progress. */ + private int loadValue; + + /** true if using a software-managed TLB. */ + private boolean usingTLB; + /** Number of TLB entries. */ + private int tlbSize = 4; + /** + * Either an associative or direct-mapped set of translation entries, + * depending on whether there is a TLB. + */ + private TranslationEntry[] translations; + + /** Size of a page, in bytes. */ + public static final int pageSize = 0x400; + /** Number of pages in a 32-bit address space. */ + public static final int maxPages = (int) (0x100000000L / pageSize); + /** Number of physical pages in memory. */ + private int numPhysPages; + /** Main memory for user programs. */ + private byte[] mainMemory; + + /** The kernel exception handler, called on every user exception. */ + private Runnable exceptionHandler = null; + + private static final char dbgProcessor = 'p'; + private static final char dbgDisassemble = 'm'; + private static final char dbgFullDisassemble = 'M'; + + private class ProcessorPrivilege implements Privilege.ProcessorPrivilege { + public void flushPipe() { + finishLoad(); + } + } + + private class MipsException extends Exception { + public MipsException(int cause) { + Lib.assertTrue(cause >= 0 && cause < exceptionNames.length); + + this.cause = cause; + } + + public MipsException(int cause, int badVAddr) { + this(cause); + + hasBadVAddr = true; + this.badVAddr = badVAddr; + } + + public void handle() { + writeRegister(regCause, cause); + + if (hasBadVAddr) + writeRegister(regBadVAddr, badVAddr); + + if (Lib.test(dbgDisassemble) || Lib.test(dbgFullDisassemble)) + System.out.println("exception: " + exceptionNames[cause]); + + finishLoad(); + + Lib.assertTrue(exceptionHandler != null); + + // autograder might not want kernel to know about this exception + if (!Machine.autoGrader().exceptionHandler(privilege)) + return; + + exceptionHandler.run(); + } + + private boolean hasBadVAddr = false; + private int cause, badVAddr; + } + + private class Instruction { + public void run() throws MipsException { + // hopefully this looks familiar to 152 students? + fetch(); + decode(); + execute(); + writeBack(); + } + + private boolean test(int flag) { + return Lib.test(flag, flags); + } + + private void fetch() throws MipsException { + if ((Lib.test(dbgDisassemble) && !Lib.test(dbgProcessor)) || + Lib.test(dbgFullDisassemble)) + System.out.print("PC=0x" + Lib.toHexString(registers[regPC]) + + "\t"); + + value = readMem(registers[regPC], 4); + } + + private void decode() { + op = Lib.extract(value, 26, 6); + rs = Lib.extract(value, 21, 5); + rt = Lib.extract(value, 16, 5); + rd = Lib.extract(value, 11, 5); + sh = Lib.extract(value, 6, 5); + func = Lib.extract(value, 0, 6); + target = Lib.extract(value, 0, 26); + imm = Lib.extend(value, 0, 16); + + Mips info; + switch (op) { + case 0: + info = Mips.specialtable[func]; + break; + case 1: + info = Mips.regimmtable[rt]; + break; + default: + info = Mips.optable[op]; + break; + } + + operation = info.operation; + name = info.name; + format = info.format; + flags = info.flags; + + mask = 0xFFFFFFFF; + branch = true; + + // get memory access size + if (test(Mips.SIZEB)) + size = 1; + else if (test(Mips.SIZEH)) + size = 2; + else if (test(Mips.SIZEW)) + size = 4; + else + size = 0; + + // get nextPC + nextPC = registers[regNextPC]+4; + + // get dstReg + if (test(Mips.DSTRA)) + dstReg = regRA; + else if (format == Mips.IFMT) + dstReg = rt; + else if (format == Mips.RFMT) + dstReg = rd; + else + dstReg = -1; + + // get jtarget + if (format == Mips.RFMT) + jtarget = registers[rs]; + else if (format == Mips.IFMT) + jtarget = registers[regNextPC] + (imm<<2); + else if (format == Mips.JFMT) + jtarget = (registers[regNextPC]&0xF0000000) | (target<<2); + else + jtarget = -1; + + // get imm + if (test(Mips.UNSIGNED)) { + imm &= 0xFFFF; + } + + // get addr + addr = registers[rs] + imm; + + // get src1 + if (test(Mips.SRC1SH)) + src1 = sh; + else + src1 = registers[rs]; + + // get src2 + if (test(Mips.SRC2IMM)) + src2 = imm; + else + src2 = registers[rt]; + + if (test(Mips.UNSIGNED)) { + src1 &= 0xFFFFFFFFL; + src2 &= 0xFFFFFFFFL; + } + + if (Lib.test(dbgDisassemble) || Lib.test(dbgFullDisassemble)) + print(); + } + + private void print() { + if (Lib.test(dbgDisassemble) && Lib.test(dbgProcessor) && + !Lib.test(dbgFullDisassemble)) + System.out.print("PC=0x" + Lib.toHexString(registers[regPC]) + + "\t"); + + if (operation == Mips.INVALID) { + System.out.print("invalid: op=" + Lib.toHexString(op, 2) + + " rs=" + Lib.toHexString(rs, 2) + + " rt=" + Lib.toHexString(rt, 2) + + " rd=" + Lib.toHexString(rd, 2) + + " sh=" + Lib.toHexString(sh, 2) + + " func=" + Lib.toHexString(func, 2) + + "\n"); + return; + } + + int spaceIndex = name.indexOf(' '); + Lib.assertTrue(spaceIndex!=-1 && spaceIndex==name.lastIndexOf(' ')); + + String instname = name.substring(0, spaceIndex); + char[] args = name.substring(spaceIndex+1).toCharArray(); + + System.out.print(instname + "\t"); + + int minCharsPrinted = 0, maxCharsPrinted = 0; + + for (int i=0; i> (src1&0x1F); + break; + case Mips.SRL: + dst = src2 >>> (src1&0x1F); + break; + + case Mips.SLT: + dst = (src1= 0); + break; + case Mips.BGTZ: + branch = (src1 > 0); + break; + case Mips.BLEZ: + branch = (src1 <= 0); + break; + case Mips.BLTZ: + branch = (src1 < 0); + break; + + case Mips.JUMP: + break; + + case Mips.MFLO: + dst = registers[regLo]; + break; + case Mips.MFHI: + dst = registers[regHi]; + break; + case Mips.MTLO: + registers[regLo] = (int) src1; + break; + case Mips.MTHI: + registers[regHi] = (int) src1; + break; + + case Mips.SYSCALL: + throw new MipsException(exceptionSyscall); + + case Mips.LOAD: + value = readMem(addr, size); + + if (!test(Mips.UNSIGNED)) + dst = Lib.extend(value, 0, size*8); + else + dst = value; + + break; + + case Mips.LWL: + value = readMem(addr&~0x3, 4); + + // LWL shifts the input left so the addressed byte is highest + preserved = (3-(addr&0x3))*8; // number of bits to preserve + mask = -1 << preserved; // preserved bits are 0 in mask + dst = value << preserved; // shift input to correct place + addr &= ~0x3; + + break; + + case Mips.LWR: + value = readMem(addr&~0x3, 4); + + // LWR shifts the input right so the addressed byte is lowest + preserved = (addr&0x3)*8; // number of bits to preserve + mask = -1 >>> preserved; // preserved bits are 0 in mask + dst = value >>> preserved; // shift input to correct place + addr &= ~0x3; + + break; + + case Mips.STORE: + writeMem(addr, size, (int) src2); + break; + + case Mips.SWL: + value = readMem(addr&~0x3, 4); + + // SWL shifts highest order byte into the addressed position + preserved = (3-(addr&0x3))*8; + mask = -1 >>> preserved; + dst = src2 >>> preserved; + + // merge values + dst = (dst & mask) | (value & ~mask); + + writeMem(addr&~0x3, 4, (int) dst); + break; + + case Mips.SWR: + value = readMem(addr&~0x3, 4); + + // SWR shifts the lowest order byte into the addressed position + preserved = (addr&0x3)*8; + mask = -1 << preserved; + dst = src2 << preserved; + + // merge values + dst = (dst & mask) | (value & ~mask); + + writeMem(addr&~0x3, 4, (int) dst); + break; + + case Mips.UNIMPL: + System.err.println("Warning: encountered unimplemented inst"); + + case Mips.INVALID: + throw new MipsException(exceptionIllegalInstruction); + + default: + Lib.assertNotReached(); + } + } + + private void writeBack() throws MipsException { + // if instruction is signed, but carry bit !+ sign bit, throw + if (test(Mips.OVERFLOW) && Lib.test(dst,31) != Lib.test(dst,32)) + throw new MipsException(exceptionOverflow); + + if (test(Mips.DELAYEDLOAD)) + delayedLoad(dstReg, (int) dst, mask); + else + finishLoad(); + + if (test(Mips.LINK)) + dst = nextPC; + + if (test(Mips.DST) && dstReg != 0) + registers[dstReg] = (int) dst; + + if ((test(Mips.DST) || test(Mips.DELAYEDLOAD)) && dstReg != 0) { + if (Lib.test(dbgFullDisassemble)) { + System.out.print("#0x" + Lib.toHexString((int) dst)); + if (test(Mips.DELAYEDLOAD)) + System.out.print(" (delayed load)"); + } + } + + if (test(Mips.BRANCH) && branch) { + nextPC = jtarget; + } + + advancePC(nextPC); + + if ((Lib.test(dbgDisassemble) && !Lib.test(dbgProcessor)) || + Lib.test(dbgFullDisassemble)) + System.out.print("\n"); + } + + // state used to execute a single instruction + int value, op, rs, rt, rd, sh, func, target, imm; + int operation, format, flags; + String name; + + int size; + int addr, nextPC, jtarget, dstReg; + long src1, src2, dst; + int mask; + boolean branch; + } + + private static class Mips { + Mips() { + } + + Mips(int operation, String name) { + this.operation = operation; + this.name = name; + } + + Mips(int operation, String name, int format, int flags) { + this(operation, name); + this.format = format; + this.flags = flags; + } + + int operation = INVALID; + String name = "invalid "; + int format; + int flags; + + // operation types + static final int + INVALID = 0, + UNIMPL = 1, + ADD = 2, + SUB = 3, + MULT = 4, + DIV = 5, + SLL = 6, + SRA = 7, + SRL = 8, + SLT = 9, + AND = 10, + OR = 11, + NOR = 12, + XOR = 13, + LUI = 14, + MFLO = 21, + MFHI = 22, + MTLO = 23, + MTHI = 24, + JUMP = 25, + BEQ = 26, + BNE = 27, + BLEZ = 28, + BGTZ = 29, + BLTZ = 30, + BGEZ = 31, + SYSCALL = 32, + LOAD = 33, + LWL = 36, + LWR = 37, + STORE = 38, + SWL = 39, + SWR = 40, + MAX = 40; + + static final int + IFMT = 1, + JFMT = 2, + RFMT = 3; + + static final int + DST = 0x00000001, + DSTRA = 0x00000002, + OVERFLOW = 0x00000004, + SRC1SH = 0x00000008, + SRC2IMM = 0x00000010, + UNSIGNED = 0x00000020, + LINK = 0x00000040, + DELAYEDLOAD = 0x00000080, + SIZEB = 0x00000100, + SIZEH = 0x00000200, + SIZEW = 0x00000400, + BRANCH = 0x00000800; + + static final char + RS = 's', + RT = 't', + RD = 'd', + IMM = 'i', + SHIFTAMOUNT = 'h', + ADDR = 'a', // imm(rs) + TARGET = 'j', + RETURNADDRESS = 'r'; // rd, or none if rd=31; can't be last + + static final Mips[] optable = { + new Mips(), // special + new Mips(), // reg-imm + new Mips(JUMP, "j j", JFMT, BRANCH), + new Mips(JUMP, "jal j", JFMT, BRANCH|LINK|DST|DSTRA), + new Mips(BEQ, "beq stj", IFMT, BRANCH), + new Mips(BNE, "bne stj", IFMT, BRANCH), + new Mips(BLEZ, "blez sj", IFMT, BRANCH), + new Mips(BGTZ, "bgtz sj", IFMT, BRANCH), + new Mips(ADD, "addi tsi", IFMT, DST|SRC2IMM|OVERFLOW), + new Mips(ADD, "addiu tsi", IFMT, DST|SRC2IMM), + new Mips(SLT, "slti tsi", IFMT, DST|SRC2IMM), + new Mips(SLT, "sltiu tsi", IFMT, DST|SRC2IMM|UNSIGNED), + new Mips(AND, "andi tsi", IFMT, DST|SRC2IMM|UNSIGNED), + new Mips(OR, "ori tsi", IFMT, DST|SRC2IMM|UNSIGNED), + new Mips(XOR, "xori tsi", IFMT, DST|SRC2IMM|UNSIGNED), + new Mips(LUI, "lui ti", IFMT, DST|SRC2IMM|UNSIGNED), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(BEQ, "beql stj", IFMT, BRANCH), + new Mips(BNE, "bnel stj", IFMT, BRANCH), + new Mips(BLEZ, "blezl sj", IFMT, BRANCH), + new Mips(BGTZ, "bgtzl sj", IFMT, BRANCH), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(LOAD, "lb ta", IFMT, DELAYEDLOAD|SIZEB), + new Mips(LOAD, "lh ta", IFMT, DELAYEDLOAD|SIZEH), + new Mips(LWL, "lwl ta", IFMT, DELAYEDLOAD), + new Mips(LOAD, "lw ta", IFMT, DELAYEDLOAD|SIZEW), + new Mips(LOAD, "lbu ta", IFMT, DELAYEDLOAD|SIZEB|UNSIGNED), + new Mips(LOAD, "lhu ta", IFMT, DELAYEDLOAD|SIZEH|UNSIGNED), + new Mips(LWR, "lwr ta", IFMT, DELAYEDLOAD), + new Mips(), + new Mips(STORE, "sb ta", IFMT, SIZEB), + new Mips(STORE, "sh ta", IFMT, SIZEH), + new Mips(SWL, "swl ta", IFMT, 0), + new Mips(STORE, "sw ta", IFMT, SIZEW), + new Mips(), + new Mips(), + new Mips(SWR, "swr ta", IFMT, 0), + new Mips(), + new Mips(UNIMPL, "ll "), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(UNIMPL, "sc "), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + }; + + static final Mips[] specialtable = { + new Mips(SLL, "sll dth", RFMT, DST|SRC1SH), + new Mips(), + new Mips(SRL, "srl dth", RFMT, DST|SRC1SH), + new Mips(SRA, "sra dth", RFMT, DST|SRC1SH), + new Mips(SLL, "sllv dts", RFMT, DST), + new Mips(), + new Mips(SRL, "srlv dts", RFMT, DST), + new Mips(SRA, "srav dts", RFMT, DST), + new Mips(JUMP, "jr s", RFMT, BRANCH), + new Mips(JUMP, "jalr rs", RFMT, BRANCH|LINK|DST), + new Mips(), + new Mips(), + new Mips(SYSCALL, "syscall "), + new Mips(UNIMPL, "break "), + new Mips(), + new Mips(UNIMPL, "sync "), + new Mips(MFHI, "mfhi d", RFMT, DST), + new Mips(MTHI, "mthi s", RFMT, 0), + new Mips(MFLO, "mflo d", RFMT, DST), + new Mips(MTLO, "mtlo s", RFMT, 0), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(MULT, "mult st", RFMT, 0), + new Mips(MULT, "multu st", RFMT, UNSIGNED), + new Mips(DIV, "div st", RFMT, 0), + new Mips(DIV, "divu st", RFMT, UNSIGNED), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(ADD, "add dst", RFMT, DST|OVERFLOW), + new Mips(ADD, "addu dst", RFMT, DST), + new Mips(SUB, "sub dst", RFMT, DST|OVERFLOW), + new Mips(SUB, "subu dst", RFMT, DST), + new Mips(AND, "and dst", RFMT, DST), + new Mips(OR, "or dst", RFMT, DST), + new Mips(XOR, "xor dst", RFMT, DST), + new Mips(NOR, "nor dst", RFMT, DST), + new Mips(), + new Mips(), + new Mips(SLT, "slt dst", RFMT, DST), + new Mips(SLT, "sltu dst", RFMT, DST|UNSIGNED), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + }; + + static final Mips[] regimmtable = { + new Mips(BLTZ, "bltz sj", IFMT, BRANCH), + new Mips(BGEZ, "bgez sj", IFMT, BRANCH), + new Mips(BLTZ, "bltzl sj", IFMT, BRANCH), + new Mips(BGEZ, "bgezl sj", IFMT, BRANCH), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(BLTZ, "bltzal sj", IFMT, BRANCH|LINK|DST|DSTRA), + new Mips(BGEZ, "bgezal sj", IFMT, BRANCH|LINK|DST|DSTRA), + new Mips(BLTZ, "bltzlal sj", IFMT, BRANCH|LINK|DST|DSTRA), + new Mips(BGEZ, "bgezlal sj", IFMT, BRANCH|LINK|DST|DSTRA), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips(), + new Mips() + }; + } +} diff --git a/machine/RiderControls.java b/machine/RiderControls.java new file mode 100644 index 0000000..43d4817 --- /dev/null +++ b/machine/RiderControls.java @@ -0,0 +1,142 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +/** + * A set of controls that can be used by a rider controller. Each rider uses a + * distinct RiderControls object. + */ +public interface RiderControls { + /** + * Return the number of floors in the elevator bank. If n is the + * number of floors in the bank, then the floors are numbered 0 + * (the ground floor) through n - 1 (the top floor). + * + * @return the number of floors in the bank. + */ + public int getNumFloors(); + + /** + * Return the number of elevators in the elevator bank. If n is the + * number of elevators in the bank, then the elevators are numbered + * 0 through n - 1. + * + * @return the numbe rof elevators in the bank. + */ + public int getNumElevators(); + + /** + * Set the rider's interrupt handler. This handler will be called when the + * rider observes an event. + * + * @param handler the rider's interrupt handler. + */ + public void setInterruptHandler(Runnable handler); + + /** + * Return the current location of the rider. If the rider is in motion, + * the returned value will be within one of the exact location. + * + * @return the floor the rider is on. + */ + public int getFloor(); + + /** + * Return an array specifying the sequence of floors at which this rider + * has successfully exited an elevator. This array naturally does not + * count the floor the rider started on, nor does it count floors where + * the rider is in the elevator and does not exit. + * + * @return an array specifying the floors this rider has visited. + */ + public int[] getFloors(); + + /** + * Return the indicated direction of the specified elevator, set by + * ElevatorControls.setDirectionDisplay(). + * + * @param elevator the elevator to check the direction of. + * @return the displayed direction for the elevator. + * + * @see nachos.machine.ElevatorControls#setDirectionDisplay + */ + public int getDirectionDisplay(int elevator); + + /** + * Press a direction button. If up is true, invoke + * pressUpButton(); otherwise, invoke pressDownButton(). + * + * @param up true to press the up button, false to + * press the down button. + * @return the return value of pressUpButton() or of + * pressDownButton(). + */ + public boolean pressDirectionButton(boolean up); + + /** + * Press the up button. The rider must not be on the top floor and must not + * be inside an elevator. If an elevator is on the same floor as this + * rider, has the doors open, and says it is going up, does nothing and + * returns false. + * + * @return true if the button event was sent to the elevator + * controller. + */ + public boolean pressUpButton(); + + /** + * Press the down button. The rider must not be on the bottom floor and + * must not be inside an elevator. If an elevator is on the same floor as + * as this rider, has the doors open, and says it is going down, does + * nothing and returns false. + * + * @return true if the button event was sent to the elevator + * controller. + */ + public boolean pressDownButton(); + + /** + * Enter an elevator. A rider cannot enter an elevator if its doors are not + * open at the same floor, or if the elevator is full. The rider must not + * already be in an elevator. + * + * @param elevator the elevator to enter. + * @return true if the rider successfully entered the elevator. + */ + public boolean enterElevator(int elevator); + + /** + * Press a floor button. The rider must be inside an elevator. If the + * elevator already has its doors open on floor, does nothing and + * returns false. + * + * @param floor the button to press. + * @return true if the button event was sent to the elevator + * controller. + */ + public boolean pressFloorButton(int floor); + + /** + * Exit the elevator. A rider cannot exit the elevator if its doors are not + * open on the requested floor. The rider must already be in an elevator. + * + * @param floor the floor to exit on. + * @return true if the rider successfully got off the elevator. + */ + public boolean exitElevator(int floor); + + /** + * Call when the rider is finished. + */ + public void finish(); + + /** + * Return the next event in the event queue. Note that there may be + * multiple events pending when a rider interrupt occurs, so this + * method should be called repeatedly until it returns null. + * + * @return the next event, or null if no further events are + * currently pending. + */ + public RiderEvent getNextEvent(); +} diff --git a/machine/RiderEvent.java b/machine/RiderEvent.java new file mode 100644 index 0000000..bbf87f7 --- /dev/null +++ b/machine/RiderEvent.java @@ -0,0 +1,33 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +/** + * An event that affects rider software. If a rider is outside the elevators, + * it will only receive events on the same floor as the rider. If a rider is + * inside an elevator, it will only receive events pertaining to that elevator. + */ +public final class RiderEvent { + public RiderEvent(int event, int floor, int elevator, int direction) { + this.event = event; + this.floor = floor; + this.elevator = elevator; + this.direction = direction; + } + + /** The event identifier. Refer to the event* constants. */ + public final int event; + /** The floor pertaining to the event, or -1 if not applicable. */ + public final int floor; + /** The elevator pertaining to the event, or -1 if not applicable. */ + public final int elevator; + /** The direction display of the elevator (neither if not applicable). */ + public final int direction; + + /** An elevator's doors have opened. */ + public static final int eventDoorsOpened = 0; + /** An elevator's doors were open and its direction display changed. */ + public static final int eventDirectionChanged = 1; + /** An elevator's doors have closed. */ + public static final int eventDoorsClosed = 2; +} diff --git a/machine/RiderInterface.java b/machine/RiderInterface.java new file mode 100644 index 0000000..94df123 --- /dev/null +++ b/machine/RiderInterface.java @@ -0,0 +1,51 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +/** + * A single rider. Each rider accesses the elevator bank through an + * instance of RiderControls. + */ +public interface RiderInterface extends Runnable { + /** + * Initialize this rider. The rider will access the elevator bank through + * controls, and the rider will make stops at different floors as + * specified in stops. This method should return immediately after + * this rider is initialized, but not until the interrupt handler is + * set. The rider will start receiving events after this method returns, + * potentially before run() is called. + * + * @param controls the rider's interface to the elevator bank. The + * rider must not attempt to access the elevator + * bank in any other way. + * @param stops an array of stops the rider should make; see + * below. + */ + public void initialize(RiderControls controls, int[] stops); + + /** + * Cause the rider to use the provided controls to make the stops specified + * in the constructor. The rider should stop at each of the floors in + * stops, an array of floor numbers. The rider should only + * make the specified stops. + * + *

+ * For example, suppose the rider uses controls to determine that + * it is initially on floor 1, and suppose the stops array contains two + * elements: { 0, 2 }. Then the rider should get on an elevator, get off + * on floor 0, get on an elevator, and get off on floor 2, pushing buttons + * as necessary. + * + *

+ * This method should not return, but instead should call + * controls.finish() when the rider is finished. + */ + public void run(); + + /** Indicates an elevator intends to move down. */ + public static final int dirDown = -1; + /** Indicates an elevator intends not to move. */ + public static final int dirNeither = 0; + /** Indicates an elevator intends to move up. */ + public static final int dirUp = 1; +} diff --git a/machine/SerialConsole.java b/machine/SerialConsole.java new file mode 100644 index 0000000..a4be880 --- /dev/null +++ b/machine/SerialConsole.java @@ -0,0 +1,49 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import nachos.security.*; + +/** + * A serial console can be used to send and receive characters. Only one + * character may be sent at a time, and only one character may be received at a + * time. + */ + +public interface SerialConsole { + /** + * Set this console's receive and send interrupt handlers. + * + *

+ * The receive interrupt handler is called every time another byte arrives + * and can be read using readByte(). + * + *

+ * The send interrupt handler is called every time a byte sent with + * writeByte() is finished being sent. This means that another + * byte can be sent. + * + * @param receiveInterruptHandler the callback to call when a byte + * arrives. + * @param sendInterruptHandler the callback to call when another byte + * can be sent. + */ + public void setInterruptHandlers(Runnable receiveInterruptHandler, + Runnable sendInterruptHandler); + + /** + * Return the next unsigned byte received (in the range 0 through + * 255). + * + * @return the next byte read, or -1 if no byte is available. + */ + public int readByte(); + + /** + * Send another byte. If a byte is already being sent, the result is not + * defined. + * + * @param value the byte to be sent (the upper 24 bits are ignored). + */ + public void writeByte(int value); +} diff --git a/machine/StandardConsole.java b/machine/StandardConsole.java new file mode 100644 index 0000000..033ae6a --- /dev/null +++ b/machine/StandardConsole.java @@ -0,0 +1,161 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import nachos.security.*; + +import java.io.IOException; + +/** + * A text-based console that uses System.in and System.out. + */ +public class StandardConsole implements SerialConsole { + /** + * Allocate a new standard console. + * + * @param privilege encapsulates privileged access to the Nachos + * machine. + */ + public StandardConsole(Privilege privilege) { + System.out.print(" console"); + + this.privilege = privilege; + + receiveInterrupt = new Runnable() { + public void run() { receiveInterrupt(); } + }; + + sendInterrupt = new Runnable() { + public void run() { sendInterrupt(); } + }; + + scheduleReceiveInterrupt(); + } + + public final void setInterruptHandlers(Runnable receiveInterruptHandler, + Runnable sendInterruptHandler) { + this.receiveInterruptHandler = receiveInterruptHandler; + this.sendInterruptHandler = sendInterruptHandler; + } + + private void scheduleReceiveInterrupt() { + privilege.interrupt.schedule(Stats.ConsoleTime, "console read", + receiveInterrupt); + } + + /** + * Attempt to read a byte from the object backing this console. + * + * @return the byte read, or -1 of no data is available. + */ + protected int in() { + try { + if (System.in.available() <= 0) + return -1; + + return System.in.read(); + } + catch (IOException e) { + return -1; + } + } + + private int translateCharacter(int c) { + // translate win32 0x0D 0x0A sequence to single newline + if (c == 0x0A && prevCarriageReturn) { + prevCarriageReturn = false; + return -1; + } + prevCarriageReturn = (c == 0x0D); + + // invalid if non-ASCII + if (c >= 0x80) + return -1; + // backspace characters + else if (c == 0x04 || c == 0x08 || c == 0x19 || c == 0x1B || c == 0x7F) + return '\b'; + // if normal ASCII range, nothing to do + else if (c >= 0x20) + return c; + // newline characters + else if (c == 0x0A || c == 0x0D) + return '\n'; + // everything else is invalid + else + return -1; + } + + + private void receiveInterrupt() { + Lib.assertTrue(incomingKey == -1); + + incomingKey = translateCharacter(in()); + if (incomingKey == -1) { + scheduleReceiveInterrupt(); + } + else { + privilege.stats.numConsoleReads++; + + if (receiveInterruptHandler != null) + receiveInterruptHandler.run(); + } + } + + public final int readByte() { + int key = incomingKey; + + if (incomingKey != -1) { + incomingKey = -1; + scheduleReceiveInterrupt(); + } + + return key; + } + + private void scheduleSendInterrupt() { + privilege.interrupt.schedule(Stats.ConsoleTime, "console write", + sendInterrupt); + } + + /** + * Write a byte to the object backing this console. + * + * @param value the byte to write. + */ + protected void out(int value) { + System.out.write(value); + System.out.flush(); + } + + private void sendInterrupt() { + Lib.assertTrue(outgoingKey != -1); + + out(outgoingKey); + outgoingKey = -1; + + privilege.stats.numConsoleWrites++; + + if (sendInterruptHandler != null) + sendInterruptHandler.run(); + } + + public final void writeByte(int value) { + if (outgoingKey == -1) + scheduleSendInterrupt(); + + outgoingKey = value&0xFF; + } + + private Privilege privilege = null; + + private Runnable receiveInterrupt; + private Runnable sendInterrupt; + + private Runnable receiveInterruptHandler = null; + private Runnable sendInterruptHandler = null; + + private int incomingKey = -1; + private int outgoingKey = -1; + + private boolean prevCarriageReturn = false; +} diff --git a/machine/Stats.java b/machine/Stats.java new file mode 100644 index 0000000..9af927c --- /dev/null +++ b/machine/Stats.java @@ -0,0 +1,100 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import nachos.machine.*; + +/** + * An object that maintains Nachos runtime statistics. + */ +public final class Stats { + /** + * Allocate a new statistics object. + */ + public Stats() { + } + + /** + * Print out the statistics in this object. + */ + public void print() { + System.out.println("Ticks: total " + totalTicks + + ", kernel " + kernelTicks + + ", user " + userTicks); + System.out.println("Disk I/O: reads " + numDiskReads + + ", writes " + numDiskWrites); + System.out.println("Console I/O: reads " + numConsoleReads + + ", writes " + numConsoleWrites); + System.out.println("Paging: page faults " + numPageFaults + + ", TLB misses " + numTLBMisses); + System.out.println("Network I/O: received " + numPacketsReceived + + ", sent " + numPacketsSent); + } + + /** + * The total amount of simulated time that has passed since Nachos + * started. + */ + public long totalTicks = 0; + /** + * The total amount of simulated time that Nachos has spent in kernel mode. + */ + public long kernelTicks = 0; + /** + * The total amount of simulated time that Nachos has spent in user mode. + */ + public long userTicks = 0; + + /** The total number of sectors Nachos has read from the simulated disk.*/ + public int numDiskReads = 0; + /** The total number of sectors Nachos has written to the simulated disk.*/ + public int numDiskWrites = 0; + /** The total number of characters Nachos has read from the console. */ + public int numConsoleReads = 0; + /** The total number of characters Nachos has written to the console. */ + public int numConsoleWrites = 0; + /** The total number of page faults that have occurred. */ + public int numPageFaults = 0; + /** The total number of TLB misses that have occurred. */ + public int numTLBMisses = 0; + /** The total number of packets Nachos has sent to the network. */ + public int numPacketsSent = 0; + /** The total number of packets Nachos has received from the network. */ + public int numPacketsReceived = 0; + + /** + * The amount to advance simulated time after each user instructions is + * executed. + */ + public static final int UserTick = 1; + /** + * The amount to advance simulated time after each interrupt enable. + */ + public static final int KernelTick = 10; + /** + * The amount of simulated time required to rotate the disk 360 degrees. + */ + public static final int RotationTime = 500; + /** + * The amount of simulated time required for the disk to seek. + */ + public static final int SeekTime = 500; + /** + * The amount of simulated time required for the console to handle a + * character. + */ + public static final int ConsoleTime = 100; + /** + * The amount of simulated time required for the network to handle a + * packet. + */ + public static final int NetworkTime = 100; + /** + * The mean amount of simulated time between timer interrupts. + */ + public static final int TimerTicks = 500; + /** + * The amount of simulated time required for an elevator to move a floor. + */ + public static final int ElevatorTicks = 2000; +} diff --git a/machine/StubFileSystem.java b/machine/StubFileSystem.java new file mode 100644 index 0000000..4f0da7d --- /dev/null +++ b/machine/StubFileSystem.java @@ -0,0 +1,216 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import nachos.security.*; +import nachos.threads.*; + +import java.io.File; +import java.io.RandomAccessFile; +import java.io.IOException; + +/** + * This class implements a file system that redirects all requests to the host + * operating system's file system. + */ +public class StubFileSystem implements FileSystem { + /** + * Allocate a new stub file system. + * + * @param privilege encapsulates privileged access to the Nachos + * machine. + * @param directory the root directory of the stub file system. + */ + public StubFileSystem(Privilege privilege, File directory) { + this.privilege = privilege; + this.directory = directory; + } + + public OpenFile open(String name, boolean truncate) { + if (!checkName(name)) + return null; + + delay(); + + try { + return new StubOpenFile(name, truncate); + } + catch (IOException e) { + return null; + } + } + + public boolean remove(String name) { + if (!checkName(name)) + return false; + + delay(); + + FileRemover fr = new FileRemover(new File(directory, name)); + privilege.doPrivileged(fr); + return fr.successful; + } + + private class FileRemover implements Runnable { + public FileRemover(File f) { + this.f = f; + } + + public void run() { + successful = f.delete(); + } + + public boolean successful = false; + private File f; + } + + private void delay() { + long time = Machine.timer().getTime(); + int amount = 1000; + ThreadedKernel.alarm.waitUntil(amount); + Lib.assertTrue(Machine.timer().getTime() >= time+amount); + } + + private class StubOpenFile extends OpenFileWithPosition { + StubOpenFile(final String name, final boolean truncate) + throws IOException { + super(StubFileSystem.this, name); + + final File f = new File(directory, name); + + if (openCount == maxOpenFiles) + throw new IOException(); + + privilege.doPrivileged(new Runnable() { + public void run() { getRandomAccessFile(f, truncate); } + }); + + if (file == null) + throw new IOException(); + + open = true; + openCount++; + } + + private void getRandomAccessFile(File f, boolean truncate) { + try { + if (!truncate && !f.exists()) + return; + + file = new RandomAccessFile(f, "rw"); + + if (truncate) + file.setLength(0); + } + catch (IOException e) { + } + } + + public int read(int pos, byte[] buf, int offset, int length) { + if (!open) + return -1; + + try { + delay(); + + file.seek(pos); + return Math.max(0, file.read(buf, offset, length)); + } + catch (IOException e) { + return -1; + } + } + + public int write(int pos, byte[] buf, int offset, int length) { + if (!open) + return -1; + + try { + delay(); + + file.seek(pos); + file.write(buf, offset, length); + return length; + } + catch (IOException e) { + return -1; + } + } + + public int length() { + try { + return (int) file.length(); + } + catch (IOException e) { + return -1; + } + } + + public void close() { + if (open) { + open = false; + openCount--; + } + + try { + file.close(); + } + catch (IOException e) { + } + } + + private RandomAccessFile file = null; + private boolean open = false; + } + + private int openCount = 0; + private static final int maxOpenFiles = 16; + + private Privilege privilege; + private File directory; + + private static boolean checkName(String name) { + char[] chars = name.toCharArray(); + + for (int i=0; i= allowedFileNameCharacters.length) + return false; + if (!allowedFileNameCharacters[(int) chars[i]]) + return false; + } + return true; + } + + private static boolean[] allowedFileNameCharacters = new boolean[0x80]; + + private static void reject(char c) { + allowedFileNameCharacters[c] = false; + } + + private static void allow(char c) { + allowedFileNameCharacters[c] = true; + } + + private static void reject(char first, char last) { + for (char c=first; c<=last; c++) + allowedFileNameCharacters[c] = false; + } + + private static void allow(char first, char last) { + for (char c=first; c<=last; c++) + allowedFileNameCharacters[c] = true; + } + + static { + reject((char) 0x00, (char) 0x7F); + + allow('A', 'Z'); + allow('a', 'z'); + allow('0', '9'); + + allow('-'); + allow('_'); + allow('.'); + allow(','); + } +} diff --git a/machine/TCB.java b/machine/TCB.java new file mode 100644 index 0000000..6081ddb --- /dev/null +++ b/machine/TCB.java @@ -0,0 +1,414 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import nachos.security.*; +import nachos.threads.KThread; + +import java.util.Vector; +import java.security.PrivilegedAction; + +/** + * A TCB simulates the low-level details necessary to create, context-switch, + * and destroy Nachos threads. Each TCB controls an underlying JVM Thread + * object. + * + *

+ * Do not use any methods in java.lang.Thread, as they are not + * compatible with the TCB API. Most Thread methods will either crash + * Nachos or have no useful effect. + * + *

+ * Do not use the synchronized keyword anywhere in your code. + * It's against the rules, and it can easily deadlock nachos. + */ +public final class TCB { + /** + * Allocate a new TCB. + */ + public TCB() { + } + + /** + * Give the TCB class the necessary privilege to create threads. This is + * necessary, because unlike other machine classes that need privilege, we + * want the kernel to be able to create TCB objects on its own. + * + * @param privilege encapsulates privileged access to the Nachos + * machine. + */ + public static void givePrivilege(Privilege privilege) { + TCB.privilege = privilege; + privilege.tcb = new TCBPrivilege(); + } + + /** + * Causes the thread represented by this TCB to begin execution. The + * specified target is run in the thread. + */ + public void start(Runnable target) { + /* We will not use synchronization here, because we're assuming that + * either this is the first call to start(), or we're being called in + * the context of another TCB. Since we only allow one TCB to run at a + * time, no synchronization is necessary. + * + * The only way this assumption could be broken is if one of our + * non-Nachos threads used the TCB code. + */ + + /* Make sure this TCB has not already been started. If done is false, + * then destroy() has not yet set javaThread back to null, so we can + * use javaThread as a reliable indicator of whether or not start() has + * already been invoked. + */ + Lib.assertTrue(javaThread == null && !done); + + /* Make sure there aren't too many running TCBs already. This + * limitation exists in an effort to prevent wild thread usage. + */ + Lib.assertTrue(runningThreads.size() < maxThreads); + + isFirstTCB = (currentTCB == null); + + /* Probably unnecessary sanity check: if this is not the first TCB, we + * make sure that the current thread is bound to the current TCB. This + * check can only fail if non-Nachos threads invoke start(). + */ + if (!isFirstTCB) + Lib.assertTrue(currentTCB.javaThread == Thread.currentThread()); + + /* At this point all checks are complete, so we go ahead and start the + * TCB. Whether or not this is the first TCB, it gets added to + * runningThreads, and we save the target closure. + */ + runningThreads.add(this); + + this.target = target; + + if (!isFirstTCB) { + /* If this is not the first TCB, we have to make a new Java thread + * to run it. Creating Java threads is a privileged operation. + */ + tcbTarget = new Runnable() { + public void run() { threadroot(); } + }; + + privilege.doPrivileged(new Runnable() { + public void run() { javaThread = new Thread(tcbTarget); } + }); + + /* The Java thread hasn't yet started, but we need to get it + * blocking in yield(). We do this by temporarily turning off the + * current TCB, starting the new Java thread, and waiting for it + * to wake us up from threadroot(). Once the new TCB wakes us up, + * it's safe to context switch to the new TCB. + */ + currentTCB.running = false; + + this.javaThread.start(); + currentTCB.waitForInterrupt(); + } + else { + /* This is the first TCB, so we don't need to make a new Java + * thread to run it; we just steal the current Java thread. + */ + javaThread = Thread.currentThread(); + + /* All we have to do now is invoke threadroot() directly. */ + threadroot(); + } + } + + /** + * Return the TCB of the currently running thread. + */ + public static TCB currentTCB() { + return currentTCB; + } + + /** + * Context switch between the current TCB and this TCB. This TCB will + * become the new current TCB. It is acceptable for this TCB to be the + * current TCB. + */ + public void contextSwitch() { + /* Probably unnecessary sanity check: we make sure that the current + * thread is bound to the current TCB. This check can only fail if + * non-Nachos threads invoke start(). + */ + Lib.assertTrue(currentTCB.javaThread == Thread.currentThread()); + + // make sure AutoGrader.runningThread() called associateThread() + Lib.assertTrue(currentTCB.associated); + currentTCB.associated = false; + + // can't switch from a TCB to itself + if (this == currentTCB) + return; + + /* There are some synchronization concerns here. As soon as we wake up + * the next thread, we cannot assume anything about static variables, + * or about any TCB's state. Therefore, before waking up the next + * thread, we must latch the value of currentTCB, and set its running + * flag to false (so that, in case we get interrupted before we call + * yield(), the interrupt will set the running flag and yield() won't + * block). + */ + + TCB previous = currentTCB; + previous.running = false; + + this.interrupt(); + previous.yield(); + } + + /** + * Destroy this TCB. This TCB must not be in use by the current thread. + * This TCB must also have been authorized to be destroyed by the + * autograder. + */ + public void destroy() { + // make sure the current TCB is correct + Lib.assertTrue(currentTCB != null && + currentTCB.javaThread == Thread.currentThread()); + // can't destroy current thread + Lib.assertTrue(this != currentTCB); + // thread must have started but not be destroyed yet + Lib.assertTrue(javaThread != null && !done); + + // ensure AutoGrader.finishingCurrentThread() called authorizeDestroy() + Lib.assertTrue(nachosThread == toBeDestroyed); + toBeDestroyed = null; + + this.done = true; + currentTCB.running = false; + + this.interrupt(); + currentTCB.waitForInterrupt(); + + this.javaThread = null; + } + + /** + * Destroy all TCBs and exit Nachos. Same as Machine.terminate(). + */ + public static void die() { + privilege.exit(0); + } + + /** + * Test if the current JVM thread belongs to a Nachos TCB. The AWT event + * dispatcher is an example of a non-Nachos thread. + * + * @return true if the current JVM thread is a Nachos thread. + */ + public static boolean isNachosThread() { + return (currentTCB != null && + Thread.currentThread() == currentTCB.javaThread); + } + + private void threadroot() { + // this should be running the current thread + Lib.assertTrue(javaThread == Thread.currentThread()); + + if (!isFirstTCB) { + /* start() is waiting for us to wake it up, signalling that it's OK + * to context switch to us. We leave the running flag false so that + * we'll still run if a context switch happens before we go to + * sleep. All we have to do is wake up the current TCB and then + * wait to get woken up by contextSwitch() or destroy(). + */ + + currentTCB.interrupt(); + this.yield(); + } + else { + /* start() called us directly, so we just need to initialize + * a couple things. + */ + + currentTCB = this; + running = true; + } + + try { + target.run(); + + // no way out of here without going throw one of the catch blocks + Lib.assertNotReached(); + } + catch (ThreadDeath e) { + // make sure this TCB is being destroyed properly + if (!done) { + System.out.print("\nTCB terminated improperly!\n"); + privilege.exit(1); + } + + runningThreads.removeElement(this); + if (runningThreads.isEmpty()) + privilege.exit(0); + } + catch (Throwable e) { + System.out.print("\n"); + e.printStackTrace(); + + runningThreads.removeElement(this); + if (runningThreads.isEmpty()) + privilege.exit(1); + else + die(); + } + } + + /** + * Invoked by threadroot() and by contextSwitch() when it is necessary to + * wait for another TCB to context switch to this TCB. Since this TCB + * might get destroyed instead, we check the done flag after + * waking up. If it is set, the TCB that woke us up is waiting for an + * acknowledgement in destroy(). Otherwise, we just set the current TCB to + * this TCB and return. + */ + private void yield() { + waitForInterrupt(); + + if (done) { + currentTCB.interrupt(); + throw new ThreadDeath(); + } + + currentTCB = this; + } + + /** + * Waits on the monitor bound to this TCB until its running flag + * is set to true. waitForInterrupt() is used whenever a + * TCB needs to go to wait for its turn to run. This includes the ping-pong + * process of starting and destroying TCBs, as well as in context switching + * from this TCB to another. We don't rely on currentTCB, since it + * is updated by contextSwitch() before we get called. + */ + private synchronized void waitForInterrupt() { + while (!running) { + try { wait(); } + catch (InterruptedException e) { } + } + } + + /** + * Wake up this TCB by setting its running flag to true + * and signalling the monitor bound to it. Used in the ping-pong process of + * starting and destroying TCBs, as well as in context switching to this + * TCB. + */ + private synchronized void interrupt() { + running = true; + notify(); + } + + private void associateThread(KThread thread) { + // make sure AutoGrader.runningThread() gets called only once per + // context switch + Lib.assertTrue(!associated); + associated = true; + + Lib.assertTrue(thread != null); + + if (nachosThread != null) + Lib.assertTrue(thread == nachosThread); + else + nachosThread = thread; + } + + private static void authorizeDestroy(KThread thread) { + // make sure AutoGrader.finishingThread() gets called only once per + // destroy + Lib.assertTrue(toBeDestroyed == null); + toBeDestroyed = thread; + } + + /** + * The maximum number of started, non-destroyed TCB's that can be in + * existence. + */ + public static final int maxThreads = 250; + + /** + * A reference to the currently running TCB. It is initialized to + * null when the TCB class is loaded, and then the first + * invocation of start(Runnable) assigns currentTCB a + * reference to the first TCB. After that, only yield() can + * change currentTCB to the current TCB, and only after + * waitForInterrupt() returns. + * + *

+ * Note that currentTCB.javaThread will not be the current thread + * if the current thread is not bound to a TCB (this includes the threads + * created for the hardware simulation). + */ + private static TCB currentTCB = null; + + /** + * A vector containing all running TCB objects. It is initialized to + * an empty vector when the TCB class is loaded. TCB objects are + * added only in start(Runnable), which can only be invoked once + * on each TCB object. TCB objects are removed only in each of the + * catch clauses of threadroot(), one of which is always + * invoked on thread termination. The maximum number of threads in + * runningThreads is limited to maxThreads by + * start(Runnable). If threadroot() drops the number of + * TCB objects in runningThreads to zero, Nachos exits, so once + * the first TCB is created, this vector is basically never empty. + */ + private static Vector runningThreads = new Vector(); + + private static Privilege privilege; + private static KThread toBeDestroyed = null; + + /** + * true if and only if this TCB is the first TCB to start, the one + * started in Machine.main(String[]). Initialized by + * start(Runnable), on the basis of whether currentTCB + * has been initialized. + */ + private boolean isFirstTCB; + + /** + * A reference to the Java thread bound to this TCB. It is initially + * null, assigned to a Java thread in start(Runnable), + * and set to null again in destroy(). + */ + private Thread javaThread = null; + + /** + * true if and only if the Java thread bound to this TCB ought to + * be running. This is an entirely different condition from membership in + * runningThreads, which contains all TCB objects that have + * started and have not terminated. running is only true + * when the associated Java thread ought to run ASAP. When starting or + * destroying a TCB, this is temporarily true for a thread other than that + * of the current TCB. + */ + private boolean running = false; + + /** + * Set to true by destroy(), so that when + * waitForInterrupt() returns in the doomed TCB, yield() + * will know that the current TCB is doomed. + */ + private boolean done = false; + + private KThread nachosThread = null; + private boolean associated = false; + private Runnable target; + private Runnable tcbTarget; + + private static class TCBPrivilege implements Privilege.TCBPrivilege { + public void associateThread(KThread thread) { + Lib.assertTrue(currentTCB != null); + currentTCB.associateThread(thread); + } + public void authorizeDestroy(KThread thread) { + TCB.authorizeDestroy(thread); + } + } +} diff --git a/machine/Timer.java b/machine/Timer.java new file mode 100644 index 0000000..a9c7dcc --- /dev/null +++ b/machine/Timer.java @@ -0,0 +1,89 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import nachos.security.*; + +/** + * A hardware timer generates a CPU timer interrupt approximately every 500 + * clock ticks. This means that it can be used for implementing time-slicing, + * or for having a thread go to sleep for a specific period of time. + * + * The Timer class emulates a hardware timer by scheduling a timer + * interrupt to occur every time approximately 500 clock ticks pass. There is + * a small degree of randomness here, so interrupts do not occur exactly every + * 500 ticks. + */ +public final class Timer { + /** + * Allocate a new timer. + * + * @param privilege encapsulates privileged access to the Nachos + * machine. + */ + public Timer(Privilege privilege) { + System.out.print(" timer"); + + this.privilege = privilege; + + timerInterrupt = new Runnable() { + public void run() { timerInterrupt(); } + }; + + autoGraderInterrupt = new Runnable() { + public void run() { + Machine.autoGrader().timerInterrupt(Timer.this.privilege, + lastTimerInterrupt); + } + }; + + scheduleInterrupt(); + } + + /** + * Set the callback to use as a timer interrupt handler. The timer + * interrupt handler will be called approximately every 500 clock ticks. + * + * @param handler the timer interrupt handler. + */ + public void setInterruptHandler(Runnable handler) { + this.handler = handler; + } + + /** + * Get the current time. + * + * @return the number of clock ticks since Nachos started. + */ + public long getTime() { + return privilege.stats.totalTicks; + } + + private void timerInterrupt() { + scheduleInterrupt(); + scheduleAutoGraderInterrupt(); + + lastTimerInterrupt = getTime(); + + if (handler != null) + handler.run(); + } + + private void scheduleInterrupt() { + int delay = Stats.TimerTicks; + delay += Lib.random(delay/10) - (delay/20); + + privilege.interrupt.schedule(delay, "timer", timerInterrupt); + } + + private void scheduleAutoGraderInterrupt() { + privilege.interrupt.schedule(1, "timerAG", autoGraderInterrupt); + } + + private long lastTimerInterrupt; + private Runnable timerInterrupt; + private Runnable autoGraderInterrupt; + + private Privilege privilege; + private Runnable handler = null; +} diff --git a/machine/TranslationEntry.java b/machine/TranslationEntry.java new file mode 100644 index 0000000..fe68d2d --- /dev/null +++ b/machine/TranslationEntry.java @@ -0,0 +1,81 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.machine; + +import nachos.machine.*; + +/** + * A single translation between a virtual page and a physical page. + */ +public final class TranslationEntry { + /** + * Allocate a new invalid translation entry. + */ + public TranslationEntry() { + valid = false; + } + + /** + * Allocate a new translation entry with the specified initial state. + * + * @param vpn the virtual page numben. + * @param ppn the physical page number. + * @param valid the valid bit. + * @param readOnly the read-only bit. + * @param used the used bit. + * @param dirty the dirty bit. + */ + public TranslationEntry(int vpn, int ppn, boolean valid, boolean readOnly, + boolean used, boolean dirty) { + this.vpn = vpn; + this.ppn = ppn; + this.valid = valid; + this.readOnly = readOnly; + this.used = used; + this.dirty = dirty; + } + + /** + * Allocate a new translation entry, copying the contents of an existing + * one. + * + * @param entry the translation entry to copy. + */ + public TranslationEntry(TranslationEntry entry) { + vpn = entry.vpn; + ppn = entry.ppn; + valid = entry.valid; + readOnly = entry.readOnly; + used = entry.used; + dirty = entry.dirty; + } + + /** The virtual page number. */ + public int vpn; + + /** The physical page number. */ + public int ppn; + + /** + * If this flag is false, this translation entry is ignored. + */ + public boolean valid; + + /** + * If this flag is true, the user pprogram is not allowed to + * modify the contents of this virtual page. + */ + public boolean readOnly; + + /** + * This flag is set to true every time the page is read or written + * by a user program. + */ + public boolean used; + + /** + * This flag is set to true every time the page is written by a + * user program. + */ + public boolean dirty; +} diff --git a/machine/package.html b/machine/package.html new file mode 100644 index 0000000..16520b2 --- /dev/null +++ b/machine/package.html @@ -0,0 +1,3 @@ + +Provides classes that implement the Nachos simulated machine. + diff --git a/network/MailMessage.java b/network/MailMessage.java new file mode 100644 index 0000000..11db548 --- /dev/null +++ b/network/MailMessage.java @@ -0,0 +1,105 @@ +package nachos.network; + +import nachos.machine.*; + +/** + * A mail message. Includes a packet header, a mail header, and the actual + * payload. + * + * @see nachos.machine.Packet + */ +public class MailMessage { + /** + * Allocate a new mail message to be sent, using the specified parameters. + * + * @param dstLink the destination link address. + * @param dstPort the destination port. + * @param srcLink the source link address. + * @param srcPort the source port. + * @param contents the contents of the packet. + */ + public MailMessage(int dstLink, int dstPort, int srcLink, int srcPort, + byte[] contents) throws MalformedPacketException { + // make sure the paramters are valid + if (dstPort < 0 || dstPort >= portLimit || + srcPort < 0 || srcPort >= portLimit || + contents.length > maxContentsLength) + throw new MalformedPacketException(); + + this.dstPort = (byte) dstPort; + this.srcPort = (byte) srcPort; + this.contents = contents; + + byte[] packetContents = new byte[headerLength + contents.length]; + + packetContents[0] = (byte) dstPort; + packetContents[1] = (byte) srcPort; + + System.arraycopy(contents, 0, packetContents, headerLength, + contents.length); + + packet = new Packet(dstLink, srcLink, packetContents); + } + + /** + * Allocate a new mail message using the specified packet from the network. + * + * @param packet the packet containg the mail message. + */ + public MailMessage(Packet packet) throws MalformedPacketException { + this.packet = packet; + + // make sure we have a valid header + if (packet.contents.length < headerLength || + packet.contents[0] < 0 || packet.contents[0] >= portLimit || + packet.contents[1] < 0 || packet.contents[1] >= portLimit) + throw new MalformedPacketException(); + + dstPort = packet.contents[0]; + srcPort = packet.contents[1]; + + contents = new byte[packet.contents.length - headerLength]; + System.arraycopy(packet.contents, headerLength, contents, 0, + contents.length); + } + + /** + * Return a string representation of the message headers. + */ + public String toString() { + return "from (" + packet.srcLink + ":" + srcPort + + ") to (" + packet.dstLink + ":" + dstPort + + "), " + contents.length + " bytes"; + } + + /** This message, as a packet that can be sent through a network link. */ + public Packet packet; + /** The port used by this message on the destination machine. */ + public int dstPort; + /** The port used by this message on the source machine. */ + public int srcPort; + /** The contents of this message, excluding the mail message header. */ + public byte[] contents; + + /** + * The number of bytes in a mail header. The header is formatted as + * follows: + * + * + * + * + * + *
offsetsizevalue
01destination port
11source port
+ */ + public static final int headerLength = 2; + + /** Maximum payload (real data) that can be included in a single mesage. */ + public static final int maxContentsLength = + Packet.maxContentsLength - headerLength; + + /** + * The upper limit on mail ports. All ports fall between 0 and + * portLimit - 1. + */ + public static final int portLimit = 128; +} diff --git a/network/NetKernel.java b/network/NetKernel.java new file mode 100644 index 0000000..551cc78 --- /dev/null +++ b/network/NetKernel.java @@ -0,0 +1,123 @@ +package nachos.network; + +import nachos.machine.*; +import nachos.threads.*; +import nachos.userprog.*; +import nachos.vm.*; +import nachos.network.*; + +/** + * A kernel with network support. + */ +public class NetKernel extends VMKernel { + /** + * Allocate a new networking kernel. + */ + public NetKernel() { + super(); + } + + /** + * Initialize this kernel. + */ + public void initialize(String[] args) { + super.initialize(args); + + postOffice = new PostOffice(); + } + + /** + * Test the network. Create a server thread that listens for pings on port + * 1 and sends replies. Then ping one or two hosts. Note that this test + * assumes that the network is reliable (i.e. that the network's + * reliability is 1.0). + */ + public void selfTest() { + super.selfTest(); + + KThread serverThread = new KThread(new Runnable() { + public void run() { pingServer(); } + }); + + serverThread.fork(); + + System.out.println("Press any key to start the network test..."); + console.readByte(true); + + int local = Machine.networkLink().getLinkAddress(); + + // ping this machine first + ping(local); + + // if we're 0 or 1, ping the opposite + if (local <= 1) + ping(1-local); + } + + private void ping(int dstLink) { + int srcLink = Machine.networkLink().getLinkAddress(); + + System.out.println("PING " + dstLink + " from " + srcLink); + + long startTime = Machine.timer().getTime(); + + MailMessage ping; + + try { + ping = new MailMessage(dstLink, 1, + Machine.networkLink().getLinkAddress(), 0, + new byte[0]); + } + catch (MalformedPacketException e) { + Lib.assertNotReached(); + return; + } + + postOffice.send(ping); + + MailMessage ack = postOffice.receive(0); + + long endTime = Machine.timer().getTime(); + + System.out.println("time=" + (endTime-startTime) + " ticks"); + } + + private void pingServer() { + while (true) { + MailMessage ping = postOffice.receive(1); + + MailMessage ack; + + try { + ack = new MailMessage(ping.packet.srcLink, ping.srcPort, + ping.packet.dstLink, ping.dstPort, + ping.contents); + } + catch (MalformedPacketException e) { + // should never happen... + continue; + } + + postOffice.send(ack); + } + } + + /** + * Start running user programs. + */ + public void run() { + super.run(); + } + + /** + * Terminate this kernel. Never returns. + */ + public void terminate() { + super.terminate(); + } + + private PostOffice postOffice; + + // dummy variables to make javac smarter + private static NetProcess dummy1 = null; +} diff --git a/network/NetProcess.java b/network/NetProcess.java new file mode 100644 index 0000000..03c7bde --- /dev/null +++ b/network/NetProcess.java @@ -0,0 +1,46 @@ +package nachos.network; + +import nachos.machine.*; +import nachos.threads.*; +import nachos.userprog.*; +import nachos.vm.*; + +/** + * A VMProcess that supports networking syscalls. + */ +public class NetProcess extends VMProcess { + /** + * Allocate a new process. + */ + public NetProcess() { + super(); + } + + private static final int + syscallConnect = 11, + syscallAccept = 12; + + /** + * Handle a syscall exception. Called by handleException(). The + * syscall argument identifies which syscall the user executed: + * + * + * + * + * + *
syscall#syscall prototype
11int connect(int host, int port);
12int accept(int port);
+ * + * @param syscall the syscall number. + * @param a0 the first syscall argument. + * @param a1 the second syscall argument. + * @param a2 the third syscall argument. + * @param a3 the fourth syscall argument. + * @return the value to be returned to the user. + */ + public int handleSyscall(int syscall, int a0, int a1, int a2, int a3) { + switch (syscall) { + default: + return super.handleSyscall(syscall, a0, a1, a2, a3); + } + } +} diff --git a/network/PostOffice.java b/network/PostOffice.java new file mode 100644 index 0000000..f704590 --- /dev/null +++ b/network/PostOffice.java @@ -0,0 +1,134 @@ +package nachos.network; + +import nachos.machine.*; +import nachos.threads.*; + +/** + * A collection of message queues, one for each local port. A + * PostOffice interacts directly with the network hardware. Because + * of the network hardware, we are guaranteed that messages will never be + * corrupted, but they might get lost. + * + *

+ * The post office uses a "postal worker" thread to wait for messages to arrive + * from the network and to place them in the appropriate queues. This cannot + * be done in the receive interrupt handler because each queue (implemented + * with a SynchList) is protected by a lock. + */ +public class PostOffice { + /** + * Allocate a new post office, using an array of SynchLists. + * Register the interrupt handlers with the network hardware and start the + * "postal worker" thread. + */ + public PostOffice() { + messageReceived = new Semaphore(0); + messageSent = new Semaphore(0); + sendLock = new Lock(); + + queues = new SynchList[MailMessage.portLimit]; + for (int i=0; i= 0 && port < queues.length); + + Lib.debug(dbgNet, "waiting for mail on port " + port); + + MailMessage mail = (MailMessage) queues[port].removeFirst(); + + if (Lib.test(dbgNet)) + System.out.println("got mail on port " + port + ": " + mail); + + return mail; + } + + /** + * Wait for incoming messages, and then put them in the correct mailbox. + */ + private void postalDelivery() { + while (true) { + messageReceived.P(); + + Packet p = Machine.networkLink().receive(); + + MailMessage mail; + + try { + mail = new MailMessage(p); + } + catch (MalformedPacketException e) { + continue; + } + + if (Lib.test(dbgNet)) + System.out.println("delivering mail to port " + mail.dstPort + + ": " + mail); + + // atomically add message to the mailbox and wake a waiting thread + queues[mail.dstPort].add(mail); + } + } + + /** + * Called when a packet has arrived and can be dequeued from the network + * link. + */ + private void receiveInterrupt() { + messageReceived.V(); + } + + /** + * Send a message to a mailbox on a remote machine. + */ + public void send(MailMessage mail) { + if (Lib.test(dbgNet)) + System.out.println("sending mail: " + mail); + + sendLock.acquire(); + + Machine.networkLink().send(mail.packet); + messageSent.P(); + + sendLock.release(); + } + + /** + * Called when a packet has been sent and another can be queued to the + * network link. Note that this is called even if the previous packet was + * dropped. + */ + private void sendInterrupt() { + messageSent.V(); + } + + private SynchList[] queues; + private Semaphore messageReceived; // V'd when a message can be dequeued + private Semaphore messageSent; // V'd when a message can be queued + private Lock sendLock; + + private static final char dbgNet = 'n'; +} diff --git a/network/package.html b/network/package.html new file mode 100644 index 0000000..aa34591 --- /dev/null +++ b/network/package.html @@ -0,0 +1,3 @@ + +Provides classes that allow Nachos processes to communicate over the network. + diff --git a/proj1/Makefile b/proj1/Makefile new file mode 100644 index 0000000..cac9d42 --- /dev/null +++ b/proj1/Makefile @@ -0,0 +1,3 @@ +DIRS = threads machine security ag + +include ../Makefile diff --git a/proj1/nachos.conf b/proj1/nachos.conf new file mode 100644 index 0000000..edeb179 --- /dev/null +++ b/proj1/nachos.conf @@ -0,0 +1,10 @@ +Machine.stubFileSystem = false +Machine.processor = false +Machine.console = false +Machine.disk = false +Machine.bank = false +Machine.networkLink = false +ElevatorBank.allowElevatorGUI = true +NachosSecurityManager.fullySecure = false +ThreadedKernel.scheduler = nachos.threads.RoundRobinScheduler #nachos.threads.PriorityScheduler +Kernel.kernel = nachos.threads.ThreadedKernel diff --git a/proj1/nachos/ag/AutoGrader.class b/proj1/nachos/ag/AutoGrader.class new file mode 100644 index 0000000000000000000000000000000000000000..9ed418e547b11ebb55c988727afc2f49c52a56bc GIT binary patch literal 6204 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 YLPX4At1#TMz7;&|pMtkniU0rr literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Coff.class b/proj1/nachos/machine/Coff.class new file mode 100644 index 0000000000000000000000000000000000000000..70d2d3637658ef3466deba9f473215f30b67e0f5 GIT binary patch literal 2861 zcmaJ@OK%%h7(Lgou_u$%aqX102{=%|aq7AR2#-E!6OxjWG;I?CeLy=NPn;>vOc;+# z3$*2pKw`rZ7KjR|LSjKBNCSle8$hg(*s`}pqt&OP^h-*?B~ z|NYq&0C(Y46+M`YLBW369FWaH6;qg2@d#!VJgVX`9E#$wiX%9x;Bgggn3R(zWOGb5 z$D`1rC`4f>D5_WsQ^Bl?6ego6$$m~YmTXSQ{ZC5FvVwVm(5zK91=f$-x-sWe^7HI0 z+ssccnD!`_wh5@F?YXD-JC^MUh%td^#WXz2u`2>SM_L_+o!Qx`+B$u;Ia4p1?zm}} zyg7mPVS0JG?ak=rsu`pLNrAZTRK16q_DOrUfKn`!BpMGLmL@|WvfZ*RZ>K;o(>Fu% z!%mUp*Nl_#zUq9zbf@)#yiQ`=G4%3`?pktQH-@}9i zNyo?0%grKi^K4l!aXCT_e87<5tIBf^2`htHiW{3h?!F@~(#;U=JjvXb_qb%1B zqG}AEN^{*Na8qWiul3$5L)c!wTTNibkna9H>lqO?%1(vis8deWHB6Z_0x^lPMXIG? zGjbYk#7!E~=+$sDZc*T9Sin;XTn!aatF(Qq2iXm}RSX*h%DB#vbpj_Wc#(|#nqaz1OEOc4TO5OgbeCr#-VW?L1;vtdeaOr{)}&@uq!9JP21d$b=Adn4yf}k9QF8YXhwp|Fb?V#rx#1QAGlb@pmw$iHA z{BZ{cI1|LalbFN~Tq1XkrW<|ieqt{n+`ov(#O80%mEHU?{G-^1c-jU07T@}LbRRcF zb63tI5jPUCC8(FtcIXncFZ+YJVD8Ei+H=7rbPR@aVcCUq@wn_Gxp+eMN;VhYw1hRh zLn_oM3h(+j+|s~Fg~RVbO@-s?`~F&I^O_Pl8>zVvt>F?+rXt4&quEsW3#=v8;9x8j zONGy4G!;$7;+eVQgKCzyNX0H=?V?#2$b zBe;(-+{Paj+i{eZB6gyT2XGR*aTY^(1;cogyWYkq-oqYzfH7ReUM%5Zd_~W1u^&I+ z0Di(jvX~~1!({R(uHrF~#38W`2Sg7Z_aprbqj?qGJpFER{h4tdWTvV3k$CrT6eF`= za4#7J$>%%VPg{trz9zq3W>68Il4UP5uuKj+I8u223>o(#D)XeCLvkc@olmuB=UoPv zPrIl{3Fg;^hBI{WjD10Qj{mIA83_bGjsW)k12hPC$N&HU literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/CoffSection.class b/proj1/nachos/machine/CoffSection.class new file mode 100644 index 0000000000000000000000000000000000000000..3f86b2276b29305ff391accd66a4642e9971ce7d GIT binary patch literal 3855 zcmaJ@TW}j^75;u}rIqAOEIU@3i`6Qr)5yxjG&FANTG-UImdK`33gJP=OiX19ozq-w$Lj2(crUjdbJ|j989Zs8 zHajz>lkOZT=4~gEG3>dQKXqUjXJ%uLDhuof|e)yc`U1TtbJigwna^*-52DERh?g9j9L#;Q%bk=MpM zK0YweF-G%!*(A+34KhndO4E~8ezcr{mceYo%#4|NTiz=|tvF>f>b81DDqbUe}RI0v6NanJlr64JUdPyr<1%GSBdt_F*eSwsZ$Rpc42r47@k-Mkz&|| zfigf`d<1yKVj-zOh%{1ia0w;;Ox8>afEYroTn1h0m$6t=Pa!8XC)A&#(uj)>-?TNI z%@c~=Tsa%wRCx`KWJ~#kCFoKJt$@c)@!i0Fe8E5r9R}jqW?(yZ7}zP~1Gv|~E+HSp zeFnOO+byIMJ9K=}z?bm4!iGAHRH-zxY~TWp6YqgS8IsX5ilfDR$zhqSq=7HvD+;Y{ z9_?&r|Iopuf*ANJE*iLm83SL#8wM`pjg@yfmX$0-^Gg+H)vC+UTe36k8ijQM+d0kt zOhy+yak0@IHSl#@5%LWKS20S>s(_B>vk9wE$nuiSHJ3<=xoH);qb>;dv(=)~uwiCv{Z)4WLcW~UmHGEgcTL!M<28*-o{m|q|CX4}9IkVU&3Tvu%%CIGx z*t0EFdxQ2Qfo{^zd~q~iA`Z0JxG4IFD0iHAlh$M@t*|!MR|{#;TwUN8OcVv!Wh8C- z-#t8VqPGm%Rg-6nR$(+-9-&Na%-yNAK<_H50}iA1iJr7YYejm@DcEVpN{&or^RjQ| zI4?P9cf@M%s_n@N2sn7!Vgvtg+h1IAHJG$d4`)kG@>s6Ygmh?+L_LW@_F+tXPA6BGVFLag}ohP z*u>B1R!(;VnzS!DO*+_J*~IS3K6Y1jth=(M-IZORlJ3XYk7>(H1XfuF~SdBKUL4=Y!aTou$FzPrqa{}E>&)e|; zB@gk$!(|W9i$1>57dIoyH!E+<)$?_syhH`)+RGU9bP$%&6K?Z=0x&&WI)cl?05 zu^5?OB5R1uK-XrWc@|(qLa~W$^H}{RT0)7IrUiuFLG$rjX!&U<_O8EM+ZI``c|x%T ztceTbUqCB!vtA1s3kY|4DGY_kNjk{3x@?eKbOCF-d}P{1PY?Spx(4o8VIZtGH{E{j zE&Bd6ABiT)M{v-?XD^>~d=ArpE_g~ZtqJkEIiJP26hITQD0z5=gyP0obd@D5PPK;; z?_eDxT;H-`9vj2@Jlf_FS?QOzSwrp;V)2^@%wQ9j#)}x?5}aWgxX4B&Yx|b3yGyR~ z^17BNInfb*Q<)Fen2C!9EiGWP3ofymA;1Jo9ybL);I|Acszz7^2=&$2O;~jiGWT<5 z4*|570NBTJAHY!-{5Ve~38yS!bcR4WkAA#_gLn;x_!WBuKgS?`!-W1GNAL#>;g9$T z{)A!t86)@$M)6mS;cs{pf5&6^2XFf)PT)2kR~nvB0X(S;OsFj|)ea=pF{IQ9q}8i9 zsb0slx(Y{Kr)2^2a2a%qU{*KWHf0sbNuv|YYb4-YZM<7$*`AYeYDc4NQ= z^Le$Me&5UH_%QF?4dXV}Lenv*hdtGY&(%GAjLEG%?7d!P z`Q^HYAFX@1vHI|Zx`!WQDQhkJst;eTdw9I=VZHkBY~8~r@Oas>x=@}(xW;Vzf4Mw< zHqM|)TE%yDS=Kg#=C%dgJ&*PkQg+7ySGc8HYl}>A^so^(My4jZeB>H0A>irKXR+12 zO-o+E28sibE6^je98SXLM8Ox~G}14lg(82L6DsTt>l|-oW+Lp3OmHsVv)qNf2(dwI4YZUYyron6+1sYuDUWb(k}@xCA47tij~3f2 qH%q771EaA=we+ag9(9`^9G&gKrf^#W2=^=PUuaNkXesI9&-xGT#VhXs literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Config.class b/proj1/nachos/machine/Config.class new file mode 100644 index 0000000000000000000000000000000000000000..db8ddcb921ea7fb7096d3daca2f5aa13ca44f61d GIT binary patch literal 5449 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 H^!$DRqY;6A literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorBank$ElevatorManager$1.class b/proj1/nachos/machine/ElevatorBank$ElevatorManager$1.class new file mode 100644 index 0000000000000000000000000000000000000000..b212c4e735b8d0451d03bfd5700189ea127d6aa9 GIT binary patch literal 934 zcmb7D-%k@k5dO9;J$jtBRHP~*2#409oEYC~e6Z1kq}4iv6_yhmN0brCrWUoAQ7z7<*h=%L#ff=?f|5zRdm5i z^wrUz-9=jU2$$K?**=5lJU&CIbB^-osbiBQ(*UQqL2`K(yo8&Cn1(3@y~}9L2%k+c uFyHwC@fDSSGX>;DKKRX4#w|i6+{PW!75d*+aE(??vMpc}0qHry^!x&h9qZEo literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorBank$ElevatorManager.class b/proj1/nachos/machine/ElevatorBank$ElevatorManager.class new file mode 100644 index 0000000000000000000000000000000000000000..8285db8f152498db7f4fe4a47d906559733f6e3b GIT binary patch literal 5643 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 literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorBank$ElevatorState.class b/proj1/nachos/machine/ElevatorBank$ElevatorState.class new file mode 100644 index 0000000000000000000000000000000000000000..d792099bf5710594e37a0414ecfaf76e0b001bc3 GIT binary patch literal 2906 zcma)7?^9G|6n@Tfm&@*65LQ5RMIcdOK`?)1LWJ@oQ4ke`KuIs`6|OAz>h4`6qD(*7 zRMXV-;{%S3)>M4)OEZF2GfkiS)IZTbP~V!SI_KVHxneQFaNhU6?|IL8&U2pk<>$Y? z{}I4J+*Z*aLK)74QHirMJ11s9%%F<%VW{5nkgN=gc{Pj?jD~Rm7sD9CYbq`UITrt@ zzsUY&IirgiS1}=DLX08iN(7Ub5@V{k8bS=iDy9jc8GY`YnJ`jm0`(9IJ8UcM=$132 zCo@JK$5sfzD@of<5h4jA?UJ`p7Zt(4Y_H$Rw2dTHV9oq^B(^ zl3c3pJOw^HU}sVjMz<-Pm#k7H{cjSf5n>xiM8iHjuVFuCH0;J64RvDbQAH?TFH{Y2 zG-!AZRT_4pN`v$Xjx0TQ zWcBe#qBgdTJP)9`xLB0R^8)_cj|04OkZ1GA<6odD-mr{7{4w(4dCO451jXdXe}Fpj z7zN7+#kVgbEGF_Tp9tU(+a3HL0@Q&JeT~iZ4Jv2}JE;?O)P=p&jl=9y&c2)hFW^NU zWhRx#+EKJ*ag6ad@k(|45tO?q;vsk!shvE72RvAwFi*!@uH3^Y3Hi(Qhdq75%|HsSDh z$-?7;hkXsSTf-iK9eaRa-oto|xr;wR;R=dMQLHZ`Duo4=hvLJ3k^8=q`BRp^LL}ym z<>DdJFHz_&eUS^QtnqRfh0M!&Y@%W2W&}HE6xDPQyJ!pt=n{_5WgMjh`e+hqGLfNa z%u~|WsfApP3uxy~@&8S(t`MO}J8j-t)J|nlVe}Y|X9>8^<%@{g8C1N72|7^9CcNguiu*2r7rgBfMAK#PddU6j&2F79&|ig)>A fzO+mZ;V4jsU0et3W=&tjZxFOOwB9zozAb{%5e literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorBank$RiderState$1.class b/proj1/nachos/machine/ElevatorBank$RiderState$1.class new file mode 100644 index 0000000000000000000000000000000000000000..76fe7a0d5e0a1c1681f6ec481d7bbe70e1a0764c GIT binary patch literal 894 zcma)5T~FIE6g_TBLqoQfvQak1_zKX4i4MeDCmyIkRO*HVh!>vR)KEikkdyRxfy9Tz z!+roi3US?4f}trQQG9)F?mfQu*nW7t{{vth)dGg_#SBw6^7v|F1k)B~EX-P%W3YQX zaO19w+#d{6EyewA7}d_nNF{1pf#~r#)SFzL)fw{rz*P$_CGN?N(EBlu1%uO6O6W$w zqew&y)ifUWInhx5luE`M3_EX5N+Yj-J7mZ;!VVQxY*7oplk>LF2fQ7Sr`!sC9vpHl z4IVgirYQz5jrK*&?kZKC)rq39YF4xN!$kXHTbdO{Un;h8%6pvZ*iwEFMpB*p5^*=| zI4EMlfsOYLhEXuE;$RUK5-vsme`;VT8S+}d)k$r)eJcEz+Ix2GB}$ndEi5rCzKxY( zGj$K@uNCTVWK+dLA9G*Sn@3HfM?o5oPA;gT$&{5bLx(aC1`C-|$tVGkC0Xd;X6P%T zM1MzV)*zfU9&h;u%=>8E{h!I9D2l;frYt51W$+1~$>!)DP2wHR%H$itJRGt^gz0$#Y|Psb literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorBank$RiderState.class b/proj1/nachos/machine/ElevatorBank$RiderState.class new file mode 100644 index 0000000000000000000000000000000000000000..25eff15efcfccf15785d78bc2ee34f66331a6701 GIT binary patch literal 6335 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 X{C6|IU*Pvn&aZKP5cl(sv*G^%9E{HH literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorBank.class b/proj1/nachos/machine/ElevatorBank.class new file mode 100644 index 0000000000000000000000000000000000000000..0f6402faee8dfb369ad1ac9e97835ade7c3a9059 GIT binary patch literal 5507 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 literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorControllerInterface.class b/proj1/nachos/machine/ElevatorControllerInterface.class new file mode 100644 index 0000000000000000000000000000000000000000..769ca1e9cb762c60bd1116f64ecaffd2a737d3b0 GIT binary patch literal 407 zcmaKozfJ=&48}j-wLLf}l=4q(3=D;VTe>k)kSZZ6f#{wdhNeoBDwit~kH)|Q@I1_b zuL~yzB3bs&`D`ct_(8pndy#)IS4hZd_=R9!E7o!DR0u3d1>1+{{4P#|Wjsf~4 zB#+t;+>4FBW3P`TC)j=zxUzu>yyRj;tx+0s4)0VRzJ9 z&)H})<2(?$zp1;@S~W4;l4T$gi_yT5SX1Jbd@n*GyjJ6N;k3pZ!kaa2BWe(~unmas MU}v?k?yA@B4@6{O!~g&Q literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorControls.class b/proj1/nachos/machine/ElevatorControls.class new file mode 100644 index 0000000000000000000000000000000000000000..6fcf0017292a7c08055d43b52f249c1ce115fe37 GIT binary patch literal 457 zcmZ{gKTpFj5XGONP5)46p+I4RFCwiBL)#hTSkq7`hvAEU4ht>wQBuk(RX1 z*Y=jnS3#O#5Kfo8;IZIx9zWz#@|mDv^vuvwYm%c)&svz2QacsOP^AScRnU`SsE0`s zy)ZQ0NFRcs^t%w{$Wf*#wV9Hm%&Z0fsQj*5@RrHUEPP^D`Zeg?jti2O;WCV-lBWx0 z;*~=tDc&yQ9YYuAQROwO$}cG2@Z#F1wo$F8GG>fRlk{sOj^ZOZ@v literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorEvent.class b/proj1/nachos/machine/ElevatorEvent.class new file mode 100644 index 0000000000000000000000000000000000000000..0489597194ccc2aa85c561fe5c6067e5a006954d GIT binary patch literal 685 zcmaJ;%We}v5Uk$a_=WRuVjM!8KpvoE4_HXtf{-8&$&y7PAij_7NwU#q2JNoRcX6 ze34q42`W0(6ID3a^yTxfAI3#t%~_`NT#p3vht}kUGDTmdV;#~4f|kE~WWSjQw_Q~P ztG;^T9R4W>_eRHe#_zK%ndp&g4F!w7^;0s^S$<@V_lpFjw~0xLcLaOgZg;;ghz{*Y z^L{Te`s4U!ptCP(kn&`?XNM~7t1NN+?l3B@l3cLaGirEc^Ue(u8$0(y9J`k}5Y#@~ zaW>Q^iC211eRZuSs*V<3)KNyIj;aeaR0Qq+sS1`{XD3zWvU57P)4ibM@3>N9nj*YJp0P$v#BPrfk27s;1qc!PX-hOdw}XZT|(@$0b4_=JinH6!L` z`~woNPZ7lJDZ+STis-v{Tw`o;N^q`-yH+{R0;gHwEKhkF|Lw;*+GJGndx%GFlfWal LOGwWRvH+X6ZdZZ~ literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorGui$ElevatorShaft.class b/proj1/nachos/machine/ElevatorGui$ElevatorShaft.class new file mode 100644 index 0000000000000000000000000000000000000000..b03460ed1fea3f2ed6169c182962643d6dad28af GIT binary patch literal 4322 zcma)AYj6|S75>hyq?N^Di-#cwo7jdlvJ9A4NHE|u*gzaiAQ+Pv3h`pCEd^O}CE4JF zq-m0pNAsXfN<*M&pbxicOG6qQreQjr{_J$7{oR>N%k)?NbUOW+VM@QVl2&#xOd0RF z=iYnHcg{VJyDR?qpWprtzy|!rLaGY$@l*sYIHp`$$%vASlB|VM9lx$57l9zJT%ihM z7>|%UZs9}(HJH%J(-xkI;3S^a$#X%P(0_>tzJcd0d{b9nP|X)3cnRN9a!Sd|7G8;9 z8D6a-c}>Z;mAtOx4HbA(4Zo$Dr*--rCEvC1wm|ZHx&?DPvzdIs$rKJa=`q)&)u5m% zkeKhBe?<>_Pj=8rA8>LhotG9RMGf_WCokLVO*%vL(C*G;++1hc z$>&{e$M0Zy#SB$CJh!*t3?AFB}@0KPD@@}E4oSUvxel+b&FaR+xa#3b8pZC(aZLCnxNa;;fDL zaE@hoYr56gc^f;hQxLliI$fVxWfp#5<9+{b=J6J=afgmcg>|Q=GFgiJ#f{IWA21&5yqNcEQGndZH(kJg(#yN`9#u zzrrOOzt+=zgv&NQ#%1=Nf5c8FGw!em=lLt;qF{=g!9mvBinVKa0o;AZ#%^K4t9^*h zY+7%V;L$XDjM=T!jJKoh$1>l>&EZ^jEW@%|Fs&+!GFp=6a8N~eaC1)i35AErAcr>$hF(3wtA zt^~$gFr3Ia$Mw1*$njJ{JqRUTRWI#nGAi*}qw%``j`6BQq#W+e>bZB?(1e>#XOFXi zhf?YE-fVhe*t@1X<#6N`@H?JU|B&Z~$#8Off zufKvwy!9&PTnk)*ZFV#$e-Y96C$JmL{V$m^dGnv~k1=-&)t8BBVhibN%mHK$s^kMy z%LO#ZMKp_zd!-s{r3RZNiftSpmigEt3$T?sjnrL_T6FLP`Yzmy2eFN#a(XHQo#Yq7 zxJj{qg)R%*MSw54Cfd-Y({&(7j*_3DrayWxx{IzFbUOJdq91YH@H`Buj4bjj+eP`3 zJ;B31RvUK|D;S@`y#G~RGEF(?D|i2Y%FAX^HuS=vJPSK|Z0Y zSdd6Y_s+waDJ)!w+N)SRi9pX~DmNp>VBJ+p#3BX*(#+uBgP3qf?!`)JnPz-d$#V^^ z1>=~79&*_2d$NUoXbd88RzQH&Qm1(?MzLBmB`f*evYNSWn+6;4v-jvMNGz>ck=7Au z1Cj2V6=@GEp%|SVw6D>L#FuK3&f?PpL~19}W)EpmQQG$@qVEpxRFCdrV+|8NOKB^R;!PgU}BmDi2|ybWSr->zk<6cNtA+TusPA4*PsthfB8V;+j$I zIG#f@YcDl@d&LkJGq?j`*@?N*O?$g=m-I}tS?AlVE7=5k{h&Xj)@i&Z-v0@#z<_r4 zEb-cdh&;w#-8U`rH9qkE+rcGn1J_5m#|ihuEO3H894IC-@Nd>!6$8}K`Z1PFVQH&r zR_Z-Dh5EDT=9=mE0M{B?Ez_E@U~a9i%)^O`sBJatt@`jlAVKk$jNs(W>#fngTcG#o zVzjTKtKiXoGul66=@$6K)T@v7&oJ<}&#2%LlxTUCJgJ5|nHYwAKYEprlzzqmt!QSi$-*X5Hh4brtuNV#rzGEdE-Qj7A20 zpr+}QxqF9US85 zNCM;H;#C>Kc^SqfN#YvEKS&zaWfWiVx2esa04ro%y7(Jnmpmi;2RRPNYsRp=Zk(1kj464`_*_n#ro3&=k$23+a>i_w zcg>ibH8;pPbE};9ZihEf&5Nd4zjk>6zmF9~PA2&AqH96<2X9f2Gge}Qej4jr&Fm;& zPvrV>kT=S8<1h~4Yef0N=)+;knPMC3aD;0C<1{YeNem!pOyLzch9FLN-Op~wO zL2_a5#y*Ie8+cH@MAHpy;jsKBrV#QzIuaIK(MLZ$Hr~KGZf`Sgz~H!E#j0kASs3#F afbfDay&L9zY#@n;IO_ir%;)n}82<&0nr6=c literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorGui$Floor.class b/proj1/nachos/machine/ElevatorGui$Floor.class new file mode 100644 index 0000000000000000000000000000000000000000..6d89dd647d00cb9cf0076dd53308e0a215a25166 GIT binary patch literal 3226 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 Z9AHt3)R#E5!CM^QPv`Uv5MC!-;D7R7JkkIF literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorTest$1.class b/proj1/nachos/machine/ElevatorTest$1.class new file mode 100644 index 0000000000000000000000000000000000000000..4653f17a9c205fb85b8125064f3830a9c90f64f4 GIT binary patch literal 214 zcmaKmO$x$54255`+FAwcS_BuaErK_Y3NFNjUSJ$Ue;8+=Q+qfU9>7D1>CTmTBp-pi zN8X?33&0lR5MhWBAwIiDt$AM>Cd@L!t!i9-Vc)DP)hfa?v)VXc+Wg2(;cg*f!on(D zIG^4HrRDV3x7rXU2Wz?B8Rb2DLefR0M%g?)T`SfNVg4r}S%T1$KfCISAX|WeFu+h| LBpu5Q36Vr!W?(gr literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorTest$ElevatorController$1.class b/proj1/nachos/machine/ElevatorTest$ElevatorController$1.class new file mode 100644 index 0000000000000000000000000000000000000000..67e88f890afe13a53ffad27c57b270e76607b5f6 GIT binary patch literal 829 zcmb7DT}vB56g`uyuBNNTXuq^oTUU%Jn2+|&;!98vVhdG#pR9u!8E0T;wq~wF>629^*xfmoYX3W{ZLL zX*uixbV^l7XoLH;!u94m=FVN~)nGKw8-q2~QnvBio1JO<(2bvTvBF^;{;+h0Jw`$H^$@5$H_Gl(zYy z<$P#q>w&d$=7xEuj&)#Kp6Ci9_pjxx5KBPVktqpQxqyqcXp;J}ZgqB9%QC0fSb&S{N4@Q%a zS*E;CJFS+$`hOU)#alK5E*zp-4U^#IEAdUR!0aMVhm1p}(s=U~qVWx-&!d_pT6WRy zqDuSZz6#5zF=G7)O|W7Gt7EJVedw5Le1Z6m^501H5mItrGe#=oF*{1ce@Y+mUwB4r Pkfp@)Cg$lQ#(e$&IjPKv literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorTest$ElevatorController.class b/proj1/nachos/machine/ElevatorTest$ElevatorController.class new file mode 100644 index 0000000000000000000000000000000000000000..6590ba7989e7c11c2bf04b5dcde512426dfcc15c GIT binary patch literal 2499 zcmai0ZF3V<6n<{rHdz)3MG6!GMI(k(Y0HbEMTqtV0-<1AD8)Cn>6R`eyLER{3yyz; z@k2k!2WK3e0iiPECr257i9do-pR?J}OeCcr?%un5&hwn}oO4h5*FV4h2H*s~(UHTb zEMpli<2nvtLU!jgoY#>;Sq>L8T-1?4WeYB0QkKg)uHX~#o66udOv^H(;i`PQCd;gb z>++nF<%WFzRCb?<-{%7Sg&e13_oW6?!@NSzc+FZd1J@gMoxpQzHOo^l%8p}sqczj_ zEngvBZGPkSP{lE;ORhgy=fifa!47wSL?L6XSWYl&+JQn}%RX50EOWshoVM!b@{;RW zG)x6cwx1tT$hE9GQD-ba5W~~9V+Usx`U{&{9=WEF7tlqg~E{EZ=yj0hA0?YFn%T(96Wd)PgY7m->I!9gwm<(&9p{j7UYs{hQ z-H_yCemG1gw#wSYR)-Z1zQUSvnboT0`}t!-^f|sM^~>}Y#q?>n;Z>~(TdKLERTPQm z=xuYwH1IBl4ZMYdfj4njc03-!>k50Kru|$ zV4xvPE0XWmvaHH-7sDFvDIDzr(j_m2tf)CyGo4$5m*;O=RW@2~GYr;0Q7B7=4t6nX zT>^!jz7>S2N&}xaorQ4T>@HL`IHwwpBR4c`u{1k;qUO3BO2Sd*HSXZ3*qmazOe!y! z@fvK6MBzqw!DyUZZ2AiAnC&qa+jYilf4OGf<<~+v3_Ig4Th16sI0^J>&GoJ5kgB^Y z){Glj-ryv(qG`#Qw8#PAFHx>0_oN$4SsaQM>!##>Us2fC5o@c9M0)gdkRJd$8F9p< zPx<2zlU4+>S?OS&HNIg()9Oh0(-Gqt(2E0)5HCJP;^)w($TdY95M_X?5$<)ojdyrr z2VgKlxQRrF&@Twd;!~vN;*X&{LVDmSGINB~*Rdsr4cs1jfKeqG(GJFP5XF$Aw}}&R zfZ0d}OdCTOZnCNCVP?Ry;zK0k>o8)t4=wQkiTD$2CE2#hz(Z`mk8ONp+dqkYVjVqk zM6NqycwwJh!*+2}5ze1+oWcd(`+1y34IlC%p2fE);X91sdwTtVb9jm}ey7!+ zxY(xTvq;H4{7AgxRPY2DdZF(qspr_M;bch-mDH({%9S{DW!5!S=1x=x(#$;l3;H%{ zr-wC~WEWj->x*>66q6wpVbp0Uos|>y*0E1vuJQ*`4_KuTbpL~Y{~q{>2F>)FO)-OQ zxJn^ru@7@?spKMpE$E>XtyFaSK1Y^`WU^o*jYQOAB#sj~RUCMX*hcW}4c*_gc+qSr z%6m9WIz^GsAeK#2=u(6z%`So@S$_3$z~&7}5=L%F3?GH-$LQy?k7POAWT(gY?^pBh J19@cA{{fJLFVz45 literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorTest$Rider$1.class b/proj1/nachos/machine/ElevatorTest$Rider$1.class new file mode 100644 index 0000000000000000000000000000000000000000..97a7f7bf58001c3f1280251e7f217126bc9ce600 GIT binary patch literal 750 zcma))-%A@o5XZlpTs%!rjlbJ!tu|-T2*zmNEWQK_LTW+9mp*MSOR{qA!tKR}{#OM{ z#fSa@{i901dj?usXnL?SJHyOpXXfVnkB4sn-e7AA0iIP+!SgC6u^M76#ETH?0u%W_ zySNo%L!ff5dnyx%PK{AnJC)8UCs6MgnGCFJ-cV_ynkT8cmATC>mCNHI=ZK)U+UWdP z;Pv)@#P3`Q1Z~?>0<#@5&xSW$m0ikiO3!@9CNjN}nfCU`8Tdj4w#LKb7RxDTLqoak zAF5v1VV0^ zEZ$-<$rn>9uJHOci+5DK%j5RA*oZkJ9RYpFvZT{jFkDx< z0*SnBd5&G6&m%d@$j{quW|0=tk{SO+UwGdmP$QS5GyOc&^+A!p}}!nom>yblkf?1DhsPG;Nv0LcxFy)cb}d5g@oZENS^^E+r3q~;nk2obuAd+H5K_(AXd*NFgU^aUwfyAt7dD3x8MPgQ;lisjg z_WWz2Fx9ccYjVU-ii$abvs*mhM0d5B%FFhy9(Gn)rlcv$T>>rtqfMk4`Mh-9_ERV6 z&9NP!L!uc$8?{SLUJja^x%x^MPAnKphK|$d){#Poj$?R+zi9gu+EmQzFtH$TAgt0Y zg~!U*bhP7XN@7(hR{{mzw0E(7pNfKxMOZp)6m?vOqvK`t=r{vchsUDCVhJ}W7gbjM zG!Aj7Dv6sISe@~iuBmHws<5ZL2N&kvg` z_Pk-u6nL`iPvtf|8!1^9x1(QH2`cHqf^Cx$H3c_J(V^10Ts&9uJUeKWDQXqEiOmLj z2^mfbLZjFHrbB_6w$*RC#ezW$v!`r{dPq9uc!OgymGl98%rb^9mrZX&F+NL8@6MBI zK*O-@jYt}Na)un?zP&_!TSY_pHBT?J(tK`#z+Ob4aEa33SGf9sWRi=Q_9~rFEt6K- z|65RK4`}Jmdx)g(Bl?s7rjulxbbzZkPEz;3H9U(Gv=hkSWN6_IqJ#!?vxV64hta#J zJ03YfiyB=;H1Z4L=?73JBlnTGhnmg@&?X6|b{)C`28)2f8WAHoO)`%rNOE?L{<9W* z@YVnz1ScpzG>i=UioKr0u$uU z?p)^@k}KFpOZ^J!Xlba@jjUsjf=zLe1v=fQfPbRCUKg}vC_|1`J(*~pO0+BTSE z@W2!6>o_O~scD0>UhJmmY|8g_%DhYY_K?L5jN>NJcncQwv`a1hHE!cOe2O)EhTrfx z9^ni8fiHb>8v}+ya@+6&UcigQA5+>0EtwUMkyi0iR_x7+(^+veOXHYFV!$zJGv`2p z2&nlPhc@a*^DTcx6?dnih7uu?!ZR(ju}GSnr{*9}hXp2czazeiU4hZ&)qno#{E-xb zT4|t?1HM5WzC}F+b_m~Bgwh-W)S`hVW;qm%-abZ>0;x%Y8lX3X?k8X_-*~$7K9mjT zD~msz%`7TCfCAK#hbW@DXa5pLF_vHYN(%MAs S9Kj4)>0F~d|6XB{O#BPop(zmn literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/ElevatorTest.class b/proj1/nachos/machine/ElevatorTest.class new file mode 100644 index 0000000000000000000000000000000000000000..afd11898749eb9675ef0c09a5da1db2a47cce166 GIT binary patch literal 1010 zcmaJ=+iuf95Iq~)ac~Vy0)*Z}A%K%Wj0^ zM>-zsc%s8%Fx@Z|aWCLWA`%AegFh58L-lPS#ypMUUKFNr6a>;(eC3CJ`kFzpnuiQ( zFB%Gl<-Q+^_oK6ch!6N6AWO9$c|17eu`l(RQB6;LO0d}vxpxvJ_8AEZw678!h$QV2 zbvz2Gj3kY|5xQ{fG8iADQS6C#zT~d_i|?HBF*i|0MMu*_3vGr@4u9h+c;1zaeyZb{ zi4JUr?Y!u0HYT3KF>wzShV>jYLs?d52R!^@?+;Fems0mR0S$+t_Md-mIwYF)fQMfh z>Q-~n{B{XI^Lt}00%QZub2gl=yw*ic$plo0Tmc5ha@|E-^WnN-D&o)F6B%)d4~Mh$ z+Pzj~=9uH%WA|F88DvJDbm2hmyL<|uVWUE4m9!Tm8A+{m4)#5B-=@{#puh2`&PFUH@I&P9&qyN_=iE@d4UIVwtqmW!i F;V*5x_`?7I literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/FileSystem.class b/proj1/nachos/machine/FileSystem.class new file mode 100644 index 0000000000000000000000000000000000000000..49b51a984b121a0236619e4fde5b1e76ef3014ac GIT binary patch literal 221 zcmZvWF%E)25Jmss3W|j`7T!P_wy~qPBB7w8Tge0=uxkKGyqbjv@KDCxio{sGnbUtRIBo82H9EEnq_9)bKP=6@O$pe z#Dx8yW>gTu+}!(;ole*~Ia}qI1*Qj1OhaglTF#Tif3Ky3!9#nC(qgH?B1Kk$urz6(YjI=&Wd5 zaubw>lV51HAxu(Z*zRiW96LhX-AQU~^5k@>IP--0zj(X^p(pQk)fYirfPpZ;P-Z9{ J$qoq-hhOLAGDZLZ literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Interrupt$InterruptPrivilege.class b/proj1/nachos/machine/Interrupt$InterruptPrivilege.class new file mode 100644 index 0000000000000000000000000000000000000000..b903a45cf4e6ee617de1564743e1316a99c3ac46 GIT binary patch literal 1311 zcmb7EYflqF6g{()UAnGNP!Wne)T(6*l!q^ZF)mukI_UEyp0-n`YLtbtF3uqpyTFdMvL=XOX^h^>;*Ns#RJZ=QZihuc~K;ZnM~C! zoITBqyCT0THyc{oEv{6yy*;m7^VC*(H4X!{wQy?Zbweqg)Iw6g`>Ip|VuiKD2fIn; zXATQkRZnf!WGHa?JSKfO@ZWJNu4`5&P|swjWbJukk65=bBQW2_%=B_+l01!l-kGsa zmTT>x0`_XX5&H5eZ58Nlc{Qbra&Q5TgDh;lnzb$uvE|YWfT==r|Hd78*~4oAO3RA zY0i;0oXI^8rk0B_zC#OaOo&`gTh2F{fuV1JyBCueYcK|ExAX~ydx(w?j0|*hG>HMe zp@*Z!6NMZuab^eNN|WI&I{72Q{Rm@paxim*%n65`uz#oGkA%mizGge-(W`!3O}HHl zU=SV2*F1)ZW1C^Psq%z8I?t?D89GAezY;%LOHUJF6g}Ter$ftBDh~w&tx&a{0tLmyh{^(E0s%2X*bmbQ47M}PbZX+tKjG5& z3)pCEG%k#56Q7BRZ{zDHa3Y<+}U?|rCb$xr!vBQP@GMCI)=XP5mZa4JT zZM)9xrZz&$zO`mmBecAeKyt&c2exy~m6Q&(@y^IA8R*A=fkDg}=!Ib*g+m7Vkk)b5 zz&XqtI1ED|-|Za#P~m0{&ff&cn;*EABAU(psyVs-;cmSN-Lh?`R?E)KUJw}n&$aU_ z$ne8VfHlzg9g_@SNIsDyB}zrI0n%wnJF-FUL##SN>n>EpDJRWB1Hya)#mqFInj^6W zV&;g}fMyn+BHn=hFe*OEcQh(_#nG=h>J8hyrSBak@E*gAn~2Gl7{M5&)Fd<|(j>TM zRKn8;V;sj@U>-4|GHbE$0zGTyW2jU7-MbG>*>779pv9!6Gp4s=O)HA2`)r{?0yViA z-~-2eKkqz-9c5fM=TH+rSr@ogp|47g;k#3KQ(ti`Xv= Z=$K5UQgmhMQg8~#D3eU?;a|omls{@C`{@7x literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Interrupt.class b/proj1/nachos/machine/Interrupt.class new file mode 100644 index 0000000000000000000000000000000000000000..c665cbc759dac49a2f1dff3e5a28b4cd4194d434 GIT binary patch literal 5082 zcmb7I33wFc8Ga{w%#quRq(dui|cw5`2ssrY^~lif`gc%Je+%>4h%_r3r3 zz27yP7v6mIaR8^_%`j?ly9_Z2;ue+2C-9~ zd`iWq!>AJ3TI>@2JHq%3?i7K$LU-_?7~F zMJ8k9+S3WkGAsp=6&c&eN_%tWN+4Lwv1#xXWHAF3+OEhR3nqB0xZkT9q%QC_RQ{CbhZEjak)t=2* zb|Pc1OQiFLk0CNCvDD0%_A&)CV`JDyaHDaZ0)KlpMXM%t@Z8n;{%#}JC61BRj%+fK zUYE$3viBbP?Ov0N*NuUe87$Vh)F|-9D1VxDlU?Js}cjAEt&_+*lAX>*GT2X?09UYOK>`o+1%V|=a>U6B~LEM zXPn5jIL>eFH8M2B-ag=X?8L5Ak>>U$GO4tYQ&4jx6j3(&sjS-B^OH;z1x-gKr#zaD zda{oxZD!6hav3AN$_Yn6I3Xpq6S0I0tA+KbAWWZ=eJgsF=Y`9RvCU?6D+n-$o!np= zcqTj9xPmp3An{aY?Z3qGSMjonZxbkyOd6KeFn``+1t$~|raZQdERl+B^NJb^=5e$9 z7#jaaEGo9m7xV>kSy((`p&U`n;&P*$913@4^SPvP4vSyGafR}kD*@H7_!)lAuor2FdKn*0*ip&tXsaXi3mw12uXOwxztQnq{7%R3#p;>~ zMmPzo;}1ggAMqM%v$ZwaWhVQgYzWcTRvmv5hPPmojvibpgmd+0S^WjC>&OV`Nh>m2 zvVCG=Avj}JS>w$5tJv{3{6ob*b^HsPm^@KhdpY`aq|vY9-#Y#yk0(W=G4|+awkMi4 zExVCzr;ENVp;cA0i>FxJS7g}|eA%8Jc5{#U5`iT;-oSrZH#!c9(OdC4(Pu};I#5dN zJvvwjaiN>}WObp0GRxsyCewMlJ6$j6m5nI`KjMti- z9g9OvtXz-)ft1mm-^|7xYcIobSn?%Ov}+vyZi2MPysPYUhJfcrC{O>qwcqC0WS@_< zJ44iI@@XcjYFcOa57^szbdQ-6k@1#!;N&D{^k=t_DSqT+rQc`S4I*pC)`eDf?C6xs z)9KkqjeJA7JPqhc=dIo~rZaPkbuu=YnY+0>J=08YVhNib+2bdfGo7u~oP5W$p^&Hr zA2FX_sb}(2DS!%@30zf3(|7J{-p-x98VXiB>+?~EHCW621jDUEP)Xm}l z2m@1B8yLlmQJk>$w}a?D-kyx&kD zbOTJ5lMuB*rm#cz1{uXn>KRxnRM|F!`J%yjA*<@i=6<|m5Dl!vG0#t;!?USKmm?>0O}|GG za|?1G8smQEl~juB`vTSma4nhs7+2RZiLS@VxQPXNGg|now;i`KX>Oy(x6{8t z#7#1*z=_2-lF%CY;OCx~WMTLY;bay0>KLE!d&qTNxtdJ*dG4#lXtu>i5odfok5o39 zCJELkW)H%@*Imwe5;en^JBtb7-&+iJGu@muF2vN@iLDcqcEKnA{ zQ*8dTm_!*S+x!FI7klxzg*=W*r?})Yskk}y08Uddba=;PGqQ+}iVUw~*#Wyy$v-DV za2K2G-I$4c*zE2_BZkQGeaxBr*=TpO8SG)kJcujs5Zmoua{mamhVcMK@htY^MI69O zIEYv9SRo2mP;)D_B$ZzE;!#OS$wI}+y(!QRVWvMEnR*CIRcvchroDla7!ZDzdI33s z;ShiuOA=`@{c{PBYLj$2-F>1DLW?XJV)JitDPVrdC|D|a=7g-Zqv-(n%X|=vxi~`s zfz{ zovg7Ve9)x|r?H|1Pmi-6eV0fX`u1>NIyd5uE$-COX(LA%F|J`xaeL)jmcBIbP<)ot zx+;pJ%k7gcK-?*kkP9HoNsD)Kb!X-GQ7)!A^xdr5PuJb-U3pa#{~cY literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Kernel.class b/proj1/nachos/machine/Kernel.class new file mode 100644 index 0000000000000000000000000000000000000000..dbde6fd6a10ceea54e73b34620acda71851a1ec8 GIT binary patch literal 576 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 I+QK*g2OC>c&j0`b literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Machine$1.class b/proj1/nachos/machine/Machine$1.class new file mode 100644 index 0000000000000000000000000000000000000000..2935fe4543e147af609b061674181f15a1ee1cf0 GIT binary patch literal 684 zcmZ`%%We}f6g|$P1B0PZN+^XES^`X1Fe&P;PzhClkWxStWy8vuSc$8NN3v%s@mXx3 zV!;RSQHW!b5I|)y_xN6)d+uZW{m0jD0CthYSVAktDy|2!7UKriBixK|E5e4r(i3A% zxi3&pI(>o0K{3<<%ROWD>uNI4?!6l1jI8vEOyzy$Oz>yHMmaWKK)$k8yMtVLuj#J$ ztjflPPbUQGq=!>%@9eRRtE@nLR8%h0FHDe@v-?NK>O`^jbDQObH+FQW%W*M`uqkmH zcO=f?yu=o^CGMgf;hw~OJP=s>UpaxxK{Cyi9i?vu$2u!H$RhNvvUWOM>ud?`W1)1M z>kG7j3_OLTl~V#PVwoN{_&a%*Vu2T*qIQb;3~1fCwL8) Lf(o^oM7H-6kJy!Z literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Machine$MachinePrivilege.class b/proj1/nachos/machine/Machine$MachinePrivilege.class new file mode 100644 index 0000000000000000000000000000000000000000..d331f63ed68aa6f430020fa9fa2d958bef6bd8ff GIT binary patch literal 913 zcma)5-A)rh7(L&%+m)pVqEx7Ypj81A7L*%<=}i+8llqfj@OrvVV9BzZ>}-iXmRA}t zd;p(<1fGLQB z%G-j<>e`;5+DSiZ!E`rD^qc-sPiOB{FXql{Hw{(1r?SZQ#bz}>h>T$7wF(bNc$Y=T zQLOg~ufIwXopoYmj3#2On-G$k;An^p3P!8U+!6Rj=bbb$sl9e(wanbrv=A479qZW( zFVIW>276c$ERHE&c-b1LIiEHK&9cx4Lxa0%KMVCsj>63GT)yIzBWF`3LF~~y9ssytFXH3U*UY=hXbE$&2GvGCiz_- z0$8WnF)ZBRYRPR@$D*HnL*>JW?b}^Bg)3(Rg~kw7C|LDb+=R@4M&=5w=Y^IvA|t8a pjSOYnOBojp+#b;8X~Mw*uCq2dVU>T`6bHG*9-Os?dzh+C`~n+c*8czi literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Machine.class b/proj1/nachos/machine/Machine.class new file mode 100644 index 0000000000000000000000000000000000000000..3e598f91fdf2a9e750fa5a1f4873e0f24d4d11d7 GIT binary patch literal 12258 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 literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/MalformedPacketException.class b/proj1/nachos/machine/MalformedPacketException.class new file mode 100644 index 0000000000000000000000000000000000000000..7bd60bcf543192ec1678801bf562ed32ed236e3f GIT binary patch literal 334 zcma)1u}%U(5Pfspae9Iftu3q&3$Kt)V?(ey3<-pOSXNoR+cn2w_$?|E3qHV)GR_iW zXToms-o7_8Z?fM%Ut0h@v=h|OjBy&HMX28!YpMrA?W#K^gnc*HgjQy(ep(eXT~2tG zi*uGa#rc#= zG(Pm=zs8$a{@?~eM1;NPmF8?;(!Z6sL?Hk5hvZ74U|rPhP6N^PCuk!^fLJgQ W2K?$Kj&?5+jBqR!A8{fWpz#YNMo-TG literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/NetworkLink$1.class b/proj1/nachos/machine/NetworkLink$1.class new file mode 100644 index 0000000000000000000000000000000000000000..8b2c1744a480000021da51994598a2adaa4a6466 GIT binary patch literal 647 zcmaJ`dUG^$_rQAmH@kYbCJBN_CabhAR0i zhY>UNejLhZAQNrlWzw+%1pG^5RMLxNnkt5k2bwgy)KgA!L))?qy-#tTgz7@uCbfTb zznaLoq>^(JMscdm=$*>O@wJPFk17s)xTx4u-Nzw3?qKx_nq5*`x*(Ef6uci!RG4w3 zzp0P8F^f6(R?~2@Kl@8nm?t{B2|grxPVFOgT1+FuP^G++PKT--UK+O#QL9yH>|nFt=R=_9_Zy)giyZ&} literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/NetworkLink$2.class b/proj1/nachos/machine/NetworkLink$2.class new file mode 100644 index 0000000000000000000000000000000000000000..5513fd1c5e11d5525ec9a59b916c6344644e85a6 GIT binary patch literal 647 zcmaJ)5FZe52QROn*&(%~ixO%2(LwJ_#W_cM zOdS@+4Ch>WnTC`7-(RNU!s`4g`eF4YwfEIlIgN~Cm1WJ1cAKg^UK+O#QLj6-yv_>$ z8Ukh~dD>>|GC}L}HAL$MmER>Mq-7QDPfXD+3{jXyoe}XRn;_y18Y8X_y{njL{eiee h^*NI*nZhAv#8kyBD=L`7JiW(0Z!uHy^C8gl`v<48izom9 literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/NetworkLink$3.class b/proj1/nachos/machine/NetworkLink$3.class new file mode 100644 index 0000000000000000000000000000000000000000..7fb8f92e1dc52cb9cdb8a18bd1d168ab0ed21a1c GIT binary patch literal 647 zcmaJ=AEqR};Lo&L~!hUG`vxFAK z2Y-M+N<6a(wiM#R-aGel?z!jQnY;U&TL3$FUx9;l56|%0!x|bc-neMGcq{Nco9MLD z6KM903@33KoY85cf`Q5|;^efi&FL<2d)nx1U!cA56mWAW;2gxqN}$S0HOS9KD)}Kt z5i|9E9Li`Y6K&&J(y;;r{3ByjauCThRSa8CH0f+pPdUjA?S^gWeUI}bREOF&sr{q- zCSd iM)`lHp9PaY#mtz>SY|~DD_Es>*yk0h1wS7GJ--L9w2L_fjxP!tb-fFBjD zNdk(X1Jga-R9Dw@e{|p80o1UbgM~Q3pp!Cn|XeqnoC$Z}y1W_qCtY1y(oy18!alSO;NS2~4n3ous!d6I`y>;69% z{-zNai@5f S8Z-13`^;jZ$Irdf^LzmvY=)2k literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/NetworkLink.class b/proj1/nachos/machine/NetworkLink.class new file mode 100644 index 0000000000000000000000000000000000000000..a1b7cb723fef6875f4ca9729d0b50473d015e709 GIT binary patch literal 6424 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 literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/OpenFile.class b/proj1/nachos/machine/OpenFile.class new file mode 100644 index 0000000000000000000000000000000000000000..6b6bd05bd7e103c9589dbc7d07469208d403726f GIT binary patch literal 1495 zcmbtS+fEZv6kTUJrKJ{&lwzkap_j5BwM( zG?9?_;0O3o#&yn2FDZ=@ZIiRloW0jt`}XtK_a6YZu$e&$#Ys%SR>xWz>lxaIDQu)r z63EnDPgXv5LfH~n-tnDUGw76BG_Eg8FZ<3X0;cb@q(FY>#ChkGJjZX8Dq-988}v;) zb$vH{F0g6+f#V{wctGA4!7+JrJ5=25wyLtd?^Hdl6x1B=z-hbcJAO37rrQx%8kN~Q zmA*=s$s{aAJJpckAb)`st2l}oxQR+JepgpG%g8Y`nr-PE3#6^`(RR69EK}$-U@Ai0 zs@=MPakR}=1oe7HhP-&vZ-h;Of>Ki#}vk;1o=T&|k(x0Hs+2;`U+8GRc{S1k(8j$0ehZ&zUq?sjX4%2)oL@-=q zg!<*QjL#>KpXigPhXiB|cN_BR+` zcrhpn)~O!v4S|z=@H`gAfD@zOjj`ZGEXCk`+N2URK99&g)5xvJ+wX;e>sZ!l8LVtY zS7_iS-&Cs&tny~kU$}(A>;F<%&=(Q1wQ?b+^%*-5OB}DF#D}dj4hz zDEh!VxEo78(#4Je)--Tl_oW9^8d28-hxzxcPlm(?Suf&#EdGjCZSKW-KWL;Kd531E bCZ#*1C#AMBnv~ky!XO?C|n~ixo^qwNc2XNe#)l&#J^$ErY`UXaMUe@2nS+mKC3HrdzK|aQCg&r$0 z&M!h+leo%CrJqamx3v%0?kQ3is!x+_lVmem-O);RqArlfRHC#)C4*hk?(8p&wvNuj z!gZ~XA7l;r(t2+G>9~gJM61HLBDUO*FivO;##O5U7S4cJLy#HFCdKdA%3@x@Rn;qV z^PgefGjpc#9+q+9zF;tCz9eJLRMIKE$-FKp(q6(OmbsrYH|gqD8w0r^aRGCf*C++f yl-2VTaD$f8%Cj!Zoh?wCz~7Nmvn>7%&-zEaHOg0rw@$n}Y;*U&;S~sL;MPxpYr7%< literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Packet.class b/proj1/nachos/machine/Packet.class new file mode 100644 index 0000000000000000000000000000000000000000..009859789ecc8f9a1ef3bcc347d5c80630547ab6 GIT binary patch literal 1288 zcmZuvU2hvj6g}hJWc*2;hV&y|pdXMryEtx0TG}QmY6_7o+<=r235ADl)U0t^F@^4N_a(B za0?LlSeu463)(abxQfLhKEaa2vOuZt2m2~rJ4n?)Ah)w7AUlJ!9Y*^CqD3@Ff(+$@ zI7(HNGOxU+{EkZ6DteIa2~_UJ(IEAsbldL^l|?ePz^R`9_-oTVOVh^}1g3b*bkpd+ z3rC>Z<;**sPND{bcGwG3UGPL;ay5*?^fsB)Tdke7`E3FFZro9vKwfHN*xOafmcQHO z$?0|+_}y(k2{nFmXs3H2IiGDuey|r0nmsxeHZyW7q`#Sx=RLn~3MisPMWFb_<3RP( zkgEwy)U(OO&3KpuYCY7`N?C`6hyIVgz|4v5%c$X+z?EZ{_x$enane(rti{_=WxRt^ zWmL79LZyr{DiYVr_!KuJZkBNiBwW=Kn_WM8(EMump$bv~tFDEaJvL@TrH|rdKYPDI zl%dw=d|AHpSeMO%L8^KJ1wTprgCOo72)On3@i8l{6OLN*+qlS|RpN8y>B*Rp(2E$) zU5w{C^yhJ!SYVoQ4(}4rjNvoHXUFh4;`3v8mNkNkI`r>x2p!Z$VZwEeFzGgqAYIuQ-TyOxguMG4dFwY6wsc_E zo*F;lWPY+Sdb-uH^c4$UqWCL^T6mxKx>;+QG-fEnIm}}g3#7P2k~f&Kh70(TH=DSG z9b85SbLgXv4_NDFDMwJ@&7{k)O<8Mi!Zi97y;MbBP3ghy*sy5vm|IAHV-(VHr;WiXLLy9{_j58VGw_*&< WPZDPFs$P5@IWB&}+E+Luhx)$+`1iX2 literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Processor$1.class b/proj1/nachos/machine/Processor$1.class new file mode 100644 index 0000000000000000000000000000000000000000..7b4ae87848d32f57b8a3fe251012bed3de7172a2 GIT binary patch literal 205 zcmZ{eJqiLb5QX39YSvYBOR=)BHVEE86f8u+6T}$yhnPUJdN>OY;Gx9X#?E=nd_0&p z%=`0v0a#-wAOr@4?CkGBn_XoMVSEZ+n;3mq*6N`MldaR%$I2B4)0F-ykP&81>C#7e zV^q$_Uudx+jP}l%u(2ve6A5{HM_T0ydA!s{H-zcGcs>WA!|%1#Wr1CS9y39oXUd)N I4l$9ZU)MP@9{>OV literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Processor$Instruction.class b/proj1/nachos/machine/Processor$Instruction.class new file mode 100644 index 0000000000000000000000000000000000000000..7ae867baa4abb469e89e3f7c61a921c5532d9f21 GIT binary patch literal 8426 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 literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Processor$Mips.class b/proj1/nachos/machine/Processor$Mips.class new file mode 100644 index 0000000000000000000000000000000000000000..b46a70ee04e8b0cac552be3e6104b6fc5dfbe1b7 GIT binary patch literal 5751 zcmb_f33wC78U06Itwy$N)&m9~*p?FxV+aO9NJ2=0unj1YWg^)IlU|Z7Y&mO*NHT=< zqW68@cY3$!nNmudH0hC^>7BHt_kG{@-864zcC}NtrC+`;e4jP%z4_<==X$%#UH9I4 z2N7*&8yhK0XCw60D23>2oW3sGZ#3fPn-YCX{(M`~vz)#o+wXGv9;fef`T?gOa{3Xc zA9MN%r=N2A8K<9f`UR(7a{3jgUvv5mr{8k=9jD)O`U9swa{3deKXdvEr@wOg8>hc> z`Uj_fa=Mq(zc?e5V~n#9XAPWLoP{~FIg4<{Ig4`E$XOF-G0vJfYvF7eXAWnroC(gB zbGCxBHqKUZwu-ZM&N?{j5MXvM z16pL^y{R#Y+Z5if^pz5iYkif%T5kuwYGU+&jPF32JtNmh*ePLpM8Yma>`9FrmUy+q z`^FXSR=UPLO4l*H*uCsjb||6O8An%YETPuXC+B%kEp&~7YE5gg?b-3MjHrcylSDXm)>c?|5Q#Y$C1V<}fGRC$;Px zGLI)R`$kmHJT7BqWPBo%mi;5ytSnH$;>t&Bxx9qGBvrDitb2ZmwD_fX1&) zm2%T_x@K${INU_dixWT9_{8TrW>kr7&AuSn!y=t5_=5uE4DO zH%y|)Py||DsRK|66kt$E;+{s*}D7hzEwYehZ(EEROUH6H;!Y8OC}9l)Fit@%nEoe}JJC0bG~@54<7m-pe-2AA=#F}RF>t-&$16`ZWkUh|Snj!;jSPx&ip6z5?7g3Y7gIcYNRi*8EWWAE8R}%F~LcagijD-9M zz|L^`qQ95?EdINLfBcNI`*sRVHQa`uGZf8ES#=ba$mtM`;Z~0O(3G9BJtYQZNGTDe zbc$xnkKsz`5-oMb(Zg1YWr3u}bqgnu)WEQ4wVXDU+KI|cVIeH1RSS(ObyO^`D@~rV z!g99in3z%;MO$5IR!WmtSyx(=(kxchm1Rn45$$!wk&4<7r!{~gfXf58LPDogbOeiO zQ&N}c45XDxS}nQ)X_bb_H;C0J{U&6Tsd8#wB$6M7Pz-PU@}d z^Q0cDHRMU>DQS)9wOYxO&iA6?R;%SnYdonBxo*9mPU{Rm}CXO-CLM<{dZNl-E@MhC_A5fQ857HK$ixU03uwvPY!qiuO^j7_BSHNNSo(?WX4*^gBj?di&{sb683T zC_8Dm)Js~`M(Po1OiI7F^;->V84DzBrXF!1khGn8#WjI+zYV3Q@BqHePEkgFA~E&J m*CIc0tdk8lTX#lQgl&AzeF=Rb`Z9eSZ6l&W^cDITHQom=Pg$`5 literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Processor$MipsException.class b/proj1/nachos/machine/Processor$MipsException.class new file mode 100644 index 0000000000000000000000000000000000000000..a51133e0c9cdb8ec307167abe98bba9345331638 GIT binary patch literal 1956 zcmaJ?TUQfT6#nL9$dF_LAzTCt0*V?!B?wqsQOZTR)P!=AatOgb~MwSDbc z?O)Ko^`+0cN}#%ykA3Jr>7Qu3_ar1Bmxr9a&pCVc_wC!s-~YaO2VfMAf{_3^FdD=~ z++yvc03_TF;$wWm+dDy8##p->q>FoeF&@CDm{2eoL>RZ~F~xG4m-|6HzziGC@-i31 zJU(OXVGv2ALRi4(3KkVCNeJy|&Xkr}o6KZv3DTy7y0lhwbkgS~)Nfa>{O*q7^bJY4 zm^8KYj^!lsBn(qeEZSCDcO1(elixmYOXw{?3} z+s@HRG-;)^+?r+^yssR}j4mOZG78Rv@6&q0H7rwtI&Ye~J)P4WN2lwvG5d~vNJPUc zu9kk9(h44cmyHn#-Di6koA+q@cQiA@G<`9SBDi7|?X*5)@KHlG6N9_jGfhJKS(#GN zgI*PvF{I)HbgEd!ih@-YkFchq3zzurii&R5zQDSQ4QwjdQt=pHO1Qx86FJSyCRSYA zFtbxdBbU*sfFb=bId^(gJi%8gzJ{h?TSXcf6*|6Ak;RSzL&Ywhs>mU)z*J$Opx|2- zHmJte&LVz1j}n?|OpcVLp~_-G%X49xw~{r(GG(ek^gWcMu}vA}TH5ZaU8Ic4u}#i$ z_&eKh^<_P4I4(z77b_P-c6G;PtLc7f+{h7#=VX|tB3VVcZ!Lox7PYEjx`eN5d2Uv% zP|(ecgd4Gw^!iU6Rgz2}*1J|Y2nj8*lZIqb&dYH`2}*(SbJV!4ry+7bX=$FNzTqLN zLf1Ln=rv!(c!Z6I&NDs|%W}~)d9a9N+k5#>l?R$x6kTi9*1VQ#rwA*CS~f9Ry&(sO zY)6^E?Q;oKJUDu~NVR;i|c?NvF&5%)l})&qxuQWw}o zlLoGX9#=qy;E^Lu@Su5;#teu=cqnP_qnDDVkJdig{X}*?lCk)}9z=W}zPN7>a_6sT z?0k*7cfUcAe~0WlfIr^32j!LL;VP|ds3VYj2#6CjMBjZeXc3T{Zi1U<&YXt2U)i}=W7*AyS<+(&&}COYx1Jp>q9fT5#oAnwC2 zW)Kpyh=@54w#N&lsS4XvfhA}B)_9>OFjN8hhrAFxeu@795$U5aU9pZI#0Gv8TliT#_F`Ad iu~cH`L?x+ literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Processor$ProcessorPrivilege.class b/proj1/nachos/machine/Processor$ProcessorPrivilege.class new file mode 100644 index 0000000000000000000000000000000000000000..d1a01da93cd9007dcd682ae2cda2454afa1534c1 GIT binary patch literal 922 zcmaKrT~8B16o%iKmfdz)Vfj#@f>x>054B(nkzl;Rn3y!!MAQ4}GSDH*uGwt~{wxy> z#tVOdKg#%yY=A_Tn>lmNob#NIJ^TC5&tCvuqUB)MTpr9eTYsu^GP+SZx-&wFUy^-DF=2%=Spwn;Z{y z`biBVTIPF6sG@;Njn#8w*(T@PMXG*kPE4c^8Q{NAXC|D|lsySMh3{FP8C=5U=62a&VnIE|tf6jW3gNLx?K* zBAqwN#-$z4nYU=XHAM4yi9EJx+#I4>zCtKmS;Q^eD!aGK(Kat_Ao4>XI*UK` zLgXXautVdkLbOcK@077!CU@z4wa&W*zDC&JqjQHK-z#$NlgIub@Lnslt_$*q_}zD?F|*Z2;NKf+`*r&96Erlgt8#eKI^ktcf znp4?aroStfNT-;l$mHgMu6UmXhj(PsUGZ!-o!OB|98M(T-EpSkcz#3sV7ALlCYiVy zXE&vR%1q^Uo5}vTSCq;WcJ}TtyW?BT{$x&8*o|dZOH*qio0WMF({$&=&bS$COC<+o z!RuaV>d$V@WYQT~@G(W46B}c(47ha`{q9q3hvS(8$@CF96=14xPBkYXmzi`aLbhm3 zQ=Ki_&E7baHDh1PLG!TLm^4$}jqSNiBGtW?$)AaL?_Oe$ORaIE4R6fD%k25(*4Vy7 zXjECi&W!@hv4EDe0M!<-Eg`^M3)rzqfO$+o5ZoRg$XOHfnRHBSGW)Yi>oqVc;3hM+ zTl67k7C_yp{@$yz@yyP6cOsjMXOy~Yfvc}z*ou~v+0~QIHfG~p{h35=u+gzP#1yL5 zQ6|qm7(A3ro3UMHraPVk3j(y7*+bYUugVE9-JgY$U}5;kUM4M<>}*fm2q!Xf88ekl zn&M~B?7V$>+Pz>Qk%~9&Dy(l#`$f4&SV@^j96#4=eEB!oe}Sr9YV*x6;ZKSeHm8a_gDq)a7NHM6b;YcOw=zrDM>^v=#`yy}!3Jp4lbL z0DDUs0k+%BBm}l6Ie`}$&tuMO&0$;&)|Jd&8PBBR2+-*+SydLmdJ)!lx8`@0 zjwLnNmnY{|lRCOCx*n&ewCBvOL#<|?;tJJ3s%Z-+7{tw zz<(z0FRfcR*#RbRrXPvQTPH^uDsq%NK?OBqk{MX`C6J()YR{>(8dnZjiz0&30e{FK z59PxKNa~swVm1JWgPov(qj}3m+2w1p5k7}^LFX*4WIn2wtxbTx4+NQ5+|JV?C?4dp#Wv3SxPjK^#?vgYAuqWZH9$7xbMTb>gq?hiJZ$G>Gj`Zab;WmVvb-2J3CIqCLuQxM`I==*P`Ikj9aC$? zlAZx<%AZ&+CzhP=#N=_DKfglGuRibj^Hrrhnw5fP_W97Ll4XmzN_H3W@`Ti}*77CK z0Lr�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 literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/RiderEvent.class b/proj1/nachos/machine/RiderEvent.class new file mode 100644 index 0000000000000000000000000000000000000000..a52c08e4212cbdf417d0a80f5c0ac1e977961864 GIT binary patch literal 632 zcmZ`$O>fgc5Pjn~braI2X$jDz<*OjIJ~Tq=4a6mYR4Jkopxig{Lbh_(mF?urU*ZrU zap(`=M^$~}6j2V?(!6;)GjC>ge_#K)0&s$tO+?slU=5GeJW=yh&9ey4BOD0oc42)f zkW>0!(=5vc>o&CuQ>xoYTyCeO%e-K#N`1$a;_T9Tn+P_BnJ-G?%dtu4w#J?ibXR$Q z3Wqb}zu82C@{hwj-on^(~g22MTCzsg#y)OA$(EOau^QrydRHpqmbbM|WriJ@> z(ZV_!Ei~2KQ`162u=`(8Zltw?luHiICg;2?LGAEpj90woh)YN4s3yIR%2r6_3Mo$9 z#RgHZNk2fFeCrPHkZ<4NJIoZ0+NFKKitntc6MOMbNZel{i1(JL#rsQyaW`C|{-e@; ys5zVo+$+?z*maZt&TYp>jGU~L*s({Z`8v5&p3WXro=&gN*{f7S#`|Oe_HFY-$%Aq-_kPtIqH9lNmvUS{_v6 zCQon6Iuv|qo!CdMI`@&ogDLoQWnK*7=)ab~BEq1NWzP7=>}I~=A`*swrD^TGnLF;u qh)Cop*@x($D|t_5NT7u`)_7AmUE?hz9l|#HfW#f_w!biFy?Z}o_)dNR literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/SerialConsole.class b/proj1/nachos/machine/SerialConsole.class new file mode 100644 index 0000000000000000000000000000000000000000..444fe721d576e976e0684e30b8a6e9b096e51faf GIT binary patch literal 251 zcmZvX!3qIU7=_QzFbqnv^Z+AeHgkYsNEf)7r&owu`+bcu&ypK%4*o literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/StandardConsole$1.class b/proj1/nachos/machine/StandardConsole$1.class new file mode 100644 index 0000000000000000000000000000000000000000..9da67833a6d6d459d777aa66922e7355d891ab89 GIT binary patch literal 671 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 literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Stats.class b/proj1/nachos/machine/Stats.class new file mode 100644 index 0000000000000000000000000000000000000000..89425ade919738ab73fa9acdf431200b228f4295 GIT binary patch literal 1881 zcmaJ?TUQ%Z6#fngWD>hSz+Higz&(K#fmMMufiJUIM>T_u90svy;J(OBfd>Y@GVoB;uXFeYj|_Y(#&-t3 zH}Hc2+rXBAnt|;MbOw(Va-kpE?uJvV2MTIgp}(%1o^E@xtw1-EsOhyDx1FHAuI+6} zUQ!rHTo0N~sOcM`z2JL+@9HFL_}J4F#Y3D$1D;W2a#@K}17}{RAX}c|*;(it9x_dN+cyhdEos))+?`=2@$x{FD zl&aQsu{n3rcM=8f=wH#{6Tg`xi=r3z>;v1x9Il&q8|O^CBk-=kdpK|6eSxCDlt4+~1A%FQ3pk&_ zj)`433a8|#vTJ)gyqFj6%(onOTQ|Aohy^oN#23rN9_j+FLU!7UIb$hgrY&I%;|+Kj z_$K!8qr$N8##$<`&R9)hPgKuCS^6ZR4oeHk19YY-jF2g8W5(JiW30y!WtcoLZILoo zBjOD0vE-@R#W79dh61vP+DNy>vbE!hSGV?bjVtbOReuUX-QbJ*Ee1v_QL^Kg*W@v{ zA#FGKHhuQ~zV^tN3&l92V}Y|%CtS%+SvXl-{=cvh`td8U`{Kz&9#H7g5MLqUitDlC zZVi!}lf|Wz=e7I7CH~4-{AvnNLMZv7gj10uts+TgMUv!-B>5FdQY?~WStLocNRn%j zB;6=a<07R(nR*XCq9DUd{^@J>wGLbAXFBXz-l^n!A>LpI zzaT{om@7SlDrKLdM<6ATE~TELSD;TIBVY(*1#$xY0_JbgBsYmyFhCqcnm1K(cbBKJt5bG(?M`Arq{Sc#v80)Ax6~}rHF`hpi>wVNu(yWsoJ?*4g%Q>k|369Q0Lo7WNaKG`eXNCg))m8-H}@ z7*Yb$ru?ZIq&F%PkVjgp>>vsAT=8;!GKbb!F1g!TscGAWi`PrbEK(*wVBv0??~ObX zGnkc_!=l6#Jc(&Y7jGoqqV1w1(3vRJcxi!pC3q6*FTqLwT15qWzCAiEwf--J9Df*! zeW4OnkRUnp?N%mM76U)#B>UGmii-fo2`nZ?)fgc5Ph3CacfNLwxmEH6pDe=P2&c^g`i$4kdQ(vkr7 zNQpok_yPPV#OyW_q(UxO@{DI^=FQ9-+dqDO`wrk4I`c5GuEawnTqPb^n8RZWOL$_U zX=1~K$6%fF$jydf>TWZv^&}65aq5pqg;MzaEFZiMBhmkqW@6N3sHpG{3=6$8e$M?c z_LZ9)w#G?v8SqRnup@@5hV7VWky|0{e-u)MllewUk?cl1O-0JkDz5APnM}2+FGCq- zI}FFo|4A&4?aoegv~kE_?8Yb5?P8C(*vm%)ksR=W>VLTx2Ru6DNvQ1Up`qqwXcyO+ z8OH6S^C?Ga_Z)l45By<<>_0I4dW9VHEh{%aKna$Yc_0L zx3Pdl=I=xLeG MmawU{Nj6=-0B%eV^#A|> literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/StubFileSystem$StubOpenFile.class b/proj1/nachos/machine/StubFileSystem$StubOpenFile.class new file mode 100644 index 0000000000000000000000000000000000000000..a4e5a60a255cc226e366117792659d67ed7aaec3 GIT binary patch literal 3050 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 literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/TCB$1.class b/proj1/nachos/machine/TCB$1.class new file mode 100644 index 0000000000000000000000000000000000000000..35d927652ad1e383b76e6bc2645c15ce02b196c9 GIT binary patch literal 600 zcmZuu+e*Vg5Ix(AX=Bt{YrS9TL#<$2@lEN2MM0m!K#<_yK;D zcoGYO?ZVDvCg+@)+4=hZ_yll(?L0DAG?B%Ui87WAtQc4|uqH4O_MD*75GZxDw0mAq zAJ92k)o zVb6Ooux?=kn-&b@EaXwNumzJdj*eJq3KU|Qx-0c#{j%FvcF5NMQdg1I!+A#O0@)yx zJ{f$UQO;q~wzO>(1eIo^flV$V3qC7Ep%Ayn{iJyFFqxg?SBr6+F>AZ85Vbd?o)e5k zOBU@NrfAE*C`_Zki1tY6GfDUCTYQYc}bKEpZ- Lm`U`xX?mU?YcO;; literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/TCB$2.class b/proj1/nachos/machine/TCB$2.class new file mode 100644 index 0000000000000000000000000000000000000000..b6524db80be46efa39dffb707e7015d4fb55c570 GIT binary patch literal 776 zcmZuvZEMp|7(I8*nl6j3&TXBqn=@*gfh~2PRvBnf5UPV&CVty(dRa5F8%WaquYt0m z;1BReiRY#PUz$Lkd!Of?bDo!bfByRR1Hc}3mtftWOOW((D+5rG6@CTcUr5YAIUUTbT>-Gy)N@tlBuR`nncdWc$x(2ZD_=6 ztnc}mypYWNMh8)xhWhlq$|mvHhUel5p1N?b?83#mK;1ywk<_Q{;UrOV?BW@k=8&)! zd=6l~f3N!w@o;pef{cCr(K?!HT{JsS7g$U)nUKNZ&2xHrPcjHpntCrfyaT^{#${Yi zqhNMBta87U`4@54bgwlZ!Zu$@4FXFL^|~1uAJ77S7dIHa$=v~c6LI|AuMqwf7A|wl z3T>4b-~@HrjTs8JaGM_Sxtbti4eN#0D_A+B;eUbnj>>1VUcfgc5Pjp=abw&xlr%IgPzs?WEz}95NGO01sgMxiLu%9m5{HeuYFyG7*-l0I z9|#cKIddZ7z>xz#3Nf3nrjQCt-r1R*_h#Pg{`&p>2Y@m*ESOlbFr}7@ShjEpm(?z( zmMbP!Ok6clAjI!@Z7;edOB+Q?bMVQ`-g!}4=cs*z~B|1^l54^W>Q-)FCADUPt zWJh(z+bi{|Xm5&y%&@}obAq+ycLG;FWYvTz7PP)64ulO0r%bHbxQ6Q{)@?W_+9=_M zjhjdlmi{vhLQ3&CEz#a}o;CKQ8<{8*RtC6Gx}Cs_4xQ1&j}4QMo=~8~7x-_OH3-+0 zVVElymC}4+f>yqrzo9j+p`d)dK~xVqEML#RP}ee~+fa1Qq{&u>6(-&45PnO+vnT51 z7i{v&CM5W+>(JE1*|XVm*b-Y~^&7OWywNbtYg`5C9g@7a`w5uAEPI4ANb{<|FF9Ld zo9QC<6Q=$JdaMhby|pe3#TM(aCE0@BBS{}HM<08vnLcvB${d*EpKz8@1~luw>T7;f z>Mnb#l)=pLqdqMaq)*W4^BAi!Vm11#DX`=Prchnq9#XMnI-(kv+;482W)bIlu=7ly Z;Q~&xU0_)z&o;&6S@zYJKpv@h;t#FK=?nk> literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/TCB.class b/proj1/nachos/machine/TCB.class new file mode 100644 index 0000000000000000000000000000000000000000..736a08e2b475981106c099002a774c461160a738 GIT binary patch literal 5106 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 literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Timer$1.class b/proj1/nachos/machine/Timer$1.class new file mode 100644 index 0000000000000000000000000000000000000000..5a484091f09b2933077069835349682b88f54dcc GIT binary patch literal 611 zcmZuuU279j5Ir~9y3M+^Ym70iZB)oZjNm5Hw@6-!f)H(KL*H+Z?iz64u0uS<~&U!qnPrM$r;@%mqK0}}7}~yVxY)I?rjM8KIBV6Yy^%m*iNaW#MR+z}sVL_F|56u)F`KDc zRRjXvzZ=R_RHQop8lI>6hDsM|Txyq5q%!V%IHVGX2jPApg1{=|scQTi@R)tb*Mzan zc!M`TAO=5C`&MFnT2|2>V~@7ILE#YsM#PtFf{4dxZn@sk+lt-6cZgr8|IgGdnfwiA Z%T&h`R@BhKQ+kJeo?*Y_=fUau-2(#9dyfDB literal 0 HcmV?d00001 diff --git a/proj1/nachos/machine/Timer$2.class b/proj1/nachos/machine/Timer$2.class new file mode 100644 index 0000000000000000000000000000000000000000..147dde6baf18fc26b23a29283a89fd9231ca053e GIT binary patch literal 906 zcmZ`&ZBNrs6n-wNE7U8@$q;-2bVawJbWFctNDNT}3^hvj{jR&&O1fKf+miUROnf1J z@CW##jOVsv3#K;dx%Zr&^E~IRzyJLF1>iY43$St5!94CcxQ}%QYuGSi)4>Bgv{AR= z+Sp@%!2id~vL2J0XiNQR{@MZQhP zeW_1HKO{@F8~Gya2^|=HVzdk?13y$s>Vr_ku_Sf15Z>)j4keu`k_|)Ue2h}<%h!Q{ zcd{&Z&cwMO_E*Xeqc~8*6Pb*nfsIET9FI91TsOCxjRr>(EskwG;dqK28y-g+yVQW9 z`rQsg#h`nkP($xs|4jM`RW&nxNR`SP75F_4n5y@1Tzu zE{nX91H)osw&hSIQtR{+b!cOnMgiYZvxiOE(0MQ{fK@7HK(x4X^m5!F>muFuNjDa! zwfzmO^#gNXGM^=qW%2>7a)snd?uDDUMH=~MXpB6TQJY{L!^$FR7bvy9f?dGMk89si rp21eh4X6{nOK^1p*vcq)9z3Ba5v57?Hdg7h=(oCqYDUbcsOwc0BLyCIkp&hWGn9=lM9#!ax80@fU!b*iRyhyK-1iIV`HUf+e}V zm&7MnPGCjFeUucesz~Bfc~e&KK!p};9!jf6Nvz><5|{8qZrA0o(TmTpso--JPw`AX z_#%NXd+`;%PT(5_-zs=6pp|UfaF#6Hbq!Y_&4ssN)(xj*dxqmQ_dEfyD$wVhI?R-J z^nJZx>GpQvNz=CVEz6h{7|@$uW5v;{ClHc*j=67I#2}pJ9D(?pX`9}>z}4JqEG9MuqDze`fiIR#+j!WlZyC;p^oG%t8x`H!)E!gq z!^5aoGa2b%3$#veXjt&0mJzsy*AD)E%bTHGw|FJHvTgVo6X?lJFjE|PdSTtuE4vT$ zy^yuvt<;Qa(=yu70yA%NO$iLQ^KsI3NgMfr4_dE_ z^7YJluUqkVEkg@p`n80NR$Xs2orT60tRfB==Sdvf}C&C){ZEs7IvGblxYq*9n4KpYz*w#>ksbNR*zb{z}m{PE- z!9r0WbBcs@@>~UV4K^AY_CV>yLdRSU9-1t%zh786YwZUtkUH*#M_W5ag-z3Ow0_`v zMxDxNGX&m8f^vSBV~)EY5v2t%lYfb5UK}Cz8{%o@1rqt|M~LMAMDiK0)FbqAt;zL; zBlK~)_^S^(!SNar94`~dwdr- zG|xBEp}6Fa9doGu=`;hK>A;G&vEs5leJnOih;@rLf>^!zLqradIz<1^+(zgQ3H+;B zA506Lg8Or{YzRYFs zD-6ec@*t`-X@L^QRSclaIzQ-0S1u%tGVM2Ui)<13kqKEBnOvE!Oh}=oN4V-c#Sj!? zjp&a%!pQ{4sRTa2?GUfPS>nZ*x1Qrl28r+QFpl9vsR$Z>gxNF3tlcj}>8x6J<2iiX nHVz6OqyOS`$-5X6eBP(HL)8K!tfa7qca%A*Ly2TTIKv zj*GTJadwp`s2;s5@$8w7qY*P_3QK9IN5@Hgtzbz>4_f1%vAd0p^i^=8cDoJTG@FtQE2oNJv<*zx|aktc282BOk$ly z zK727N60VB5jj}@h29*k{GOHWw?!?qPi_d=1lQqf7^I+0l8QO4;QLGQMGg)7}Za{f+r{jL<+V93nHIL z>9!!nJA&?ime?iXQ;ON+X}j3KGfLmbE}rv`d101Vo0I)n;sEPBB>x3g%h_wc0k;u` A`2YX_ literal 0 HcmV?d00001 diff --git a/proj1/nachos/security/NachosSecurityManager$1.class b/proj1/nachos/security/NachosSecurityManager$1.class new file mode 100644 index 0000000000000000000000000000000000000000..35684003efff20b2c8bfef7ac638b47770a2c9eb GIT binary patch literal 755 zcma)4T}vBL5Ir~9y2-jVF=LKUkfzL@xGVohKs8oFWa zhro76OK0eZtx!2};6@Lv%M^DrcpPB~a?PT3yDY zz6x$+-(#fG@g3>)WZ)(^3mQpV0`|GqDrkE$3>9Hxx_Y%ec9{=iOGv-mr vw2tT#Mxprx@rwLJ$x7J=<^h*@I@2M)2cGy8UDp5M;Q|Led10KA7kjVUY|^U6gTuPa!>vV#=|s}9x} z+>r=95u_^842|xI7>RZ$^q~DC(^~XG`H`WV4prj4W7z6y5e%cGoyZ`IReIV!$njwT z_k|V%8Jm<(N~?62Vb`B9=doWmj~Pmxs4p3+U8Utg_OmDBBO{BU-i-ng9*bBRTpX5+ zR0jT4YZ-S!ktC8}b21Iy4k@?e%v8c}J`nV+cOrw7F5SZ@ivzi*jDUqlAOF^rko11h zK^P@U5B6m`jQS4NIXrA|xTtVE!88ZQrh_ex1~#d-6P4E6VW^FpbSsQuDL=aJ%J*1} zNa8^DKNp?dn24PU*N?`@4DMiTB*&-tBm&%@pCKR}G&?vddn=NM+nrlucRPR`+a-8S6Mxm|Bx@wcxuQ#<5#kyKU;({R@qGO3U{ z>3xRCrd8z(*UE;;ck3Syxcyc;sL{!A+0wPzzGfR@?;l2lTMR>cw$U(Z{E+Y2R>P=r zn?Ws^Cbu_hn&WU1Sq|qz@&bu&qE@ZoxXLh=Dj#bNEmzab!`z#?X$psm!g*QKUBfaN zM!HEb6nxDfc4ycPPqUalr}+BdnCmXtPqYquYcZ_$CT}-&{zr9lpom??)!aHoot2_kWT=F#fRIVbd(oDfRF6_K&yWtSNB&i;x~=mU zR4xn?U5j^Cq*p~811hdU6|1EvmQ_4OQN;>YRjgrM#WO6a*uZm!#ZXOgvA7tQ>nGDiElAV;U_exTz`cfiE)1l-kSemYL$4TbrDAa4Av)H3O+O&B=d-rd& zo>A!DGHp`}!c_IYO$DL8tcRuyvtfPU+f@I%mTSB>bWOC~j%HSC+@@}5J5>-)Wy3l} zU4;Za$O^sOY;aIiB&}pfqCi1UrT3ysvE6FzRW19#;MDW3Od zy(enYN8KWMakoyC+=<%iiMmawDMCbOzC-^B+@(=KOTK^c%nwAxl_yWpe|F^o^pVgG zDV8W^FV7i>2iK0{9_~{{KzW$3cf|iIzmbk@3LKi;NkhJjc=` WEg^#unulo>qu=7|G$(0Ke}4g9WB!T& literal 0 HcmV?d00001 diff --git a/proj1/nachos/security/NachosSecurityManager.class b/proj1/nachos/security/NachosSecurityManager.class new file mode 100644 index 0000000000000000000000000000000000000000..a4fe3cccb1361e558140d3f91cf95c559d2bb663 GIT binary patch literal 7062 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 literal 0 HcmV?d00001 diff --git a/proj1/nachos/security/Privilege$InterruptPrivilege.class b/proj1/nachos/security/Privilege$InterruptPrivilege.class new file mode 100644 index 0000000000000000000000000000000000000000..8b0b16197eb713cc171741c96335705160ca2a16 GIT binary patch literal 303 zcmZ{fy=nqc5QWd^W>+`Q~?TTPu>Q7|2BG_FwU%15nJ3a(wvNb)MI!YF2^Cb`=ArhPK0>FVBM1Q+e&Y>25=ry` literal 0 HcmV?d00001 diff --git a/proj1/nachos/security/Privilege$ProcessorPrivilege.class b/proj1/nachos/security/Privilege$ProcessorPrivilege.class new file mode 100644 index 0000000000000000000000000000000000000000..c8a187892f85bde8fb2606d0cebe0c70ea8f0a57 GIT binary patch literal 243 zcmZ{fy$ZrW5QJxAOiYX-cJ>wu;x)d3AXpg??9b!O564CBl7O#f;RE^VaML>B3Z2@l+Q~XwR+QhA!jxjoiu@EyBxRo?}&6?RVnl=`Y8l8zD6R(T}oZ zJ1)YB?854EpeSUSiP?I?$`iVGlOqD57Jdb4b;1McK)}WsgC1RKjHiHUa1tJoM#%}| C(oCEH literal 0 HcmV?d00001 diff --git a/proj1/nachos/security/Privilege.class b/proj1/nachos/security/Privilege.class new file mode 100644 index 0000000000000000000000000000000000000000..7ca26549071a2bfc154347e5c3ca1142737772e8 GIT binary patch literal 2304 zcmaJ?TUQ%Z6#h<a#_DK8HS_~UiO}|XW!0uzJ1Q0|NZ(qfNN-_F@lnY&(esY zl)^ARSE8)Mf)a~L+*V>qxqP9-oqklXti+cZR{Al3yBfYqVHNk1xSz(?_(sFG8otx; zy@0+vH@oD@ZP~DD7MCU4w%oaf;dz#)!4Mc)avjt1JjadPG_28HvVF^STTQ>iZVH@O zFwDBNt;i~H#@dnoqT|bTX&SzC>|2IiZCI`+Fk0R)wv9r|myJSM+M8CjEIq#{kgCX< zZTKyhO^w&X^i4}!`ZJ8o z=2ip}b54~=4iaN)v9+~kxyuSK9%I=tjmC=MO0^D+3BN80;Q8L=SV6Bk5m;4$)7it$ zL)E?({yB(o^@geFP|S6N-d@|VOvQlfy~E~rOslCPkBU!6UL-ObOehvoWlO55b4Il~ ze>g2kkb0Y-0>d4hMI;j#llHc=Y4u1z=meo1>4;sfyUq^*L-|iec>~^;I7f!>xZLw` zQqf^l67=!U{gl}Tckvgt81=w*s98@{Xfx$G&nk%cpxyY0M6zzcE_Y= zLL@Wm2D`6naCLa#F`Vr=c)UXP%e2`baH*&JL?`h%(Y+lH4%U(G2ZvZ7-#h!u*M-34 zU>iMIAJKCU@h&oOaLG`TsB^5s*~r}!NXn2kyhF3${B$KCn@D4C(b^%}yaX7Nu!F_$ zo_}z}(Y(domfeMY<)P8LBx_A9aDWDaVndd>aXDVGs}4n2)pA#u#?k%8x95 z6>rf)Zx^8FRUpB84ex~d-B7d7`c>+&zSRFs6I-AF literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/Alarm$1.class b/proj1/nachos/threads/Alarm$1.class new file mode 100644 index 0000000000000000000000000000000000000000..7061dbdddb89124344d50cea546f01c87c1311ad GIT binary patch literal 577 zcmZuuT}uK%6g{JBtJ{{Q=11QTKA1sf^i~KV1%ee+_&%}>xl=mUD_2lS(& zyQ>g{3w!U}!@1|&JM;bX`32w%`#Bh>S;(Mjp@O=JEfd=&b{JN)>xGRIhRQ&4#|^@^ zc9r1cuzl%sH9IH9g(p4TWvDloQx1m=MlTo(hWx;j;x?L%gnHy7pOE4paJWC@%8Tm- zXvC%rc3(=NdOi3$qeLAkl(9+KAfGDoi9S6iW%_;r D2HbMI literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/Alarm.class b/proj1/nachos/threads/Alarm.class new file mode 100644 index 0000000000000000000000000000000000000000..cd63ab6f8d6b0c81791319faa6d824f197f3d0cc GIT binary patch literal 940 zcmZuvU2hUW6g|U77uKakiv6J453LGSi>=z18WU|a7O5r{YkVAFQnp=|W>~EL51)PY z*_TQ*@dx;Gd^YMCV8NR1W@ql5J@?#m@7y21zkUaB7aKNgT(ofs^A;9tM6qaN372hL z!LnJd8uyxo>lX3?&bIF>z2(VvTeSto?z_GlJP?TH3wr{wtyWzLOq5+;J?}KDN>^mn z<4LC6s!4B8YS;LK!&uO8$uU*-Wv$U_7lVdYvfeH}^rUWX3XBJCQ|WC#P+E760)gbQ zbc0uZ;Cf7zFPV(u9lw%5;#eN43h@G|-9Xk3cjVC^jlJ9I=$d-s8X3%4DtVco$Uq#SndoU&QE`S z8ro=2UWQJ#uJ=t>udXixZ(@c=0 zDseX%yFx#5H=s_r8+ttGb1f4*YZ~!TMhtdGDWTf|k0L>^)>YgahLIBwwcvi_T!uVu zoU}+oPZWdI3n$tW*D~2#NG^{?{F#&LmGXixl4@`(;$i5U*s`&Wx{W26Hg;e#R2S}M zC?zYLfUALX?~a5QljV8qVWQOZJ1PtK3^`W}Bw4FBJDp$me2^Ny(cBlhm4s95@$pk2 zIx&T#xqiVhvXm*&Dc}q}WRp;yP7YN@HFx+1_L^Q7(t)J82aDeJbO6g(A;hryM?Ot4 oV7wzU=US=6K1nwI@r@Zjiz2ZyC}EANL4UbI3ZO}fohp$30br|U$^ZZW literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/Boat.class b/proj1/nachos/threads/Boat.class new file mode 100644 index 0000000000000000000000000000000000000000..5188e6a8a5934b1a377acb142a5588e0ff481c59 GIT binary patch literal 1597 zcmZ`(Yf}?f7=BJJY_hI^0YuccYo!HKB$Zli#Y>d}Mgm%rV*PlM9Fx_}F0;GQp+BMj zrgjE8Wu`x%KdRH`oLmS@{qml(@8x-)_p;}ofB*U$z-|0uV-_nGzOj+QN}if;bGT#U zF21vI5#Q%2?pav1k=JhbZJfh{93JZPkrqGbz{grV$ze^OKWeeA#fF7V3r_`{auBF! z&6jbkVu4h>C2+A4$VNMiOR`mZ63S#Vl1&w@3XI+N0xx+ekY2p8Cy-eSn@V7!;st7_ z+o`LlChI;mg-Y0v{+^6H{oPk)lD5YTGXwCX9Vyw2O$K7;V&%WCsW=f3b%AVMwY)&! z%3`@Zh&WA0GZ>T2uAdN9l!?%2dww%gj1rN+bmfhFCriEzTBY4?5NImQBbeaQ0CB)! zt7gd1JpNcCmJ^l~$>@NJHH|u=n5fFmzOP0!b~Wrq4YlFv+Vi?&%R04#E4WG?|JO_l zWe3l&B~Y~8VzHZfzHl&y%WP*KeNc%8 zn7_ptp3(O!)SRAkK)o7FI=5H5gBSS8!7i>ksA^Hu+e)_5C+QKXNfVHxk+2O zb*6G<&~#fNl}YGshkp20dSvS0XAQBZ#Y>Gdb%u_nDKL35q388Cs&QIXJ%|(4;j)EY z8fJRq^up4M$P1Ec!tLpBU{eO;v|7O0*G@iHVPm}fAjCU>@#UqH{c}d~Zz7vqaXS_Q-2eNW8?{M?;PXYtD8q~?q%jOh4Y6Pe>s;q#KcLS%d8H>%8;sqFPUe7rYJP#Oko8zA7CZf1eaG?}K1oHlZ%cRzvZmAy`w4U*nubDy#aWlroF T!M-N16mGFFJp#TuJb~PQO-4{M literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/Communicator.class b/proj1/nachos/threads/Communicator.class new file mode 100644 index 0000000000000000000000000000000000000000..2981b3b409a5fdc95dc617e77858adace170bc99 GIT binary patch literal 461 zcmaJ-yH3L}6g_U57D|DpKollI22gh=v4~4*qr`!qVqrpJ-~;$5 z#I;kQOjz=Lo_o%#9h^jkJnEljU^IUw9vF_zb)Ms4)yIGR(Pp4DaH(NDL0p zq8HoaftG+zwnNz&c}Ctp{s4QYpoK2k9(iCuzyK>0^=lATsRN4FT*VSx(6!jcaL0l7 p-QcKhE(h)CIyT7C_Y!@*!->m@#(Q&Qc7dAXup!?16Av6}_zNMKOW*(i literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/Condition.class b/proj1/nachos/threads/Condition.class new file mode 100644 index 0000000000000000000000000000000000000000..404d1e7dda9aed8e145991e7ad7de72851b393c9 GIT binary patch literal 1348 zcmZuw>rN9<5dKbESh_4wDWD==C@O7Hs)$!EauEbAh!%=Q zHea$6PTmqcXD4KOf+4uib?0?OR0Km`a+mM%M8(mKL{c{kBA3){M;4{@9g{m1i;Bk1 zEShYFPl+Ng=S!BDm?nVMN!`?)X@(2Y=0aCTEX@#@FXafoi828H zq`9Tb*h>bSylyk}H^a^UKQ^(p*oF{g27grIx5|?W>x`a;R#LIg3&h!xa(K3|!pk0= zBGa>m!Jwu}6)P(ibt$d0PB$t?r=cGa4L#^(=s9ba8v1Zv!L){_m{BmRVGi>&m8QF? z3zC4(G%R3I!*dC}B+arkFEFFwC6XFeWOxIS(>Qf?3?WyJ!Ofk-tIV#*It<|^R&P;s zdr26%xr6zNWeL++clX5|;x^rd*HffrqI;q>$gtG{ZP^6jw!mmP%JwK4DFUEmiB1cmQ9L#qOsFJ)SSj3 z?S7bkDIYyFe%GT>gJ$CT7ZD)8AD74uP-cVv8XvuT<40iekwf_6$MA0*A#jM6FK)|a zvfb1MOp%>N5Hkcliz}4rt2N^)u2DoVE-5J?ArX(_qeqd5e}%7#)^AXb(YED3LNH0G zmXRvd&Dyti^0k`V(ICG9g`n4<;ticGMY=aIgfxb+Nq_&_6G9T6kTBH@;W`Omav?k+ z+>L=qLx|+BqVp3%HLvR@+NuaiZa*3ae^1<;j+UWgWnDgvun5WHyXn@mK}rtS>E3yC p182~w@hZ-J{`%Wl&^6o&tC+`4t#rcG#@P;M=~q(Q1Bgg^*{1d%Eh5nT{<(cQ!uk!f8Ud;#%T zNZiDN2jHO)|2U>bQ8#SPZO-}5Wq$qs@e{xU^js{Uy$A;#7uT`r;s$OS>y{C>9o%uS zC9o94(O73Xjs|gXF0eL;WH5$HA_LJ?wkvnwJB#1UfVORuF*|gYiQd zz44DnXDY}9S~Kb8)pYt&h2s|=`+1V6C>s{XE5<(M`en@pFU!;T13lvCGEG&I4U?Rs z+uc*MpOdIi$<(YUgLk=36t?(*3;a+4%WOi+rd@|exkT@Xaf{mReS_%T`vU6|Jqyc} z%cxOqu%gY{4jS~_XvRS(#Y)0e+P6 zjI4(E2*utz_wGH9x%2k^@(SP>%@VTM@UZD&%R@t;aH@??&IGdU{k}l%JQ^y2T2C8w zJ)I1cy_18Goq8_{WZ0KhyE<*=l97%Dc6vqzqbT;1kyUaS`xl{_$t1Gpkx6V6hRSvY zN=``2P(PAxxBZ2g5K6J1n7Hfg6oWYfMOsS%yn~$@3f)Fi8>ma|d^dl4IULKGEF+Hs zS(iE&Sab7!D9wX^GZ?EN5$L3_f6Vj3S0+*RUIq#+WVmy#mJi@Ebs0TYN6dmb-+6|3 z;vs_~V~H845KzSmPv!X#`>U)3>k6YIIN|4J7r>4i*!~1I=08)QgH};vwLa<-y3h)?g1Aw-DGFj$P;oy^M;nb3NK$`9^gjeeap4E} zQR11j(2WLiUz~f+y?4HUKED9$U@Zp=a}I_u@1TeU8zmcyHkJg2la3#kYXWmkExk?{ zSCdYpWIL`NU#7txG5fyule$1@{Xfvgm4MX<+e%=f>1%b`y>F@LQnmtC3eC`y!Ig}B zllP035f*Tdv{q3gka4V-F8m`<-sT+HsHq8NhfUESaz|3f(siXE^;PXg~OfyUb(z2kT+D-K}^QATyEmg+A9Vz3CXKyh3~+J799s?kDy5aCLl^7T^uxqov2U?iNFyi7~iiBe;OwZA1uz#$j0Xt`uN^TCjRkivJd z4~F}q|BzsDCT#c!Je|~nXG||Y!fEs*0=$)C=p_q`yn4?nB-oNd;Iz! lq+!b5`o%6x*yXH;v^7*H&0!u@iaP!4MH&R6(B>%u#cz#!X(|8! literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/KThread$PingTest.class b/proj1/nachos/threads/KThread$PingTest.class new file mode 100644 index 0000000000000000000000000000000000000000..9b27f65f659053279e529238f4cbd280a5bc39eb GIT binary patch literal 1066 zcmah|TTc^F5dLP{vfE|3SfD5%6hSRjC@9_lK|x7~Rf#1SAD8V3UEJxg1RLt5@*Qe-ro(QsC(<2ojg)iH@FDbA@luVPxo1w!m`(YA^NS|PN|*{&VV6Qb#r zv31^-yn-Nff35M*zy)s)dc9Q^=a0!!GPiNL@duBwJ z3TMXwe%pUsYoS+f6`?zQ7{~#-nh+wWWl7KB$LncEh@UgryjcX@v@8(>qf?WUgg#E% z9LT9-+qQ5DNb%fvf^dYFB43>Ugu<&EJ#0y`w#;W~(KEZCO#eqH?`oJ{mhFfD^aN3Q zia0&PQMM)PXdJ@;pV+S!l}8ZAG1!Rtn*C(Vg~(jL_69TW5&4YhgI&ZDEmf$Q4^XPm z5^>i1rJ}P^MQatt9@_5jq5V10+h1QLkq9J_Bw|ct2P(b56usnu-N8J)`b$XR$s6M0 jNG5GiOR*k@@&gKe$1L+1W`lwg=;vK$Xb1oAKIp#z*@*A! literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/KThread.class b/proj1/nachos/threads/KThread.class new file mode 100644 index 0000000000000000000000000000000000000000..6948a57f2bafa2c5df547cf7899ac831cf6ba613 GIT binary patch literal 6255 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 aVixVqp))J?(KTikslu{`yvj)mmHz>=N>)e! literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/LotteryScheduler.class b/proj1/nachos/threads/LotteryScheduler.class new file mode 100644 index 0000000000000000000000000000000000000000..678eadf01ae722e002d23edd6d8215d7d70bf10e GIT binary patch literal 465 zcmah`yH3ME5S(@F7)%HuJX#1WP@ATPfWmJ#{-a;B}w4`{FdU;f5)ERZg z@dJEt`~aO1WPI=g{3yqLaw#PptPf32_StLgwb$86fB*UU3%~@fMIj?2qa8zHm6b7! z5gDg3DkF!yj4_;%aRTGwG9lrtgmVlDo2#aEPv^I|QQ?ODjDf8&MC_7brSlB^1yj{Z z6)R_#xULqhoS(O>mGok@tn+Ego-s_rzQiz?X`a3|w8{{ks}yyHj)Gz8OVy2aov*0t zWr`#V6-_O#s@xFIUN9`wFvR@Yx2t-Ua+O8X)cIUlwJe>s^G$1~_Yjcq*b~*T7b<*K z({zg{dK&cKSaJHE7NW@%;Q>Quu#%s}AgS7;s=-N}Z0b*K7tPR}8QLEc-!!y`OSNnX z=NZ~voW@Azg={)>=2YVcHBW86jO>u2i|EFBrn(R0DSOf%;fg5J!iC z1O^l+h)I}KFog>erWMTKqJ&EdF5`-XSp`=yr=Sb-3XWo)VYJzh>~)^}2moB|-noth zHXG#Dw@U4J=^HetG)}pj?wuh@2I!nuH_3+HT?hTVMSqvv>I`ty_88iVh9zc^&YirZ zcOx0dEg0)$uoyyauW&J#;fyonea-q{h~L+}8Szf~`u-Cb9H4*NLOqQ)P&Fd_h~qpB zIei+$7X%1_-Y>*}L_&-OMI!V|-~h#ww7N?fEp+e54sU^Fe;}0Y-9pPZ3Wacxu5oAk zIih$$>z6o0u|5}q!|0?Z0z1^qS&3qzXcxM@5_jl1M0=?ngtyVUgGlx}*zh)_>^9nh zm0nS$*TnqBsg!b&wMr@UpqF?V&Fg>hM}z!tiT@q(y>G&Q497kFQ%*ggy{4airFL9< zWJll!BK_zPDwIsAp5QQ9b<(35@n}MI=!ld3sSX+PkPK-Ic*sc)Dc1z-Hs#j;O!dFi dvB(}v2!oE&Q#eBRBxx0YA1Q=sKE}|G@LwKte}4b~ literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/PriorityScheduler$ThreadState.class b/proj1/nachos/threads/PriorityScheduler$ThreadState.class new file mode 100644 index 0000000000000000000000000000000000000000..66f63469385d40af6afa553d632233ce0880b561 GIT binary patch literal 1342 zcma)6TTc@~7(LT2-Ch=3DC9Ko@I^yIYL^#vkAd ziD;q*A5DDoRb%2$@D~uz>~5hHV}0n%H{X2cobR&Jue%?10NlVe6IU`YQOP2WF>Tpd zF5}voFmctyq(CaDdrGbdjLbKsQ*Zgz$l+J-FNHVL0_hFUZFz3+NXzGdgF6DZEB(WJBRV;ZEejYktraDZpLd(;LHl`4c}ud^pr<(B za%5v!dagdlP9vzhzCbQ2Vlj{bBdxh+Q+YED>HCV8lf80>@-KJ6SxatB1)UgyWMz!q z7^3gq>Z)=AcT??O=KStZqcW#U7-SyKvjw>kCpq|1y1{JAyX!d0_f1q8(xG_VR&Azy zy?@ur2O!g0D5HsEhN=El9wZPjrSqcgdX&#Dw%VSfW?kLr;ZEG%d?(lCrW7dkd^(5X zEDYj^g*>J#WRSHmiqjTyummRhVY_D_P|%9ihHS1?AJ*2{b&jzwLnoiOBOKf^&hr(d z`A(8BbV{@goe)qc=wx|LfnOU6T#xef6bZ%xL-zPK683u}?TKv|w($-FTl6PTItfh;AE^-<*x4r?6*k0p%Ibmgn%z0p%n$h zgaW7j5B%+~U`~T{y2>Y%N^s9><v+Q}Ka+6N2BK8{>)%LrKi%%i?nP!{ NlJ+>Kc8+@q#vhM6AAO9fwGNfy`|Hq7p(t^FzL zIL`RNFa4l18W=m{_{|xARL67ojZ7HC581urCBCHZ(H*Or^PwxZ%wiCR^$ zCeX5WU>kaI)zw`?K%28H!=5hbj$=3it;@DqwoUh&m5Nc}=k}vu{=nGNDzR zwj5Wt+zq`{G2&D$YM_gzWgb=zqY%2NK(?Y3N+fOp=PcbN3&_U(*25~ zVx7?zje1-gmHEL)99@__SH+oBhJi#L4Aw9)xrxrQr@f(lCN;4LNKJ^j}1-;a%)#&?U#Z zhFuio_EEWfLqkzg8rTyUy@;qb0aD{WtDPKynzAUp`E`{tm6_r1}$7P@OYq9Oh=JKC%4RMAdAPZdc;#_fx_%7Or9pkfv+m`4W| z(8a&yZYMI2;R zm#JoM(j&j2<8LHKULm!a9XZAuzoSF0{e_gQbw7`7o_Wux?l~Ltg{Q=?&2(gFIxtk) d7>DR2{Wym)Ot6eu_8g_y7?+r$7~fq`{slxQ1GfMG literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/Rider.class b/proj1/nachos/threads/Rider.class new file mode 100644 index 0000000000000000000000000000000000000000..68aa50e6735cc8062f80140c40efd82012dc03e3 GIT binary patch literal 559 zcmaJ;yH3ME5S()!4kiyCAwa=PGyx=Bgf0k*NJx<)kN~Agb#V@Ikz*s7 zJ_<3Hn3oh$c=vX1W_E7<{_*+--~^ivGFY=wv$1YtLm+>u1D%`+WaR6!G38Xg+V>cN_N)BT8S`Spz6mX2TmcD+X z!hZb=HYS?-GgvDOk|^}!X0L4w6uh(+*!~|ckc*S>f%C0ioBpFoz==2EB=XdSHlCfS zkK>Vilttu_7pTrNDzIcAt}lao_o_cqULvrSBL8@82Z@UAq^Gb4i;LvGxK)#>&Sw6e5~C3~=a(_PAF|N~cBaJL*=0&J)G{j5 ed%gq99K)aW?dHe`%@b?;P(Q2hkELTcs! literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/RoundRobinScheduler$1.class b/proj1/nachos/threads/RoundRobinScheduler$1.class new file mode 100644 index 0000000000000000000000000000000000000000..8d2ef69223b6e40f92292d123ba29fa78db8df86 GIT binary patch literal 235 zcmah@%L>9U5S-O&Y8C9!qe#yd!9NfM4UA z{dv9s9I+G-0t-Tv+o4l@X*3fynH@}-*`hJIs<|9Acl%a8Bw>9vN?X^M>c)L-OM!@x z7^!OO(!TCkmM;DAo*W3Pt1;Z2v~-RgAs!P`Elri)iTRw;)V>`EjOx;Z=Z{ Q=Kyn$p})v`$TQ;b3lt|l3;+NC literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/RoundRobinScheduler$FifoQueue.class b/proj1/nachos/threads/RoundRobinScheduler$FifoQueue.class new file mode 100644 index 0000000000000000000000000000000000000000..3087e1bbd9e039187ad7cfa7b4978f595504e426 GIT binary patch literal 2390 zcma)8ZBrXn6n<`iEQF?WM+5oz2`jVJm)-TH^2Y=%dY^g+TVm(@Pxo{*lN}C%>1ggX_(pE zwx0J2x-IRe4AXF@1x6C5aTr|}Xr8t5Oztex)|b5Erf#okn+5K~GgeM3tZTL**TH79 zOo+7RjmK8NU0pCu-JUIIj-&JF$|(X5AGtH<4q3-}%f6k<=?($TpGdu05t%M4BFiMu zAC6PC5{Q}lzFVoHz(8X3zb!kmu9n+f)Jg$8Maw<$4B4!fl5Lo-KvP0S6^1}hUHcYX z-PT;oPAm9A!IuJyCz5W|pl~7$Y=$S(GGJt%O^@tP3S2s!6Io|1&(7)dhHPGc1L!MK zqbi1QQN^1Wluy@4tC4b5oW}(Pk5qgGO~Iy$9P$cu6_2r{VjG5v9pqK)qCoXGRA3=Lalk=2j}}vdCL^Jfo1;Z50j*DqMK1H?woGr{XF06&$Fzimw%X zBQPEc)qrMATx@>GydsJ~xbYhEYCkz>A&*7@*p({fB4?L_lUl6YIT=)qZrfgo+PP4Z zUe#`)dP?E<2cb@!3AE-7M@}7eP62Lk7(=!hW0M`1BWJs7wtNLOCpM&TnzTHfdJ`3~ z`c+=u+|hGxTEZxXGgmCR2LkQ3UbOb87TaN_J&uO@uFLC~TbM z@;S;A&LmIX;%XL6Tm!wyu@{IW57Cr-h31EcXnBF?4?KuqnAezZG=w&+;%%-~y3+}l zFv`0?5@P}2GA$)w_e&^cw7x`J@+U;c%7{Iv!JT1LAVIh!;&hdeeHFI=k^mUTWrFe* zk5mBu$X^44$H2>Ie})$ETm~vb{S6(@iPz*O9_I%ac!!a05b-8ce!q^uU=VG>w->#H zpFCo+!j)vw6AngBVJfo>FvkG%byRwesPr6Bxr%Ey9V|Q>@&o!l@hu(=C&)sw2#ABllG7P`U^SK_7ZGiJ4q^WDOt^bdg~Nk?;K4~4$d z($dm-Wnf(fvt_xuFY40kEW4!I`6GYkF+^c9oULvyHy?gOe*)3LTsvL?6Ig0njVMB)d-Nf;=N1E>6JS{o@!}@0S2uBuZn0 zcCjf5aU=-Q@UcnOOHd__$2C6@cqp<7f^UQZqyQqm>d4QKnX+aXyb3AG&nTMq`P(qa PrwB*LBe_Pq5Xk-lEFZ2; literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/Scheduler.class b/proj1/nachos/threads/Scheduler.class new file mode 100644 index 0000000000000000000000000000000000000000..0b2904204a55f4041413114cdee7a029c93a37c2 GIT binary patch literal 1439 zcma)5T~pIQ6g}Gp(x#!H0zyFnKU+kifS<*$VRQzqUjxGfZ)vj7FePO+2@byMyFb9c z;EONF_}~xlM>*b2(vXRCWID6k-97i*bI-l`{paT|084nJLBkadS8+|lbyPLfFstDP z<}?&>Q!evzF;v`Aahsuk*>N5JF+;vu+h9;uIyPq*Y&b4|6YMs*ST~z(x;fkESY~^} z6plQ{mx|wVJcdfcHLX_1GyIm|rtKMPR*Ty~n~OR_+2tSB!~6FE4~S{1x>?HxqyQ9B z+UEW{;dF%KA23W*v*=e5yk1)+{ZUSav0kXKG(rv&>+`KGZu!nWKc+8v>12~VldVd7 z3VVqxMwCi5yd82}iwgHrtmNhj$w@G7?(>06I6IF^C`b%HQJ`TZM<#nP~{AxF?yFeMm;uO zM>|8&aeXdCut%WDYSN)DZngVL{pn`>=Zy@q9ZwF3O%s#J)Nq;%n(295`0GMWfjy$l0ZAOv^)sNFPY$Fefmx-vsUtg$>McNtdeX~EnzSEx^ z${{F6YZ(d#>4y+bAPnIQppbZ+qgxspjKoAMw9A;%5psvfA3@1~qhp%x32As5(v3#Y zh)xD!6z7RR5{|`$3xtu%3bRM(J4F96TYq@}G9|1KGcnosIQ|rZED~h@N6>gLL26cz zd!itk!B|j(_B<7&B@Si%J|I0GLzd|XnHZ$S2FdnK;zDRm1s7xHXM~pC7o}AbhbUx; wKcRrnsX~hhaWSNm&QD=FrkkT(I-g5*F!KCMs>EF4`OGOIzn&O*NoK+2zejEU=l}o! literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/Semaphore$PingTest.class b/proj1/nachos/threads/Semaphore$PingTest.class new file mode 100644 index 0000000000000000000000000000000000000000..07784e67b7264a4ec3756c4ea7ba24ab738ef66a GIT binary patch literal 761 zcmZ`%&2G~`7@S?FF)?lv0;Fx)LP`sSfXD@j0~MD_g-C9RNEM0W#$7co={m9C(GLJ+wX5?cGus3fBgpF3ECc9tXELRhBdc5+(yfqO&51u zY`NGLC`}`CEYJ*$3deEU&BlpVM`?GUPt|lBC;FM~iEU4LCo)m?T;OTDxVyOWU`V9h z_(%&>gUINE+383phiWuorXIwhnhaGE*?68TW#cFnxYDP@L!D*`qjgYF4%i z*|z`9P`;DQ3~k#A5D`~TU~!PC@a?{u&Z)dXJWE2o7g;e&mxq6RqTVSVJ{mqM@O)f_ z=i;u9dp2_)4S~&~i@TH{P_r=Ii89CCSECah@+9^Dsn;`OE^c9^2#ccoTtl?@kS=&9 zko+i#FDk-eODRxVDy>OK8+y?qp|zBXB7xF^XsERe$$<=nN!HAy)puWf z_0dOP`dVE!uw*SC`{1AP-KEvVmb;W$*LtZ{H?=y!q{S05?(5aTb#?e26I> z8BE8}iQ7ut(eV-P>X^Yj9o?AKaUUP6-JH7nL>)g>$9WB(>9k+akkzoLqX$ds{y{r# zsC8M1hsxrS5-S>31=^P_dwW&7o`5lL+tQgWnXW5cf#@@{RFwi^ULf||w7iE^sm{Y$ z+sqfsZrUq4(k!^?)%sf3W(3-%E!*<$2t?xZi8U^>Jw@?#Mj*jYNN0-07XM;ZlpCZ0Vi{iCXFtKc(Aqq)*sGWX~?b=+pf zb2ucKAipQG5ZNj_yBOuS=PbW?A^ve3>O0N`*9e5_XUdB_Tc#jVGaZtV8aPxh`&BOuP zYS5;Wzasi0`nW_6&|X9A0Qw7bBy+rv6zH0ELp8jk7=)o1j6kEjOc`fr2@D{~yDL0R zAdPFsm`pU7XtYXVoD5QYsUh??MnsH9&Rv7n4+IZWnL45sslixGy@sBup(CKQ@&A-2 z2|dMxWYC9c4DwfG4EN}Ewod7Sj~`IF)S%SG6kR3pP@SBP&_5Uy8YW^)@3ny6OSIMB z&m5vN7v4wLLUWTnM0f5GJ-OugK6>}j*L$jl(>3&mZx46tKcOdC!z5{p!&xVE75{g*U=9Z1yXlS!; z;f{q33!4IklSmy1)O{s`L7cX-K@!S-+UmSl!N8Bw?3u2KbxpAysVLhK*mkE^PtP>F zMB0t}p+MP>RQPIi+zXR^*&8xa_2WPeyE2KiKM5AHL6izye?y7;VVVgzdrF1L?og&_ z$jru6w#|z>ly4>@MeAw-BI4Q;nC)aTIC?2hCRBDO9wkBeBGO{!E}MUNC{LvW2Q>#J z*bZi3Ti9}N7xx^vXbP-P8{DM?fr^G{4W&A0z3v@`0XwN)h2D;o8c$(q8kWFJ5+28= z6qx8a%)3qh3Sf+>JC*&uz=HdKuGvL{Z@>b_34HQ}7+=E;%+n)4P9yS@CNfB{fZBv+NZ(*? z&1|n!?2lOVzQE)%&QUnWwGTpk`ukIpngqHaZBzeqLbS1pot(6m!_={eB?1#}Lch#& b3C3?2;un@#RA<1z3T|?@Sz6?;P=);uZV#kr^L-@ITOh!e?ik*6(iCkO@qZd(S=h+;hHj&UbJAc>e2e0Pf*f!xWZP zyssgIC>rL2maMtiz_ ztYSw)6i+ma;Nu7u~n$0mSvZ6X4MnWS8dyLm&-=AYE}i5 zvL&_A%%SnrNYy;6oXS}Cky*@8pBCuJS|!`?YOW~|ztm{HsVy6JDYdzGXcoNmA`dEM zr*I@NlCh1#fm2O+2d-%ptEmjt(yxrWQaSdX35<2xEIW45@+`-uVfVacTi&8TI5xXO zx64kEQ2Ghd+^ALdOgCrjm8lt`W23xdxRzW8O2s>{nB;{3*=Kg)AjmLm6pO?eyO@TI zCmiY8FHU=g0=-$!C>*UD$3dtou32%Onhz~k*7Is?_Oe5fs#)G|_F=eff7SNPlIb#A zVez-hG>_RZIXQNTjb~d0w5(He3ydJs?Q5lQM}pIlK$2lE>!OYs+!PqTq!Bu9BPMXI zW2;qv>Glg9vxuwsQip*(9R(zHyoRC!QCFRuZiv)LPExg}`*j zM(fPY|G6u{9LnKHM;R3zwoG~Oyf;A^rHLaUzAi9uzT4y`!Nof1=2KEOdnmwAA!W%g z-h@4tUEUPe%egg{U5V{VL)9pJRkP%sxRf`$H2m5);ND!m#l-;h`wj_SqhgUVd4Wq)S$#$Ep=aN87RwDDy!gR{at@{i*jS4Dpf#N!Q!_!&a^2EwOM zD0WfoK7~p#l8^rkwSk^fXg~SB?r@Cq;RE{Up`V`tjA4-M8$ya&o&M<+ui`FeAsZY- z{Dz1^)Fl$XLsd?ognz*m>Ant~lai>T_X!29j=rY4Uxo}rh8#mT$8oy9&V+C9^_*n7 zQw%iihmAH}2Voh65BwVp{3cIzArx8Sjg_=-VG;g;WLx|?2EIdY6Tslfi@zx;bv`Qr zmc)-8V3JT-$w9&!CxjV>jx$?XgC>|{0A>a~ZD16H)M08Kv^wz@Q&V{A@fn6$`KxQe zoH@ft{tVH4Jkh{t1J{OLs$;B<@$kaLfc8CZpJ5_D(ZKbM_*@+~SiZ@*AI>ZLZAhHF z`18Diw-^+7B>&OavNcj;od7ooWD|?nqO^`2w*3U+1oVLaRQK>U>mTPQjd>O)A)sk=diN1;5Iug^RDihnVwVrfbIL-P>cWzZ1b!^@mCnn&5bX=wie(*C3M literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/ThreadQueue.class b/proj1/nachos/threads/ThreadQueue.class new file mode 100644 index 0000000000000000000000000000000000000000..7c66e423891bcc059f306170645110ef99951af8 GIT binary patch literal 426 zcmZ`#yH3ME5S&Zw7)(M!coaZG=TP8=E(i%BrNIIrqV(s>314K+a6SiqiwcQ?58$H^ zdv*$hlr465Ml-9?e*b)a0XWA&h&FZu>;>3o=v*kR>?K1x8qFBI>tZe$`iau=wt7mX znesFzW|$O$=QD1U!zvby|jiiv8Nwk@3gcKQ18@agbmuejR2bn0gqve V7&m*^u4jLR2Xqvq-Knn(e*t&0VCnz> literal 0 HcmV?d00001 diff --git a/proj1/nachos/threads/ThreadedKernel.class b/proj1/nachos/threads/ThreadedKernel.class new file mode 100644 index 0000000000000000000000000000000000000000..98e0f4eb065e0b0cc21d66ea297e465b32f317e6 GIT binary patch literal 2450 zcmai0Yg5}+5Ir|G7FNWgh5+FaNT3Oj5E@8GTWH#ZkT$_QViQu5zGPcqfh7J5uDOFs0a)Vo!mkpdb)0X7fg_WErkNf6~^od8at-7w{({WdcvT)a-RTo+q8`IVbL>)8VFDYdNgfg`a#V|Xe?JM6b^3)j0LbDV#+Dm zxs;PJ?Z(&@{EWb*Fn--N9oO^@o6)lZ7sKeJ<9UXA3ixJ2#z88Jj-4|-)3Il28Q&5Z z3j17i3WbtwW_8bTYrwfv>Xb5bMjdfmU^MJ%$ubV48%FkA$6`;U!v)hey*mPt@rg}= z=%SM|1Uix|>T0QwG29J3V{s>ubh5g&sk^3puWm-Yyjc_&4oBMX8*Jp34c9g-Mp0!D zQ@6|)bk#HdJh`hM=+l;N?@XsX*R*%${ouO0Lw8-Lm<8HuOj^|oenL$?1lsE)si4}@ zo}S%X(f9p~71#o;MZ?Jkx*vIDzTn$AqUf+KWfQE~>Byc|Ds(u^Vs%M)Sui|({Qfe^C2%ful?qJ+I>Q}phLXG6<_>$dV|W$j2wWaN zg-*>|FJjCnb=^nmxqCsP6BoX5o$J0x#4@PW4z!KY!vkU zyyKGM!SR~u(9Y(Qrks;#Mz{Ak=gskhZ^}Ian8HA)!i{FS$?KL!rVsOH3Q!T3tmji) z($CiO+2(5!&e!CeuSq-V7=#>2%G-RKr54mJlgALh@Zk*Jq*STF zpS&pA@fM%73J7mwo^JvRc!yFt_zMxDfQ`hNG9oM2%834fmLtRx3g1_!PS82!@3kHw z{xf>YP*0#y`mc(hdWo}J;uzY~muTBMM*9&u%IN$RugQEOem*nI0O(=zz34=-t(rHp#2viL%wt%^d$`M6_HgGOpCUXfZyfm> zR}|dmUwec=4tVvV&!}aky2?nDrR*-_+zDc3^wjh0r)O};BP@B0#f`J%9V~Z(wW`;# ztD29D$RG*&eNc;Ym76k7LpNm0z&z_7M6DC=*AB`iOI);!-f$=HGtN@O`DpcgD?X^5 zH~iDU1bY(W>X5zR>f<`k)z3A+HOMu@bwLIZetRZK7|>M|kHG(|*sL|SX&v2oj6S5; Ts5C}c{4qS?iHF3V!J~fxetAYm literal 0 HcmV?d00001 diff --git a/proj2/Makefile b/proj2/Makefile new file mode 100644 index 0000000..64c9da5 --- /dev/null +++ b/proj2/Makefile @@ -0,0 +1,3 @@ +DIRS = userprog threads machine security ag + +include ../Makefile diff --git a/proj2/nachos.conf b/proj2/nachos.conf new file mode 100644 index 0000000..79a6b90 --- /dev/null +++ b/proj2/nachos.conf @@ -0,0 +1,14 @@ +Machine.stubFileSystem = true +Machine.processor = true +Machine.console = true +Machine.disk = false +Machine.bank = false +Machine.networkLink = false +Processor.usingTLB = false +Processor.numPhysPages = 64 +ElevatorBank.allowElevatorGUI = false +NachosSecurityManager.fullySecure = false +ThreadedKernel.scheduler = nachos.threads.RoundRobinScheduler #nachos.threads.LotteryScheduler +Kernel.shellProgram = halt.coff #sh.coff +Kernel.processClassName = nachos.userprog.UserProcess +Kernel.kernel = nachos.userprog.UserKernel diff --git a/proj3/Makefile b/proj3/Makefile new file mode 100644 index 0000000..9901fc5 --- /dev/null +++ b/proj3/Makefile @@ -0,0 +1,3 @@ +DIRS = vm userprog threads machine security ag + +include ../Makefile diff --git a/proj3/nachos.conf b/proj3/nachos.conf new file mode 100644 index 0000000..7622166 --- /dev/null +++ b/proj3/nachos.conf @@ -0,0 +1,14 @@ +Machine.stubFileSystem = true +Machine.processor = true +Machine.console = true +Machine.disk = false +Machine.bank = false +Machine.networkLink = false +Processor.usingTLB = true +Processor.numPhysPages = 16 +ElevatorBank.allowElevatorGUI = false +NachosSecurityManager.fullySecure = false +ThreadedKernel.scheduler = nachos.threads.RoundRobinScheduler +Kernel.shellProgram = sh.coff +Kernel.processClassName = nachos.vm.VMProcess +Kernel.kernel = nachos.vm.VMKernel diff --git a/proj4/Makefile b/proj4/Makefile new file mode 100644 index 0000000..e2890ef --- /dev/null +++ b/proj4/Makefile @@ -0,0 +1,3 @@ +DIRS = network vm userprog threads machine security ag + +include ../Makefile diff --git a/proj4/nachos.conf b/proj4/nachos.conf new file mode 100644 index 0000000..e1e3b01 --- /dev/null +++ b/proj4/nachos.conf @@ -0,0 +1,16 @@ +Machine.stubFileSystem = true +Machine.processor = true +Machine.console = true +Machine.disk = false +Machine.bank = false +Machine.networkLink = true +Processor.usingTLB = true +Processor.variableTLB = true +Processor.numPhysPages = 16 +ElevatorBank.allowElevatorGUI = false +NetworkLink.reliability = 1.0 # use 0.9 when you're ready +NachosSecurityManager.fullySecure = false +ThreadedKernel.scheduler = nachos.threads.RoundRobinScheduler +Kernel.shellProgram = sh.coff +Kernel.processClassName = nachos.network.NetProcess +Kernel.kernel = nachos.network.NetKernel diff --git a/security/NachosSecurityManager.java b/security/NachosSecurityManager.java new file mode 100644 index 0000000..8961575 --- /dev/null +++ b/security/NachosSecurityManager.java @@ -0,0 +1,318 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.security; + +import nachos.machine.*; + +import java.io.File; +import java.security.Permission; +import java.io.FilePermission; +import java.util.PropertyPermission; +import java.net.NetPermission; +import java.awt.AWTPermission; +import java.security.PrivilegedAction; +import java.security.PrivilegedExceptionAction; +import java.security.PrivilegedActionException; + +/** + * Protects the environment from malicious Nachos code. + */ +public class NachosSecurityManager extends SecurityManager { + /** + * Allocate a new Nachos security manager. + * + * @param testDirectory the directory usable by the stub file system. + */ + public NachosSecurityManager(File testDirectory) { + this.testDirectory = testDirectory; + + fullySecure = Config.getBoolean("NachosSecurityManager.fullySecure"); + } + + /** + * Return a privilege object for this security manager. This security + * manager must not be the active security manager. + * + * @return a privilege object for this security manager. + */ + public Privilege getPrivilege() { + Lib.assertTrue(this != System.getSecurityManager()); + + return new PrivilegeProvider(); + } + + /** + * Install this security manager. + */ + public void enable() { + Lib.assertTrue(this != System.getSecurityManager()); + + doPrivileged(new Runnable() { + public void run() { + System.setSecurityManager(NachosSecurityManager.this); + } + }); + } + + private class PrivilegeProvider extends Privilege { + public void doPrivileged(Runnable action) { + NachosSecurityManager.this.doPrivileged(action); + } + + public Object doPrivileged(PrivilegedAction action) { + return NachosSecurityManager.this.doPrivileged(action); + } + + public Object doPrivileged(PrivilegedExceptionAction action) + throws PrivilegedActionException { + return NachosSecurityManager.this.doPrivileged(action); + } + + public void exit(int exitStatus) { + invokeExitNotificationHandlers(); + NachosSecurityManager.this.exit(exitStatus); + } + } + + private void enablePrivilege() { + if (privilegeCount == 0) { + Lib.assertTrue(privileged == null); + privileged = Thread.currentThread(); + privilegeCount++; + } + else { + Lib.assertTrue(privileged == Thread.currentThread()); + privilegeCount++; + } + } + + private void rethrow(Throwable e) { + disablePrivilege(); + + if (e instanceof RuntimeException) + throw (RuntimeException) e; + else if (e instanceof Error) + throw (Error) e; + else + Lib.assertNotReached(); + } + + private void disablePrivilege() { + Lib.assertTrue(privileged != null && privilegeCount > 0); + privilegeCount--; + if (privilegeCount == 0) + privileged = null; + } + + private void forcePrivilege() { + privileged = Thread.currentThread(); + privilegeCount = 1; + } + + private void exit(int exitStatus) { + forcePrivilege(); + System.exit(exitStatus); + } + + private boolean isPrivileged() { + // the autograder does not allow non-Nachos threads to be created, so.. + if (!TCB.isNachosThread()) + return true; + + return (privileged == Thread.currentThread()); + } + + private void doPrivileged(final Runnable action) { + doPrivileged(new PrivilegedAction() { + public Object run() { action.run(); return null; } + }); + } + + private Object doPrivileged(PrivilegedAction action) { + Object result = null; + enablePrivilege(); + try { + result = action.run(); + } + catch (Throwable e) { + rethrow(e); + } + disablePrivilege(); + return result; + } + + private Object doPrivileged(PrivilegedExceptionAction action) + throws PrivilegedActionException { + Object result = null; + enablePrivilege(); + try { + result = action.run(); + } + catch (Exception e) { + throw new PrivilegedActionException(e); + } + catch (Throwable e) { + rethrow(e); + } + disablePrivilege(); + return result; + } + + private void no() { + throw new SecurityException(); + } + + private void no(Permission perm) { + System.err.println("\n\nLacked permission: " + perm); + throw new SecurityException(); + } + + /** + * Check the specified permission. Some operations are permissible while + * not grading. These operations are regulated here. + * + * @param perm the permission to check. + */ + public void checkPermission(Permission perm) { + String name = perm.getName(); + + // some permissions are strictly forbidden + if (perm instanceof RuntimePermission) { + // no creating class loaders + if (name.equals("createClassLoader")) + no(perm); + } + + // allow the AWT mess when not grading + if (!fullySecure) { + if (perm instanceof NetPermission) { + // might be needed to load awt stuff + if (name.equals("specifyStreamHandler")) + return; + } + + if (perm instanceof RuntimePermission) { + // might need to load libawt + if (name.startsWith("loadLibrary.")) { + String lib = name.substring("loadLibrary.".length()); + if (lib.equals("awt")) { + Lib.debug(dbgSecurity, "\tdynamically linking " + lib); + return; + } + } + } + + if (perm instanceof AWTPermission) { + // permit AWT stuff + if (name.equals("accessEventQueue")) + return; + } + } + + // some are always allowed + if (perm instanceof PropertyPermission) { + // allowed to read properties + if (perm.getActions().equals("read")) + return; + } + + // some require some more checking + if (perm instanceof FilePermission) { + if (perm.getActions().equals("read")) { + // the test directory can only be read with privilege + if (isPrivileged()) + return; + + enablePrivilege(); + + // not allowed to read test directory directly w/out privilege + try { + File f = new File(name); + if (f.isFile()) { + File p = f.getParentFile(); + if (p != null) { + if (p.equals(testDirectory)) + no(perm); + } + } + } + catch (Throwable e) { + rethrow(e); + } + + disablePrivilege(); + return; + } + else if (perm.getActions().equals("write") || + perm.getActions().equals("delete")) { + // only allowed to write test diretory, and only with privilege + verifyPrivilege(); + + try { + File f = new File(name); + if (f.isFile()) { + File p = f.getParentFile(); + if (p != null && p.equals(testDirectory)) + return; + } + } + catch (Throwable e) { + no(perm); + } + } + else if (perm.getActions().equals("execute")) { + // only allowed to execute with privilege, and if there's a net + verifyPrivilege(); + + if (Machine.networkLink() == null) + no(perm); + } + else { + no(perm); + } + } + + // default to requiring privilege + verifyPrivilege(perm); + } + + /** + * Called by the java.lang.Thread constructor to determine a + * thread group for a child thread of the current thread. The caller must + * be privileged in order to successfully create the thread. + * + * @return a thread group for the new thread, or null to use the + * current thread's thread group. + */ + public ThreadGroup getThreadGroup() { + verifyPrivilege(); + return null; + } + + /** + * Verify that the caller is privileged. + */ + public void verifyPrivilege() { + if (!isPrivileged()) + no(); + } + + /** + * Verify that the caller is privileged, so as to check the specified + * permission. + * + * @param perm the permission being checked. + */ + public void verifyPrivilege(Permission perm) { + if (!isPrivileged()) + no(perm); + } + + private File testDirectory; + private boolean fullySecure; + + private Thread privileged = null; + private int privilegeCount = 0; + + private static final char dbgSecurity = 'S'; +} diff --git a/security/Privilege.java b/security/Privilege.java new file mode 100644 index 0000000..28f8a90 --- /dev/null +++ b/security/Privilege.java @@ -0,0 +1,195 @@ +// PART OF THE MACHINE SIMULATION. DO NOT CHANGE. + +package nachos.security; + +import nachos.machine.*; +import nachos.threads.KThread; + +import java.util.LinkedList; +import java.util.Iterator; +import java.security.PrivilegedAction; +import java.security.PrivilegedExceptionAction; +import java.security.PrivilegedActionException; + +/** + * A capability that allows privileged access to the Nachos machine. + * + *

+ * Some privileged operations are guarded by the Nachos security manager: + *

    + *
  1. creating threads + *
  2. writing/deleting files in the test directory + *
  3. exit with specific status code + *
+ * These operations can only be performed through doPrivileged(). + * + *

+ * Some privileged operations require a capability: + *

    + *
  1. scheduling interrupts + *
  2. advancing the simulated time + *
  3. accessing machine statistics + *
  4. installing a console + *
  5. flushing the simulated processor's pipeline + *
  6. approving TCB operations + *
+ * These operations can be directly performed using a Privilege + * object. + * + *

+ * The Nachos kernel should never be able to directly perform any of + * these privileged operations. If you have discovered a loophole somewhere, + * notify someone. + */ +public abstract class Privilege { + /** + * Allocate a new Privilege object. Note that this object in + * itself does not encapsulate privileged access until the machine devices + * fill it in. + */ + public Privilege() { + } + + /** + * Perform the specified action with privilege. + * + * @param action the action to perform. + */ + public abstract void doPrivileged(Runnable action); + + /** + * Perform the specified PrivilegedAction with privilege. + * + * @param action the action to perform. + * @return the return value of the action. + */ + public abstract Object doPrivileged(PrivilegedAction action); + + /** + * Perform the specified PrivilegedExceptionAction with privilege. + * + * @param action the action to perform. + * @return the return value of the action. + */ + public abstract Object doPrivileged(PrivilegedExceptionAction action) + throws PrivilegedActionException; + + /** + * Exit Nachos with the specified status. + * + * @param exitStatus the exit status of the Nachos process. + */ + public abstract void exit(int exitStatus); + + /** + * Add an exit() notification handler. The handler will be invoked + * by exit(). + * + * @param handler the notification handler. + */ + public void addExitNotificationHandler(Runnable handler) { + exitNotificationHandlers.add(handler); + } + + /** + * Invoke each exit() notification handler added by + * addExitNotificationHandler(). Called by exit(). + */ + protected void invokeExitNotificationHandlers() { + for (Iterator i=exitNotificationHandlers.iterator(); i.hasNext(); ) { + try { + ((Runnable) i.next()).run(); + } + catch (Throwable e) { + System.out.println("exit() notification handler failed"); + } + } + } + + private LinkedList exitNotificationHandlers = + new LinkedList(); + + /** Nachos runtime statistics. */ + public Stats stats = null; + + /** Provides access to some private Machine methods. */ + public MachinePrivilege machine = null; + /** Provides access to some private Interrupt methods. */ + public InterruptPrivilege interrupt = null; + /** Provides access to some private Processor methods. */ + public ProcessorPrivilege processor = null; + /** Provides access to some private TCB methods. */ + public TCBPrivilege tcb = null; + + /** + * An interface that provides access to some private Machine + * methods. + */ + public interface MachinePrivilege { + /** + * Install a hardware console. + * + * @param console the new hardware console. + */ + public void setConsole(SerialConsole console); + } + + /** + * An interface that provides access to some private Interrupt + * methods. + */ + public interface InterruptPrivilege { + /** + * Schedule an interrupt to occur at some time in the future. + * + * @param when the number of ticks until the interrupt should + * occur. + * @param type a name for the type of interrupt being + * scheduled. + * @param handler the interrupt handler to call. + */ + public void schedule(long when, String type, Runnable handler); + + /** + * Advance the simulated time. + * + * @param inKernelMode true if the current thread is running kernel + * code, false if the current thread is running + * MIPS user code. + */ + public void tick(boolean inKernelMode); + } + + /** + * An interface that provides access to some private Processor + * methods. + */ + public interface ProcessorPrivilege { + /** + * Flush the processor pipeline in preparation for switching to kernel + * mode. + */ + public void flushPipe(); + } + + /** + * An interface that provides access to some private TCB methods. + */ + public interface TCBPrivilege { + /** + * Associate the current TCB with the specified KThread. + * AutoGrader.runningThread() must call this method + * before returning. + * + * @param thread the current thread. + */ + public void associateThread(KThread thread); + /** + * Authorize the TCB associated with the specified thread to be + * destroyed. + * + * @param thread the thread whose TCB is about to be destroyed. + */ + public void authorizeDestroy(KThread thread); + } +} diff --git a/security/package.html b/security/package.html new file mode 100644 index 0000000..a38c48e --- /dev/null +++ b/security/package.html @@ -0,0 +1,4 @@ + +Provides classes that can be used to protect the host system from malicious +Nachos kernels. + diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..17b699c --- /dev/null +++ b/test/Makefile @@ -0,0 +1,59 @@ +# GNU Makefile for building user programs to run on top of Nachos +# +# Things to be aware of: +# +# The value of the ARCHDIR environment variable must be set before using +# this makefile. If you are using an instructional machine, this should +# be automatic. However, if you are not using an instructional machine, +# you need to point ARCHDIR at the cross-compiler directory, e.g. +# setenv ARCHDIR ../mips-x86.win32-xgcc + +# you need to point to the right executables +GCCDIR = $(ARCHDIR)/mips- + +ASFLAGS = -mips1 +CPPFLAGS = +CFLAGS = -O2 -B$(GCCDIR) -G 0 -Wa,-mips1 -nostdlib -ffreestanding +LDFLAGS = -s -T script -N -warn-common -warn-constructors -warn-multiple-gp + +CC = $(GCCDIR)gcc +AS = $(GCCDIR)as +LD = $(GCCDIR)ld +CPP = $(GCCDIR)cpp +AR = $(GCCDIR)ar +RANLIB = $(GCCDIR)ranlib + +STDLIB_H = stdio.h stdlib.h ag.h +STDLIB_C = stdio.c stdlib.c +STDLIB_O = start.o stdio.o stdlib.o + +LIB = assert atoi printf readline stdio strncmp strcat strcmp strcpy strlen memcpy memset +NLIB = libnachos.a + +TARGETS = halt sh matmult sort echo cat cp mv rm #chat chatserver + +.SECONDARY: $(patsubst %.c,%.o,$(wildcard *.c)) + +all: $(patsubst %,%.coff,$(TARGETS)) + +ag: grade-file.coff grade-exec.coff grade-mini.coff grade-dumb.coff + +clean: + rm -f strt.s *.o *.coff $(NLIB) + +agclean: clean + rm -f f1-* f2-* + +$(NLIB): $(patsubst %,$(NLIB)(%.o),$(LIB)) start.o + $(RANLIB) $(NLIB) + +start.o: start.s syscall.h + $(CPP) $(CPPFLAGS) start.s > strt.s + $(AS) $(ASFLAGS) -o start.o strt.s + rm strt.s + +%.o: %.c *.h + $(CC) $(CFLAGS) -c $< + +%.coff: %.o $(NLIB) + $(LD) $(LDFLAGS) -o $@ $< start.o -lnachos diff --git a/test/assert.c b/test/assert.c new file mode 100644 index 0000000..072af4b --- /dev/null +++ b/test/assert.c @@ -0,0 +1,7 @@ +#include "stdio.h" +#include "stdlib.h" + +void __assert(char* file, int line) { + printf("\nAssertion failed: line %d file %s\n", line, file); + exit(1); +} diff --git a/test/assert.o b/test/assert.o new file mode 100644 index 0000000000000000000000000000000000000000..ca403baaaeb1fb75081dbbc1215e5e9e29105ff6 GIT binary patch literal 876 zcmah_Jx{_=6upJ|1tgNlz<{wD3A!{y9f)zLgNDS#A7D~SDcA%{LuQQ_07ggL-0Hb~uh^u6C%HZM+ccQbgBhS0}7E3}9VQBQWG|+|We_;y&>eYN-*Sge z?_3+Yo}<-!S|3uY2Zgj9cM#?9Y#snUs(|xEvl| z@IAN%eg(7tGv!-@uCW>5UIc)qKZ3a&ql)h??ZtiRiT&KX=@2Eaxh{*G=eCjWumQMQ zM$v&t{?-6qo%DGhA<#I#2bKCe+nec(N=v}x17hSg2}*!99bITJTb p#wGu8Dhs^FEQD+Ik6FWC1@C0Bom8aOq~`rFjs?-vx9~Sp`WLJlcya&$ literal 0 HcmV?d00001 diff --git a/test/atoi.c b/test/atoi.c new file mode 100644 index 0000000..9dad017 --- /dev/null +++ b/test/atoi.c @@ -0,0 +1,15 @@ +#include "stdlib.h" + +int atoi(const char *s) { + int result=0, sign=1; + + if (*s == -1) { + sign = -1; + s++; + } + + while (*s >= '0' && *s <= '9') + result = result*10 + (*(s++)-'0'); + + return result*sign; +} diff --git a/test/atoi.o b/test/atoi.o new file mode 100644 index 0000000000000000000000000000000000000000..319f628ada391c97c8fa7d9dd75646839bb3c06d GIT binary patch literal 776 zcmah_y-LGS7(F+kwp!F8rDRZSAcI2<#VKPDl!A+IkTz+l1+|4n=y(SopwA#afbSr6 z?&#>?;OOEeT)!{5sc9>C;JfFX@8|x7!UW?|0BvFq1yK}bLy}&Fqy)#eNQl%j+_*Q1 zb16xBp7Sj06mGW@cZj79qU3z$3_b}r9FN&c9jsR&R}ywp!uB}%ER`}G6Jb@Lx&OzMjqvt|%KQvZG9OUbJ3h2WXJ z3Q)pZ`hmPDVRKYAQnkF&_u`3`4dQn;8a&*fi6*f}d_;Uj%q`R0PTcpZJ=YY0=uaHr zFsWxf*>M+bzHf^2V`^&YyiMwV%`3Y)j`BkL|?6fg6Dd{U|yKqT$VGaNX;= u2!j6Y-NFYEkN($^?4!@f&OFwh|7;y;*Wy0w4Zj(B6Pw*EqkUa_{)-<@C}?T` literal 0 HcmV?d00001 diff --git a/test/cat.c b/test/cat.c new file mode 100644 index 0000000..c3e758a --- /dev/null +++ b/test/cat.c @@ -0,0 +1,31 @@ +#include "syscall.h" +#include "stdio.h" +#include "stdlib.h" + +#define BUFSIZE 1024 + +char buf[BUFSIZE]; + +int main(int argc, char** argv) +{ + int fd, amount; + + if (argc!=2) { + printf("Usage: cat \n"); + return 1; + } + + fd = open(argv[1]); + if (fd==-1) { + printf("Unable to open %s\n", argv[1]); + return 1; + } + + while ((amount = read(fd, buf, BUFSIZE))>0) { + write(1, buf, amount); + } + + close(fd); + + return 0; +} diff --git a/test/cat.coff b/test/cat.coff new file mode 100644 index 0000000000000000000000000000000000000000..9946f7b9a2dc9626fb8acba8a27fb1a00e8f7b57 GIT binary patch literal 7020 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 literal 0 HcmV?d00001 diff --git a/test/cat.o b/test/cat.o new file mode 100644 index 0000000000000000000000000000000000000000..928f28ddebd2cd788bb2631a955b57fca894ffdf GIT binary patch literal 1212 zcmah|O=}ZT6g`=YNoobF6e(Eo1tvBN8REyHNRcS01zor)xDY0j$s`S=$&gI3%LrMx zG8-3NcHzQZ>JKQo@CRh!59q=lP{Boa#`fDqZ^`FtANp??sjf-L?sS^P$@!lk(Ee!~r2T^CP<>wDs1s6lOO zTYRRRD@ga!3aB!$>w`h8#dC3=xBv_jK8;Q`R&YEi4u@F9*U1{bO<1~8{BQ&VhLwYH zU0cm9$xkt|?gE7jYbLCZl9PIISVa^WRvyL;(I!f)>2H3`eFI$MKKJfe+@q*q6w8W} z=6RJW<~7WmbskmMGcajoUA!C^`x~>*F?${taGF&(*H9=3kUx``$V \n"); + return 1; + } + + src = open(argv[1]); + if (src==-1) { + printf("Unable to open %s\n", argv[1]); + return 1; + } + + creat(argv[2]); + dst = open(argv[2]); + if (dst==-1) { + printf("Unable to create %s\n", argv[2]); + return 1; + } + + while ((amount = read(src, buf, BUFSIZE))>0) { + write(dst, buf, amount); + } + + close(src); + close(dst); + + return 0; +} diff --git a/test/cp.coff b/test/cp.coff new file mode 100644 index 0000000000000000000000000000000000000000..a9d55b32a34c20e02019f4267936da615889f8f1 GIT binary patch literal 7112 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 literal 0 HcmV?d00001 diff --git a/test/halt.c b/test/halt.c new file mode 100644 index 0000000..1e58ab0 --- /dev/null +++ b/test/halt.c @@ -0,0 +1,20 @@ +/* halt.c + * Simple program to test whether running a user program works. + * + * Just do a "syscall" that shuts down the OS. + * + * NOTE: for some reason, user programs with global data structures + * sometimes haven't worked in the Nachos environment. So be careful + * out there! One option is to allocate data structures as + * automatics within a procedure, but if you do this, you have to + * be careful to allocate a big enough stack to hold the automatics! + */ + +#include "syscall.h" + +int +main() +{ + halt(); + /* not reached */ +} diff --git a/test/halt.coff b/test/halt.coff new file mode 100644 index 0000000000000000000000000000000000000000..65c5d567488e8529bf96ec328033283375332d9a GIT binary patch literal 2472 zcma)7IZPWt6#ce23?_+llY`)p1C+zEkP?yGIj|fdMM!C=VwPovo!Dy&FN&k2pri{W zktkBqg_0sDO$tg%%9NCpbk2J-9(%Jwt32^M@4r9u*Zwm*%tc~C97IHBF-}Ntq&Jd? zrVtxsjOc;@&xm|CmVZopPQ&vVtg-8hDN|s2-tsI4t$LJvz8_fx>A8AcdA@o6In>Jm zW52mQnv`EZk|G04oobEnzA}!>pV**mk5adw=AFa5tEsHYYd?CO3C?F6k$>Z8AdUs% zu0Y%!h8E3@Ic@&gFWxp$7~Ddr7i3dxus@KNyCGNRpg80kVC^!7w~Rl4R{Xm;iCM zL-80{@)$VN8gb4;@dR0tJu8AIK+{LaBk>e2c^YhhC&4RV7@i?X^82iSTss1WA&Vq= z0bB#mf;Yi1JV%ne3~qqu!CPP$ULZ*hgIge!<(UB(^~n^Z{QW_uWGG)=(q41^f$FuJ~V5r(BIWs z`Oxp+tls zClF@O`R)>Y9|^u=1m7Ei?*hT|P4LVTJck6&e;Y-s?4@m~SS42$YiCuMF$M(dsZKvi*{Zrkx%H?#?d_QxZO<#|`xAiR3N3+J%$UvC&+!NMF vfdub(g9vU#)?j~FL+_N%-p0T>W>3FC^N#Y*L8!p9FaolMsgr{C!}xyzc6+(} literal 0 HcmV?d00001 diff --git a/test/halt.o b/test/halt.o new file mode 100644 index 0000000000000000000000000000000000000000..3f97e842e93d254ddf8aecb274bac3d5acbb883d GIT binary patch literal 756 zcmah_Jx>Bb5S;`33L3AZ&`4vT(2Fq^mNpU+|ANVK90W-KFX2oq@fX-yTG0Co2!Fw! zU}-_29o_lf?sBeN;Y;@3yf<^Rv(xs9LinCY3w$XhZ_6te&STUTb zR%BMQIcO1V;Kc`*z&ml7W9Gmo#Q1E2rxX_4-U6C4F2NVzIy$iA*6FkXJ++#-6aY<@ zh7lT6K!Av%$!0&b2KSeTnKGL#U-0YTeH8mE$Lgxp Q+zWARNS?k;{fVQ008esYD*ylh literal 0 HcmV?d00001 diff --git a/test/libnachos.a b/test/libnachos.a new file mode 100644 index 0000000000000000000000000000000000000000..2aa6f4072775c0969021f6ab01e2bb209464d562 GIT binary patch literal 15112 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 bMC(2O*{+dNqn<`0(0i7o$$0XI>+k;;xX4{x literal 0 HcmV?d00001 diff --git a/test/matmult.c b/test/matmult.c new file mode 100644 index 0000000..934ac64 --- /dev/null +++ b/test/matmult.c @@ -0,0 +1,36 @@ +/* matmult.c + * Test program to do matrix multiplication on large arrays. + * + * Intended to stress virtual memory system. Should return 7220 if Dim==20 + */ + +#include "syscall.h" + +#define Dim 20 /* sum total of the arrays doesn't fit in + * physical memory + */ + +int A[Dim][Dim]; +int B[Dim][Dim]; +int C[Dim][Dim]; + +int +main() +{ + int i, j, k; + + for (i = 0; i < Dim; i++) /* first initialize the matrices */ + for (j = 0; j < Dim; j++) { + A[i][j] = i; + B[i][j] = j; + C[i][j] = 0; + } + + for (i = 0; i < Dim; i++) /* then multiply them together */ + for (j = 0; j < Dim; j++) + for (k = 0; k < Dim; k++) + C[i][j] += A[i][k] * B[k][j]; + + printf("C[%d][%d] = %d\n", Dim-1, Dim-1, C[Dim-1][Dim-1]); + return (C[Dim-1][Dim-1]); /* and then we're done */ +} diff --git a/test/matmult.coff b/test/matmult.coff new file mode 100644 index 0000000000000000000000000000000000000000..754c7a84cc2ff6b4b274b1597d6291f7408fc172 GIT binary patch literal 2728 zcma)8O^g#|7=EW)Xt!Ok0%H9^X0U}uP1A5NRjUpn+K49gVn{qJv$G?u{dGGV*2HL| zCX%>D;)w${W5QvLd*lFtC^2|3d*rBlfpFT3$(oqd=lQ-FwhWumCp>+h_j$j+`R1E% znKPz@*hq++MyyK8NEz9LiJZ8;N2FqCElEW1pU-49aPA9b-&^u09FDOzkyDyrdEW6I zCc$`=oPQEFlJeYesJx&Z*Am4jV%!;DJ(81aKQ%;VShA}8&DJE@E{bGocIGX_-L)(G ze=pwn`?sQHqfH*HOdD1yV_0SuPkVhODZds(zDN84@v9X>+`>MYD{YSLeM$MUV90Ic z>!l6k4M`XEJiBV6+>aQ42JF=gXKI6v@kRXA7HyffYNKn30t@WJ+>rb8L?oYzt_;~9%K_QAbAdK=%cSn*i!ifc?t2#PGzZ|r}29+4I-AN zw|sWJft>MTX3IBnIh>#W^H29dOBn+QqfH&}4TfVQ2jrlt2W?c1ef|sV`*_fZ&&GA) zu*AYdm1JA?-vLf+1+oXhy(Bp{_bvraYzMLj@ggjeZL1)+bvGD?mrx`*b{))u+gt~5 zw@`y5cY&vZxF0bNFQZ6u&zj&vV7QNv+u{|tDKRjKixal3dR@kbMt4B3S~%@8INVeI8)R8+dU%8@QmQ4$b#SoY)wT`8))5*td?nqFj-al2GT7 zfA2U>6+ZiO92?Q5kH*w#unvveTeh5RzIaP5{&=o@*vC-r zg6H_sA9y{1nwPT+E#DKj(;s@W*z2@YxI-O3rsg{SW zR|xlY`+Hlr3imPW6LeMo&kOtWop1~@DDsXEVPI!D2KR?!=r^US&mvS{hVPVrHxEbJ U=$85n9zwz~!g0*77{t*37Z3;cDF6Tf literal 0 HcmV?d00001 diff --git a/test/matmult.o b/test/matmult.o new file mode 100644 index 0000000000000000000000000000000000000000..4c8a3d174c34556da70caf91e9de3ef46b2ea64b GIT binary patch literal 1132 zcmah{O=}ZT6g@AAP1>Xyw2Lg1&OkzEAwv)sS!9v;Srj4vV46%z8`{)DQ*a?TNkTY3>J9stj(aLTw-D*c168lv&a|@=q3@&@I-ma5}`Dl(}0-IZf%WiCL ziXMxTg9yBcE#?n@XD*93FKK2(nDgf=M{FT`_?{n4XJ{zGtK-jm_I}Akabe@{^N%$%X5w>|b^mMXOSR-d-q2i`s8JRXUa!nb%1J9A?vCn z?w%$eqc${mSr`-4mges5PT?n!D1x+<&aOJGqe#UjYvy;IQ$D9_Gd%5+Seh z61O6`Mm|sW$P)iroFS6rL8!&&6D03Ia~LIa1kPYK@P{!$E(y54z%L~RafP!Ln;#hS zwD}8gdEfVEBev8M%xjVvYP9O@*4A3vcG0Rg*Rkxn=N$KDYoocgv}nU|me;pN+HwEu z50W@eKvi7eYtR_hm-z@}en+9BM!g*k_;Hv3t>iDx%6&A1l M(%L?xrN5#7FK*|negFUf literal 0 HcmV?d00001 diff --git a/test/memcpy.c b/test/memcpy.c new file mode 100644 index 0000000..029b608 --- /dev/null +++ b/test/memcpy.c @@ -0,0 +1,10 @@ +#include "stdlib.h" + +void *memcpy(void *s1, const void *s2, unsigned n) { + int i; + + for (i=0; i;n#l$5eA0l1sn_ym=y&W7&!~Lnb3>?b3x8Y01|9KdJ2-; zK%sR9$TtDfFMzZLkd^_O08-+DWD-bS50np*`ws*_3M-IhkO#}d)PU53fOi4|0~eUZ zz~CkTVS~cL1IQMHio1UJ|6c)#4b$rZ6@$hu14C|VZgN4TUNV%yke-}u6rY@*TacNP znxe-LAD^CA3g^csgR~P;0x=R|5zJmgsJ)*3-M4)^HC?6Ca E04(=aHvj+t literal 0 HcmV?d00001 diff --git a/test/memset.c b/test/memset.c new file mode 100644 index 0000000..5416093 --- /dev/null +++ b/test/memset.c @@ -0,0 +1,10 @@ +#include "stdlib.h" + +void *memset(void *s, int c, unsigned int n) { + int i; + + for (i=0; i(k0?Or%Nmd{lcHd+m19FxB{xT^Ixh_&*%`xCyH=NHK5#R9s@T;yP!NcB>_xK*J@+>d1(pWSEGi#3%dz;U%uCu8@ ulFV-I7CN!K=f8-b|{kDO}W%~JtQYH=sg`9 \n"); + return 1; + } + + src = open(argv[1]); + if (src==-1) { + printf("Open to open %s\n", argv[1]); + return 1; + } + + creat(argv[2]); + dst = open(argv[2]); + if (dst==-1) { + printf("Unable to create %s\n", argv[2]); + return 1; + } + + while ((amount = read(src, buf, BUFSIZE))>0) { + write(dst, buf, amount); + } + + close(src); + close(dst); + unlink(argv[1]); + + return 0; +} diff --git a/test/mv.coff b/test/mv.coff new file mode 100644 index 0000000000000000000000000000000000000000..18f4cfd284a3e76669925c25537bbef01b4b5622 GIT binary patch literal 7128 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 bEP{7>`$&I(M>JvTX68me)a60_>5%>hA3WG? literal 0 HcmV?d00001 diff --git a/test/printf.c b/test/printf.c new file mode 100644 index 0000000..083386d --- /dev/null +++ b/test/printf.c @@ -0,0 +1,184 @@ +#include "stdio.h" +#include "stdlib.h" + +static char digittoascii(unsigned n, int uppercase) { + assert(n<36); + + if (n<=9) + return '0'+n; + else if (uppercase) + return 'A'+n-10; + else + return 'a'+n-10; +} + +static int charprint(char **s, char c) { + *((*s)++) = c; + + return 1; +} + +static int mcharprint(char **s, char* chars, int length) { + memcpy(*s, chars, length); + *s += length; + + return length; +} + +static int integerprint(char **s, int n, unsigned base, int min, int zpad, int upper) { + char buf[32]; + int i=32, digit, len=0; + + assert(base>=2 && base < 36); + + if (min>32) + min=32; + + if (n==0) { + for (i=1; i32-min) + buf[--i] = zpad ? '0' : ' '; + + len += mcharprint(s, &buf[i], 32-i); + return len; +} + +static int stringprint(char **s, char *string) { + return mcharprint(s, string, strlen(string)); +} + +static int _vsprintf(char *s, char *format, va_list ap) { + int min,zpad,len=0,regular=0; + char *temp; + + /* process format string */ + while (*format != 0) { + /* if switch, process */ + if (*format == '%') { + if (regular > 0) { + len += mcharprint(&s, format-regular, regular); + regular = 0; + } + format++; + /* bug: '-' here will potentially screw things up */ + assert(*format != '-'); + + min=zpad=0; + + if (*format == '0') + zpad=1; + + min = atoi(format); + + temp = format; + while (*temp >= '0' && *temp <= '9') + temp++; + + switch (*(temp++)) { + + case 'c': + len += charprint(&s, va_arg(ap, int)); + break; + + case 'd': + len += integerprint(&s, va_arg(ap, int), 10, min, zpad, 0); + break; + + case 'x': + len += integerprint(&s, va_arg(ap, int), 16, min, zpad, 0); + break; + + case 'X': + len += integerprint(&s, va_arg(ap, int), 16, min, zpad, 1); + break; + + case 's': + len += stringprint(&s, (char*) va_arg(ap, int)); + break; + + default: + len += charprint(&s, '%'); + temp = format; + } + + format = temp; + } + else { + regular++; + format++; + } + } + + if (regular > 0) { + len += mcharprint(&s, format-regular, regular); + regular = 0; + } + + *s = 0; + + return len; +} + +void vsprintf(char *s, char *format, va_list ap) { + _vsprintf(s, format, ap); +} + +static char vfprintfbuf[256]; + +void vfprintf(int fd, char *format, va_list ap) { + int len = _vsprintf(vfprintfbuf, format, ap); + assert(len < sizeof(vfprintfbuf)); + write(fd, vfprintfbuf, len); +} + +void vprintf(char *format, va_list ap) { + vfprintf(stdout, format, ap); +} + +void sprintf(char *s, char *format, ...) { + va_list ap; + va_start(ap,format); + + vsprintf(s, format, ap); + + va_end(ap); +} + +void fprintf(int fd, char *format, ...) { + va_list ap; + va_start(ap,format); + + vfprintf(fd, format, ap); + + va_end(ap); +} + +void printf(char *format, ...) { + va_list ap; + va_start(ap,format); + + vprintf(format, ap); + + va_end(ap); +} diff --git a/test/printf.o b/test/printf.o new file mode 100644 index 0000000000000000000000000000000000000000..c33248c2f99f1444c130fcfc13d6feeeeffa4f85 GIT binary patch literal 4584 zcmb7IO>9)x75?VUcrbtM3mA8rI_i7zU`EKelc;K(%2KBWEK8{z7lFbel7Gg=9@U14 zJ)uNm@nX>mr4|oSq@wSy(+SD70m8F9cG3!|4lIn(t~sOLhl! zDeCgDx-2;DuMpqhK)Zz`2iN%A$LF4YE7p?^?j8UZ7LB{3K?42UYvHEo60ox3-}v<) zaTuT3OXAPM$hoOT#*+Kk0bXS01 z;N#G}!YAnCpnbyHj)GmQeaM`w?iKqy$M@w7&bn2r9qam6tJbu$IH&T+ch}ocheU&wBXGtIs+`eQ}a~ z(O7%e3#5OTdx;&)l|w(EAI|fIroHumwa;knJEHzwW&cWzf$pdmfIRoiv9=C-BA-BO zFRq8utNW46&f;)X(=>wTDL>Ge+o%2l%Uv3`+-0e;-325U4l#Ev7?14h`{M*_#>y;6 z%z5E7VwPZGHA4Uql%s#H|Uyz=Y^L6w5 za;`=j(XrRUHUuH@w7gZ8N>xYqQt;(Ox$9c}Z&M6)eerGymfAj}0+O zOcM8gxf4*mZ#Ox9<_S$C-&bxpMBx8AAI(S&z|tv zH$HoacV;w@cd3`X`DOGj-V6D3?2???Tqh{{OkM8+&-GQ)FLg<;O7Dujykk5o8^`KN z^UX*g#s1iMNB_X{h|JA7QbhJPWbLMRQ(|y!4{knSzoeMcd*M)m_PN5Qcv83#w&H_u z7ycZ^u@BJJ!3V7Cw_|T+EBiLH1@B5T`zhLY;KruC%X6jEl~X-M$(2wc1zdZ^@p%&X zhT~c78|}_D@#9cdPYx$cx|21S%Ms~viO&VnMD}&0?=YBih@yX!$bXrN;(5hI#V-^) zxH;KOLGdb)U*k*HbzW6$+_kVD3wztg9+!c)n;K z#c9Q|;-cbJ#XxaI@sXm_qHzsSa zQXDmCPbf|+&M1}@D~jh7&ntS07ZfilE-GGDysEgQcug@-yso&ccvEpj@s{Ep#ZMGh z71tCWD1N5+Q1NrcFBBgst}AXY?_?S`lRPr3{LT3SF~565&-V|D-vMqCtHd?pH71<7 zXXT(ftJYrf{1eOp}Put&eQ#Wm7vLa#kcfbAR65c^Pg>8nBVvZwGv zdBb;zoV-i)L_TczBO)i?Oj`zC@H74DiQ?@R6MSTjV9r1H*=o zTyi;3HhiA*LGm6^=xDW8^9>vE0r@KJ?^DjBMl`4>_fm*%B9i+fBzHnc`dlb} zGNd1cq{oD$Z-k^5grpWi@~%YmNfr;5dwM~Y`=%cYsgi5`rMOr3uF$$X@UvuZ#7_9^^7 z+i#sFUD!^<1ekiL?Lvypr>{ z#y3p`qBmdJI@lHQPwG^s*~GGML>AW`I(K42ogdQqyI&dmpKva{AKMqmdK~fmHQ`CI z{W0=uBGCOt$jW_;=f4siDYl;@FZVLmpBE)5*1t;x8QWJ(c-wj`)7c{4Pg)FaHZ1m8u{B literal 0 HcmV?d00001 diff --git a/test/readline.c b/test/readline.c new file mode 100644 index 0000000..761e18a --- /dev/null +++ b/test/readline.c @@ -0,0 +1,37 @@ +#include "stdio.h" +#include "stdlib.h" + +void readline(char *s, int maxlength) { + int i = 0; + + while (1) { + char c = getch(); + /* if end of line, finish up */ + if (c == '\n') { + putchar('\n'); + s[i] = 0; + return; + } + /* else if backspace... */ + else if (c == '\b') { + /* if nothing to delete, beep */ + if (i == 0) { + beep(); + } + /* else delete it */ + else { + printf("\b \b"); + i--; + } + } + /* else if bad character or no room for more, beep */ + else if (c < 0x20 || i+1 == maxlength) { + beep(); + } + /* else add the character */ + else { + s[i++] = c; + putchar(c); + } + } +} diff --git a/test/readline.o b/test/readline.o new file mode 100644 index 0000000000000000000000000000000000000000..f2ced4af7675cefe61d1bb60da03183c8fc2c106 GIT binary patch literal 1076 zcmah{J#W)c6g_rQlBSV}NKa!bF@r0vE}9`}4URWD^K!c}wfJL0Z&pYam$MiSyaD&AWyv`|QxByEV@KOm59uSw zdg%x_pm2^(P9zpj=94%NKMgLEi`_atNA_EvvwVx}Fy#5?kxj#Ge2pr&(Q4pJRK|9z zh3^r|sY4s`)oJ|**|m(R((+QyvBC%5Fi$n7)o2J=2y^2?Mzk)`fDjW_38w6B9Tc+bo= z@{gQ@XQRr`KDj~elAn>q|4x!Ar0!Q5OD-XRrvFEA=Hj4~chFRM?a{r&@ubhQL=cZ_ zT3=EhQr}d&z@w`qk;f2-ma_zhn&hrD7Nf!Ncsd(7E;5OU>)!9VFJH{3$D^TxUT-ox zUBx|D3jb$W^%_q`o{RDPl;8PcI`hWr+-#l)dJ1))smzgft!B+-)+B$U?D7Aok;YaU V$~_70YQn4E+JEn#IGacEe*wFFo*)1K literal 0 HcmV?d00001 diff --git a/test/rm.c b/test/rm.c new file mode 100644 index 0000000..cb5c213 --- /dev/null +++ b/test/rm.c @@ -0,0 +1,18 @@ +#include "syscall.h" +#include "stdio.h" +#include "stdlib.h" + +int main(int argc, char** argv) +{ + if (argc!=2) { + printf("Usage: rm \n"); + return 1; + } + + if (unlink(argv[1]) != 0) { + printf("Unable to remove %s\n", argv[1]); + return 1; + } + + return 0; +} diff --git a/test/rm.coff b/test/rm.coff new file mode 100644 index 0000000000000000000000000000000000000000..62536f3d2a8946d9ee3a82e3c55ed038e23f3228 GIT binary patch literal 6936 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 literal 0 HcmV?d00001 diff --git a/test/rm.o b/test/rm.o new file mode 100644 index 0000000000000000000000000000000000000000..eb186b599726f5c17449f7dc51b9c5750bb8fd6d GIT binary patch literal 992 zcmah`L2DCX5S`tuX=?<7^iTzH0|^Z%OVJ*R6v;&icvbKqY&Y9&2xd27vy~ot_yiB0 z%*8{G`3I>#pm^~I_!D~cSZ^ML_}vCCfZW_g-_mSJ0u$*HPpB0g_HrU4bc9h$X!1(9RcELE+RtJ0o`W2YI zx617|VEQ)3HI!Guvv<*{f=`zm*eTzkx#tI%$M^%Le~--q{GKT^dkX+BHotQ&U3d`E z`|=>~t4C+i@$x|TGk<}ba^?x5i@e4n@ce4AxTk5Ja~IK7;*At(?1d5sgGBma_}C9e z@fdeL^u+i3$?>)JL;0^EpW^#DjnhGr9m#Pr93=0GRplEV7Mkx~g}Scaw`%xT!EdCv bT~-S17MiyqT1xWam-_i15v6{jGS`0ro@tJK literal 0 HcmV?d00001 diff --git a/test/script b/test/script new file mode 100644 index 0000000..5be8ccf --- /dev/null +++ b/test/script @@ -0,0 +1,15 @@ +OUTPUT_FORMAT("ecoff-littlemips") +SEARCH_DIR(.) +ENTRY(__start) + +SECTIONS { + .text 0 : { *(.text) } + .text.startup BLOCK(0x400) : { *(.text.startup) } + .rdata BLOCK(0x400) : { *(.rdata) } + .data BLOCK(0x400) : { *(.data) } + .rodata BLOCK(0x400) : { *(.rodata) *(.rodata.str1.4)} + .sbss BLOCK(0x400) : { *(.sbss) } + .bss BLOCK(0x400) : { *(.bss) } + .scommon BLOCK(0x400) : { *(.scommon) } + /DISCARD/ : { *(.reginfo) *(.pdr) *(.comment) *(.gnu.attributes) } +} diff --git a/test/script_old b/test/script_old new file mode 100644 index 0000000..9776fe4 --- /dev/null +++ b/test/script_old @@ -0,0 +1,12 @@ +OUTPUT_FORMAT("ecoff-littlemips") +SEARCH_DIR(.) +ENTRY(__start) + +SECTIONS { + .text 0 : { *(.text) } + .rdata BLOCK(0x400) : { *(.rdata) } + .data BLOCK(0x400) : { *(.data) } + .sbss BLOCK(0x400) : { *(.sbss) } + .bss BLOCK(0x400) : { *(.bss) } + .scommon BLOCK(0x400) : { *(.scommon) } +} diff --git a/test/sh.c b/test/sh.c new file mode 100644 index 0000000..3b808c6 --- /dev/null +++ b/test/sh.c @@ -0,0 +1,203 @@ +#include "stdio.h" +#include "stdlib.h" + +#define BUFFERSIZE 64 + +#define MAXARGSIZE 16 +#define MAXARGS 16 + +/** + * tokenizeCommand + * + * Splits the specified command line into tokens, creating a token array with a maximum + * of maxTokens entries, using storage to hold the tokens. The storage array should be as + * long as the command line. + * + * Whitespace (spaces, tabs, newlines) separate tokens, unless + * enclosed in double quotes. Any character can be quoted by preceeding + * it with a backslash. Quotes must be terminated. + * + * Returns the number of tokens, or -1 on error. + */ +static int tokenizeCommand(char* command, int maxTokens, char *tokens[], char* storage) { + const int quotingCharacter = 0x00000001; + const int quotingString = 0x00000002; + const int startedArg = 0x00000004; + + int state = 0; + int numTokens = 0; + + char c; + + assert(maxTokens > 0); + + while ((c = *(command++)) != '\0') { + if (state & quotingCharacter) { + switch (c) { + case 't': + c = '\t'; + break; + case 'n': + c = '\n'; + break; + } + *(storage++) = c; + state &= ~quotingCharacter; + } + else if (state & quotingString) { + switch (c) { + case '\\': + state |= quotingCharacter; + break; + case '"': + state &= ~quotingString; + break; + default: + *(storage++) = c; + break; + } + } + else { + switch (c) { + case ' ': + case '\t': + case '\n': + if (state & startedArg) { + *(storage++) = '\0'; + state &= ~startedArg; + } + break; + default: + if (!(state & startedArg)) { + if (numTokens == maxTokens) { + return -1; + } + tokens[numTokens++] = storage; + state |= startedArg; + } + + switch (c) { + case '\\': + state |= quotingCharacter; + break; + case '"': + state |= quotingString; + break; + default: + *(storage++) = c; + break; + } + } + } + } + + if (state & quotingCharacter) { + printf("Unmatched \\.\n"); + return -1; + } + + if (state & quotingString) { + printf("Unmatched \".\n"); + return -1; + } + + if (state & startedArg) { + *(storage++) = '\0'; + } + + return numTokens; +} + +void runline(char* line) { + int pid, background, status; + + char args[BUFFERSIZE], prog[BUFFERSIZE]; + char *argv[MAXARGS]; + + int argc = tokenizeCommand(line, MAXARGS, argv, args); + if (argc <= 0) + return; + + if (argc > 0 && strcmp(argv[argc-1], "&") == 0) { + argc--; + background = 1; + } + else { + background = 0; + } + + if (argc > 0) { + if (strcmp(argv[0], "exit")==0) { + if (argc == 1) { + exit(0); + } + else if (argc == 2) { + exit(atoi(argv[1])); + } + else { + printf("exit: Expression Syntax.\n"); + return; + } + } + else if (strcmp(argv[0], "halt")==0) { + if (argc == 1) { + halt(); + printf("Not the root process!\n"); + } + else { + printf("halt: Expression Syntax.\n"); + } + return; + } + else if (strcmp(argv[0], "join")==0) { + if (argc == 2) { + pid = atoi(argv[1]); + } + else { + printf("join: Expression Syntax.\n"); + return; + } + } + else { + strcpy(prog, argv[0]); + strcat(prog, ".coff"); + + pid = exec(prog, argc, argv); + if (pid == -1) { + printf("%s: exec failed.\n", argv[0]); + return; + } + } + + if (!background) { + switch (join(pid, &status)) { + case -1: + printf("join: Invalid process ID.\n"); + break; + case 0: + printf("\n[%d] Unhandled exception\n", pid); + break; + case 1: + printf("\n[%d] Done (%d)\n", pid, status); + break; + } + } + else { + printf("\n[%d]\n", pid); + } + } +} + +int main(int argc, char *argv[]) { + char prompt[] = "nachos% "; + + char buffer[BUFFERSIZE]; + + while (1) { + printf("%s", prompt); + + readline(buffer, BUFFERSIZE); + + runline(buffer); + } +} diff --git a/test/sh.coff b/test/sh.coff new file mode 100644 index 0000000000000000000000000000000000000000..f766485074955af21e055def0b47e3eb27844a6a GIT binary patch literal 10468 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 VwHRZJ5AKOFv?=XD-P{Lt{4Ye-8<_wA literal 0 HcmV?d00001 diff --git a/test/sh.o b/test/sh.o new file mode 100644 index 0000000000000000000000000000000000000000..f13c8056abd900bac7b41cf73ed2ad0feeac6109 GIT binary patch literal 3440 zcmai1O>7fK6n@^U^ItG+np%j$ZrCIXLXkmLMNuRy2q>r(joKo$YFgW|H`pbyU3)>H zMXHN($RUz_;NSy?C_gO{NC_>KkPvE46_q&Tz<~pY9CFBkgDY`BYFhVuGqa8{ppIgH z^WOJ(oWJm(3ZXJ@o6cS>`p~SvKe9$fDnt%^R!ar@~&FeqSci z2iNpz3!yp<@&iv^<*+9x8t~C4eQD~nT1d(Dxa1*33aogP&jd?IuUqOYVTyMq@T& zcImL`z`RM#TPP{)x|JVN)Wz)AnqkLz_mcajkMe!!$Ss}zuyi{7zMmYm#zZZb4|>k2 z0loEkHTbg{?cy5n{&eKy^>V$&VE-63Yk`i}$GS~bL(ZK7U#)7E2Hp%rHK^uM>mq7j zL?4RiNfG@jqDMvatJq5GO(DA9A3z@isPSX;utY2UW{9)^{oMZ)ecD9-Hqgs;^cnFw zpNRg3X_k!L=&x3-hWZMD0GWX?xxQp^?aVnMoCox(%lZL6;HX54MbB;v zc5lPZN1ElQo^B1u{-!~+f&E~PubytkYr>B@d5!^_aLtBm!8+YPZFTyjUwt0Kzhv!H zdAxXR&w)H&yUy3sh3jw z#F-Q4u!3_~!Z}Rh%q4KfI8PMkk!aW8mj7^{fjV=YDyUNv&EtldFSpRbj7|&XR$45) zMe{cUG=J|MTDaLo3-^MwxL_Kxh5@bxYRWOgM1ZMtqzTae0X^zkMI-7xbW_%nrz4>E?Gv&mM@mOlYNr>Fi?@anqY$BELk{V}* zm~8*DH}REmE}e{}6R?MG+{wCFe2p8*q#eWVO&s9uOMA@Hv3N3*?=@K0i?;+na44z~ zmS_(Fn~2KSfq3NvR}?-}s6)y6qYA?cCx9Hsm1t*`zM%BeN`~2Jh-l6h>O_GTyWB<@0^pF$w^#Pl)IRoNTnT`jNxWHACDi2#50pw zap6%Uaz1^rCP(7*zXpxbBav7>@8n#{=2B^Qyp}ER=HioCdELj{OiEnZ#M A(j)) + swap(&A(i), &A(j)); + } + } + + /* and last, verify */ + for (i=0; iq(TUq6qe5X6lo$_msg~4Nr|Y^P((Uu^WMyDa^6G>PxtP7-4r+7LUB_a&CI~_F^w@$b#!k(w~@@{Eca6e@(<#FIrN@ z)`V`$%89f0g*Yu6t9auF5fc=du@)tVK8{Ua#+{;=hI}?H#=^|Mad{#y*0eLZX2!B! z{0BM5=y~#(XBW@3gLQ}u%i@F~rfZ1ra^CxDtbSIktBrNFv931O)yBHoSW}y8FUp;> zLztH}KIQy&S@fRJF>@1CNgVOYEk|L525 zj}Qa>;g5wgGNsy+K0E}RQ|D8yUTSO+ZRs&AiYNL{@Cd)s@5N)zd7f~k`aN{85lHss zc$_Dk$82!_N!I4`7QlfmMD{q|g+;RO9LQJkG?<0=&`7d2?y`)5&w*K(MLK%(Z%ivA$1#lY7 z!bfN%PlLC>mq6Z&EG(droC0ryoUa6CVG)fa*Kh>B3Z4VA@G%-m-pga~4EPS1g$rmT zi(qmOmRtO`XJN=?v&_+NYOQ?e&pD3%zShczUV* zlYUogCflbWs0kkKY#} z`PB29LGVlvyxRotE5SQR@LmzTD+JF!!81+poD#er4-q!DqLMG+HLoc(uTqyQzJG4j zZ`7KVYOqm~)zvHYs}J*4^o%@=2+^Pvq8hg8RU-+uEBp(5`Kp0Z{#M{c(r5;Cf!dI3 zTa_pfzuE``xmvGQ>R(H(hI#!)y&m|Hc)lMrBMGmEzE`c5_`V5jw?eYVBmMkj(EFS0 zYceM3W5Gzq^Zl@f-ETbKj|?Vumo>OYtf8wy0B?b;lf2&_kr%0) z+cKrdU^G@kTPe>TE7#DlXj=ub=j*_WvbEa+w06ZrgRS*!-^{^!dJmQ_TfFid(0PEW zxr7{JtdiI`wIDztQkcI6wnwL3yXfUlJHi-_o(?yg-?n7 zFtMNO%t-I2M2tQ^@}^%i5v+|Sw|@{iAD6eE8c zBa4z!F)#Y#6S)=oPUgrRB6s|_XTi&SYw2I=HHptBc=>va$6_bGNG)>vyHZvRBb?T3 zCbo1u*+C?|?QXy3q4&V;VAI{$!n)_pJKpwYXXF0bY7LIFzO^&qj>n|`Mf|PhI8jNr z+jSqs*QNc;$26KPff*G))}+Ub=M?0;V!Mz!5?)HU>`&w>kL*zPCQ^+R9{-5*ZwTjG I-}38@GMFUfCbx5=B(hK$NG3!M z&KR?l=(5dX7_`F!9gN)+KQ%YXih?N4d7-Bm&nLS#29L%>akkaM9~?*fpq36coF60% z7&CaiFlKUQ+r6O4-l8LJXAaZ2qQiq)Pt>-NL+8Pim1NpVJTN0F~iGHIkC#cj1S zLqmGZzx=r`YUE!vtPvNZQ9OqY>yFxg3I%llWBER>)GN}&x&U*J2)!ofBvsGU3ydv^ zesNr+>A5~Xw~vPbHbvT$0o#Yu5hr0KOf zf#0(%_%7!tO=IeW3!)>=iaR1rZ`28w#i}?j?uj(LRVQ2%>w@PMMVj8J6L^OWaY;NB zX?m|txGlEC74cZ4>4Q39M8tJ4p~~V6p>b^-p8YH9gT26yk2;?tFF&jZ=V{R<*1l42I-h@VM+fsZ3Zy`h{7=EtwyT`c=LBB&$8UCmJH z5V4QLg8D<;mnA`cp__s;MqMH1stD={aUWF$b%Y*?wxE6xb1e(%25~=k1oeWrcUA>; Wf+obepgz!~*bvkOs)#K?J^Th-O257U literal 0 HcmV?d00001 diff --git a/test/start.s b/test/start.s new file mode 100644 index 0000000..1289390 --- /dev/null +++ b/test/start.s @@ -0,0 +1,69 @@ +/* Start.s + * Assembly language assist for user programs running on top of Nachos. + * + * Since we don't want to pull in the entire C library, we define + * what we need for a user program here, namely Start and the system + * calls. + */ + +#define START_S +#include "syscall.h" + + .text + .align 2 + +/* ------------------------------------------------------------- + * __start + * Initialize running a C program, by calling "main". + * ------------------------------------------------------------- + */ + + .globl __start + .ent __start +__start: + jal main + addu $4,$2,$0 + jal exit /* if we return from main, exit(return value) */ + .end __start + + .globl __main + .ent __main +__main: + jr $31 + .end __main + +/* ------------------------------------------------------------- + * System call stubs: + * Assembly language assist to make system calls to the Nachos kernel. + * There is one stub per system call, that places the code for the + * system call into register r2, and leaves the arguments to the + * system call alone (in other words, arg1 is in r4, arg2 is + * in r5, arg3 is in r6, arg4 is in r7) + * + * The return value is in r2. This follows the standard C calling + * convention on the MIPS. + * ------------------------------------------------------------- + */ + +#define SYSCALLSTUB(name, number) \ + .globl name ; \ + .ent name ; \ +name: ; \ + addiu $2,$0,number ; \ + syscall ; \ + j $31 ; \ + .end name + + SYSCALLSTUB(halt, syscallHalt) + SYSCALLSTUB(exit, syscallExit) + SYSCALLSTUB(exec, syscallExec) + SYSCALLSTUB(join, syscallJoin) + SYSCALLSTUB(creat, syscallCreate) + SYSCALLSTUB(open, syscallOpen) + SYSCALLSTUB(read, syscallRead) + SYSCALLSTUB(write, syscallWrite) + SYSCALLSTUB(close, syscallClose) + SYSCALLSTUB(unlink, syscallUnlink) + SYSCALLSTUB(mmap, syscallMmap) + SYSCALLSTUB(connect, syscallConnect) + SYSCALLSTUB(accept, syscallAccept) diff --git a/test/stdarg.h b/test/stdarg.h new file mode 100644 index 0000000..be93076 --- /dev/null +++ b/test/stdarg.h @@ -0,0 +1,205 @@ +/* stdarg.h for GNU. + Note that the type used in va_arg is supposed to match the + actual type **after default promotions**. + Thus, va_arg (..., short) is not valid. */ + +#ifndef _STDARG_H +#ifndef _ANSI_STDARG_H_ +#ifndef __need___va_list +#define _STDARG_H +#define _ANSI_STDARG_H_ +#endif /* not __need___va_list */ +#undef __need___va_list + +#ifdef __clipper__ +#include "va-clipper.h" +#else +#ifdef __m88k__ +#include "va-m88k.h" +#else +#ifdef __i860__ +#include "va-i860.h" +#else +#ifdef __hppa__ +#include "va-pa.h" +#else +#ifdef __mips__ +#include "va-mips.h" +#else +#ifdef __sparc__ +#include "va-sparc.h" +#else +#ifdef __i960__ +#include "va-i960.h" +#else +#ifdef __alpha__ +#include "va-alpha.h" +#else +#if defined (__H8300__) || defined (__H8300H__) || defined (__H8300S__) +#include "va-h8300.h" +#else +#if defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32)) +#include "va-ppc.h" +#else +#ifdef __arc__ +#include "va-arc.h" +#else +#ifdef __M32R__ +#include "va-m32r.h" +#else +#ifdef __sh__ +#include "va-sh.h" +#else +#ifdef __mn10300__ +#include "va-mn10300.h" +#else +#ifdef __mn10200__ +#include "va-mn10200.h" +#else +#ifdef __v850__ +#include "va-v850.h" +#else + +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +#if defined(__svr4__) || defined(_AIX) || defined(_M_UNIX) || defined(__NetBSD__) +typedef char *__gnuc_va_list; +#else +typedef void *__gnuc_va_list; +#endif +#endif + +/* Define the standard macros for the user, + if this invocation was from the user program. */ +#ifdef _STDARG_H + +/* Amount of space required in an argument list for an arg of type TYPE. + TYPE may alternatively be an expression whose type is used. */ + +#if defined(sysV68) +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (short) - 1) / sizeof (short)) * sizeof (short)) +#else +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) +#endif + +#define va_start(AP, LASTARG) \ + (AP = ((__gnuc_va_list) __builtin_next_arg (LASTARG))) + +#undef va_end +void va_end (__gnuc_va_list); /* Defined in libgcc.a */ +#define va_end(AP) ((void)0) + +/* We cast to void * and then to TYPE * because this avoids + a warning about increasing the alignment requirement. */ + +#if (defined (__arm__) && ! defined (__ARMEB__)) || defined (__i386__) || defined (__i860__) || defined (__ns32000__) || defined (__vax__) +/* This is for little-endian machines; small args are padded upward. */ +#define va_arg(AP, TYPE) \ + (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \ + *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE)))) +#else /* big-endian */ +/* This is for big-endian machines; small args are padded downward. */ +#define va_arg(AP, TYPE) \ + (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \ + *((TYPE *) (void *) ((char *) (AP) \ + - ((sizeof (TYPE) < __va_rounded_size (char) \ + ? sizeof (TYPE) : __va_rounded_size (TYPE)))))) +#endif /* big-endian */ + +/* Copy __gnuc_va_list into another variable of this type. */ +#define __va_copy(dest, src) (dest) = (src) + +#endif /* _STDARG_H */ + +#endif /* not v850 */ +#endif /* not mn10200 */ +#endif /* not mn10300 */ +#endif /* not sh */ +#endif /* not m32r */ +#endif /* not arc */ +#endif /* not powerpc with V.4 calling sequence */ +#endif /* not h8300 */ +#endif /* not alpha */ +#endif /* not i960 */ +#endif /* not sparc */ +#endif /* not mips */ +#endif /* not hppa */ +#endif /* not i860 */ +#endif /* not m88k */ +#endif /* not clipper */ + +#ifdef _STDARG_H +/* Define va_list, if desired, from __gnuc_va_list. */ +/* We deliberately do not define va_list when called from + stdio.h, because ANSI C says that stdio.h is not supposed to define + va_list. stdio.h needs to have access to that data type, + but must not use that name. It should use the name __gnuc_va_list, + which is safe because it is reserved for the implementation. */ + +#ifdef _HIDDEN_VA_LIST /* On OSF1, this means varargs.h is "half-loaded". */ +#undef _VA_LIST +#endif + +#ifdef _BSD_VA_LIST +#undef _BSD_VA_LIST +#endif + +#if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST)) +/* SVR4.2 uses _VA_LIST for an internal alias for va_list, + so we must avoid testing it and setting it here. + SVR4 uses _VA_LIST as a flag in stdarg.h, but we should + have no conflict with that. */ +#ifndef _VA_LIST_ +#define _VA_LIST_ +#ifdef __i860__ +#ifndef _VA_LIST +#define _VA_LIST va_list +#endif +#endif /* __i860__ */ +typedef __gnuc_va_list va_list; +#ifdef _SCO_DS +#define __VA_LIST +#endif +#endif /* _VA_LIST_ */ +#else /* not __svr4__ || _SCO_DS */ + +/* The macro _VA_LIST_ is the same thing used by this file in Ultrix. + But on BSD NET2 we must not test or define or undef it. + (Note that the comments in NET 2's ansi.h + are incorrect for _VA_LIST_--see stdio.h!) */ +#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT) +/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */ +#ifndef _VA_LIST_DEFINED +/* The macro _VA_LIST is used in SCO Unix 3.2. */ +#ifndef _VA_LIST +/* The macro _VA_LIST_T_H is used in the Bull dpx2 */ +#ifndef _VA_LIST_T_H +typedef __gnuc_va_list va_list; +#endif /* not _VA_LIST_T_H */ +#endif /* not _VA_LIST */ +#endif /* not _VA_LIST_DEFINED */ +#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__)) +#define _VA_LIST_ +#endif +#ifndef _VA_LIST +#define _VA_LIST +#endif +#ifndef _VA_LIST_DEFINED +#define _VA_LIST_DEFINED +#endif +#ifndef _VA_LIST_T_H +#define _VA_LIST_T_H +#endif + +#endif /* not _VA_LIST_, except on certain systems */ + +#endif /* not __svr4__ */ + +#endif /* _STDARG_H */ + +#endif /* not _ANSI_STDARG_H_ */ +#endif /* not _STDARG_H */ diff --git a/test/stdio.c b/test/stdio.c new file mode 100644 index 0000000..0c792d4 --- /dev/null +++ b/test/stdio.c @@ -0,0 +1,18 @@ +#include "stdio.h" +#include "stdlib.h" + +int fgetc(int fd) { + unsigned char c; + + while (read(fd, &c, 1) != 1); + + return c; +} + +void fputc(char c, int fd) { + write(fd, &c, 1); +} + +void fputs(const char *s, int fd) { + write(fd, (char*) s, strlen(s)); +} diff --git a/test/stdio.h b/test/stdio.h new file mode 100644 index 0000000..c157362 --- /dev/null +++ b/test/stdio.h @@ -0,0 +1,40 @@ +/*------------------------------------------------------------- + * stdio.h + * + * Header file for standard I/O routines. + *-------------------------------------------------------------*/ + +#ifndef STDIO_H +#define STDIO_H + +#include "syscall.h" +#include "stdarg.h" + +typedef int FILE; +#define stdin fdStandardInput +#define stdout fdStandardOutput + +int fgetc(FILE stream); +void readline(char *s, int maxlength); +int tryreadline(char *s, char c, int maxlength); + +#define getc(stream) fgetc(stream) +#define getchar() getc(stdin) +#define getch() getchar() + +void fputc(char c, FILE stream); +void fputs(const char *s, FILE stream); + +#define puts(s) fputs(s,stdout) +#define putc(c,stream) fputc(c,stream) +#define putchar(c) putc(c,stdout) +#define beep() putchar(0x07) + +void vsprintf(char *s, char *format, va_list ap); +void vfprintf(FILE f, char *format, va_list ap); +void vprintf(char *format, va_list ap); +void sprintf(char *s, char *format, ...); +void fprintf(FILE f, char *format, ...); +void printf(char *format, ...); + +#endif // STDIO_H diff --git a/test/stdio.o b/test/stdio.o new file mode 100644 index 0000000000000000000000000000000000000000..5170a21ba96f5ddc89015160ba4a43e172e50f1d GIT binary patch literal 1160 zcmah{O=}ZT6upyFn_9tHv`|p-4TL7B3~e_GR>(p_!A*aF5Yx#R0<{g9DZ1z)?z$Vn zO_!nSPDuR$rSlV9y6jKToeN<+=e;*EWLi9M-#Pc)k9X(2*>TE3oH`<}z>j6lnRgaT zDfBE-Y|vsUk3a?ZariEt+D)Oq!#rB}?#Q>XcQlk0IUPIVR+XHOJ*7&ne5oP*rX$y@f3oc*vv=|l@dPyq@{@{Ol2+yx!prH1vDb$RE+sv&v*%j7?RpWi)0>of63@bfod=;>7a EFCdi39{>OV literal 0 HcmV?d00001 diff --git a/test/stdlib.c b/test/stdlib.c new file mode 100644 index 0000000..9df87d1 --- /dev/null +++ b/test/stdlib.c @@ -0,0 +1 @@ +#include "stdlib.h" diff --git a/test/stdlib.h b/test/stdlib.h new file mode 100644 index 0000000..70570cf --- /dev/null +++ b/test/stdlib.h @@ -0,0 +1,37 @@ +/*------------------------------------------------------------- + * stdlib.h + * + * Header file for standard library functions. + *-------------------------------------------------------------*/ + +#ifndef STDLIB_H +#define STDLIB_H + +#include "syscall.h" + +#define null 0L +#define true 1 +#define false 0 + +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) + +#define divRoundDown(n,s) ((n) / (s)) +#define divRoundUp(n,s) (((n) / (s)) + ((((n) % (s)) > 0) ? 1 : 0)) + +#define assert(_EX) ((_EX) ? (void) 0 : __assert(__FILE__, __LINE__)) +void __assert(char* file, int line); + +#define assertNotReached() assert(false) + +void *memcpy(void *s1, const void *s2, unsigned int n); +void *memset(void *s, int c, unsigned int n); + +unsigned int strlen(const char *str); +char *strcpy(char *dst, const char *src); +int strcmp(const char *a, const char *b); +int strncmp(const char *a, const char *b, int n); + +int atoi(const char *s); + +#endif // STDLIB_H diff --git a/test/strcat.c b/test/strcat.c new file mode 100644 index 0000000..70a9f90 --- /dev/null +++ b/test/strcat.c @@ -0,0 +1,16 @@ +#include "stdlib.h" + +/* concatenates s2 to the end of s1 and returns s1 */ +char *strcat(char *s1, const char *s2) { + char* result = s1; + + while (*s1 != 0) + s1++; + + do { + *(s1++) = *(s2); + } + while (*(s2++) != 0); + + return result; +} diff --git a/test/strcat.o b/test/strcat.o new file mode 100644 index 0000000000000000000000000000000000000000..76578cf0923fd34ffbbc0e1f9c36ddb53a9ec35b GIT binary patch literal 748 zcmah_%SyvQ6uoKCsuir@q8l-VE?fl_7cN|6qZD-MK9fvK5quOgg3BO&KtDkW{zaF5 zfS=$exOE}pxs#bNq=E--&g0&BWbz;+#z8w9~4MC-8hU!)F!z&c-4HZ(_wUxCh<`UxIl= zc{}mk!g}s$0Q4tzY0vcCj63c^5N+5M=lFBhSEwQMw$0DJw2nOO)(&mP_b@2bgUnPc zsS-4i@+g(}x6|vJ@hGM=o!mXvK9#)YzY)8W+1{OdXk7JfR(e!T)pznbOA`OZ*_LZq JA6d`u@e3!-T?+sJ literal 0 HcmV?d00001 diff --git a/test/strcmp.c b/test/strcmp.c new file mode 100644 index 0000000..5c3be03 --- /dev/null +++ b/test/strcmp.c @@ -0,0 +1,14 @@ +#include "stdlib.h" + +/* lexicographically compares a and b */ +int strcmp(const char* a, const char* b) { + do { + if (*a < *b) + return -1; + if (*a > *b) + return 1; + } + while (*(a++) != 0 && *(b++) != 0); + + return 0; +} diff --git a/test/strcmp.o b/test/strcmp.o new file mode 100644 index 0000000000000000000000000000000000000000..fcfe125b66e4dc30ec589a8fac08659db2fdfffa GIT binary patch literal 740 zcmah_O-jRH6r7~-w}=s3xDg{{QMw2yE?jn@QgGu9(l)I{Xtme~E?g9J;YI8TT)Ggv zfJf*N1P>5rk}ol|f&=fHH}9MGzMqa&fl#x67Wo*CwPIE63l-;}n&JVN%x$GIhO zX+z#mhR4~0$YTWEcHAcC^OzPM6yzi`Axz= z%?>+`$S%1?J|W98C{2>@)oAS{1nE!gVlUm#J^69xEnwYrobm3;^=D1yTc&>cl_Xv% z&wHDuRy=kb-$uhx5Fty@kD|jcx*3kH2EA^8FzjF76*`R6{-4E6N>9qqJuv6$-xiU% ViaRYDek**J#AaSG+A~`J@dGnoSxo={ literal 0 HcmV?d00001 diff --git a/test/strcpy.c b/test/strcpy.c new file mode 100644 index 0000000..3186514 --- /dev/null +++ b/test/strcpy.c @@ -0,0 +1,15 @@ +#include "stdlib.h" + +/* copies src to dst, returning dst */ +char *strcpy(char *dst, const char *src) { + int n=0; + char *result = dst; + + do { + *(dst++) = *src; + n++; + } + while (*(src++) != 0); + + return result; +} diff --git a/test/strcpy.o b/test/strcpy.o new file mode 100644 index 0000000000000000000000000000000000000000..b05d561522dfc938af9f18c345092e1b59b9f5fd GIT binary patch literal 700 zcmYddWM%*ZMh1oiAj5)zm64s1o5=toib8_KK-h+Xp#en#%F!!Httdf~0I9uz#0N1I zfLJdju_O^l!^{IR85n@}BLfE@M=z$<50d*21V9QakY$hu%fr-w)PsO`0s{jVn8m>0CIDgU0Qnw3 zwjfm8^~3-F3P^02UJs}kGpzr_yBw15x literal 0 HcmV?d00001 diff --git a/test/strlen.c b/test/strlen.c new file mode 100644 index 0000000..d0715c5 --- /dev/null +++ b/test/strlen.c @@ -0,0 +1,11 @@ +#include "stdlib.h" + +/* returns the length of the character string str, not including the null-terminator */ +unsigned strlen(const char *str) { + int result=0; + + while (*(str++) != 0) + result++; + + return result; +} diff --git a/test/strlen.o b/test/strlen.o new file mode 100644 index 0000000000000000000000000000000000000000..50be5d5d8e5200b577a91489af4360f44db6210d GIT binary patch literal 708 zcmah_!AiqG6nxu?MtiV=haOr?AqP)E#e>IQl!E?4(r!Z)YAq&$$0B}$M?cC>@ZbmZ z1B5uU*)5wYIIx+S_hw&qcdVL11WF_YU&xl)QLV-aiyL5#t1GhHXc-$9*>mAFnEjx~ zY)2tPJQ)=uu$#x8%NUK%04pBnIejh1f`_H2DRG;i-{CkNiM*KhcR4sz@)`y5+3dGd z#%jRvI=hQjqgJ$rN592q8~jdV!B_i&KL@YC$KVJP7`gE#G52OYdnEw+6FoUHeV1XL zxK2g(j1swOR~na-A@qT*U#`kB^t9VMv^Ac?ATJ(g**w-#37KkrmgtB3#oa8M#F8Y_ r`P14bntT3>*hyx*`|qi7)w@~gQI%Ss$?N=*xEE{tu3>#>J>TO83hq!% literal 0 HcmV?d00001 diff --git a/test/strncmp.c b/test/strncmp.c new file mode 100644 index 0000000..809ea28 --- /dev/null +++ b/test/strncmp.c @@ -0,0 +1,20 @@ +#include "stdlib.h" + +/* lexicographically compares a and b up to n chars */ +int strncmp(const char* a, const char* b, int n) +{ + assert(n > 0); + + do { + if (*a < *b) + return -1; + if (*a > *b) + return 1; + n--; + a++; + b++; + } + while (n > 0); + + return 0; +} diff --git a/test/strncmp.o b/test/strncmp.o new file mode 100644 index 0000000000000000000000000000000000000000..59c415404d2d5051c71ee6a7d93b364f8cdcd342 GIT binary patch literal 896 zcmah{Jxjw-6g{c6RVoor6v2WTS*9REnuI#j--{gGKrAdX2c=24&xkY zp*}dx>RB^Z75^I}*(;+}q2fC{j3O-)`)e$n0;R?Qh?hW&_KW<>qV Z@e1!K>1eNJ@~p{aHUjy!f{S;hz5(C!h9m$0 literal 0 HcmV?d00001 diff --git a/test/syscall.h b/test/syscall.h new file mode 100644 index 0000000..e5ac795 --- /dev/null +++ b/test/syscall.h @@ -0,0 +1,262 @@ +/** + * The Nachos system call interface. These are Nachos kernel operations that + * can be invoked from user programs using the syscall instruction. + * + * This interface is derived from the UNIX syscalls. This information is + * largely copied from the UNIX man pages. + */ + +#ifndef SYSCALL_H +#define SYSCALL_H + +/** + * System call codes, passed in $r0 to tell the kernel which system call to do. + */ +#define syscallHalt 0 +#define syscallExit 1 +#define syscallExec 2 +#define syscallJoin 3 +#define syscallCreate 4 +#define syscallOpen 5 +#define syscallRead 6 +#define syscallWrite 7 +#define syscallClose 8 +#define syscallUnlink 9 +#define syscallMmap 10 +#define syscallConnect 11 +#define syscallAccept 12 + +/* Don't want the assembler to see C code, but start.s includes syscall.h. */ +#ifndef START_S + +/* When a process is created, two streams are already open. File descriptor 0 + * refers to keyboard input (UNIX stdin), and file descriptor 1 refers to + * display output (UNIX stdout). File descriptor 0 can be read, and file + * descriptor 1 can be written, without previous calls to open(). + */ +#define fdStandardInput 0 +#define fdStandardOutput 1 + +/* The system call interface. These are the operations the Nachos kernel needs + * to support, to be able to run user programs. + * + * Each of these is invoked by a user program by simply calling the procedure; + * an assembly language stub stores the syscall code (see above) into $r0 and + * executes a syscall instruction. The kernel exception handler is then + * invoked. + */ + +/* Halt the Nachos machine by calling Machine.halt(). Only the root process + * (the first process, executed by UserKernel.run()) should be allowed to + * execute this syscall. Any other process should ignore the syscall and return + * immediately. + */ +void halt(); + +/* PROCESS MANAGEMENT SYSCALLS: exit(), exec(), join() */ + +/** + * Terminate the current process immediately. Any open file descriptors + * belonging to the process are closed. Any children of the process no longer + * have a parent process. + * + * status is returned to the parent process as this process's exit status and + * can be collected using the join syscall. A process exiting normally should + * (but is not required to) set status to 0. + * + * exit() never returns. + */ +void exit(int status); + +/** + * Execute the program stored in the specified file, with the specified + * arguments, in a new child process. The child process has a new unique + * process ID, and starts with stdin opened as file descriptor 0, and stdout + * opened as file descriptor 1. + * + * file is a null-terminated string that specifies the name of the file + * containing the executable. Note that this string must include the ".coff" + * extension. + * + * argc specifies the number of arguments to pass to the child process. This + * number must be non-negative. + * + * argv is an array of pointers to null-terminated strings that represent the + * arguments to pass to the child process. argv[0] points to the first + * argument, and argv[argc-1] points to the last argument. + * + * exec() returns the child process's process ID, which can be passed to + * join(). On error, returns -1. + */ +int exec(char *file, int argc, char *argv[]); + +/** + * Suspend execution of the current process until the child process specified + * by the processID argument has exited. If the child has already exited by the + * time of the call, returns immediately. When the current process resumes, it + * disowns the child process, so that join() cannot be used on that process + * again. + * + * processID is the process ID of the child process, returned by exec(). + * + * status points to an integer where the exit status of the child process will + * be stored. This is the value the child passed to exit(). If the child exited + * because of an unhandled exception, the value stored is not defined. + * + * If the child exited normally, returns 1. If the child exited as a result of + * an unhandled exception, returns 0. If processID does not refer to a child + * process of the current process, returns -1. + */ +int join(int processID, int *status); + +/* FILE MANAGEMENT SYSCALLS: creat, open, read, write, close, unlink + * + * A file descriptor is a small, non-negative integer that refers to a file on + * disk or to a stream (such as console input, console output, and network + * connections). A file descriptor can be passed to read() and write() to + * read/write the corresponding file/stream. A file descriptor can also be + * passed to close() to release the file descriptor and any associated + * resources. + */ + +/** + * Attempt to open the named disk file, creating it if it does not exist, + * and return a file descriptor that can be used to access the file. + * + * Note that creat() can only be used to create files on disk; creat() will + * never return a file descriptor referring to a stream. + * + * Returns the new file descriptor, or -1 if an error occurred. + */ +int creat(char *name); + +/** + * Attempt to open the named file and return a file descriptor. + * + * Note that open() can only be used to open files on disk; open() will never + * return a file descriptor referring to a stream. + * + * Returns the new file descriptor, or -1 if an error occurred. + */ +int open(char *name); + +/** + * Attempt to read up to count bytes into buffer from the file or stream + * referred to by fileDescriptor. + * + * On success, the number of bytes read is returned. If the file descriptor + * refers to a file on disk, the file position is advanced by this number. + * + * It is not necessarily an error if this number is smaller than the number of + * bytes requested. If the file descriptor refers to a file on disk, this + * indicates that the end of the file has been reached. If the file descriptor + * refers to a stream, this indicates that the fewer bytes are actually + * available right now than were requested, but more bytes may become available + * in the future. Note that read() never waits for a stream to have more data; + * it always returns as much as possible immediately. + * + * On error, -1 is returned, and the new file position is undefined. This can + * happen if fileDescriptor is invalid, if part of the buffer is read-only or + * invalid, or if a network stream has been terminated by the remote host and + * no more data is available. + */ +int read(int fileDescriptor, void *buffer, int count); + +/** + * Attempt to write up to count bytes from buffer to the file or stream + * referred to by fileDescriptor. write() can return before the bytes are + * actually flushed to the file or stream. A write to a stream can block, + * however, if kernel queues are temporarily full. + * + * On success, the number of bytes written is returned (zero indicates nothing + * was written), and the file position is advanced by this number. It IS an + * error if this number is smaller than the number of bytes requested. For + * disk files, this indicates that the disk is full. For streams, this + * indicates the stream was terminated by the remote host before all the data + * was transferred. + * + * On error, -1 is returned, and the new file position is undefined. This can + * happen if fileDescriptor is invalid, if part of the buffer is invalid, or + * if a network stream has already been terminated by the remote host. + */ +int write(int fileDescriptor, void *buffer, int count); + +/** + * Close a file descriptor, so that it no longer refers to any file or stream + * and may be reused. + * + * If the file descriptor refers to a file, all data written to it by write() + * will be flushed to disk before close() returns. + * If the file descriptor refers to a stream, all data written to it by write() + * will eventually be flushed (unless the stream is terminated remotely), but + * not necessarily before close() returns. + * + * The resources associated with the file descriptor are released. If the + * descriptor is the last reference to a disk file which has been removed using + * unlink, the file is deleted (this detail is handled by the file system + * implementation). + * + * Returns 0 on success, or -1 if an error occurred. + */ +int close(int fileDescriptor); + +/** + * Delete a file from the file system. If no processes have the file open, the + * file is deleted immediately and the space it was using is made available for + * reuse. + * + * If any processes still have the file open, the file will remain in existence + * until the last file descriptor referring to it is closed. However, creat() + * and open() will not be able to return new file descriptors for the file + * until it is deleted. + * + * Returns 0 on success, or -1 if an error occurred. + */ +int unlink(char *name); + +/** + * Map the file referenced by fileDescriptor into memory at address. The file + * may be as large as 0x7FFFFFFF bytes. + * + * To maintain consistency, further calls to read() and write() on this file + * descriptor will fail (returning -1) until the file descriptor is closed. + * + * When the file descriptor is closed, all remaining dirty pages of the map + * will be flushed to disk and the map will be removed. + * + * Returns the length of the file on success, or -1 if an error occurred. + */ +int mmap(int fileDescriptor, char *address); + +/** + * Attempt to initiate a new connection to the specified port on the specified + * remote host, and return a new file descriptor referring to the connection. + * connect() does not give up if the remote host does not respond immediately. + * + * Returns the new file descriptor, or -1 if an error occurred. + */ +int connect(int host, int port); + +/** + * Attempt to accept a single connection on the specified local port and return + * a file descriptor referring to the connection. + * + * If any connection requests are pending on the port, one request is dequeued + * and an acknowledgement is sent to the remote host (so that its connect() + * call can return). Since the remote host will never cancel a connection + * request, there is no need for accept() to wait for the remote host to + * confirm the connection (i.e. a 2-way handshake is sufficient; TCP's 3-way + * handshake is unnecessary). + * + * If no connection requests are pending, returns -1 immediately. + * + * In either case, accept() returns without waiting for a remote host. + * + * Returns a new file descriptor referring to the connection, or -1 if an error + * occurred. + */ +int accept(int port); + +#endif /* START_S */ + +#endif /* SYSCALL_H */ diff --git a/test/va-mips.h b/test/va-mips.h new file mode 100644 index 0000000..9a4b6ef --- /dev/null +++ b/test/va-mips.h @@ -0,0 +1,276 @@ +/* ---------------------------------------- */ +/* VARARGS for MIPS/GNU CC */ +/* */ +/* */ +/* */ +/* */ +/* ---------------------------------------- */ + + +/* These macros implement varargs for GNU C--either traditional or ANSI. */ + +/* Define __gnuc_va_list. */ + +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST +#if defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float) + +typedef struct { + /* Pointer to FP regs. */ + char *__fp_regs; + /* Number of FP regs remaining. */ + int __fp_left; + /* Pointer to GP regs followed by stack parameters. */ + char *__gp_regs; +} __gnuc_va_list; + +#else /* ! (defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)) */ + +typedef char * __gnuc_va_list; + +#endif /* ! (defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)) */ +#endif /* not __GNUC_VA_LIST */ + +/* If this is for internal libc use, don't define anything but + __gnuc_va_list. */ +#if defined (_STDARG_H) || defined (_VARARGS_H) + +#ifndef _VA_MIPS_H_ENUM +#define _VA_MIPS_H_ENUM +enum { + __no_type_class = -1, + __void_type_class, + __integer_type_class, + __char_type_class, + __enumeral_type_class, + __boolean_type_class, + __pointer_type_class, + __reference_type_class, + __offset_type_class, + __real_type_class, + __complex_type_class, + __function_type_class, + __method_type_class, + __record_type_class, + __union_type_class, + __array_type_class, + __string_type_class, + __set_type_class, + __file_type_class, + __lang_type_class +}; +#endif + +/* In GCC version 2, we want an ellipsis at the end of the declaration + of the argument list. GCC version 1 can't parse it. */ + +#if __GNUC__ > 1 +#define __va_ellipsis ... +#else +#define __va_ellipsis +#endif + +#ifdef __mips64 +#define __va_rounded_size(__TYPE) \ + (((sizeof (__TYPE) + 8 - 1) / 8) * 8) +#else +#define __va_rounded_size(__TYPE) \ + (((sizeof (__TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) +#endif + +#ifdef __mips64 +#define __va_reg_size 8 +#else +#define __va_reg_size 4 +#endif + +/* Get definitions for _MIPS_SIM_ABI64 etc. */ +#ifdef _MIPS_SIM +//#include +#endif + +#ifdef _STDARG_H +#if defined (__mips_eabi) +#if ! defined (__mips_soft_float) && ! defined (__mips_single_float) +#ifdef __mips64 +#define va_start(__AP, __LASTARG) \ + (__AP.__gp_regs = ((char *) __builtin_next_arg (__LASTARG) \ + - (__builtin_args_info (2) < 8 \ + ? (8 - __builtin_args_info (2)) * __va_reg_size \ + : 0)), \ + __AP.__fp_left = 8 - __builtin_args_info (3), \ + __AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * __va_reg_size) +#else /* ! defined (__mips64) */ +#define va_start(__AP, __LASTARG) \ + (__AP.__gp_regs = ((char *) __builtin_next_arg (__LASTARG) \ + - (__builtin_args_info (2) < 8 \ + ? (8 - __builtin_args_info (2)) * __va_reg_size \ + : 0)), \ + __AP.__fp_left = (8 - __builtin_args_info (3)) / 2, \ + __AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * 8, \ + __AP.__fp_regs = (char *) ((int) __AP.__fp_regs & -8)) +#endif /* ! defined (__mips64) */ +#else /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float) ) */ +#define va_start(__AP, __LASTARG) \ + (__AP = ((__gnuc_va_list) __builtin_next_arg (__LASTARG) \ + - (__builtin_args_info (2) >= 8 ? 0 \ + : (8 - __builtin_args_info (2)) * __va_reg_size))) +#endif /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float) ) */ +#else /* ! defined (__mips_eabi) */ +#define va_start(__AP, __LASTARG) \ + (__AP = (__gnuc_va_list) __builtin_next_arg (__LASTARG)) +#endif /* ! (defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)) */ +#else /* ! _STDARG_H */ +#define va_alist __builtin_va_alist +#ifdef __mips64 +/* This assumes that `long long int' is always a 64 bit type. */ +#define va_dcl long long int __builtin_va_alist; __va_ellipsis +#else +#define va_dcl int __builtin_va_alist; __va_ellipsis +#endif +#if defined (__mips_eabi) +#if ! defined (__mips_soft_float) && ! defined (__mips_single_float) +#ifdef __mips64 +#define va_start(__AP) \ + (__AP.__gp_regs = ((char *) __builtin_next_arg () \ + - (__builtin_args_info (2) < 8 \ + ? (8 - __builtin_args_info (2)) * __va_reg_size \ + : __va_reg_size)), \ + __AP.__fp_left = 8 - __builtin_args_info (3), \ + __AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * __va_reg_size) +#else /* ! defined (__mips64) */ +#define va_start(__AP) \ + (__AP.__gp_regs = ((char *) __builtin_next_arg () \ + - (__builtin_args_info (2) < 8 \ + ? (8 - __builtin_args_info (2)) * __va_reg_size \ + : __va_reg_size)), \ + __AP.__fp_left = (8 - __builtin_args_info (3)) / 2, \ + __AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * 8, \ + __AP.__fp_regs = (char *) ((int) __AP.__fp_regs & -8)) +#endif /* ! defined (__mips64) */ +#else /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */ +#define va_start(__AP) \ + (__AP = ((__gnuc_va_list) __builtin_next_arg () \ + - (__builtin_args_info (2) >= 8 ? __va_reg_size \ + : (8 - __builtin_args_info (2)) * __va_reg_size))) +#endif /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */ +/* Need alternate code for _MIPS_SIM_ABI64. */ +#elif defined(_MIPS_SIM) && (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32) +#define va_start(__AP) \ + (__AP = (__gnuc_va_list) __builtin_next_arg () \ + + (__builtin_args_info (2) >= 8 ? -8 : 0)) +#else +#define va_start(__AP) __AP = (char *) &__builtin_va_alist +#endif +#endif /* ! _STDARG_H */ + +#ifndef va_end +void va_end (__gnuc_va_list); /* Defined in libgcc.a */ +#endif +#define va_end(__AP) ((void)0) + +#if defined (__mips_eabi) + +#if ! defined (__mips_soft_float) && ! defined (__mips_single_float) +#ifdef __mips64 +#define __va_next_addr(__AP, __type) \ + ((__builtin_classify_type (*(__type *) 0) == __real_type_class \ + && __AP.__fp_left > 0) \ + ? (--__AP.__fp_left, (__AP.__fp_regs += 8) - 8) \ + : (__AP.__gp_regs += __va_reg_size) - __va_reg_size) +#else +#define __va_next_addr(__AP, __type) \ + ((__builtin_classify_type (*(__type *) 0) == __real_type_class \ + && __AP.__fp_left > 0) \ + ? (--__AP.__fp_left, (__AP.__fp_regs += 8) - 8) \ + : (((__builtin_classify_type (* (__type *) 0) < __record_type_class \ + && __alignof__ (__type) > 4) \ + ? __AP.__gp_regs = (char *) (((int) __AP.__gp_regs + 8 - 1) & -8) \ + : (char *) 0), \ + (__builtin_classify_type (* (__type *) 0) >= __record_type_class \ + ? (__AP.__gp_regs += __va_reg_size) - __va_reg_size \ + : ((__AP.__gp_regs += __va_rounded_size (__type)) \ + - __va_rounded_size (__type))))) +#endif +#else /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */ +#ifdef __mips64 +#define __va_next_addr(__AP, __type) \ + ((__AP += __va_reg_size) - __va_reg_size) +#else +#define __va_next_addr(__AP, __type) \ + (((__builtin_classify_type (* (__type *) 0) < __record_type_class \ + && __alignof__ (__type) > 4) \ + ? __AP = (char *) (((int) __AP + 8 - 1) & -8) \ + : (char *) 0), \ + (__builtin_classify_type (* (__type *) 0) >= __record_type_class \ + ? (__AP += __va_reg_size) - __va_reg_size \ + : ((__AP += __va_rounded_size (__type)) \ + - __va_rounded_size (__type)))) +#endif +#endif /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */ + +#ifdef __MIPSEB__ +#define va_arg(__AP, __type) \ + ((__va_rounded_size (__type) <= __va_reg_size) \ + ? *(__type *) (void *) (__va_next_addr (__AP, __type) \ + + __va_reg_size \ + - sizeof (__type)) \ + : (__builtin_classify_type (*(__type *) 0) >= __record_type_class \ + ? **(__type **) (void *) (__va_next_addr (__AP, __type) \ + + __va_reg_size \ + - sizeof (char *)) \ + : *(__type *) (void *) __va_next_addr (__AP, __type))) +#else +#define va_arg(__AP, __type) \ + ((__va_rounded_size (__type) <= __va_reg_size) \ + ? *(__type *) (void *) __va_next_addr (__AP, __type) \ + : (__builtin_classify_type (* (__type *) 0) >= __record_type_class \ + ? **(__type **) (void *) __va_next_addr (__AP, __type) \ + : *(__type *) (void *) __va_next_addr (__AP, __type))) +#endif + +#else /* ! defined (__mips_eabi) */ + +/* We cast to void * and then to TYPE * because this avoids + a warning about increasing the alignment requirement. */ +/* The __mips64 cases are reversed from the 32 bit cases, because the standard + 32 bit calling convention left-aligns all parameters smaller than a word, + whereas the __mips64 calling convention does not (and hence they are + right aligned). */ +#ifdef __mips64 +#ifdef __MIPSEB__ +#define va_arg(__AP, __type) \ + ((__type *) (void *) (__AP = (char *) ((((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8) \ + + __va_rounded_size (__type))))[-1] +#else +#define va_arg(__AP, __type) \ + ((__AP = (char *) ((((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8) \ + + __va_rounded_size (__type))), \ + *(__type *) (void *) (__AP - __va_rounded_size (__type))) +#endif + +#else /* not __mips64 */ + +#ifdef __MIPSEB__ +/* For big-endian machines. */ +#define va_arg(__AP, __type) \ + ((__AP = (char *) ((__alignof__ (__type) > 4 \ + ? ((int)__AP + 8 - 1) & -8 \ + : ((int)__AP + 4 - 1) & -4) \ + + __va_rounded_size (__type))), \ + *(__type *) (void *) (__AP - __va_rounded_size (__type))) +#else +/* For little-endian machines. */ +#define va_arg(__AP, __type) \ + ((__type *) (void *) (__AP = (char *) ((__alignof__(__type) > 4 \ + ? ((int)__AP + 8 - 1) & -8 \ + : ((int)__AP + 4 - 1) & -4) \ + + __va_rounded_size(__type))))[-1] +#endif +#endif +#endif /* ! defined (__mips_eabi) */ + +/* Copy __gnuc_va_list into another variable of this type. */ +#define __va_copy(dest, src) (dest) = (src) + +#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */ diff --git a/threads/Alarm.java b/threads/Alarm.java new file mode 100644 index 0000000..07b11b0 --- /dev/null +++ b/threads/Alarm.java @@ -0,0 +1,53 @@ +package nachos.threads; + +import nachos.machine.*; + +/** + * Uses the hardware timer to provide preemption, and to allow threads to sleep + * until a certain time. + */ +public class Alarm { + /** + * Allocate a new Alarm. Set the machine's timer interrupt handler to this + * alarm's callback. + * + *

Note: Nachos will not function correctly with more than one + * alarm. + */ + public Alarm() { + Machine.timer().setInterruptHandler(new Runnable() { + public void run() { timerInterrupt(); } + }); + } + + /** + * The timer interrupt handler. This is called by the machine's timer + * periodically (approximately every 500 clock ticks). Causes the current + * thread to yield, forcing a context switch if there is another thread + * that should be run. + */ + public void timerInterrupt() { + KThread.currentThread().yield(); + } + + /** + * Put the current thread to sleep for at least x ticks, + * waking it up in the timer interrupt handler. The thread must be + * woken up (placed in the scheduler ready set) during the first timer + * interrupt where + * + *

+ * (current time) >= (WaitUntil called time)+(x) + *
+ * + * @param x the minimum number of clock ticks to wait. + * + * @see nachos.machine.Timer#getTime() + */ + public void waitUntil(long x) { + // for now, cheat just to get something working (busy waiting is bad) + long wakeTime = Machine.timer().getTime() + x; + while (wakeTime > Machine.timer().getTime()) + KThread.yield(); + } +} diff --git a/threads/Boat.java b/threads/Boat.java new file mode 100644 index 0000000..cdf7d69 --- /dev/null +++ b/threads/Boat.java @@ -0,0 +1,76 @@ +package nachos.threads; +import nachos.ag.BoatGrader; + +public class Boat +{ + static BoatGrader bg; + + public static void selfTest() + { + BoatGrader b = new BoatGrader(); + + System.out.println("\n ***Testing Boats with only 2 children***"); + begin(0, 2, b); + +// System.out.println("\n ***Testing Boats with 2 children, 1 adult***"); +// begin(1, 2, b); + +// System.out.println("\n ***Testing Boats with 3 children, 3 adults***"); +// begin(3, 3, b); + } + + public static void begin( int adults, int children, BoatGrader b ) + { + // Store the externally generated autograder in a class + // variable to be accessible by children. + bg = b; + + // Instantiate global variables here + + // Create threads here. See section 3.4 of the Nachos for Java + // Walkthrough linked from the projects page. + + Runnable r = new Runnable() { + public void run() { + SampleItinerary(); + } + }; + KThread t = new KThread(r); + t.setName("Sample Boat Thread"); + t.fork(); + + } + + static void AdultItinerary() + { + bg.initializeAdult(); //Required for autograder interface. Must be the first thing called. + //DO NOT PUT ANYTHING ABOVE THIS LINE. + + /* This is where you should put your solutions. Make calls + to the BoatGrader to show that it is synchronized. For + example: + bg.AdultRowToMolokai(); + indicates that an adult has rowed the boat across to Molokai + */ + } + + static void ChildItinerary() + { + bg.initializeChild(); //Required for autograder interface. Must be the first thing called. + //DO NOT PUT ANYTHING ABOVE THIS LINE. + } + + static void SampleItinerary() + { + // Please note that this isn't a valid solution (you can't fit + // all of them on the boat). Please also note that you may not + // have a single thread calculate a solution and then just play + // it back at the autograder -- you will be caught. + System.out.println("\n ***Everyone piles on the boat and goes to Molokai***"); + bg.AdultRowToMolokai(); + bg.ChildRideToMolokai(); + bg.AdultRideToMolokai(); + bg.ChildRideToMolokai(); + } + +} diff --git a/threads/Communicator.java b/threads/Communicator.java new file mode 100644 index 0000000..47c0a6b --- /dev/null +++ b/threads/Communicator.java @@ -0,0 +1,41 @@ +package nachos.threads; + +import nachos.machine.*; + +/** + * A communicator allows threads to synchronously exchange 32-bit + * messages. Multiple threads can be waiting to speak, + * and multiple threads can be waiting to listen. But there should never + * be a time when both a speaker and a listener are waiting, because the two + * threads can be paired off at this point. + */ +public class Communicator { + /** + * Allocate a new communicator. + */ + public Communicator() { + } + + /** + * Wait for a thread to listen through this communicator, and then transfer + * word to the listener. + * + *

+ * Does not return until this thread is paired up with a listening thread. + * Exactly one listener should receive word. + * + * @param word the integer to transfer. + */ + public void speak(int word) { + } + + /** + * Wait for a thread to speak through this communicator, and then return + * the word that thread passed to speak(). + * + * @return the integer transferred. + */ + public int listen() { + return 0; + } +} diff --git a/threads/Condition.java b/threads/Condition.java new file mode 100644 index 0000000..40ccfc4 --- /dev/null +++ b/threads/Condition.java @@ -0,0 +1,114 @@ +package nachos.threads; + +import nachos.machine.*; + +import java.util.LinkedList; + +/** + * An implementation of condition variables built upon semaphores. + * + *

+ * A condition variable is a synchronization primitive that does not have + * a value (unlike a semaphore or a lock), but threads may still be queued. + * + *

    + * + *
  • sleep(): atomically release the lock and relinkquish the CPU + * until woken; then reacquire the lock. + * + *
  • wake(): wake up a single thread sleeping in this condition + * variable, if possible. + * + *
  • wakeAll(): wake up all threads sleeping inn this condition + * variable. + * + *
+ * + *

+ * Every condition variable is associated with some lock. Multiple condition + * variables may be associated with the same lock. All three condition variable + * operations can only be used while holding the associated lock. + * + *

+ * In Nachos, condition variables are summed to obey Mesa-style + * semantics. When a wake() or wakeAll() wakes up another + * thread, the woken thread is simply put on the ready list, and it is the + * responsibility of the woken thread to reacquire the lock (this reacquire is + * taken core of in sleep()). + * + *

+ * By contrast, some implementations of condition variables obey + * Hoare-style semantics, where the thread that calls wake() + * gives up the lock and the CPU to the woken thread, which runs immediately + * and gives the lock and CPU back to the waker when the woken thread exits the + * critical section. + * + *

+ * The consequence of using Mesa-style semantics is that some other thread + * can acquire the lock and change data structures, before the woken thread + * gets a chance to run. The advance to Mesa-style semantics is that it is a + * lot easier to implement. + */ +public class Condition { + /** + * Allocate a new condition variable. + * + * @param conditionLock the lock associated with this condition + * variable. The current thread must hold this + * lock whenever it uses sleep(), + * wake(), or wakeAll(). + */ + public Condition(Lock conditionLock) { + this.conditionLock = conditionLock; + + waitQueue = new LinkedList(); + } + + /** + * Atomically release the associated lock and go to sleep on this condition + * variable until another thread wakes it using wake(). The + * current thread must hold the associated lock. The thread will + * automatically reacquire the lock before sleep() returns. + * + *

+ * This implementation uses semaphores to implement this, by allocating a + * semaphore for each waiting thread. The waker will V() this + * semaphore, so thre is no chance the sleeper will miss the wake-up, even + * though the lock is released before caling P(). + */ + public void sleep() { + Lib.assertTrue(conditionLock.isHeldByCurrentThread()); + + Semaphore waiter = new Semaphore(0); + waitQueue.add(waiter); + + conditionLock.release(); + waiter.P(); + conditionLock.acquire(); + } + + /** + * Wake up at most one thread sleeping on this condition variable. The + * current thread must hold the associated lock. + */ + public void wake() { + Lib.assertTrue(conditionLock.isHeldByCurrentThread()); + + if (!waitQueue.isEmpty()) + ((Semaphore) waitQueue.removeFirst()).V(); + } + + /** + * Wake up all threads sleeping on this condition variable. The current + * thread must hold the associated lock. + */ + public void wakeAll() { + Lib.assertTrue(conditionLock.isHeldByCurrentThread()); + + while (!waitQueue.isEmpty()) + wake(); + } + + private Lock conditionLock; + private LinkedList waitQueue; +} diff --git a/threads/Condition2.java b/threads/Condition2.java new file mode 100644 index 0000000..a17d98b --- /dev/null +++ b/threads/Condition2.java @@ -0,0 +1,58 @@ +package nachos.threads; + +import nachos.machine.*; + +/** + * An implementation of condition variables that disables interrupt()s for + * synchronization. + * + *

+ * You must implement this. + * + * @see nachos.threads.Condition + */ +public class Condition2 { + /** + * Allocate a new condition variable. + * + * @param conditionLock the lock associated with this condition + * variable. The current thread must hold this + * lock whenever it uses sleep(), + * wake(), or wakeAll(). + */ + public Condition2(Lock conditionLock) { + this.conditionLock = conditionLock; + } + + /** + * Atomically release the associated lock and go to sleep on this condition + * variable until another thread wakes it using wake(). The + * current thread must hold the associated lock. The thread will + * automatically reacquire the lock before sleep() returns. + */ + public void sleep() { + Lib.assertTrue(conditionLock.isHeldByCurrentThread()); + + conditionLock.release(); + + conditionLock.acquire(); + } + + /** + * Wake up at most one thread sleeping on this condition variable. The + * current thread must hold the associated lock. + */ + public void wake() { + Lib.assertTrue(conditionLock.isHeldByCurrentThread()); + } + + /** + * Wake up all threads sleeping on this condition variable. The current + * thread must hold the associated lock. + */ + public void wakeAll() { + Lib.assertTrue(conditionLock.isHeldByCurrentThread()); + } + + private Lock conditionLock; +} diff --git a/threads/ElevatorController.java b/threads/ElevatorController.java new file mode 100644 index 0000000..6758d11 --- /dev/null +++ b/threads/ElevatorController.java @@ -0,0 +1,38 @@ +package nachos.threads; + +import nachos.machine.*; + +/** + * A controller for all the elevators in an elevator bank. The controller + * accesses the elevator bank through an instance of ElevatorControls. + */ +public class ElevatorController implements ElevatorControllerInterface { + /** + * Allocate a new elevator controller. + */ + public ElevatorController() { + } + + /** + * Initialize this elevator controller. The controller will access the + * elevator bank through controls. This constructor should return + * immediately after this controller is initialized, but not until the + * interupt handler is set. The controller will start receiving events + * after this method returns, but potentially before run() is + * called. + * + * @param controls the controller's interface to the elevator + * bank. The controler must not attempt to access + * the elevator bank in any other way. + */ + public void initialize(ElevatorControls controls) { + } + + /** + * Cause the controller to use the provided controls to receive and process + * requests from riders. This method should not return, but instead should + * call controls.finish() when the controller is finished. + */ + public void run() { + } +} diff --git a/threads/KThread.java b/threads/KThread.java new file mode 100644 index 0000000..7bb06c8 --- /dev/null +++ b/threads/KThread.java @@ -0,0 +1,447 @@ +package nachos.threads; + +import nachos.machine.*; + +/** + * A KThread is a thread that can be used to execute Nachos kernel code. Nachos + * allows multiple threads to run concurrently. + * + * To create a new thread of execution, first declare a class that implements + * the Runnable interface. That class then implements the run + * method. An instance of the class can then be allocated, passed as an + * argument when creating KThread, and forked. For example, a thread + * that computes pi could be written as follows: + * + *

+ * class PiRun implements Runnable {
+ *     public void run() {
+ *         // compute pi
+ *         ...
+ *     }
+ * }
+ * 
+ *

The following code would then create a thread and start it running: + * + *

+ * PiRun p = new PiRun();
+ * new KThread(p).fork();
+ * 
+ */ +public class KThread { + /** + * Get the current thread. + * + * @return the current thread. + */ + public static KThread currentThread() { + Lib.assertTrue(currentThread != null); + return currentThread; + } + + /** + * Allocate a new KThread. If this is the first KThread, + * create an idle thread as well. + */ + public KThread() { + if (currentThread != null) { + tcb = new TCB(); + } + else { + readyQueue = ThreadedKernel.scheduler.newThreadQueue(false); + readyQueue.acquire(this); + + currentThread = this; + tcb = TCB.currentTCB(); + name = "main"; + restoreState(); + + createIdleThread(); + } + } + + /** + * Allocate a new KThread. + * + * @param target the object whose run method is called. + */ + public KThread(Runnable target) { + this(); + this.target = target; + } + + /** + * Set the target of this thread. + * + * @param target the object whose run method is called. + * @return this thread. + */ + public KThread setTarget(Runnable target) { + Lib.assertTrue(status == statusNew); + + this.target = target; + return this; + } + + /** + * Set the name of this thread. This name is used for debugging purposes + * only. + * + * @param name the name to give to this thread. + * @return this thread. + */ + public KThread setName(String name) { + this.name = name; + return this; + } + + /** + * Get the name of this thread. This name is used for debugging purposes + * only. + * + * @return the name given to this thread. + */ + public String getName() { + return name; + } + + /** + * Get the full name of this thread. This includes its name along with its + * numerical ID. This name is used for debugging purposes only. + * + * @return the full name given to this thread. + */ + public String toString() { + return (name + " (#" + id + ")"); + } + + /** + * Deterministically and consistently compare this thread to another + * thread. + */ + public int compareTo(Object o) { + KThread thread = (KThread) o; + + if (id < thread.id) + return -1; + else if (id > thread.id) + return 1; + else + return 0; + } + + /** + * Causes this thread to begin execution. The result is that two threads + * are running concurrently: the current thread (which returns from the + * call to the fork method) and the other thread (which executes + * its target's run method). + */ + public void fork() { + Lib.assertTrue(status == statusNew); + Lib.assertTrue(target != null); + + Lib.debug(dbgThread, + "Forking thread: " + toString() + " Runnable: " + target); + + boolean intStatus = Machine.interrupt().disable(); + + tcb.start(new Runnable() { + public void run() { + runThread(); + } + }); + + ready(); + + Machine.interrupt().restore(intStatus); + } + + private void runThread() { + begin(); + target.run(); + finish(); + } + + private void begin() { + Lib.debug(dbgThread, "Beginning thread: " + toString()); + + Lib.assertTrue(this == currentThread); + + restoreState(); + + Machine.interrupt().enable(); + } + + /** + * Finish the current thread and schedule it to be destroyed when it is + * safe to do so. This method is automatically called when a thread's + * run method returns, but it may also be called directly. + * + * The current thread cannot be immediately destroyed because its stack and + * other execution state are still in use. Instead, this thread will be + * destroyed automatically by the next thread to run, when it is safe to + * delete this thread. + */ + public static void finish() { + Lib.debug(dbgThread, "Finishing thread: " + currentThread.toString()); + + Machine.interrupt().disable(); + + Machine.autoGrader().finishingCurrentThread(); + + Lib.assertTrue(toBeDestroyed == null); + toBeDestroyed = currentThread; + + + currentThread.status = statusFinished; + + sleep(); + } + + /** + * Relinquish the CPU if any other thread is ready to run. If so, put the + * current thread on the ready queue, so that it will eventually be + * rescheuled. + * + *

+ * Returns immediately if no other thread is ready to run. Otherwise + * returns when the current thread is chosen to run again by + * readyQueue.nextThread(). + * + *

+ * Interrupts are disabled, so that the current thread can atomically add + * itself to the ready queue and switch to the next thread. On return, + * restores interrupts to the previous state, in case yield() was + * called with interrupts disabled. + */ + public static void yield() { + Lib.debug(dbgThread, "Yielding thread: " + currentThread.toString()); + + Lib.assertTrue(currentThread.status == statusRunning); + + boolean intStatus = Machine.interrupt().disable(); + + currentThread.ready(); + + runNextThread(); + + Machine.interrupt().restore(intStatus); + } + + /** + * Relinquish the CPU, because the current thread has either finished or it + * is blocked. This thread must be the current thread. + * + *

+ * If the current thread is blocked (on a synchronization primitive, i.e. + * a Semaphore, Lock, or Condition), eventually + * some thread will wake this thread up, putting it back on the ready queue + * so that it can be rescheduled. Otherwise, finish() should have + * scheduled this thread to be destroyed by the next thread to run. + */ + public static void sleep() { + Lib.debug(dbgThread, "Sleeping thread: " + currentThread.toString()); + + Lib.assertTrue(Machine.interrupt().disabled()); + + if (currentThread.status != statusFinished) + currentThread.status = statusBlocked; + + runNextThread(); + } + + /** + * Moves this thread to the ready state and adds this to the scheduler's + * ready queue. + */ + public void ready() { + Lib.debug(dbgThread, "Ready thread: " + toString()); + + Lib.assertTrue(Machine.interrupt().disabled()); + Lib.assertTrue(status != statusReady); + + status = statusReady; + if (this != idleThread) + readyQueue.waitForAccess(this); + + Machine.autoGrader().readyThread(this); + } + + /** + * Waits for this thread to finish. If this thread is already finished, + * return immediately. This method must only be called once; the second + * call is not guaranteed to return. This thread must not be the current + * thread. + */ + public void join() { + Lib.debug(dbgThread, "Joining to thread: " + toString()); + + Lib.assertTrue(this != currentThread); + + } + + /** + * Create the idle thread. Whenever there are no threads ready to be run, + * and runNextThread() is called, it will run the idle thread. The + * idle thread must never block, and it will only be allowed to run when + * all other threads are blocked. + * + *

+ * Note that ready() never adds the idle thread to the ready set. + */ + private static void createIdleThread() { + Lib.assertTrue(idleThread == null); + + idleThread = new KThread(new Runnable() { + public void run() { while (true) yield(); } + }); + idleThread.setName("idle"); + + Machine.autoGrader().setIdleThread(idleThread); + + idleThread.fork(); + } + + /** + * Determine the next thread to run, then dispatch the CPU to the thread + * using run(). + */ + private static void runNextThread() { + KThread nextThread = readyQueue.nextThread(); + if (nextThread == null) + nextThread = idleThread; + + nextThread.run(); + } + + /** + * Dispatch the CPU to this thread. Save the state of the current thread, + * switch to the new thread by calling TCB.contextSwitch(), and + * load the state of the new thread. The new thread becomes the current + * thread. + * + *

+ * If the new thread and the old thread are the same, this method must + * still call saveState(), contextSwitch(), and + * restoreState(). + * + *

+ * The state of the previously running thread must already have been + * changed from running to blocked or ready (depending on whether the + * thread is sleeping or yielding). + * + * @param finishing true if the current thread is + * finished, and should be destroyed by the new + * thread. + */ + private void run() { + Lib.assertTrue(Machine.interrupt().disabled()); + + Machine.yield(); + + currentThread.saveState(); + + Lib.debug(dbgThread, "Switching from: " + currentThread.toString() + + " to: " + toString()); + + currentThread = this; + + tcb.contextSwitch(); + + currentThread.restoreState(); + } + + /** + * Prepare this thread to be run. Set status to + * statusRunning and check toBeDestroyed. + */ + protected void restoreState() { + Lib.debug(dbgThread, "Running thread: " + currentThread.toString()); + + Lib.assertTrue(Machine.interrupt().disabled()); + Lib.assertTrue(this == currentThread); + Lib.assertTrue(tcb == TCB.currentTCB()); + + Machine.autoGrader().runningThread(this); + + status = statusRunning; + + if (toBeDestroyed != null) { + toBeDestroyed.tcb.destroy(); + toBeDestroyed.tcb = null; + toBeDestroyed = null; + } + } + + /** + * Prepare this thread to give up the processor. Kernel threads do not + * need to do anything here. + */ + protected void saveState() { + Lib.assertTrue(Machine.interrupt().disabled()); + Lib.assertTrue(this == currentThread); + } + + private static class PingTest implements Runnable { + PingTest(int which) { + this.which = which; + } + + public void run() { + for (int i=0; i<5; i++) { + System.out.println("*** thread " + which + " looped " + + i + " times"); + currentThread.yield(); + } + } + + private int which; + } + + /** + * Tests whether this module is working. + */ + public static void selfTest() { + Lib.debug(dbgThread, "Enter KThread.selfTest"); + + new KThread(new PingTest(1)).setName("forked thread").fork(); + new PingTest(0).run(); + } + + private static final char dbgThread = 't'; + + /** + * Additional state used by schedulers. + * + * @see nachos.threads.PriorityScheduler.ThreadState + */ + public Object schedulingState = null; + + private static final int statusNew = 0; + private static final int statusReady = 1; + private static final int statusRunning = 2; + private static final int statusBlocked = 3; + private static final int statusFinished = 4; + + /** + * The status of this thread. A thread can either be new (not yet forked), + * ready (on the ready queue but not running), running, or blocked (not + * on the ready queue and not running). + */ + private int status = statusNew; + private String name = "(unnamed thread)"; + private Runnable target; + private TCB tcb; + + /** + * Unique identifer for this thread. Used to deterministically compare + * threads. + */ + private int id = numCreated++; + /** Number of times the KThread constructor was called. */ + private static int numCreated = 0; + + private static ThreadQueue readyQueue = null; + private static KThread currentThread = null; + private static KThread toBeDestroyed = null; + private static KThread idleThread = null; +} diff --git a/threads/Lock.java b/threads/Lock.java new file mode 100644 index 0000000..8a4a51b --- /dev/null +++ b/threads/Lock.java @@ -0,0 +1,79 @@ +package nachos.threads; + +import nachos.machine.*; + +/** + * A Lock is a synchronization primitive that has two states, + * busy and free. There are only two operations allowed on a + * lock: + * + *

    + *
  • acquire(): atomically wait until the lock is free and + * then set it to busy. + *
  • release(): set the lock to be free, waking up one + * waiting thread if possible. + *
+ * + *

+ * Also, only the thread that acquired a lock may release it. As with + * semaphores, the API does not allow you to read the lock state (because the + * value could change immediately after you read it). + */ +public class Lock { + /** + * Allocate a new lock. The lock will initially be free. + */ + public Lock() { + } + + /** + * Atomically acquire this lock. The current thread must not already hold + * this lock. + */ + public void acquire() { + Lib.assertTrue(!isHeldByCurrentThread()); + + boolean intStatus = Machine.interrupt().disable(); + KThread thread = KThread.currentThread(); + + if (lockHolder != null) { + waitQueue.waitForAccess(thread); + KThread.sleep(); + } + else { + waitQueue.acquire(thread); + lockHolder = thread; + } + + Lib.assertTrue(lockHolder == thread); + + Machine.interrupt().restore(intStatus); + } + + /** + * Atomically release this lock, allowing other threads to acquire it. + */ + public void release() { + Lib.assertTrue(isHeldByCurrentThread()); + + boolean intStatus = Machine.interrupt().disable(); + + if ((lockHolder = waitQueue.nextThread()) != null) + lockHolder.ready(); + + Machine.interrupt().restore(intStatus); + } + + /** + * Test if the current thread holds this lock. + * + * @return true if the current thread holds this lock. + */ + public boolean isHeldByCurrentThread() { + return (lockHolder == KThread.currentThread()); + } + + private KThread lockHolder = null; + private ThreadQueue waitQueue = + ThreadedKernel.scheduler.newThreadQueue(true); +} diff --git a/threads/LotteryScheduler.java b/threads/LotteryScheduler.java new file mode 100644 index 0000000..a9a06da --- /dev/null +++ b/threads/LotteryScheduler.java @@ -0,0 +1,48 @@ +package nachos.threads; + +import nachos.machine.*; + +import java.util.TreeSet; +import java.util.HashSet; +import java.util.Iterator; + +/** + * A scheduler that chooses threads using a lottery. + * + *

+ * A lottery scheduler associates a number of tickets with each thread. When a + * thread needs to be dequeued, a random lottery is held, among all the tickets + * of all the threads waiting to be dequeued. The thread that holds the winning + * ticket is chosen. + * + *

+ * Note that a lottery scheduler must be able to handle a lot of tickets + * (sometimes billions), so it is not acceptable to maintain state for every + * ticket. + * + *

+ * A lottery scheduler must partially solve the priority inversion problem; in + * particular, tickets must be transferred through locks, and through joins. + * Unlike a priority scheduler, these tickets add (as opposed to just taking + * the maximum). + */ +public class LotteryScheduler extends PriorityScheduler { + /** + * Allocate a new lottery scheduler. + */ + public LotteryScheduler() { + } + + /** + * Allocate a new lottery thread queue. + * + * @param transferPriority true if this queue should + * transfer tickets from waiting threads + * to the owning thread. + * @return a new lottery thread queue. + */ + public ThreadQueue newThreadQueue(boolean transferPriority) { + // implement me + return null; + } +} diff --git a/threads/PriorityScheduler.java b/threads/PriorityScheduler.java new file mode 100644 index 0000000..aa6dc51 --- /dev/null +++ b/threads/PriorityScheduler.java @@ -0,0 +1,261 @@ +package nachos.threads; + +import nachos.machine.*; + +import java.util.TreeSet; +import java.util.HashSet; +import java.util.Iterator; + +/** + * A scheduler that chooses threads based on their priorities. + * + *

+ * A priority scheduler associates a priority with each thread. The next thread + * to be dequeued is always a thread with priority no less than any other + * waiting thread's priority. Like a round-robin scheduler, the thread that is + * dequeued is, among all the threads of the same (highest) priority, the + * thread that has been waiting longest. + * + *

+ * Essentially, a priority scheduler gives access in a round-robin fassion to + * all the highest-priority threads, and ignores all other threads. This has + * the potential to + * starve a thread if there's always a thread waiting with higher priority. + * + *

+ * A priority scheduler must partially solve the priority inversion problem; in + * particular, priority must be donated through locks, and through joins. + */ +public class PriorityScheduler extends Scheduler { + /** + * Allocate a new priority scheduler. + */ + public PriorityScheduler() { + } + + /** + * Allocate a new priority thread queue. + * + * @param transferPriority true if this queue should + * transfer priority from waiting threads + * to the owning thread. + * @return a new priority thread queue. + */ + public ThreadQueue newThreadQueue(boolean transferPriority) { + return new PriorityQueue(transferPriority); + } + + public int getPriority(KThread thread) { + Lib.assertTrue(Machine.interrupt().disabled()); + + return getThreadState(thread).getPriority(); + } + + public int getEffectivePriority(KThread thread) { + Lib.assertTrue(Machine.interrupt().disabled()); + + return getThreadState(thread).getEffectivePriority(); + } + + public void setPriority(KThread thread, int priority) { + Lib.assertTrue(Machine.interrupt().disabled()); + + Lib.assertTrue(priority >= priorityMinimum && + priority <= priorityMaximum); + + getThreadState(thread).setPriority(priority); + } + + public boolean increasePriority() { + boolean intStatus = Machine.interrupt().disable(); + + KThread thread = KThread.currentThread(); + + int priority = getPriority(thread); + if (priority == priorityMaximum) + return false; + + setPriority(thread, priority+1); + + Machine.interrupt().restore(intStatus); + return true; + } + + public boolean decreasePriority() { + boolean intStatus = Machine.interrupt().disable(); + + KThread thread = KThread.currentThread(); + + int priority = getPriority(thread); + if (priority == priorityMinimum) + return false; + + setPriority(thread, priority-1); + + Machine.interrupt().restore(intStatus); + return true; + } + + /** + * The default priority for a new thread. Do not change this value. + */ + public static final int priorityDefault = 1; + /** + * The minimum priority that a thread can have. Do not change this value. + */ + public static final int priorityMinimum = 0; + /** + * The maximum priority that a thread can have. Do not change this value. + */ + public static final int priorityMaximum = 7; + + /** + * Return the scheduling state of the specified thread. + * + * @param thread the thread whose scheduling state to return. + * @return the scheduling state of the specified thread. + */ + protected ThreadState getThreadState(KThread thread) { + if (thread.schedulingState == null) + thread.schedulingState = new ThreadState(thread); + + return (ThreadState) thread.schedulingState; + } + + /** + * A ThreadQueue that sorts threads by priority. + */ + protected class PriorityQueue extends ThreadQueue { + PriorityQueue(boolean transferPriority) { + this.transferPriority = transferPriority; + } + + public void waitForAccess(KThread thread) { + Lib.assertTrue(Machine.interrupt().disabled()); + getThreadState(thread).waitForAccess(this); + } + + public void acquire(KThread thread) { + Lib.assertTrue(Machine.interrupt().disabled()); + getThreadState(thread).acquire(this); + } + + public KThread nextThread() { + Lib.assertTrue(Machine.interrupt().disabled()); + // implement me + return null; + } + + /** + * Return the next thread that nextThread() would return, + * without modifying the state of this queue. + * + * @return the next thread that nextThread() would + * return. + */ + protected ThreadState pickNextThread() { + // implement me + return null; + } + + public void print() { + Lib.assertTrue(Machine.interrupt().disabled()); + // implement me (if you want) + } + + /** + * true if this queue should transfer priority from waiting + * threads to the owning thread. + */ + public boolean transferPriority; + } + + /** + * The scheduling state of a thread. This should include the thread's + * priority, its effective priority, any objects it owns, and the queue + * it's waiting for, if any. + * + * @see nachos.threads.KThread#schedulingState + */ + protected class ThreadState { + /** + * Allocate a new ThreadState object and associate it with the + * specified thread. + * + * @param thread the thread this state belongs to. + */ + public ThreadState(KThread thread) { + this.thread = thread; + + setPriority(priorityDefault); + } + + /** + * Return the priority of the associated thread. + * + * @return the priority of the associated thread. + */ + public int getPriority() { + return priority; + } + + /** + * Return the effective priority of the associated thread. + * + * @return the effective priority of the associated thread. + */ + public int getEffectivePriority() { + // implement me + return priority; + } + + /** + * Set the priority of the associated thread to the specified value. + * + * @param priority the new priority. + */ + public void setPriority(int priority) { + if (this.priority == priority) + return; + + this.priority = priority; + + // implement me + } + + /** + * Called when waitForAccess(thread) (where thread is + * the associated thread) is invoked on the specified priority queue. + * The associated thread is therefore waiting for access to the + * resource guarded by waitQueue. This method is only called + * if the associated thread cannot immediately obtain access. + * + * @param waitQueue the queue that the associated thread is + * now waiting on. + * + * @see nachos.threads.ThreadQueue#waitForAccess + */ + public void waitForAccess(PriorityQueue waitQueue) { + // implement me + } + + /** + * Called when the associated thread has acquired access to whatever is + * guarded by waitQueue. This can occur either as a result of + * acquire(thread) being invoked on waitQueue (where + * thread is the associated thread), or as a result of + * nextThread() being invoked on waitQueue. + * + * @see nachos.threads.ThreadQueue#acquire + * @see nachos.threads.ThreadQueue#nextThread + */ + public void acquire(PriorityQueue waitQueue) { + // implement me + } + + /** The thread with which this object is associated. */ + protected KThread thread; + /** The priority of the associated thread. */ + protected int priority; + } +} diff --git a/threads/Rider.java b/threads/Rider.java new file mode 100644 index 0000000..feb6b52 --- /dev/null +++ b/threads/Rider.java @@ -0,0 +1,52 @@ +package nachos.threads; + +import nachos.machine.*; + +/** + * A single rider. Each rider accesses the elevator bank through an + * instance of RiderControls. + */ +public class Rider implements RiderInterface { + /** + * Allocate a new rider. + */ + public Rider() { + } + + /** + * Initialize this rider. The rider will access the elevator bank through + * controls, and the rider will make stops at different floors as + * specified in stops. This method should return immediately after + * this rider is initialized, but not until the interrupt handler is + * set. The rider will start receiving events after this method returns, + * potentially before run() is called. + * + * @param controls the rider's interface to the elevator bank. The + * rider must not attempt to access the elevator + * bank in any other way. + * @param stops an array of stops the rider should make; see + * below. + */ + public void initialize(RiderControls controls, int[] stops) { + } + + /** + * Cause the rider to use the provided controls to make the stops specified + * in the constructor. The rider should stop at each of the floors in + * stops, an array of floor numbers. The rider should only + * make the specified stops. + * + *

+ * For example, suppose the rider uses controls to determine that + * it is initially on floor 1, and suppose the stops array contains two + * elements: { 0, 2 }. Then the rider should get on an elevator, get off + * on floor 0, get on an elevator, and get off on floor 2, pushing buttons + * as necessary. + * + *

+ * This method should not return, but instead should call + * controls.finish() when the rider is finished. + */ + public void run() { + } +} diff --git a/threads/RoundRobinScheduler.java b/threads/RoundRobinScheduler.java new file mode 100644 index 0000000..ade31a6 --- /dev/null +++ b/threads/RoundRobinScheduler.java @@ -0,0 +1,84 @@ +package nachos.threads; + +import nachos.machine.*; + +import java.util.LinkedList; +import java.util.Iterator; + +/** + * A round-robin scheduler tracks waiting threads in FIFO queues, implemented + * with linked lists. When a thread begins waiting for access, it is appended + * to the end of a list. The next thread to receive access is always the first + * thread in the list. This causes access to be given on a first-come + * first-serve basis. + */ +public class RoundRobinScheduler extends Scheduler { + /** + * Allocate a new round-robin scheduler. + */ + public RoundRobinScheduler() { + } + + /** + * Allocate a new FIFO thread queue. + * + * @param transferPriority ignored. Round robin schedulers have + * no priority. + * @return a new FIFO thread queue. + */ + public ThreadQueue newThreadQueue(boolean transferPriority) { + return new FifoQueue(); + } + + private class FifoQueue extends ThreadQueue { + /** + * Add a thread to the end of the wait queue. + * + * @param thread the thread to append to the queue. + */ + public void waitForAccess(KThread thread) { + Lib.assertTrue(Machine.interrupt().disabled()); + + waitQueue.add(thread); + } + + /** + * Remove a thread from the beginning of the queue. + * + * @return the first thread on the queue, or null if the + * queue is + * empty. + */ + public KThread nextThread() { + Lib.assertTrue(Machine.interrupt().disabled()); + + if (waitQueue.isEmpty()) + return null; + + return (KThread) waitQueue.removeFirst(); + } + + /** + * The specified thread has received exclusive access, without using + * waitForAccess() or nextThread(). Assert that no + * threads are waiting for access. + */ + public void acquire(KThread thread) { + Lib.assertTrue(Machine.interrupt().disabled()); + + Lib.assertTrue(waitQueue.isEmpty()); + } + + /** + * Print out the contents of the queue. + */ + public void print() { + Lib.assertTrue(Machine.interrupt().disabled()); + + for (Iterator i=waitQueue.iterator(); i.hasNext(); ) + System.out.print((KThread) i.next() + " "); + } + + private LinkedList waitQueue = new LinkedList(); + } +} diff --git a/threads/Scheduler.java b/threads/Scheduler.java new file mode 100644 index 0000000..6e86f99 --- /dev/null +++ b/threads/Scheduler.java @@ -0,0 +1,157 @@ +package nachos.threads; + +import nachos.machine.*; + +/** + * Coordinates a group of thread queues of the same kind. + * + * @see nachos.threads.ThreadQueue + */ +public abstract class Scheduler { + /** + * Allocate a new scheduler. + */ + public Scheduler() { + } + + /** + * Allocate a new thread queue. If transferPriority is + * true, then threads waiting on the new queue will transfer their + * "priority" to the thread that has access to whatever is being guarded by + * the queue. This is the mechanism used to partially solve priority + * inversion. + * + *

+ * If there is no definite thread that can be said to have "access" (as in + * the case of semaphores and condition variables), this parameter should + * be false, indicating that no priority should be transferred. + * + *

+ * The processor is a special case. There is clearly no purpose to donating + * priority to a thread that already has the processor. When the processor + * wait queue is created, this parameter should be false. + * + *

+ * Otherwise, it is beneficial to donate priority. For example, a lock has + * a definite owner (the thread that holds the lock), and a lock is always + * released by the same thread that acquired it, so it is possible to help + * a high priority thread waiting for a lock by donating its priority to + * the thread holding the lock. Therefore, a queue for a lock should be + * created with this parameter set to true. + * + *

+ * Similarly, when a thread is asleep in join() waiting for the + * target thread to finish, the sleeping thread should donate its priority + * to the target thread. Therefore, a join queue should be created with + * this parameter set to true. + * + * @param transferPriority true if the thread that has + * access should receive priority from the + * threads that are waiting on this queue. + * @return a new thread queue. + */ + public abstract ThreadQueue newThreadQueue(boolean transferPriority); + + /** + * Get the priority of the specified thread. Must be called with + * interrupts disabled. + * + * @param thread the thread to get the priority of. + * @return the thread's priority. + */ + public int getPriority(KThread thread) { + Lib.assertTrue(Machine.interrupt().disabled()); + return 0; + } + + /** + * Get the priority of the current thread. Equivalent to + * getPriority(KThread.currentThread()). + * + * @return the current thread's priority. + */ + public int getPriority() { + return getPriority(KThread.currentThread()); + } + + /** + * Get the effective priority of the specified thread. Must be called with + * interrupts disabled. + * + *

+ * The effective priority of a thread is the priority of a thread after + * taking into account priority donations. + * + *

+ * For a priority scheduler, this is the maximum of the thread's priority + * and the priorities of all other threads waiting for the thread through a + * lock or a join. + * + *

+ * For a lottery scheduler, this is the sum of the thread's tickets and the + * tickets of all other threads waiting for the thread through a lock or a + * join. + * + * @param thread the thread to get the effective priority of. + * @return the thread's effective priority. + */ + public int getEffectivePriority(KThread thread) { + Lib.assertTrue(Machine.interrupt().disabled()); + return 0; + } + + /** + * Get the effective priority of the current thread. Equivalent to + * getEffectivePriority(KThread.currentThread()). + * + * @return the current thread's priority. + */ + public int getEffectivePriority() { + return getEffectivePriority(KThread.currentThread()); + } + + /** + * Set the priority of the specified thread. Must be called with interrupts + * disabled. + * + * @param thread the thread to set the priority of. + * @param priority the new priority. + */ + public void setPriority(KThread thread, int priority) { + Lib.assertTrue(Machine.interrupt().disabled()); + } + + /** + * Set the priority of the current thread. Equivalent to + * setPriority(KThread.currentThread(), priority). + * + * @param priority the new priority. + */ + public void setPriority(int priority) { + setPriority(KThread.currentThread(), priority); + } + + /** + * If possible, raise the priority of the current thread in some + * scheduler-dependent way. + * + * @return true if the scheduler was able to increase the current + * thread's + * priority. + */ + public boolean increasePriority() { + return false; + } + + /** + * If possible, lower the priority of the current thread user in some + * scheduler-dependent way, preferably by the same amount as would a call + * to increasePriority(). + * + * @return true if the scheduler was able to decrease the current + * thread's priority. + */ + public boolean decreasePriority() { + return false; + } +} diff --git a/threads/Semaphore.java b/threads/Semaphore.java new file mode 100644 index 0000000..e999921 --- /dev/null +++ b/threads/Semaphore.java @@ -0,0 +1,104 @@ +package nachos.threads; + +import nachos.machine.*; + +/** + * A Semaphore is a synchronization primitive with an unsigned value. + * A semaphore has only two operations: + * + *

    + *
  • P(): waits until the semaphore's value is greater than zero, + * then decrements it. + *
  • V(): increments the semaphore's value, and wakes up one thread + * waiting in P() if possible. + *
+ * + *

+ * Note that this API does not allow a thread to read the value of the + * semaphore directly. Even if you did read the value, the only thing you would + * know is what the value used to be. You don't know what the value is now, + * because by the time you get the value, a context switch might have occurred, + * and some other thread might have called P() or V(), so the + * true value might now be different. + */ +public class Semaphore { + /** + * Allocate a new semaphore. + * + * @param initialValue the initial value of this semaphore. + */ + public Semaphore(int initialValue) { + value = initialValue; + } + + /** + * Atomically wait for this semaphore to become non-zero and decrement it. + */ + public void P() { + boolean intStatus = Machine.interrupt().disable(); + + if (value == 0) { + waitQueue.waitForAccess(KThread.currentThread()); + KThread.sleep(); + } + else { + value--; + } + + Machine.interrupt().restore(intStatus); + } + + /** + * Atomically increment this semaphore and wake up at most one other thread + * sleeping on this semaphore. + */ + public void V() { + boolean intStatus = Machine.interrupt().disable(); + + KThread thread = waitQueue.nextThread(); + if (thread != null) { + thread.ready(); + } + else { + value++; + } + + Machine.interrupt().restore(intStatus); + } + + private static class PingTest implements Runnable { + PingTest(Semaphore ping, Semaphore pong) { + this.ping = ping; + this.pong = pong; + } + + public void run() { + for (int i=0; i<10; i++) { + ping.P(); + pong.V(); + } + } + + private Semaphore ping; + private Semaphore pong; + } + + /** + * Test if this module is working. + */ + public static void selfTest() { + Semaphore ping = new Semaphore(0); + Semaphore pong = new Semaphore(0); + + new KThread(new PingTest(ping, pong)).setName("ping").fork(); + + for (int i=0; i<10; i++) { + ping.V(); + pong.P(); + } + } + + private int value; + private ThreadQueue waitQueue = + ThreadedKernel.scheduler.newThreadQueue(false); +} diff --git a/threads/SynchList.java b/threads/SynchList.java new file mode 100644 index 0000000..824b32e --- /dev/null +++ b/threads/SynchList.java @@ -0,0 +1,88 @@ +package nachos.threads; + +import java.util.LinkedList; +import nachos.machine.*; +import nachos.threads.*; + +/** + * A synchronized queue. + */ +public class SynchList { + /** + * Allocate a new synchronized queue. + */ + public SynchList() { + list = new LinkedList(); + lock = new Lock(); + listEmpty = new Condition(lock); + } + + /** + * Add the specified object to the end of the queue. If another thread is + * waiting in removeFirst(), it is woken up. + * + * @param o the object to add. Must not be null. + */ + public void add(Object o) { + Lib.assertTrue(o != null); + + lock.acquire(); + list.add(o); + listEmpty.wake(); + lock.release(); + } + + /** + * Remove an object from the front of the queue, blocking until the queue + * is non-empty if necessary. + * + * @return the element removed from the front of the queue. + */ + public Object removeFirst() { + Object o; + + lock.acquire(); + while (list.isEmpty()) + listEmpty.sleep(); + o = list.removeFirst(); + lock.release(); + + return o; + } + + private static class PingTest implements Runnable { + PingTest(SynchList ping, SynchList pong) { + this.ping = ping; + this.pong = pong; + } + + public void run() { + for (int i=0; i<10; i++) + pong.add(ping.removeFirst()); + } + + private SynchList ping; + private SynchList pong; + } + + /** + * Test that this module is working. + */ + public static void selfTest() { + SynchList ping = new SynchList(); + SynchList pong = new SynchList(); + + new KThread(new PingTest(ping, pong)).setName("ping").fork(); + + for (int i=0; i<10; i++) { + Integer o = new Integer(i); + ping.add(o); + Lib.assertTrue(pong.removeFirst() == o); + } + } + + private LinkedList list; + private Lock lock; + private Condition listEmpty; +} + diff --git a/threads/ThreadQueue.java b/threads/ThreadQueue.java new file mode 100644 index 0000000..a942245 --- /dev/null +++ b/threads/ThreadQueue.java @@ -0,0 +1,98 @@ +package nachos.threads; + +/** + * Schedules access to some sort of resource with limited access constraints. A + * thread queue can be used to share this limited access among multiple + * threads. + * + *

+ * Examples of limited access in Nachos include: + * + *

    + *
  1. the right for a thread to use the processor. Only one thread may run on + * the processor at a time. + * + *
  2. the right for a thread to acquire a specific lock. A lock may be held by + * only one thread at a time. + * + *
  3. the right for a thread to return from Semaphore.P() when the + * semaphore is 0. When another thread calls Semaphore.V(), only one + * thread waiting in Semaphore.P() can be awakened. + * + *
  4. the right for a thread to be woken while sleeping on a condition + * variable. When another thread calls Condition.wake(), only one + * thread sleeping on the condition variable can be awakened. + * + *
  5. the right for a thread to return from KThread.join(). Threads + * are not allowed to return from join() until the target thread has + * finished. + *
+ * + * All these cases involve limited access because, for each of them, it is not + * necessarily possible (or correct) for all the threads to have simultaneous + * access. Some of these cases involve concrete resources (e.g. the processor, + * or a lock); others are more abstract (e.g. waiting on semaphores, condition + * variables, or join). + * + *

+ * All thread queue methods must be invoked with interrupts disabled. + */ +public abstract class ThreadQueue { + /** + * Notify this thread queue that the specified thread is waiting for + * access. This method should only be called if the thread cannot + * immediately obtain access (e.g. if the thread wants to acquire a lock + * but another thread already holds the lock). + * + *

+ * A thread must not simultaneously wait for access to multiple resources. + * For example, a thread waiting for a lock must not also be waiting to run + * on the processor; if a thread is waiting for a lock it should be + * sleeping. + * + *

+ * However, depending on the specific objects, it may be acceptable for a + * thread to wait for access to one object while having access to another. + * For example, a thread may attempt to acquire a lock while holding + * another lock. Note, though, that the processor cannot be held while + * waiting for access to anything else. + * + * @param thread the thread waiting for access. + */ + public abstract void waitForAccess(KThread thread); + + /** + * Notify this thread queue that another thread can receive access. Choose + * and return the next thread to receive access, or null if there + * are no threads waiting. + * + *

+ * If the limited access object transfers priority, and if there are other + * threads waiting for access, then they will donate priority to the + * returned thread. + * + * @return the next thread to receive access, or null if there + * are no threads waiting. + */ + public abstract KThread nextThread(); + + /** + * Notify this thread queue that a thread has received access, without + * going through request() and nextThread(). For example, + * if a thread acquires a lock that no other threads are waiting for, it + * should call this method. + * + *

+ * This method should not be called for a thread returned from + * nextThread(). + * + * @param thread the thread that has received access, but was not + * returned from nextThread(). + */ + public abstract void acquire(KThread thread); + + /** + * Print out all the threads waiting for access, in no particular order. + */ + public abstract void print(); +} diff --git a/threads/ThreadedKernel.java b/threads/ThreadedKernel.java new file mode 100644 index 0000000..486b402 --- /dev/null +++ b/threads/ThreadedKernel.java @@ -0,0 +1,86 @@ +package nachos.threads; + +import nachos.machine.*; + +/** + * A multi-threaded OS kernel. + */ +public class ThreadedKernel extends Kernel { + /** + * Allocate a new multi-threaded kernel. + */ + public ThreadedKernel() { + super(); + } + + /** + * Initialize this kernel. Creates a scheduler, the first thread, and an + * alarm, and enables interrupts. Creates a file system if necessary. + */ + public void initialize(String[] args) { + // set scheduler + String schedulerName = Config.getString("ThreadedKernel.scheduler"); + scheduler = (Scheduler) Lib.constructObject(schedulerName); + + // set fileSystem + String fileSystemName = Config.getString("ThreadedKernel.fileSystem"); + if (fileSystemName != null) + fileSystem = (FileSystem) Lib.constructObject(fileSystemName); + else if (Machine.stubFileSystem() != null) + fileSystem = Machine.stubFileSystem(); + else + fileSystem = null; + + // start threading + new KThread(null); + + alarm = new Alarm(); + + Machine.interrupt().enable(); + } + + /** + * Test this kernel. Test the KThread, Semaphore, + * SynchList, and ElevatorBank classes. Note that the + * autograder never calls this method, so it is safe to put additional + * tests here. + */ + public void selfTest() { + KThread.selfTest(); + Semaphore.selfTest(); + SynchList.selfTest(); + if (Machine.bank() != null) { + ElevatorBank.selfTest(); + } + } + + /** + * A threaded kernel does not run user programs, so this method does + * nothing. + */ + public void run() { + } + + /** + * Terminate this kernel. Never returns. + */ + public void terminate() { + Machine.halt(); + } + + /** Globally accessible reference to the scheduler. */ + public static Scheduler scheduler = null; + /** Globally accessible reference to the alarm. */ + public static Alarm alarm = null; + /** Globally accessible reference to the file system. */ + public static FileSystem fileSystem = null; + + // dummy variables to make javac smarter + private static RoundRobinScheduler dummy1 = null; + private static PriorityScheduler dummy2 = null; + private static LotteryScheduler dummy3 = null; + private static Condition2 dummy4 = null; + private static Communicator dummy5 = null; + private static Rider dummy6 = null; + private static ElevatorController dummy7 = null; +} diff --git a/threads/package.html b/threads/package.html new file mode 100644 index 0000000..28e9547 --- /dev/null +++ b/threads/package.html @@ -0,0 +1,3 @@ + +Provides classes that support a multithreaded kernel. + diff --git a/userprog/SynchConsole.java b/userprog/SynchConsole.java new file mode 100644 index 0000000..50e1985 --- /dev/null +++ b/userprog/SynchConsole.java @@ -0,0 +1,147 @@ +package nachos.userprog; + +import nachos.machine.*; +import nachos.threads.*; +import nachos.userprog.*; + +/** + * Provides a simple, synchronized interface to the machine's console. The + * interface can also be accessed through OpenFile objects. + */ +public class SynchConsole { + /** + * Allocate a new SynchConsole. + * + * @param console the underlying serial console to use. + */ + public SynchConsole(SerialConsole console) { + this.console = console; + + Runnable receiveHandler = new Runnable() { + public void run() { receiveInterrupt(); } + }; + Runnable sendHandler = new Runnable() { + public void run() { sendInterrupt(); } + }; + console.setInterruptHandlers(receiveHandler, sendHandler); + } + + /** + * Return the next unsigned byte received (in the range 0 through + * 255). If a byte has not arrived at, blocks until a byte + * arrives, or returns immediately, depending on the value of block. + * + * @param block true if readByte() should wait for a + * byte if none is available. + * @return the next byte read, or -1 if block was false + * and no byte was available. + */ + public int readByte(boolean block) { + int value; + boolean intStatus = Machine.interrupt().disable(); + readLock.acquire(); + + if (block || charAvailable) { + charAvailable = false; + readWait.P(); + + value = console.readByte(); + Lib.assertTrue(value != -1); + } + else { + value = -1; + } + + readLock.release(); + Machine.interrupt().restore(intStatus); + return value; + } + + /** + * Return an OpenFile that can be used to read this as a file. + * + * @return a file that can read this console. + */ + public OpenFile openForReading() { + return new File(true, false); + } + + private void receiveInterrupt() { + charAvailable = true; + readWait.V(); + } + + /** + * Send a byte. Blocks until the send is complete. + * + * @param value the byte to be sent (the upper 24 bits are ignored). + */ + public void writeByte(int value) { + writeLock.acquire(); + console.writeByte(value); + writeWait.P(); + writeLock.release(); + } + + /** + * Return an OpenFile that can be used to write this as a file. + * + * @return a file that can write this console. + */ + public OpenFile openForWriting() { + return new File(false, true); + } + + private void sendInterrupt() { + writeWait.V(); + } + + private boolean charAvailable = false; + + private SerialConsole console; + private Lock readLock = new Lock(); + private Lock writeLock = new Lock(); + private Semaphore readWait = new Semaphore(0); + private Semaphore writeWait = new Semaphore(0); + + private class File extends OpenFile { + File(boolean canRead, boolean canWrite) { + super(null, "SynchConsole"); + + this.canRead = canRead; + this.canWrite = canWrite; + } + + public void close() { + canRead = canWrite = false; + } + + public int read(byte[] buf, int offset, int length) { + if (!canRead) + return 0; + + int i; + for (i=0; i + * A thread capable of running user code actually has two sets of + * CPU registers: one for its state while executing user code, and one for + * its state while executing kernel code. While this thread is not running, + * its user state is stored here. + */ + public int userRegisters[] = new int[Processor.numUserRegisters]; + + /** + * The process to which this thread belongs. + */ + public UserProcess process; +} diff --git a/userprog/UserKernel.java b/userprog/UserKernel.java new file mode 100644 index 0000000..ad39e99 --- /dev/null +++ b/userprog/UserKernel.java @@ -0,0 +1,115 @@ +package nachos.userprog; + +import nachos.machine.*; +import nachos.threads.*; +import nachos.userprog.*; + +/** + * A kernel that can support multiple user processes. + */ +public class UserKernel extends ThreadedKernel { + /** + * Allocate a new user kernel. + */ + public UserKernel() { + super(); + } + + /** + * Initialize this kernel. Creates a synchronized console and sets the + * processor's exception handler. + */ + public void initialize(String[] args) { + super.initialize(args); + + console = new SynchConsole(Machine.console()); + + Machine.processor().setExceptionHandler(new Runnable() { + public void run() { exceptionHandler(); } + }); + } + + /** + * Test the console device. + */ + public void selfTest() { + super.selfTest(); + + System.out.println("Testing the console device. Typed characters"); + System.out.println("will be echoed until q is typed."); + + char c; + + do { + c = (char) console.readByte(true); + console.writeByte(c); + } + while (c != 'q'); + + System.out.println(""); + } + + /** + * Returns the current process. + * + * @return the current process, or null if no process is current. + */ + public static UserProcess currentProcess() { + if (!(KThread.currentThread() instanceof UThread)) + return null; + + return ((UThread) KThread.currentThread()).process; + } + + /** + * The exception handler. This handler is called by the processor whenever + * a user instruction causes a processor exception. + * + *

+ * When the exception handler is invoked, interrupts are enabled, and the + * processor's cause register contains an integer identifying the cause of + * the exception (see the exceptionZZZ constants in the + * Processor class). If the exception involves a bad virtual + * address (e.g. page fault, TLB miss, read-only, bus error, or address + * error), the processor's BadVAddr register identifies the virtual address + * that caused the exception. + */ + public void exceptionHandler() { + Lib.assertTrue(KThread.currentThread() instanceof UThread); + + UserProcess process = ((UThread) KThread.currentThread()).process; + int cause = Machine.processor().readRegister(Processor.regCause); + process.handleException(cause); + } + + /** + * Start running user programs, by creating a process and running a shell + * program in it. The name of the shell program it must run is returned by + * Machine.getShellProgramName(). + * + * @see nachos.machine.Machine#getShellProgramName + */ + public void run() { + super.run(); + + UserProcess process = UserProcess.newUserProcess(); + + String shellProgram = Machine.getShellProgramName(); + Lib.assertTrue(process.execute(shellProgram, new String[] { })); + + KThread.currentThread().finish(); + } + + /** + * Terminate this kernel. Never returns. + */ + public void terminate() { + super.terminate(); + } + + /** Globally accessible reference to the synchronized console. */ + public static SynchConsole console; + + // dummy variables to make javac smarter + private static Coff dummy1 = null; +} diff --git a/userprog/UserProcess.java b/userprog/UserProcess.java new file mode 100644 index 0000000..e75f7ef --- /dev/null +++ b/userprog/UserProcess.java @@ -0,0 +1,449 @@ +package nachos.userprog; + +import nachos.machine.*; +import nachos.threads.*; +import nachos.userprog.*; + +import java.io.EOFException; + +/** + * Encapsulates the state of a user process that is not contained in its + * user thread (or threads). This includes its address translation state, a + * file table, and information about the program being executed. + * + *

+ * This class is extended by other classes to support additional functionality + * (such as additional syscalls). + * + * @see nachos.vm.VMProcess + * @see nachos.network.NetProcess + */ +public class UserProcess { + /** + * Allocate a new process. + */ + public UserProcess() { + int numPhysPages = Machine.processor().getNumPhysPages(); + pageTable = new TranslationEntry[numPhysPages]; + for (int i=0; inachos.conf key + * Kernel.processClassName. + * + * @return a new process of the correct class. + */ + public static UserProcess newUserProcess() { + return (UserProcess)Lib.constructObject(Machine.getProcessClassName()); + } + + /** + * Execute the specified program with the specified arguments. Attempts to + * load the program, and then forks a thread to run it. + * + * @param name the name of the file containing the executable. + * @param args the arguments to pass to the executable. + * @return true if the program was successfully executed. + */ + public boolean execute(String name, String[] args) { + if (!load(name, args)) + return false; + + new UThread(this).setName(name).fork(); + + return true; + } + + /** + * Save the state of this process in preparation for a context switch. + * Called by UThread.saveState(). + */ + public void saveState() { + } + + /** + * Restore the state of this process after a context switch. Called by + * UThread.restoreState(). + */ + public void restoreState() { + Machine.processor().setPageTable(pageTable); + } + + /** + * Read a null-terminated string from this process's virtual memory. Read + * at most maxLength + 1 bytes from the specified address, search + * for the null terminator, and convert it to a java.lang.String, + * without including the null terminator. If no null terminator is found, + * returns null. + * + * @param vaddr the starting virtual address of the null-terminated + * string. + * @param maxLength the maximum number of characters in the string, + * not including the null terminator. + * @return the string read, or null if no null terminator was + * found. + */ + public String readVirtualMemoryString(int vaddr, int maxLength) { + Lib.assertTrue(maxLength >= 0); + + byte[] bytes = new byte[maxLength+1]; + + int bytesRead = readVirtualMemory(vaddr, bytes); + + for (int length=0; lengthreadVirtualMemory(vaddr, data, 0, data.length). + * + * @param vaddr the first byte of virtual memory to read. + * @param data the array where the data will be stored. + * @return the number of bytes successfully transferred. + */ + public int readVirtualMemory(int vaddr, byte[] data) { + return readVirtualMemory(vaddr, data, 0, data.length); + } + + /** + * Transfer data from this process's virtual memory to the specified array. + * This method handles address translation details. This method must + * not destroy the current process if an error occurs, but instead + * should return the number of bytes successfully copied (or zero if no + * data could be copied). + * + * @param vaddr the first byte of virtual memory to read. + * @param data the array where the data will be stored. + * @param offset the first byte to write in the array. + * @param length the number of bytes to transfer from virtual memory to + * the array. + * @return the number of bytes successfully transferred. + */ + public int readVirtualMemory(int vaddr, byte[] data, int offset, + int length) { + Lib.assertTrue(offset >= 0 && length >= 0 && offset+length <= data.length); + + byte[] memory = Machine.processor().getMemory(); + + // for now, just assume that virtual addresses equal physical addresses + if (vaddr < 0 || vaddr >= memory.length) + return 0; + + int amount = Math.min(length, memory.length-vaddr); + System.arraycopy(memory, vaddr, data, offset, amount); + + return amount; + } + + /** + * Transfer all data from the specified array to this process's virtual + * memory. + * Same as writeVirtualMemory(vaddr, data, 0, data.length). + * + * @param vaddr the first byte of virtual memory to write. + * @param data the array containing the data to transfer. + * @return the number of bytes successfully transferred. + */ + public int writeVirtualMemory(int vaddr, byte[] data) { + return writeVirtualMemory(vaddr, data, 0, data.length); + } + + /** + * Transfer data from the specified array to this process's virtual memory. + * This method handles address translation details. This method must + * not destroy the current process if an error occurs, but instead + * should return the number of bytes successfully copied (or zero if no + * data could be copied). + * + * @param vaddr the first byte of virtual memory to write. + * @param data the array containing the data to transfer. + * @param offset the first byte to transfer from the array. + * @param length the number of bytes to transfer from the array to + * virtual memory. + * @return the number of bytes successfully transferred. + */ + public int writeVirtualMemory(int vaddr, byte[] data, int offset, + int length) { + Lib.assertTrue(offset >= 0 && length >= 0 && offset+length <= data.length); + + byte[] memory = Machine.processor().getMemory(); + + // for now, just assume that virtual addresses equal physical addresses + if (vaddr < 0 || vaddr >= memory.length) + return 0; + + int amount = Math.min(length, memory.length-vaddr); + System.arraycopy(data, offset, memory, vaddr, amount); + + return amount; + } + + /** + * Load the executable with the specified name into this process, and + * prepare to pass it the specified arguments. Opens the executable, reads + * its header information, and copies sections and arguments into this + * process's virtual memory. + * + * @param name the name of the file containing the executable. + * @param args the arguments to pass to the executable. + * @return true if the executable was successfully loaded. + */ + private boolean load(String name, String[] args) { + Lib.debug(dbgProcess, "UserProcess.load(\"" + name + "\")"); + + OpenFile executable = ThreadedKernel.fileSystem.open(name, false); + if (executable == null) { + Lib.debug(dbgProcess, "\topen failed"); + return false; + } + + try { + coff = new Coff(executable); + } + catch (EOFException e) { + executable.close(); + Lib.debug(dbgProcess, "\tcoff load failed"); + return false; + } + + // make sure the sections are contiguous and start at page 0 + numPages = 0; + for (int s=0; s pageSize) { + coff.close(); + Lib.debug(dbgProcess, "\targuments too long"); + return false; + } + + // program counter initially points at the program entry point + initialPC = coff.getEntryPoint(); + + // next comes the stack; stack pointer initially points to top of it + numPages += stackPages; + initialSP = numPages*pageSize; + + // and finally reserve 1 page for arguments + numPages++; + + if (!loadSections()) + return false; + + // store arguments in last page + int entryOffset = (numPages-1)*pageSize; + int stringOffset = entryOffset + args.length*4; + + this.argc = args.length; + this.argv = entryOffset; + + for (int i=0; itrue if the sections were successfully loaded. + */ + protected boolean loadSections() { + if (numPages > Machine.processor().getNumPhysPages()) { + coff.close(); + Lib.debug(dbgProcess, "\tinsufficient physical memory"); + return false; + } + + // load sections + for (int s=0; sloadSections(). + */ + protected void unloadSections() { + } + + /** + * Initialize the processor's registers in preparation for running the + * program loaded into this process. Set the PC register to point at the + * start function, set the stack pointer register to point at the top of + * the stack, set the A0 and A1 registers to argc and argv, respectively, + * and initialize all other registers to 0. + */ + public void initRegisters() { + Processor processor = Machine.processor(); + + // by default, everything's 0 + for (int i=0; ihandleException(). The + * syscall argument identifies which syscall the user executed: + * + * + * + * + * + * + * + * + * + * + * + * + * + *
syscall#syscall prototype
0void halt();
1void exit(int status);
2int exec(char *name, int argc, char **argv); + *
3int join(int pid, int *status);
4int creat(char *name);
5int open(char *name);
6int read(int fd, char *buffer, int size); + *
7int write(int fd, char *buffer, int size); + *
8int close(int fd);
9int unlink(char *name);
+ * + * @param syscall the syscall number. + * @param a0 the first syscall argument. + * @param a1 the second syscall argument. + * @param a2 the third syscall argument. + * @param a3 the fourth syscall argument. + * @return the value to be returned to the user. + */ + public int handleSyscall(int syscall, int a0, int a1, int a2, int a3) { + switch (syscall) { + case syscallHalt: + return handleHalt(); + + + default: + Lib.debug(dbgProcess, "Unknown syscall " + syscall); + Lib.assertNotReached("Unknown system call!"); + } + return 0; + } + + /** + * Handle a user exception. Called by + * UserKernel.exceptionHandler(). The + * cause argument identifies which exception occurred; see the + * Processor.exceptionZZZ constants. + * + * @param cause the user exception that occurred. + */ + public void handleException(int cause) { + Processor processor = Machine.processor(); + + switch (cause) { + case Processor.exceptionSyscall: + int result = handleSyscall(processor.readRegister(Processor.regV0), + processor.readRegister(Processor.regA0), + processor.readRegister(Processor.regA1), + processor.readRegister(Processor.regA2), + processor.readRegister(Processor.regA3) + ); + processor.writeRegister(Processor.regV0, result); + processor.advancePC(); + break; + + default: + Lib.debug(dbgProcess, "Unexpected exception: " + + Processor.exceptionNames[cause]); + Lib.assertNotReached("Unexpected exception"); + } + } + + /** The program being run by this process. */ + protected Coff coff; + + /** This process's page table. */ + protected TranslationEntry[] pageTable; + /** The number of contiguous pages occupied by the program. */ + protected int numPages; + + /** The number of pages in the program's stack. */ + protected final int stackPages = 8; + + private int initialPC, initialSP; + private int argc, argv; + + private static final int pageSize = Processor.pageSize; + private static final char dbgProcess = 'a'; +} diff --git a/userprog/package.html b/userprog/package.html new file mode 100644 index 0000000..bcc8368 --- /dev/null +++ b/userprog/package.html @@ -0,0 +1,4 @@ + +Provides classes that allow Nachos to load and execute single-threaded user +programs in separate address spaces. + diff --git a/vm/VMKernel.java b/vm/VMKernel.java new file mode 100644 index 0000000..62be1d8 --- /dev/null +++ b/vm/VMKernel.java @@ -0,0 +1,51 @@ +package nachos.vm; + +import nachos.machine.*; +import nachos.threads.*; +import nachos.userprog.*; +import nachos.vm.*; + +/** + * A kernel that can support multiple demand-paging user processes. + */ +public class VMKernel extends UserKernel { + /** + * Allocate a new VM kernel. + */ + public VMKernel() { + super(); + } + + /** + * Initialize this kernel. + */ + public void initialize(String[] args) { + super.initialize(args); + } + + /** + * Test this kernel. + */ + public void selfTest() { + super.selfTest(); + } + + /** + * Start running user programs. + */ + public void run() { + super.run(); + } + + /** + * Terminate this kernel. Never returns. + */ + public void terminate() { + super.terminate(); + } + + // dummy variables to make javac smarter + private static VMProcess dummy1 = null; + + private static final char dbgVM = 'v'; +} diff --git a/vm/VMProcess.java b/vm/VMProcess.java new file mode 100644 index 0000000..4530c06 --- /dev/null +++ b/vm/VMProcess.java @@ -0,0 +1,73 @@ +package nachos.vm; + +import nachos.machine.*; +import nachos.threads.*; +import nachos.userprog.*; +import nachos.vm.*; + +/** + * A UserProcess that supports demand-paging. + */ +public class VMProcess extends UserProcess { + /** + * Allocate a new process. + */ + public VMProcess() { + super(); + } + + /** + * Save the state of this process in preparation for a context switch. + * Called by UThread.saveState(). + */ + public void saveState() { + super.saveState(); + } + + /** + * Restore the state of this process after a context switch. Called by + * UThread.restoreState(). + */ + public void restoreState() { + super.restoreState(); + } + + /** + * Initializes page tables for this process so that the executable can be + * demand-paged. + * + * @return true if successful. + */ + protected boolean loadSections() { + return super.loadSections(); + } + + /** + * Release any resources allocated by loadSections(). + */ + protected void unloadSections() { + super.unloadSections(); + } + + /** + * Handle a user exception. Called by + * UserKernel.exceptionHandler(). The + * cause argument identifies which exception occurred; see the + * Processor.exceptionZZZ constants. + * + * @param cause the user exception that occurred. + */ + public void handleException(int cause) { + Processor processor = Machine.processor(); + + switch (cause) { + default: + super.handleException(cause); + break; + } + } + + private static final int pageSize = Processor.pageSize; + private static final char dbgProcess = 'a'; + private static final char dbgVM = 'v'; +} diff --git a/vm/package.html b/vm/package.html new file mode 100644 index 0000000..a711183 --- /dev/null +++ b/vm/package.html @@ -0,0 +1,4 @@ + +Provides classes that allow Nachos processes to be demand paged, and to use a +hardware TLB for address translation. +