Index: src/Makefile.build
diff -u src/Makefile.build~ src/Makefile.build
---- src/Makefile.build~ 2005-06-18 20:20:47.000000000 -0700
-+++ src/Makefile.build 2006-05-16 13:44:56.000000000 -0700
+--- src/Makefile.build~
++++ src/Makefile.build
@@ -53,7 +53,9 @@ userprog_SRC += userprog/gdt.c # GDT in
userprog_SRC += userprog/tss.c # TSS management.
# No virtual memory code yet.
--#vm_SRC = vm/filename.c # Some file.
+-#vm_SRC = vm/file.c # Some file.
+vm_SRC = vm/page.c
+vm_SRC += vm/frame.c
+vm_SRC += vm/swap.c
filesys_SRC = filesys/filesys.c # Filesystem core.
Index: src/devices/timer.c
diff -u src/devices/timer.c~ src/devices/timer.c
---- src/devices/timer.c~ 2005-07-06 13:45:36.000000000 -0700
-+++ src/devices/timer.c 2006-05-16 13:44:56.000000000 -0700
+--- src/devices/timer.c~
++++ src/devices/timer.c
@@ -23,6 +23,9 @@ static volatile int64_t ticks;
Initialized by timer_calibrate(). */
static unsigned loops_per_tick;
}
/* Calibrates loops_per_tick, used to implement brief delays. */
-@@ -87,15 +92,36 @@ timer_elapsed (int64_t then)
+@@ -93,16 +93,37 @@
return timer_ticks () - then;
}
+ return a->wakeup_time < b->wakeup_time;
+}
+
- /* Suspends execution for approximately TICKS timer ticks. */
+ /* Sleeps for approximately TICKS timer ticks. Interrupts must
+ be turned on. */
void
timer_sleep (int64_t ticks)
{
+ sema_down (&t->timer_sema);
}
- /* Suspends execution for approximately MS milliseconds. */
+ /* Sleeps for approximately MS milliseconds. Interrupts must be
@@ -132,6 +158,16 @@ timer_interrupt (struct intr_frame *args
{
ticks++;
/* Returns true if LOOPS iterations waits for more than one timer
Index: src/threads/init.c
diff -u src/threads/init.c~ src/threads/init.c
---- src/threads/init.c~ 2006-04-25 11:35:56.000000000 -0700
-+++ src/threads/init.c 2006-05-16 13:44:56.000000000 -0700
+--- src/threads/init.c~
++++ src/threads/init.c
@@ -33,6 +33,8 @@
#include "filesys/filesys.h"
#include "filesys/fsutil.h"
+#include "vm/swap.h"
/* Amount of physical memory, in 4 kB pages. */
- size_t ram_pages;
+ size_t init_ram_pages;
@@ -124,6 +126,9 @@ main (void)
filesys_init (format_filesys);
#endif
/* Run actions specified on kernel command line. */
Index: src/threads/interrupt.c
diff -u src/threads/interrupt.c~ src/threads/interrupt.c
---- src/threads/interrupt.c~ 2006-04-25 11:35:56.000000000 -0700
-+++ src/threads/interrupt.c 2006-05-16 13:44:56.000000000 -0700
+--- src/threads/interrupt.c~
++++ src/threads/interrupt.c
@@ -354,6 +354,8 @@ intr_handler (struct intr_frame *frame)
in_external_intr = true;
yield_on_return = false;
If there is no handler, invoke the unexpected interrupt
Index: src/threads/thread.c
diff -u src/threads/thread.c~ src/threads/thread.c
---- src/threads/thread.c~ 2006-04-25 11:35:57.000000000 -0700
-+++ src/threads/thread.c 2006-05-16 13:44:56.000000000 -0700
+--- src/threads/thread.c~
++++ src/threads/thread.c
@@ -13,6 +13,7 @@
#include "threads/vaddr.h"
#ifdef USERPROG
/* Stack frame for kernel_thread(). */
kf = alloc_frame (t, sizeof *kf);
-@@ -253,16 +254,19 @@ thread_tid (void)
+@@ -288,10 +289,11 @@ thread_tid (void)
void
thread_exit (void)
{
-+ struct thread *t = thread_current ();
-+
ASSERT (!intr_context ());
+ syscall_exit ();
#ifdef USERPROG
process_exit ();
#endif
--
-+
- /* Just set our status to dying and schedule another process.
- We will be destroyed during the call to schedule_tail(). */
- intr_disable ();
-- thread_current ()->status = THREAD_DYING;
-+ t->status = THREAD_DYING;
- schedule ();
- NOT_REACHED ();
- }
+
+ /* Remove thread from all threads list, set our status to dying,
@@ -406,17 +410,28 @@ is_thread (struct thread *t)
/* Does basic initialization of T as a blocked thread named
NAME. */
Index: src/threads/thread.h
diff -u src/threads/thread.h~ src/threads/thread.h
---- src/threads/thread.h~ 2006-04-13 13:53:34.000000000 -0700
-+++ src/threads/thread.h 2006-05-16 13:44:56.000000000 -0700
+--- src/threads/thread.h~
++++ src/threads/thread.h
@@ -2,8 +2,10 @@
#define THREADS_THREAD_H
+ struct semaphore dead; /* 1=child alive, 0=child dead. */
+ };
+
- void thread_init (void);
- void thread_start (void);
-
+ /* If false (default), use round-robin scheduler.
+ If true, use multi-level feedback queue scheduler.
+ Controlled by kernel command-line options "-o mlfqs".
Index: src/userprog/exception.c
diff -u src/userprog/exception.c~ src/userprog/exception.c
---- src/userprog/exception.c~ 2006-01-29 13:32:56.000000000 -0800
-+++ src/userprog/exception.c 2006-05-16 13:44:56.000000000 -0700
+--- src/userprog/exception.c~
++++ src/userprog/exception.c
@@ -4,6 +4,7 @@
#include "userprog/gdt.h"
#include "threads/interrupt.h"
not_present ? "not present" : "rights violation",
Index: src/userprog/pagedir.c
diff -u src/userprog/pagedir.c~ src/userprog/pagedir.c
---- src/userprog/pagedir.c~ 2006-04-25 11:35:58.000000000 -0700
-+++ src/userprog/pagedir.c 2006-05-16 13:44:56.000000000 -0700
+--- src/userprog/pagedir.c~
++++ src/userprog/pagedir.c
@@ -35,15 +35,7 @@ pagedir_destroy (uint32_t *pd)
- ASSERT (pd != base_page_dir);
+ ASSERT (pd != init_page_dir);
for (pde = pd; pde < pd + pd_no (PHYS_BASE); pde++)
if (*pde & PTE_P)
- {
Index: src/userprog/process.c
diff -u src/userprog/process.c~ src/userprog/process.c
---- src/userprog/process.c~ 2006-04-25 11:35:58.000000000 -0700
-+++ src/userprog/process.c 2006-05-16 13:44:56.000000000 -0700
+--- src/userprog/process.c~
++++ src/userprog/process.c
@@ -14,12 +14,26 @@
#include "threads/flags.h"
#include "threads/init.h"
+#include "vm/page.h"
+#include "vm/frame.h"
- static thread_func execute_thread NO_RETURN;
+ static thread_func start_process NO_RETURN;
-static bool load (const char *cmdline, void (**eip) (void), void **esp);
+static bool load (const char *cmd_line, void (**eip) (void), void **esp);
+
+/* Data structure shared between process_execute() in the
-+ invoking thread and execute_thread() in the newly invoked
++ invoking thread and start_process() in the newly invoked
+ thread. */
+struct exec_info
+ {
-+ const char *filename; /* Program to load. */
++ const char *file_name; /* Program to load. */
+ struct semaphore load_done; /* "Up"ed when loading complete. */
+ struct wait_status *wait_status; /* Child process. */
+ bool success; /* Program successfully loaded? */
+ };
/* Starts a new thread running a user program loaded from
- FILENAME. The new thread may be scheduled (and may even exit)
+ FILE_NAME. The new thread may be scheduled (and may even exit)
@@ -28,29 +42,37 @@ static bool load (const char *cmdline, v
tid_t
- process_execute (const char *filename)
+ process_execute (const char *file_name)
{
- char *fn_copy;
+ struct exec_info exec;
+ char *save_ptr;
tid_t tid;
-- /* Make a copy of FILENAME.
+- /* Make a copy of FILE_NAME.
- Otherwise there's a race between the caller and load(). */
- fn_copy = palloc_get_page (0);
- if (fn_copy == NULL)
- return TID_ERROR;
-- strlcpy (fn_copy, filename, PGSIZE);
+- strlcpy (fn_copy, file_name, PGSIZE);
+ /* Initialize exec_info. */
-+ exec.filename = filename;
++ exec.file_name = file_name;
+ sema_init (&exec.load_done, 0);
- /* Create a new thread to execute FILENAME. */
-- tid = thread_create (filename, PRI_DEFAULT, execute_thread, fn_copy);
+ /* Create a new thread to execute FILE_NAME. */
+- tid = thread_create (file_name, PRI_DEFAULT, start_process, fn_copy);
- if (tid == TID_ERROR)
- palloc_free_page (fn_copy);
-+ strlcpy (thread_name, filename, sizeof thread_name);
++ strlcpy (thread_name, file_name, sizeof thread_name);
+ strtok_r (thread_name, " ", &save_ptr);
-+ tid = thread_create (thread_name, PRI_DEFAULT, execute_thread, &exec);
++ tid = thread_create (thread_name, PRI_DEFAULT, start_process, &exec);
+ if (tid != TID_ERROR)
+ {
+ sema_down (&exec.load_done);
/* A thread function that loads a user process and starts it
running. */
static void
--execute_thread (void *filename_)
-+execute_thread (void *exec_)
+-start_process (void *file_name_)
++start_process (void *exec_)
{
-- char *filename = filename_;
+- char *file_name = file_name_;
+ struct exec_info *exec = exec_;
struct intr_frame if_;
bool success;
-@@ -59,10 +81,28 @@ execute_thread (void *filename_)
+@@ -59,10 +81,28 @@ start_process (void *file_name_)
if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG;
if_.cs = SEL_UCSEG;
if_.eflags = FLAG_IF | FLAG_MBS;
-- success = load (filename, &if_.eip, &if_.esp);
-+ success = load (exec->filename, &if_.eip, &if_.esp);
+- success = load (file_name, &if_.eip, &if_.esp);
++ success = load (exec->file_name, &if_.eip, &if_.esp);
+
+ /* Allocate wait_status. */
+ if (success)
+ }
- /* If load failed, quit. */
-- palloc_free_page (filename);
+- palloc_free_page (file_name);
+ /* Initialize wait_status. */
+ if (success)
+ {
if (!success)
thread_exit ();
-@@ -76,18 +116,47 @@ execute_thread (void *filename_)
+@@ -76,18 +116,47 @@ start_process (void *file_name_)
NOT_REACHED ();
}
and its initial stack pointer into *ESP.
Returns true if successful, false otherwise. */
bool
--load (const char *filename, void (**eip) (void), void **esp)
+-load (const char *file_name, void (**eip) (void), void **esp)
+load (const char *cmd_line, void (**eip) (void), void **esp)
{
struct thread *t = thread_current ();
-+ char filename[NAME_MAX + 2];
++ char file_name[NAME_MAX + 2];
struct Elf32_Ehdr ehdr;
struct file *file = NULL;
off_t file_ofs;
int i;
/* Allocate and activate page directory. */
-@@ -220,13 +318,28 @@ load (const char *filename, void (**eip)
+@@ -220,13 +318,28 @@ load (const char *file_name, void (**eip)
goto done;
process_activate ();
+ goto done;
+ hash_init (t->pages, page_hash, page_less, NULL);
+
-+ /* Extract filename from command line. */
++ /* Extract file_name from command line. */
+ while (*cmd_line == ' ')
+ cmd_line++;
-+ strlcpy (filename, cmd_line, sizeof filename);
-+ cp = strchr (filename, ' ');
++ strlcpy (file_name, cmd_line, sizeof file_name);
++ cp = strchr (file_name, ' ');
+ if (cp != NULL)
+ *cp = '\0';
+
/* Open executable file. */
-- file = filesys_open (filename);
-+ t->bin_file = file = filesys_open (filename);
+- file = filesys_open (file_name);
++ t->bin_file = file = filesys_open (file_name);
if (file == NULL)
{
- printf ("load: %s: open failed\n", filename);
+ printf ("load: %s: open failed\n", file_name);
goto done;
}
+ file_deny_write (t->bin_file);
/* Read and verify executable header. */
if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr
-@@ -301,7 +414,7 @@ load (const char *filename, void (**eip)
+@@ -301,7 +414,7 @@ load (const char *file_name, void (**eip)
}
/* Set up stack. */
goto done;
/* Start address. */
-@@ -311,14 +424,11 @@ load (const char *filename, void (**eip)
+@@ -311,14 +424,11 @@ load (const char *file_name, void (**eip)
done:
/* We arrive here whether the load is successful or not. */
}
Index: src/userprog/syscall.c
diff -u src/userprog/syscall.c~ src/userprog/syscall.c
---- src/userprog/syscall.c~ 2005-06-18 20:21:21.000000000 -0700
-+++ src/userprog/syscall.c 2006-05-16 14:17:02.000000000 -0700
+--- src/userprog/syscall.c~
++++ src/userprog/syscall.c
@@ -1,20 +1,598 @@
#include "userprog/syscall.h"
#include <stdio.h>
#include <syscall-nr.h>
+#include "userprog/process.h"
+#include "userprog/pagedir.h"
-+#include "devices/kbd.h"
++#include "devices/input.h"
++#include "devices/shutdown.h"
+#include "filesys/directory.h"
+#include "filesys/filesys.h"
+#include "filesys/file.h"
-+#include "threads/init.h"
#include "threads/interrupt.h"
+#include "threads/malloc.h"
+#include "threads/palloc.h"
+static int
+sys_halt (void)
+{
-+ power_off ();
++ shutdown_power_off ();
+}
+
+/* Exit system call. */
+
+ for (i = 0; i < read_amt; i++)
+ {
-+ char c = kbd_getc ();
++ char c = input_getc ();
+ if (!page_lock (udst, true))
+ thread_exit ();
+ udst[i] = c;
+}
Index: src/userprog/syscall.h
diff -u src/userprog/syscall.h~ src/userprog/syscall.h
---- src/userprog/syscall.h~ 2004-09-05 22:38:45.000000000 -0700
-+++ src/userprog/syscall.h 2006-05-16 13:44:56.000000000 -0700
+--- src/userprog/syscall.h~
++++ src/userprog/syscall.h
@@ -2,5 +2,6 @@
#define USERPROG_SYSCALL_H
#endif /* userprog/syscall.h */
Index: src/vm/frame.c
diff -u src/vm/frame.c~ src/vm/frame.c
---- src/vm/frame.c~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/frame.c 2006-05-16 13:44:56.000000000 -0700
+--- src/vm/frame.c~
++++ src/vm/frame.c
@@ -0,0 +1,162 @@
+#include "vm/frame.h"
+#include <stdio.h>
+
+ lock_init (&scan_lock);
+
-+ frames = malloc (sizeof *frames * ram_pages);
++ frames = malloc (sizeof *frames * init_ram_pages);
+ if (frames == NULL)
+ PANIC ("out of memory allocating page frames");
+
+}
Index: src/vm/frame.h
diff -u src/vm/frame.h~ src/vm/frame.h
---- src/vm/frame.h~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/frame.h 2006-05-16 13:44:56.000000000 -0700
+--- src/vm/frame.h~
++++ src/vm/frame.h
@@ -0,0 +1,23 @@
+#ifndef VM_FRAME_H
+#define VM_FRAME_H
+#endif /* vm/frame.h */
Index: src/vm/page.c
diff -u src/vm/page.c~ src/vm/page.c
---- src/vm/page.c~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/page.c 2006-05-16 13:44:56.000000000 -0700
+--- src/vm/page.c~
++++ src/vm/page.c
@@ -0,0 +1,293 @@
+#include "vm/page.h"
+#include <stdio.h>
+ return false;
+
+ /* Copy data into the frame. */
-+ if (p->sector != (disk_sector_t) -1)
++ if (p->sector != (block_sector_t) -1)
+ {
+ /* Get data from swap. */
+ swap_in (p);
+
+ p->frame = NULL;
+
-+ p->sector = (disk_sector_t) -1;
++ p->sector = (block_sector_t) -1;
+
+ p->file = NULL;
+ p->file_offset = 0;
+}
Index: src/vm/page.h
diff -u src/vm/page.h~ src/vm/page.h
---- src/vm/page.h~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/page.h 2006-05-16 13:44:56.000000000 -0700
+--- src/vm/page.h~
++++ src/vm/page.h
@@ -0,0 +1,50 @@
+#ifndef VM_PAGE_H
+#define VM_PAGE_H
+
+#include <hash.h>
-+#include "devices/disk.h"
++#include "devices/block.h"
+#include "filesys/off_t.h"
+#include "threads/synch.h"
+
+ struct frame *frame; /* Page frame. */
+
+ /* Swap information, protected by frame->frame_lock. */
-+ disk_sector_t sector; /* Starting sector of swap area, or -1. */
++ block_sector_t sector; /* Starting sector of swap area, or -1. */
+
+ /* Memory-mapped file information, protected by frame->frame_lock. */
+ bool private; /* False to write back to file,
+#endif /* vm/page.h */
Index: src/vm/swap.c
diff -u src/vm/swap.c~ src/vm/swap.c
---- src/vm/swap.c~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/swap.c 2006-05-16 13:44:56.000000000 -0700
+--- src/vm/swap.c~
++++ src/vm/swap.c
@@ -0,0 +1,85 @@
+#include "vm/swap.h"
+#include <bitmap.h>
+#include <stdio.h>
+#include "vm/frame.h"
+#include "vm/page.h"
-+#include "devices/disk.h"
+#include "threads/synch.h"
+#include "threads/vaddr.h"
+
-+/* The swap disk. */
-+static struct disk *swap_disk;
++/* The swap device. */
++static struct block *swap_device;
+
+/* Used swap pages. */
+static struct bitmap *swap_bitmap;
+static struct lock swap_lock;
+
+/* Number of sectors per page. */
-+#define PAGE_SECTORS (PGSIZE / DISK_SECTOR_SIZE)
++#define PAGE_SECTORS (PGSIZE / BLOCK_SECTOR_SIZE)
+
+/* Sets up swap. */
+void
+swap_init (void)
+{
-+ swap_disk = disk_get (1, 1);
-+ if (swap_disk == NULL)
++ swap_device = block_get_role (BLOCK_SWAP);
++ if (swap_device == NULL)
+ {
-+ printf ("no swap disk--swap disabled\n");
++ printf ("no swap device--swap disabled\n");
+ swap_bitmap = bitmap_create (0);
+ }
+ else
-+ swap_bitmap = bitmap_create (disk_size (swap_disk) / PAGE_SECTORS);
++ swap_bitmap = bitmap_create (block_size (swap_device)
++ / PAGE_SECTORS);
+ if (swap_bitmap == NULL)
+ PANIC ("couldn't create swap bitmap");
+ lock_init (&swap_lock);
+
+ ASSERT (p->frame != NULL);
+ ASSERT (lock_held_by_current_thread (&p->frame->lock));
-+ ASSERT (p->sector != (disk_sector_t) -1);
++ ASSERT (p->sector != (block_sector_t) -1);
+
+ for (i = 0; i < PAGE_SECTORS; i++)
-+ disk_read (swap_disk, p->sector + i,
-+ p->frame->base + i * DISK_SECTOR_SIZE);
++ block_read (swap_device, p->sector + i,
++ p->frame->base + i * BLOCK_SECTOR_SIZE);
+ bitmap_reset (swap_bitmap, p->sector / PAGE_SECTORS);
-+ p->sector = (disk_sector_t) -1;
++ p->sector = (block_sector_t) -1;
+}
+
+/* Swaps out page P, which must have a locked frame. */
+
+ p->sector = slot * PAGE_SECTORS;
+ for (i = 0; i < PAGE_SECTORS; i++)
-+ disk_write (swap_disk, p->sector + i,
-+ p->frame->base + i * DISK_SECTOR_SIZE);
++ block_write (swap_device, p->sector + i,
++ p->frame->base + i * BLOCK_SECTOR_SIZE);
+
+ p->private = false;
+ p->file = NULL;
+}
Index: src/vm/swap.h
diff -u src/vm/swap.h~ src/vm/swap.h
---- src/vm/swap.h~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/swap.h 2006-05-16 13:44:56.000000000 -0700
+--- src/vm/swap.h~
++++ src/vm/swap.h
@@ -0,0 +1,11 @@
+#ifndef VM_SWAP_H
+#define VM_SWAP_H 1