#include "userprog/syscall.h" #include #include #include "threads/interrupt.h" #include "threads/thread.h" #include "filesys/filesys.h" #include "filesys/off_t.h" #include "threads/init.h" #include "threads/malloc.h" static void syscall_handler (struct intr_frame *); void syscall_init (void) { intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall"); } static void halt (void) { power_off(); } static bool create (const char *filename, off_t initial_size) { return filesys_create (filename, initial_size); } static int open (const char *filename) { struct thread *t = thread_current (); if (!t->fds) { printf("[%s] open: allocating %d file descriptors\n", t->name, MAX_FDS); t->fds = (struct fd *) calloc (MAX_FDS, sizeof (struct fd)); } struct file *file = filesys_open(filename); if (!file) { printf("[%s] open: couldn't find file %s\n", t->name, filename); return -1; } for (int i = 0; i < MAX_FDS; i++) { struct fd *fd = t->fds + i; if (!fd->active) { fd->active = true; fd->file = file; return i + 2; // 0 and 1 are reserved for stdin and stdout } } free(file); printf("[%s] open: unable to find empty file descriptor\n", t->name); return -1; } static void write (const char *buf) { printf ("printf: %s", buf); } static void close (int i) { struct thread *t = thread_current (); if (!t->fds) { printf("[%s] close: no files have been opened\n", t->name); return; } struct fd *fd = t->fds + i - 2; // -2 since 0 and 1 are reserved and not present in the array if (!fd->active) { printf("[%s] close: tried to close inactive file descriptor %d\n", t->name, i); return; } free(fd->file); fd->active = false; } // cast to TYPE and deref argument N from f->esp #define INTR_ESP(N, TYPE) *(TYPE *)(f->esp+(4*(N))) static void syscall_handler (struct intr_frame *f UNUSED) { int syscall_number = INTR_ESP (0, int); switch (syscall_number) { case 0: // halt halt (); break; case 1: // exit break; case 4: // create f->eax = create (INTR_ESP (1, char *), INTR_ESP (2, off_t)); break; case 6: // open f->eax = open (INTR_ESP (1, char *)); break; case 8: // read break; case 9: // write write (INTR_ESP(2, char *)); break; case 12: // close close (INTR_ESP(1, int)); break; default: printf ("kernel: unknown syscall '%d'\n", syscall_number); break; } } #undef INTR_ESP