X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=solutions%2Fp2.patch;h=41f6764d445a0c27b2218abffec0bc202f95cf01;hb=310108ababf7c5e3f4da1b90100230db8b36d053;hp=70e5dbe4fd2b2824f5063ea3f836c7e6b94028b0;hpb=096f7f960b7a6ae9659a37a80d5647557aa9aca8;p=pintos-anon diff --git a/solutions/p2.patch b/solutions/p2.patch index 70e5dbe..41f6764 100644 --- a/solutions/p2.patch +++ b/solutions/p2.patch @@ -1,100 +1,7 @@ -Index: src/constants.h -=================================================================== -RCS file: /afs/ir.stanford.edu/users/b/l/blp/private/cvs/pintos/src/constants.h,v -retrieving revision 1.4 -diff -u -p -r1.4 constants.h ---- src/constants.h 19 Oct 2004 17:37:30 -0000 1.4 -+++ src/constants.h 1 Jan 2005 02:13:41 -0000 -@@ -8,4 +8,4 @@ - /*#define MACRONAME 1 */ - - /* Uncomment if if you've implemented thread_join(). */ --/*#define THREAD_JOIN_IMPLEMENTED 1*/ -+#define THREAD_JOIN_IMPLEMENTED 1 -Index: src/threads/synch.c -=================================================================== -RCS file: /afs/ir.stanford.edu/users/b/l/blp/private/cvs/pintos/src/threads/synch.c,v -retrieving revision 1.15 -diff -u -p -r1.15 synch.c ---- src/threads/synch.c 31 Dec 2004 21:13:38 -0000 1.15 -+++ src/threads/synch.c 1 Jan 2005 02:13:41 -0000 -@@ -330,3 +330,45 @@ cond_name (const struct condition *cond) - - return cond->name; - } -+ -+/* Initializes LATCH and names it NAME (for debugging purposes). -+ A latch is a boolean condition. Until it is released for the -+ first time, all threads block attempting to acquire. After it -+ is released once, all ongoing and subsequent acquisitions -+ "fall through" immediately. Releases after the first have no -+ additional effect. */ -+void -+latch_init (struct latch *latch, const char *name) -+{ -+ latch->released = false; -+ lock_init (&latch->monitor_lock, name); -+ cond_init (&latch->rel_cond, name); -+} -+ -+/* Acquires LATCH, blocking until it is released for the first -+ time. */ -+void -+latch_acquire (struct latch *latch) -+{ -+ lock_acquire (&latch->monitor_lock); -+ if (!latch->released) -+ { -+ cond_wait (&latch->rel_cond, &latch->monitor_lock); -+ ASSERT (latch->released); -+ } -+ lock_release (&latch->monitor_lock); -+} -+ -+/* Releases LATCH, causing all ongoing and subsequent -+ acquisitions to pass through immediately. */ -+void -+latch_release (struct latch *latch) -+{ -+ lock_acquire (&latch->monitor_lock); -+ if (!latch->released) -+ { -+ latch->released = true; -+ cond_signal (&latch->rel_cond, &latch->monitor_lock); -+ } -+ lock_release (&latch->monitor_lock); -+} -Index: src/threads/synch.h -=================================================================== -RCS file: /afs/ir.stanford.edu/users/b/l/blp/private/cvs/pintos/src/threads/synch.h,v -retrieving revision 1.7 -diff -u -p -r1.7 synch.h ---- src/threads/synch.h 29 Sep 2004 01:04:09 -0000 1.7 -+++ src/threads/synch.h 1 Jan 2005 02:13:41 -0000 -@@ -44,4 +44,16 @@ void cond_signal (struct condition *, st - void cond_broadcast (struct condition *, struct lock *); - const char *cond_name (const struct condition *); - -+/* Latch. */ -+struct latch -+ { -+ bool released; /* Released yet? */ -+ struct lock monitor_lock; /* Monitor lock. */ -+ struct condition rel_cond; /* Signaled when released. */ -+ }; -+ -+void latch_init (struct latch *, const char *); -+void latch_acquire (struct latch *); -+void latch_release (struct latch *); -+ - #endif /* threads/synch.h */ Index: src/threads/thread.c -=================================================================== -RCS file: /afs/ir.stanford.edu/users/b/l/blp/private/cvs/pintos/src/threads/thread.c,v -retrieving revision 1.48 -diff -u -p -r1.48 thread.c ---- src/threads/thread.c 9 Oct 2004 18:01:37 -0000 1.48 -+++ src/threads/thread.c 1 Jan 2005 02:13:42 -0000 +diff -u src/threads/thread.c~ src/threads/thread.c +--- src/threads/thread.c~ ++++ src/threads/thread.c @@ -13,6 +13,7 @@ #include "threads/synch.h" #ifdef USERPROG @@ -103,107 +10,42 @@ diff -u -p -r1.48 thread.c #endif /* Random value for struct thread's `magic' member. -@@ -81,6 +82,7 @@ thread_init (void) - init_thread (initial_thread, "main", PRI_DEFAULT); - initial_thread->status = THREAD_RUNNING; - initial_thread->tid = allocate_tid (); -+ sema_up (&initial_thread->can_die); - } - - /* Starts preemptive thread scheduling by enabling interrupts. -@@ -149,6 +151,7 @@ thread_create (const char *name, int pri - /* Initialize thread. */ - init_thread (t, name, priority); - tid = t->tid = allocate_tid (); -+ list_push_back (&thread_current ()->children, &t->children_elem); - - /* Stack frame for kernel_thread(). */ - kf = alloc_frame (t, sizeof *kf); -@@ -241,16 +244,36 @@ thread_tid (void) +@@ -251,18 +252,19 @@ thread_tid (void) void thread_exit (void) { -+ struct thread *t = thread_current (); -+ list_elem *e, *next; -+ ASSERT (!intr_context ()); #ifdef USERPROG process_exit (); #endif +- + syscall_exit (); + -+ /* Notify our parent that we're dying. */ -+ latch_release (&t->ready_to_die); -+ -+ /* Notify our children that they can die. */ -+ for (e = list_begin (&t->children); e != list_end (&t->children); -+ e = next) -+ { -+ struct thread *child = list_entry (e, struct thread, children_elem); -+ next = list_next (e); -+ list_remove (e); -+ sema_up (&child->can_die); -+ } -+ -+ /* Wait until our parent is ready for us to die. */ -+ sema_down (&t->can_die); - - /* Just set our status to dying and schedule another process. - We will be destroyed during the call to schedule_tail(). */ + /* Remove thread from all threads list, set our status to dying, + and schedule another process. That process will destroy us + when it calls thread_schedule_tail(). */ intr_disable (); -- thread_current ()->status = THREAD_DYING; -+ t->status = THREAD_DYING; + list_remove (&thread_current()->allelem); + thread_current ()->status = THREAD_DYING; schedule (); NOT_REACHED (); } -@@ -300,6 +323,26 @@ kernel_thread (thread_func *function, vo - function (aux); /* Execute the thread function. */ - thread_exit (); /* If function() returns, kill the thread. */ - } -+ -+/* Waits for thread with tid CHILD_TID to die. */ -+int -+thread_join (tid_t child_tid) -+{ -+ struct thread *cur = thread_current (); -+ list_elem *e; -+ -+ for (e = list_begin (&cur->children); e != list_end (&cur->children); ) -+ { -+ struct thread *child = list_entry (e, struct thread, children_elem); -+ e = list_next (e); -+ if (child->tid == child_tid) -+ { -+ latch_acquire (&child->ready_to_die); -+ return child->exit_code; -+ } -+ } -+ return -1; -+} - - /* Returns the running thread. */ - struct thread * -@@ -336,6 +379,12 @@ init_thread (struct thread *t, const cha +@@ -400,6 +404,10 @@ init_thread (struct thread *t, const cha strlcpy (t->name, name, sizeof t->name); t->stack = (uint8_t *) t + PGSIZE; t->priority = priority; -+ latch_init (&t->ready_to_die, "ready-to-die"); -+ sema_init (&t->can_die, 0, "can-die"); + list_init (&t->children); -+ t->exit_code = -1; ++ t->wait_status = NULL; + list_init (&t->fds); + t->next_handle = 2; t->magic = THREAD_MAGIC; } Index: src/threads/thread.h -=================================================================== -RCS file: /afs/ir.stanford.edu/users/b/l/blp/private/cvs/pintos/src/threads/thread.h,v -retrieving revision 1.28 -diff -u -p -r1.28 thread.h ---- src/threads/thread.h 29 Sep 2004 01:04:20 -0000 1.28 -+++ src/threads/thread.h 1 Jan 2005 02:13:42 -0000 +diff -u src/threads/thread.h~ src/threads/thread.h +--- src/threads/thread.h~ ++++ src/threads/thread.h @@ -4,6 +4,7 @@ #include #include @@ -212,47 +54,54 @@ diff -u -p -r1.28 thread.h /* States in a thread's life cycle. */ enum thread_status -@@ -89,12 +90,23 @@ struct thread +@@ -89,6 +90,10 @@ struct thread uint8_t *stack; /* Saved stack pointer. */ int priority; /* Priority. */ -+ /* Members for implementing thread_join(). */ -+ struct latch ready_to_die; /* Release when thread about to die. */ -+ struct semaphore can_die; /* Up when thread allowed to die. */ -+ struct list children; /* List of child threads. */ -+ list_elem children_elem; /* Element of `children' list. */ -+ int exit_code; /* Return status. */ ++ /* Owned by process.c. */ ++ struct wait_status *wait_status; /* This process's completion status. */ ++ struct list children; /* Completion status of children. */ + /* Shared between thread.c and synch.c. */ - list_elem elem; /* List element. */ + struct list_elem elem; /* List element. */ - #ifdef USERPROG +@@ -96,11 +102,31 @@ struct thread /* Owned by userprog/process.c. */ uint32_t *pagedir; /* Page directory. */ + #endif ++ struct file *bin_file; /* Executable. */ + + /* Owned by syscall.c. */ + struct list fds; /* List of file descriptors. */ + int next_handle; /* Next handle value. */ - #endif /* Owned by thread.c. */ -@@ -120,7 +132,7 @@ void thread_exit (void) NO_RETURN; - void thread_yield (void); - - /* This function will be implemented in problem 1-2. */ --void thread_join (tid_t); -+int thread_join (tid_t); + unsigned magic; /* Detects stack overflow. */ + }; - /* These functions will be implemented in problem 1-3. */ - void thread_set_priority (int); ++/* Tracks the completion of a process. ++ Reference held by both the parent, in its `children' list, ++ and by the child, in its `wait_status' pointer. */ ++struct wait_status ++ { ++ struct list_elem elem; /* `children' list element. */ ++ struct lock lock; /* Protects ref_cnt. */ ++ int ref_cnt; /* 2=child and parent both alive, ++ 1=either child or parent alive, ++ 0=child and parent both dead. */ ++ tid_t tid; /* Child thread id. */ ++ int exit_code; /* Child exit code, if dead. */ ++ struct semaphore dead; /* 1=child alive, 0=child dead. */ ++ }; ++ + /* 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 -=================================================================== -RCS file: /afs/ir.stanford.edu/users/b/l/blp/private/cvs/pintos/src/userprog/exception.c,v -retrieving revision 1.10 -diff -u -p -r1.10 exception.c ---- src/userprog/exception.c 26 Sep 2004 21:15:17 -0000 1.10 -+++ src/userprog/exception.c 1 Jan 2005 02:13:42 -0000 -@@ -147,6 +147,14 @@ page_fault (struct intr_frame *f) +diff -u src/userprog/exception.c~ src/userprog/exception.c +--- src/userprog/exception.c~ ++++ src/userprog/exception.c +@@ -150,6 +150,14 @@ page_fault (struct intr_frame *f) write = (f->error_code & PF_W) != 0; user = (f->error_code & PF_U) != 0; @@ -268,118 +117,219 @@ diff -u -p -r1.10 exception.c body, and replace it with code that brings in the page to which fault_addr refers. */ Index: src/userprog/process.c -=================================================================== -RCS file: /afs/ir.stanford.edu/users/b/l/blp/private/cvs/pintos/src/userprog/process.c,v -retrieving revision 1.6 -diff -u -p -r1.6 process.c ---- src/userprog/process.c 15 Dec 2004 02:32:02 -0000 1.6 -+++ src/userprog/process.c 1 Jan 2005 02:13:43 -0000 -@@ -18,7 +18,17 @@ +diff -u src/userprog/process.c~ src/userprog/process.c +--- src/userprog/process.c~ ++++ src/userprog/process.c +@@ -14,11 +14,23 @@ + #include "threads/init.h" + #include "threads/interrupt.h" ++#include "threads/malloc.h" + #include "threads/palloc.h" #include "threads/thread.h" + #include "threads/vaddr.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. */ -+ struct semaphore load_done; /* "Up"ed when loading complete. */ -+ bool success; /* True if program successfully loaded. */ ++ 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 before -@@ -26,31 +36,31 @@ static bool load (const char *cmdline, v + FILE_NAME. The new thread may be scheduled (and may even exit) +@@ -27,29 +39,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 thread_name[16]; ++ 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; -+ sema_init (&exec.load_done, 0, "load done"); ++ 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); -+ tid = thread_create (filename, PRI_DEFAULT, execute_thread, &exec); ++ strlcpy (thread_name, file_name, sizeof thread_name); ++ strtok_r (thread_name, " ", &save_ptr); ++ tid = thread_create (thread_name, PRI_DEFAULT, start_process, &exec); + if (tid != TID_ERROR) + { + sema_down (&exec.load_done); -+ if (!exec.success) ++ if (exec.success) ++ list_push_back (&thread_current ()->children, &exec.wait_status->elem); ++ else + tid = TID_ERROR; + } ++ return tid; } /* 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; + bool success; - /* Initialize interrupt frame and load executable. */ - memset (&if_, 0, sizeof if_); -@@ -59,11 +69,9 @@ execute_thread (void *filename_) +@@ -58,10 +78,29 @@ 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; - if_.ss = SEL_UDSEG; -- success = load (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) ++ { ++ exec->wait_status = thread_current ()->wait_status ++ = malloc (sizeof *exec->wait_status); ++ success = exec->wait_status != NULL; ++ } + - /* If load failed, quit. */ -- palloc_free_page (filename); -- if (!success) -+ exec->success = load (exec->filename, &if_.eip, &if_.esp); +- palloc_free_page (file_name); ++ /* Initialize wait_status. */ ++ if (success) ++ { ++ lock_init (&exec->wait_status->lock); ++ exec->wait_status->ref_cnt = 2; ++ exec->wait_status->tid = thread_current ()->tid; ++ exec->wait_status->exit_code = -1; ++ sema_init (&exec->wait_status->dead, 0); ++ } ++ ++ /* Notify parent thread and clean up. */ ++ exec->success = success; + sema_up (&exec->load_done); -+ if (!exec->success) + if (!success) thread_exit (); - /* Switch page tables. */ -@@ -89,6 +97,8 @@ process_exit (void) +@@ -75,18 +113,47 @@ start_process (void *file_name_) + NOT_REACHED (); + } + ++/* Releases one reference to CS and, if it is now unreferenced, ++ frees it. */ ++static void ++release_child (struct wait_status *cs) ++{ ++ int new_ref_cnt; ++ ++ lock_acquire (&cs->lock); ++ new_ref_cnt = --cs->ref_cnt; ++ lock_release (&cs->lock); ++ ++ if (new_ref_cnt == 0) ++ free (cs); ++} ++ + /* Waits for thread TID to die and returns its exit status. If + it was terminated by the kernel (i.e. killed due to an + exception), returns -1. If TID is invalid or if it was not a + child of the calling process, or if process_wait() has already + been successfully called for the given TID, returns -1 +- immediately, without waiting. +- +- This function will be implemented in problem 2-2. For now, it +- does nothing. */ ++ immediately, without waiting. */ + int +-process_wait (tid_t child_tid UNUSED) ++process_wait (tid_t child_tid) + { ++ struct thread *cur = thread_current (); ++ struct list_elem *e; ++ ++ for (e = list_begin (&cur->children); e != list_end (&cur->children); ++ e = list_next (e)) ++ { ++ struct wait_status *cs = list_entry (e, struct wait_status, elem); ++ if (cs->tid == child_tid) ++ { ++ int exit_code; ++ list_remove (e); ++ sema_down (&cs->dead); ++ exit_code = cs->exit_code; ++ release_child (cs); ++ return exit_code; ++ } ++ } + return -1; + } + +@@ -95,8 +162,30 @@ void + process_exit (void) + { struct thread *cur = thread_current (); ++ struct list_elem *e, *next; uint32_t *pd; -+ printf ("%s: exit(%d)\n", cur->name, cur->exit_code); ++ /* Close executable (and allow writes). */ ++ file_close (cur->bin_file); ++ ++ /* Notify parent that we're dead. */ ++ if (cur->wait_status != NULL) ++ { ++ struct wait_status *cs = cur->wait_status; ++ printf ("%s: exit(%d)\n", cur->name, cs->exit_code); ++ sema_up (&cs->dead); ++ release_child (cs); ++ } + ++ /* Free entries of children list. */ ++ for (e = list_begin (&cur->children); e != list_end (&cur->children); ++ e = next) ++ { ++ struct wait_status *cs = list_entry (e, struct wait_status, elem); ++ next = list_remove (e); ++ release_child (cs); ++ } ++ /* Destroy the current process's page directory and switch back - to the kernel-only page directory. We have to set - cur->pagedir to NULL before switching page directories, or a -@@ -182,7 +192,7 @@ struct Elf32_Phdr + to the kernel-only page directory. */ + pd = cur->pagedir; +@@ -193,7 +284,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); - - /* Aborts loading an executable, with an error message. */ - #define LOAD_ERROR(MSG) \ -@@ -198,13 +208,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, + bool writable); +@@ -209,13 +300,15 @@ static bool setup_stack (void **esp); 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; @@ -387,23 +337,32 @@ diff -u -p -r1.6 process.c + char *cp; int i; - /* Allocate page directory. */ -@@ -212,6 +224,14 @@ load (const char *filename, void (**eip) - if (t->pagedir == NULL) - LOAD_ERROR (("page directory allocation failed")); + /* Allocate and activate page directory. */ +@@ -224,13 +317,22 @@ load (const char *file_name, void (**eip) + goto done; + process_activate (); -+ /* 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); - if (file == NULL) -@@ -272,7 +292,7 @@ load (const char *filename, void (**eip) +- file = filesys_open (file_name); ++ t->bin_file = file = filesys_open (file_name); + if (file == NULL) + { + printf ("load: %s: open failed\n", file_name); + goto done; + } ++ file_deny_write (file); + + /* Read and verify executable header. */ + if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr +@@ -284,7 +386,7 @@ load (const char *file_name, void (**eip) } /* Set up stack. */ @@ -412,7 +371,15 @@ diff -u -p -r1.6 process.c goto done; /* Start address. */ -@@ -381,10 +401,92 @@ load_segment (struct file *file, const s +@@ -294,7 +396,6 @@ load (const char *file_name, void (**eip) + + done: + /* We arrive here whether the load is successful or not. */ +- file_close (file); + return success; + } + +@@ -393,10 +494,92 @@ load_segment (struct file *file, const s return true; } @@ -478,7 +445,7 @@ diff -u -p -r1.6 process.c + for (karg = strtok_r (cmd_line_copy, " ", &saveptr); karg != NULL; + karg = strtok_r (NULL, " ", &saveptr)) + { -+ char *uarg = upage + (karg - (char *) kpage); ++ void *uarg = upage + (karg - (char *) kpage); + if (push (kpage, &ofs, &uarg, sizeof uarg) == NULL) + return false; + argc++; @@ -508,49 +475,46 @@ diff -u -p -r1.6 process.c { uint8_t *kpage; bool success = false; -@@ -392,9 +494,9 @@ setup_stack (void **esp) +@@ -404,9 +587,9 @@ setup_stack (void **esp) kpage = palloc_get_page (PAL_USER | PAL_ZERO); if (kpage != NULL) { -- success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage); +- success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage, true); - if (success) - *esp = PHYS_BASE; + uint8_t *upage = ((uint8_t *) PHYS_BASE) - PGSIZE; -+ if (install_page (upage, kpage)) ++ if (install_page (upage, kpage, true)) + success = init_cmd_line (kpage, upage, cmd_line, esp); else palloc_free_page (kpage); } Index: src/userprog/syscall.c -=================================================================== -RCS file: /afs/ir.stanford.edu/users/b/l/blp/private/cvs/pintos/src/userprog/syscall.c,v -retrieving revision 1.4 -diff -u -p -r1.4 syscall.c ---- src/userprog/syscall.c 26 Sep 2004 21:15:17 -0000 1.4 -+++ src/userprog/syscall.c 1 Jan 2005 02:13:43 -0000 -@@ -1,20 +1,478 @@ +diff -u src/userprog/syscall.c~ src/userprog/syscall.c +--- src/userprog/syscall.c~ ++++ src/userprog/syscall.c +@@ -1,20 +1,486 @@ #include "userprog/syscall.h" #include +#include #include +#include "userprog/process.h" +#include "userprog/pagedir.h" -+#include "devices/kbd.h" ++#include "devices/input.h" ++#include "devices/shutdown.h" +#include "filesys/filesys.h" +#include "filesys/file.h" -+#include "threads/init.h" #include "threads/interrupt.h" +#include "threads/malloc.h" -+#include "threads/mmu.h" +#include "threads/palloc.h" #include "threads/thread.h" ++#include "threads/vaddr.h" - + + +static int sys_halt (void); +static int sys_exit (int status); +static int sys_exec (const char *ufile); -+static int sys_join (tid_t); ++static int sys_wait (tid_t); +static int sys_create (const char *ufile, unsigned initial_size); +static int sys_remove (const char *ufile); +static int sys_open (const char *ufile); @@ -565,13 +529,14 @@ diff -u -p -r1.4 syscall.c - +static void copy_in (void *, const void *, size_t); + ++/* Serializes file system operations. */ +static struct lock fs_lock; + void syscall_init (void) { - intr_register (0x30, 3, INTR_ON, syscall_handler, "syscall"); -+ lock_init (&fs_lock, "fs"); + intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall"); ++ lock_init (&fs_lock); } + +/* System call handler. */ @@ -588,12 +553,12 @@ diff -u -p -r1.4 syscall.c + }; + + /* Table of system calls. */ -+ static const struct syscall syscall_table[] = ++ static const struct syscall syscall_table[] = + { + {0, (syscall_function *) sys_halt}, + {1, (syscall_function *) sys_exit}, + {1, (syscall_function *) sys_exec}, -+ {1, (syscall_function *) sys_join}, ++ {1, (syscall_function *) sys_wait}, + {2, (syscall_function *) sys_create}, + {1, (syscall_function *) sys_remove}, + {1, (syscall_function *) sys_open}, @@ -605,13 +570,13 @@ diff -u -p -r1.4 syscall.c + {1, (syscall_function *) sys_close}, + }; + -+ struct syscall *sc; -+ int call_nr; ++ const struct syscall *sc; ++ unsigned call_nr; + int args[3]; + + /* Get the system call. */ + copy_in (&call_nr, f->esp, sizeof call_nr); -+ if (call_nr < 0 || call_nr >= sizeof syscall_table / sizeof *syscall_table) ++ if (call_nr >= sizeof syscall_table / sizeof *syscall_table) + thread_exit (); + sc = syscall_table + call_nr; @@ -630,7 +595,8 @@ diff -u -p -r1.4 syscall.c +static bool +verify_user (const void *uaddr) +{ -+ return pagedir_get_page (thread_current ()->pagedir, uaddr) != NULL; ++ return (uaddr < PHYS_BASE ++ && pagedir_get_page (thread_current ()->pagedir, uaddr) != NULL); +} + +/* Copies a byte from user address USRC to kernel address DST. @@ -640,7 +606,7 @@ diff -u -p -r1.4 syscall.c +get_user (uint8_t *dst, const uint8_t *usrc) +{ + int eax; -+ asm ("mov %%eax, offset 1f; mov %%al, %2; mov %0, %%al; 1:" ++ asm ("movl $1f, %%eax; movb %2, %%al; movb %%al, %0; 1:" + : "=m" (*dst), "=&a" (eax) : "m" (*usrc)); + return eax != 0; +} @@ -652,8 +618,8 @@ diff -u -p -r1.4 syscall.c +put_user (uint8_t *udst, uint8_t byte) +{ + int eax; -+ asm ("mov %%eax, offset 1f; mov %0, %b2; 1:" -+ : "=m" (*udst), "=&a" (eax) : "r" (byte)); ++ asm ("movl $1f, %%eax; movb %b2, %0; 1:" ++ : "=m" (*udst), "=&a" (eax) : "q" (byte)); + return eax != 0; +} + @@ -690,7 +656,10 @@ diff -u -p -r1.4 syscall.c + for (length = 0; length < PGSIZE; length++) + { + if (us >= (char *) PHYS_BASE || !get_user (ks + length, us++)) -+ thread_exit (); ++ { ++ palloc_free_page (ks); ++ thread_exit (); ++ } + + if (ks[length] == '\0') + return ks; @@ -703,14 +672,14 @@ diff -u -p -r1.4 syscall.c +static int +sys_halt (void) +{ -+ power_off (); ++ shutdown_power_off (); +} + +/* Exit system call. */ +static int +sys_exit (int exit_code) +{ -+ thread_current ()->exit_code = exit_code; ++ thread_current ()->wait_status->exit_code = exit_code; + thread_exit (); + NOT_REACHED (); +} @@ -731,11 +700,11 @@ diff -u -p -r1.4 syscall.c + return tid; +} + -+/* Join system call. */ ++/* Wait system call. */ +static int -+sys_join (tid_t child) ++sys_wait (tid_t child) +{ -+ return thread_join (child); ++ return process_wait (child); +} + +/* Create system call. */ @@ -774,9 +743,9 @@ diff -u -p -r1.4 syscall.c +/* A file descriptor, for binding a file handle to a file. */ +struct file_descriptor + { -+ list_elem elem; /* List element. */ -+ struct file *file; /* File. */ -+ int handle; /* File handle. */ ++ struct list_elem elem; /* List element. */ ++ struct file *file; /* File. */ ++ int handle; /* File handle. */ + }; + +/* Open system call. */ @@ -814,7 +783,7 @@ diff -u -p -r1.4 syscall.c +lookup_fd (int handle) +{ + struct thread *cur = thread_current (); -+ list_elem *e; ++ struct list_elem *e; + + for (e = list_begin (&cur->fds); e != list_end (&cur->fds); + e = list_next (e)) @@ -826,7 +795,7 @@ diff -u -p -r1.4 syscall.c + } + thread_exit (); -+} + } + +/* Filesize system call. */ +static int @@ -854,7 +823,7 @@ diff -u -p -r1.4 syscall.c + if (handle == STDIN_FILENO) + { + for (bytes_read = 0; (size_t) bytes_read < size; bytes_read++) -+ if (udst >= (uint8_t *) PHYS_BASE || !put_user (udst++, kbd_getc ())) ++ if (udst >= (uint8_t *) PHYS_BASE || !put_user (udst++, input_getc ())) + thread_exit (); + return bytes_read; + } @@ -962,7 +931,8 @@ diff -u -p -r1.4 syscall.c + struct file_descriptor *fd = lookup_fd (handle); + + lock_acquire (&fs_lock); -+ file_seek (fd->file, position); ++ if ((off_t) position >= 0) ++ file_seek (fd->file, position); + lock_release (&fs_lock); + + return 0; @@ -1000,24 +970,23 @@ diff -u -p -r1.4 syscall.c +syscall_exit (void) +{ + struct thread *cur = thread_current (); -+ list_elem *e, *next; ++ struct list_elem *e, *next; + + for (e = list_begin (&cur->fds); e != list_end (&cur->fds); e = next) + { + struct file_descriptor *fd; + fd = list_entry (e, struct file_descriptor, elem); + next = list_next (e); ++ lock_acquire (&fs_lock); + file_close (fd->file); ++ lock_release (&fs_lock); + free (fd); + } - } ++} Index: src/userprog/syscall.h -=================================================================== -RCS file: /afs/ir.stanford.edu/users/b/l/blp/private/cvs/pintos/src/userprog/syscall.h,v -retrieving revision 1.2 -diff -u -p -r1.2 syscall.h ---- src/userprog/syscall.h 6 Sep 2004 05:38:45 -0000 1.2 -+++ src/userprog/syscall.h 1 Jan 2005 02:13:43 -0000 +diff -u src/userprog/syscall.h~ src/userprog/syscall.h +--- src/userprog/syscall.h~ ++++ src/userprog/syscall.h @@ -2,5 +2,6 @@ #define USERPROG_SYSCALL_H