X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fuserprog%2Fprocess.c;h=31629c7b594717689115e190e98286bdac3b15c4;hb=5d1a6ed11fee1efccec0b7d8cb30bdc42a52c584;hp=b8d4a14462c63faecf6ac69944db4180b83d2914;hpb=d97c24e174bb94bc9ff96b0094bf25b78a576295;p=pintos-anon diff --git a/src/userprog/process.c b/src/userprog/process.c index b8d4a14..31629c7 100644 --- a/src/userprog/process.c +++ b/src/userprog/process.c @@ -21,8 +21,9 @@ static thread_func execute_thread NO_RETURN; static bool load (const char *cmdline, void (**eip) (void), void **esp); /* Starts a new thread running a user program loaded from - FILENAME. The new thread may be scheduled before - process_execute() returns.*/ + FILENAME. The new thread may be scheduled (and may even exit) + before process_execute() returns. Returns the new process's + thread id, or TID_ERROR if the thread cannot be created. */ tid_t process_execute (const char *filename) { @@ -54,11 +55,9 @@ execute_thread (void *filename_) /* Initialize interrupt frame and load executable. */ memset (&if_, 0, sizeof if_); - if_.es = SEL_UDSEG; - if_.ds = SEL_UDSEG; + 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); /* If load failed, quit. */ @@ -66,22 +65,31 @@ execute_thread (void *filename_) if (!success) thread_exit (); - /* Switch page tables. */ - process_activate (); - /* Start the user process by simulating a return from an interrupt, implemented by intr_exit (in - threads/intr-stubs.pl). Because intr_exit takes all of its + threads/intr-stubs.S). Because intr_exit takes all of its arguments on the stack in the form of a `struct intr_frame', we just point the stack pointer (%esp) to our stack frame and jump to it. */ - asm ("mov %0, %%esp\n" - "jmp intr_exit\n" - : /* no outputs */ - : "g" (&if_)); + asm ("mov %%esp, %0; jmp intr_exit" :: "g" (&if_)); NOT_REACHED (); } +/* 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. */ +int +process_wait (tid_t child_tid UNUSED) +{ + return -1; +} + /* Free the current process's resources. */ void process_exit (void) @@ -90,13 +98,16 @@ process_exit (void) uint32_t *pd; /* 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 - timer interrupt might switch back to the process page - directory. */ + to the kernel-only page directory. */ pd = cur->pagedir; if (pd != NULL) { + /* We must set cur->pagedir to NULL before switching page + directories, so that a timer interrupt can't switch back + to the process page directory. We must activate the + base page directory before destroying the process's page + directory, or our active page directory will be one + that's been freed (and cleared). */ cur->pagedir = NULL; pagedir_activate (NULL); pagedir_destroy (pd); @@ -185,12 +196,12 @@ static bool load_segment (struct file *, const struct Elf32_Phdr *); static bool setup_stack (void **esp); /* Aborts loading an executable, with an error message. */ -#define LOAD_ERROR(MSG) \ - do { \ - printf ("load: %s: ", filename); \ - printf MSG; \ - printf ("\n"); \ - goto done; \ +#define LOAD_ERROR(MSG) \ + do { \ + printf ("load: %s: ", filename); \ + printf MSG; \ + printf ("\n"); \ + goto done; \ } while (0) /* Loads an ELF executable from FILENAME into the current thread. @@ -207,10 +218,11 @@ load (const char *filename, void (**eip) (void), void **esp) bool success = false; int i; - /* Allocate page directory. */ + /* Allocate and activate page directory. */ t->pagedir = pagedir_create (); if (t->pagedir == NULL) LOAD_ERROR (("page directory allocation failed")); + process_activate (); /* Open executable file. */ file = filesys_open (filename); @@ -320,7 +332,7 @@ load_segment (struct file *file, const struct Elf32_Phdr *phdr) } /* p_offset must point within file. */ - if (phdr->p_offset < 0 || phdr->p_offset > file_length (file)) + if (phdr->p_offset > (Elf32_Off) file_length (file)) { printf ("bad p_offset %"PE32Ox, phdr->p_offset); return false; @@ -338,10 +350,10 @@ load_segment (struct file *file, const struct Elf32_Phdr *phdr) /* Validate virtual memory region to be mapped. The region must both start and end within the user address space range starting at 0 and ending at PHYS_BASE (typically - 3 GB == 0xc0000000). */ + 3 GB == 0xc0000000). We don't allow mapping page 0 .*/ start = pg_round_down ((void *) phdr->p_vaddr); end = pg_round_up ((void *) (phdr->p_vaddr + phdr->p_memsz)); - if (start >= PHYS_BASE || end >= PHYS_BASE || end < start) + if (start == 0 || start >= PHYS_BASE || end >= PHYS_BASE || end < start) { printf ("bad virtual region %08lx...%08lx\n", (unsigned long) start, (unsigned long) end);