+Index: src/Makefile.build
diff -u src/Makefile.build~ src/Makefile.build
---- src/Makefile.build~ 2005-06-02 17:24:02.000000000 -0700
-+++ src/Makefile.build 2005-06-08 14:10:54.000000000 -0700
+--- src/Makefile.build~ 2005-06-18 20:20:47.000000000 -0700
++++ src/Makefile.build 2006-04-08 18:52:50.000000000 -0700
@@ -53,7 +53,9 @@ userprog_SRC += userprog/gdt.c # GDT in
userprog_SRC += userprog/tss.c # TSS management.
# Filesystem code.
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-05-24 15:52:43.000000000 -0700
-+++ src/devices/timer.c 2005-06-08 14:10:54.000000000 -0700
+--- src/devices/timer.c~ 2005-07-06 13:45:36.000000000 -0700
++++ src/devices/timer.c 2006-04-08 18:52:50.000000000 -0700
@@ -23,6 +23,9 @@ static volatile int64_t ticks;
Initialized by timer_calibrate(). */
static unsigned loops_per_tick;
}
/* 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~ 2005-06-02 15:43:44.000000000 -0700
-+++ src/threads/init.c 2005-06-08 14:10:54.000000000 -0700
+--- src/threads/init.c~ 2006-01-29 13:32:55.000000000 -0800
++++ src/threads/init.c 2006-04-08 18:52:50.000000000 -0700
@@ -33,6 +33,8 @@
#include "filesys/filesys.h"
#include "filesys/fsutil.h"
/* Amount of physical memory, in 4 kB pages. */
size_t ram_pages;
-@@ -131,6 +133,9 @@ main (void)
+@@ -124,6 +126,9 @@ main (void)
filesys_init (format_filesys);
#endif
printf ("Boot complete.\n");
/* 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~ 2005-01-21 13:43:16.000000000 -0800
-+++ src/threads/interrupt.c 2005-06-08 14:10:54.000000000 -0700
-@@ -331,6 +331,8 @@ intr_handler (struct intr_frame *frame)
+--- src/threads/interrupt.c~ 2006-01-29 13:32:55.000000000 -0800
++++ src/threads/interrupt.c 2006-04-08 18:52:50.000000000 -0700
+@@ -354,6 +354,8 @@ intr_handler (struct intr_frame *frame)
in_external_intr = true;
yield_on_return = false;
}
/* Invoke the interrupt's handler.
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~ 2005-06-02 14:35:12.000000000 -0700
-+++ src/threads/thread.c 2005-06-08 14:10:54.000000000 -0700
+--- src/threads/thread.c~ 2006-04-08 12:09:39.000000000 -0700
++++ src/threads/thread.c 2006-04-08 18:52:50.000000000 -0700
@@ -13,6 +13,7 @@
#include "threads/synch.h"
#ifdef USERPROG
}
/* Starts preemptive thread scheduling by enabling interrupts.
-@@ -157,8 +158,8 @@ thread_create (const char *name, int pri
+@@ -159,8 +160,8 @@ thread_create (const char *name, int pri
return TID_ERROR;
/* Initialize thread. */
/* Stack frame for kernel_thread(). */
kf = alloc_frame (t, sizeof *kf);
-@@ -251,16 +252,19 @@ thread_tid (void)
+@@ -253,16 +254,19 @@ thread_tid (void)
void
thread_exit (void)
{
schedule ();
NOT_REACHED ();
}
-@@ -389,17 +393,28 @@ is_thread (struct thread *t)
+@@ -406,17 +410,28 @@ is_thread (struct thread *t)
/* Does basic initialization of T as a blocked thread named
NAME. */
static void
t->magic = THREAD_MAGIC;
}
+Index: src/threads/thread.h
diff -u src/threads/thread.h~ src/threads/thread.h
---- src/threads/thread.h~ 2005-06-02 14:32:36.000000000 -0700
-+++ src/threads/thread.h 2005-06-08 14:10:54.000000000 -0700
+--- src/threads/thread.h~ 2005-06-18 20:21:21.000000000 -0700
++++ src/threads/thread.h 2006-04-08 18:52:50.000000000 -0700
@@ -2,8 +2,10 @@
#define THREADS_THREAD_H
+
void thread_init (void);
void thread_start (void);
- void thread_tick (void);
+
+Index: src/userprog/exception.c
diff -u src/userprog/exception.c~ src/userprog/exception.c
---- src/userprog/exception.c~ 2005-01-01 18:09:59.000000000 -0800
-+++ src/userprog/exception.c 2005-06-08 14:10:54.000000000 -0700
+--- src/userprog/exception.c~ 2006-01-29 13:32:56.000000000 -0800
++++ src/userprog/exception.c 2006-04-08 18:52:50.000000000 -0700
@@ -4,6 +4,7 @@
#include "userprog/gdt.h"
#include "threads/interrupt.h"
/* Number of page faults processed. */
static long long page_fault_cnt;
-@@ -150,9 +151,14 @@ page_fault (struct intr_frame *f)
+@@ -148,9 +149,14 @@ page_fault (struct intr_frame *f)
write = (f->error_code & PF_W) != 0;
user = (f->error_code & PF_U) != 0;
printf ("Page fault at %p: %s error %s page in %s context.\n",
fault_addr,
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~ 2005-05-20 15:44:13.000000000 -0700
-+++ src/userprog/pagedir.c 2005-06-08 14:10:54.000000000 -0700
-@@ -34,15 +34,7 @@ pagedir_destroy (uint32_t *pd)
+--- src/userprog/pagedir.c~ 2006-01-29 13:32:56.000000000 -0800
++++ src/userprog/pagedir.c 2006-04-08 18:52:50.000000000 -0700
+@@ -35,15 +35,7 @@ pagedir_destroy (uint32_t *pd)
ASSERT (pd != base_page_dir);
for (pde = pd; pde < pd + pd_no (PHYS_BASE); pde++)
if (*pde & PG_P)
palloc_free_page (pd);
}
+Index: src/userprog/process.c
diff -u src/userprog/process.c~ src/userprog/process.c
---- src/userprog/process.c~ 2005-05-26 13:19:48.000000000 -0700
-+++ src/userprog/process.c 2005-06-08 14:13:25.000000000 -0700
-@@ -14,11 +14,25 @@
+--- src/userprog/process.c~ 2006-04-08 19:37:00.000000000 -0700
++++ src/userprog/process.c 2006-04-08 19:35:29.000000000 -0700
+@@ -15,11 +15,25 @@
#include "threads/init.h"
#include "threads/interrupt.h"
#include "threads/mmu.h"
/* Starts a new thread running a user program loaded from
FILENAME. The new thread may be scheduled (and may even exit)
-@@ -27,29 +41,37 @@ static bool load (const char *cmdline, v
+@@ -28,29 +42,37 @@ static bool load (const char *cmdline, v
tid_t
process_execute (const char *filename)
{
struct intr_frame if_;
bool success;
-@@ -58,10 +80,28 @@ execute_thread (void *filename_)
+@@ -59,10 +81,28 @@ execute_thread (void *filename_)
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);
-
-- /* If load failed, quit. */
-- palloc_free_page (filename);
++
+ /* Allocate wait_status. */
+ if (success)
+ {
+ = malloc (sizeof *exec->wait_status);
+ success = exec->wait_status != NULL;
+ }
-+
+
+- /* If load failed, quit. */
+- palloc_free_page (filename);
+ /* Initialize wait_status. */
+ if (success)
+ {
if (!success)
thread_exit ();
-@@ -75,18 +115,47 @@ execute_thread (void *filename_)
+@@ -76,18 +116,47 @@ execute_thread (void *filename_)
NOT_REACHED ();
}
return -1;
}
-@@ -95,8 +164,35 @@ void
+@@ -96,8 +165,35 @@ void
process_exit (void)
{
struct thread *cur = thread_current ();
/* Destroy the current process's page directory and switch back
to the kernel-only page directory. */
pd = cur->pagedir;
-@@ -193,7 +289,7 @@ struct Elf32_Phdr
+@@ -194,7 +290,7 @@ struct Elf32_Phdr
+ #define PF_W 2 /* Writable. */
#define PF_R 4 /* Readable. */
- static bool load_segment (struct file *, const struct Elf32_Phdr *);
-static bool setup_stack (void **esp);
+static bool setup_stack (const char *cmd_line, void **esp);
-
- /* Loads an ELF executable from FILENAME into the current thread.
- Stores the executable's entry point into *EIP
-@@ -209,13 +305,15 @@ static bool setup_stack (void **esp);
+ static bool validate_segment (const struct Elf32_Phdr *, struct file *);
+ static bool load_segment (struct file *file, off_t ofs, uint8_t *upage,
+ uint32_t read_bytes, uint32_t zero_bytes,
+@@ -205,13 +301,15 @@ static bool load_segment (struct file *f
and its initial stack pointer into *ESP.
Returns true if successful, false otherwise. */
bool
int i;
/* Allocate and activate page directory. */
-@@ -224,13 +322,28 @@ load (const char *filename, void (**eip)
+@@ -220,13 +318,28 @@ load (const char *filename, void (**eip)
goto done;
process_activate ();
/* Read and verify executable header. */
if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr
-@@ -284,7 +397,7 @@ load (const char *filename, void (**eip)
+@@ -301,7 +414,7 @@ load (const char *filename, void (**eip)
}
/* Set up stack. */
goto done;
/* Start address. */
-@@ -294,14 +407,11 @@ load (const char *filename, void (**eip)
+@@ -311,14 +424,11 @@ load (const char *filename, void (**eip)
done:
/* We arrive here whether the load is successful or not. */
\f
/* load() helpers. */
--static bool install_page (void *upage, void *kpage);
+-static bool install_page (void *upage, void *kpage, bool writable);
-
- /* Loads the segment described by PHDR from FILE into user
- address space. Return true if successful, false otherwise. */
+ /* Checks whether PHDR describes a valid, loadable segment in
+ FILE and returns true if so, false otherwise. */
static bool
-@@ -309,6 +419,7 @@ load_segment (struct file *file, const s
- {
- void *start, *end; /* Page-rounded segment start and end. */
- uint8_t *upage; /* Iterator from start to end. */
-+ off_t file_offset; /* Offset into file. */
- off_t filesz_left; /* Bytes left of file data (as opposed to
- zero-initialized bytes). */
-
-@@ -316,7 +427,7 @@ load_segment (struct file *file, const s
- commented out. You'll want to use it when implementing VM
- to decide whether to page the segment from its executable or
- from swap. */
-- //bool read_only = (phdr->p_flags & PF_W) == 0;
-+ bool read_only = (phdr->p_flags & PF_W) == 0;
+@@ -387,79 +497,127 @@ load_segment (struct file *file, off_t o
+ ASSERT (pg_ofs (upage) == 0);
+ ASSERT (ofs % PGSIZE == 0);
- ASSERT (file != NULL);
- ASSERT (phdr != NULL);
-@@ -360,73 +471,129 @@ load_segment (struct file *file, const s
- return false;
- }
-
-- /* Load the segment page-by-page into memory. */
-+ /* Add the segment page-by-page to the hash table. */
- filesz_left = phdr->p_filesz + (phdr->p_vaddr & PGMASK);
-- file_seek (file, ROUND_DOWN (phdr->p_offset, PGSIZE));
-+ file_offset = ROUND_DOWN (phdr->p_offset, PGSIZE);
- for (upage = start; upage < (uint8_t *) end; upage += PGSIZE)
+- file_seek (file, ofs);
+ while (read_bytes > 0 || zero_bytes > 0)
{
-- /* We want to read min(PGSIZE, filesz_left) bytes from the
-- file into the page and zero the rest. */
-- size_t read_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left;
-- size_t zero_bytes = PGSIZE - read_bytes;
+- /* Calculate how to fill this page.
+- We will read PAGE_READ_BYTES bytes from FILE
+- and zero the final PAGE_ZERO_BYTES bytes. */
+ size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
+ size_t page_zero_bytes = PGSIZE - page_read_bytes;
+-
+- /* Get a page of memory. */
- uint8_t *kpage = palloc_get_page (PAL_USER);
- if (kpage == NULL)
-+ struct page *p = page_allocate (upage, read_only);
++ struct page *p = page_allocate (upage, !writable);
+ if (p == NULL)
return false;
-
-- /* Do the reading and zeroing. */
-- if (file_read (file, kpage, read_bytes) != (int) read_bytes)
+-
+- /* Load this page. */
+- if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes)
- {
- palloc_free_page (kpage);
- return false;
- }
-- memset (kpage + read_bytes, 0, zero_bytes);
-- filesz_left -= read_bytes;
+- memset (kpage + page_read_bytes, 0, page_zero_bytes);
-
- /* Add the page to the process's address space. */
-- if (!install_page (upage, kpage))
-+ if (filesz_left > 0)
+- if (!install_page (upage, kpage, writable))
++ if (page_read_bytes > 0)
{
- palloc_free_page (kpage);
- return false;
-+ size_t file_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left;
+ p->file = file;
-+ p->file_offset = file_offset;
-+ p->file_bytes = file_bytes;
-+ filesz_left -= file_bytes;
-+ file_offset += file_bytes;
++ p->file_offset = ofs;
++ p->file_bytes = page_read_bytes;
}
+-
+- /* Advance. */
+ read_bytes -= page_read_bytes;
+ zero_bytes -= page_zero_bytes;
++ ofs += page_read_bytes;
+ upage += PGSIZE;
}
-
return true;
}
-/* Create a minimal stack by mapping a zeroed page at the top of
- user virtual memory. */
--static bool
--setup_stack (void **esp)
+/* Reverse the order of the ARGC pointers to char in ARGV. */
+static void
+reverse (int argc, char **argv)
- {
-- uint8_t *kpage;
-- bool success = false;
--
-- kpage = palloc_get_page (PAL_USER | PAL_ZERO);
-- if (kpage != NULL)
++{
+ for (; argc > 1; argc -= 2, argv++)
- {
-- success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
-- if (success)
-- *esp = PHYS_BASE;
-- else
-- palloc_free_page (kpage);
++ {
+ char *tmp = argv[0];
+ argv[0] = argv[argc - 1];
+ argv[argc - 1] = tmp;
- }
++ }
+}
+
-- return success;
+/* Pushes the SIZE bytes in BUF onto the stack in KPAGE, whose
+ page-relative stack pointer is *OFS, and then adjusts *OFS
+ appropriately. The bytes pushed are rounded to a 32-bit
+ *ofs -= padsize;
+ memcpy (kpage + *ofs + (padsize - size), buf, size);
+ return kpage + *ofs + (padsize - size);
- }
-
--/* Adds a mapping from user virtual address UPAGE to kernel
-- virtual address KPAGE to the page table.
-- UPAGE must not already be mapped.
-- KPAGE should probably be a page obtained from the user pool
-- with palloc_get_page().
-- Returns true on success, false if UPAGE is already mapped or
-- if memory allocation fails. */
++}
++
+/* Sets up command line arguments in KPAGE, which will be mapped
+ to UPAGE in user space. The command line arguments are taken
+ from CMD_LINE, separated by spaces. Sets *ESP to the initial
+ stack pointer for the process. */
static bool
--install_page (void *upage, void *kpage)
+-setup_stack (void **esp)
+init_cmd_line (uint8_t *kpage, uint8_t *upage, const char *cmd_line,
+ void **esp)
{
-- struct thread *t = thread_current ();
+- uint8_t *kpage;
+- bool success = false;
+ size_t ofs = PGSIZE;
+ char *const null = NULL;
+ char *cmd_line_copy;
+
+ if (push (kpage, &ofs, &null, sizeof null) == NULL)
+ return false;
-+
+
+- kpage = palloc_get_page (PAL_USER | PAL_ZERO);
+- if (kpage != NULL)
+ /* Parse command line into arguments
+ and push them in reverse order. */
+ argc = 0;
+ for (karg = strtok_r (cmd_line_copy, " ", &saveptr); karg != NULL;
+ karg = strtok_r (NULL, " ", &saveptr))
-+ {
+ {
+- success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage, true);
+- if (success)
+- *esp = PHYS_BASE;
+- else
+- palloc_free_page (kpage);
+ void *uarg = upage + (karg - (char *) kpage);
+ if (push (kpage, &ofs, &uarg, sizeof uarg) == NULL)
+ return false;
+ argc++;
-+ }
+ }
+- return success;
+
+ /* Reverse the order of the command line arguments. */
+ argv = (char **) (upage + ofs);
+ /* Set initial stack pointer. */
+ *esp = upage + ofs;
+ return true;
-+}
+ }
-- /* Verify that there's not already a page at that virtual
-- address, then map our page there. */
-- return (pagedir_get_page (t->pagedir, upage) == NULL
-- && pagedir_set_page (t->pagedir, upage, kpage, true));
+-/* Adds a mapping from user virtual address UPAGE to kernel
+- virtual address KPAGE to the page table.
+- If WRITABLE is true, the user process may modify the page;
+- otherwise, it is read-only.
+- UPAGE must not already be mapped.
+- KPAGE should probably be a page obtained from the user pool
+- with palloc_get_page().
+- Returns true on success, false if UPAGE is already mapped or
+- if memory allocation fails. */
+/* Create a minimal stack for T by mapping a page at the
+ top of user virtual memory. Fills in the page using CMD_LINE
+ and sets *ESP to the stack pointer. */
-+static bool
+ static bool
+-install_page (void *upage, void *kpage, bool writable)
+setup_stack (const char *cmd_line, void **esp)
-+{
+ {
+- struct thread *t = thread_current ();
+-
+- /* Verify that there's not already a page at that virtual
+- address, then map our page there. */
+- return (pagedir_get_page (t->pagedir, upage) == NULL
+- && pagedir_set_page (t->pagedir, upage, kpage, writable));
+ struct page *page = page_allocate (((uint8_t *) PHYS_BASE) - PGSIZE, false);
+ if (page != NULL)
+ {
+ }
+ return false;
}
+Index: src/userprog/syscall.c
diff -u src/userprog/syscall.c~ src/userprog/syscall.c
---- src/userprog/syscall.c~ 2004-09-26 14:15:17.000000000 -0700
-+++ src/userprog/syscall.c 2005-06-08 14:10:54.000000000 -0700
+--- src/userprog/syscall.c~ 2005-06-18 20:21:21.000000000 -0700
++++ src/userprog/syscall.c 2006-04-08 19:36:04.000000000 -0700
@@ -1,20 +1,557 @@
#include "userprog/syscall.h"
#include <stdio.h>
+/* Halt system call. */
+static int
+sys_halt (void)
- {
-- printf ("system call!\n");
++{
+ power_off ();
+}
+
+sys_exit (int exit_code)
+{
+ thread_current ()->exit_code = exit_code;
- thread_exit ();
++ thread_exit ();
+ NOT_REACHED ();
+}
+
+/* Read system call. */
+static int
+sys_read (int handle, void *udst_, unsigned size)
-+{
+ {
+- printf ("system call!\n");
+ uint8_t *udst = udst_;
+ struct file_descriptor *fd;
+ int bytes_read = 0;
+ /* Do the write. */
+ if (handle == STDOUT_FILENO)
+ {
-+ putbuf (usrc, write_amt);
++ putbuf ((char *) usrc, write_amt);
+ retval = write_amt;
+ }
+ else
+ return m;
+ }
+
-+ thread_exit ();
-+}
+ thread_exit ();
+ }
+
+/* Remove mapping M from the virtual address space,
+ writing back any pages that have changed. */
+ next = list_next (e);
+ unmap (m);
+ }
- }
++}
+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 2005-06-08 14:10:54.000000000 -0700
++++ src/userprog/syscall.h 2006-04-08 18:52:50.000000000 -0700
@@ -2,5 +2,6 @@
#define USERPROG_SYSCALL_H
+void syscall_exit (void);
#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 2005-06-08 14:10:54.000000000 -0700
++++ src/vm/frame.c 2006-04-08 18:52:50.000000000 -0700
@@ -0,0 +1,162 @@
+#include "vm/frame.h"
+#include <stdio.h>
+ ASSERT (lock_held_by_current_thread (&f->lock));
+ lock_release (&f->lock);
+}
+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 2005-06-08 14:10:54.000000000 -0700
++++ src/vm/frame.h 2006-04-08 18:52:50.000000000 -0700
@@ -0,0 +1,23 @@
+#ifndef VM_FRAME_H
+#define VM_FRAME_H
+void frame_unlock (struct frame *);
+
+#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 2005-06-08 14:10:54.000000000 -0700
++++ src/vm/page.c 2006-04-08 18:52:50.000000000 -0700
@@ -0,0 +1,293 @@
+#include "vm/page.h"
+#include <stdio.h>
+ ASSERT (p != NULL);
+ frame_unlock (p->frame);
+}
+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 2005-06-08 14:10:54.000000000 -0700
++++ src/vm/page.h 2006-04-08 18:52:50.000000000 -0700
@@ -0,0 +1,50 @@
+#ifndef VM_PAGE_H
+#define VM_PAGE_H
+hash_less_func page_less;
+
+#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 2005-06-08 14:10:54.000000000 -0700
++++ src/vm/swap.c 2006-04-08 18:52:50.000000000 -0700
@@ -0,0 +1,85 @@
+#include "vm/swap.h"
+#include <bitmap.h>
+
+ return true;
+}
+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 2005-06-08 14:10:54.000000000 -0700
++++ src/vm/swap.h 2006-04-08 18:52:50.000000000 -0700
@@ -0,0 +1,11 @@
+#ifndef VM_SWAP_H
+#define VM_SWAP_H 1