This repository has been archived on 2021-05-26. You can view files and clone it, but cannot push or open issues or pull requests.
OS/pintos-env/pintos/userprog/syscall.c

296 lines
7.1 KiB
C
Raw Normal View History

#include "userprog/syscall.h"
#include <stdio.h>
#include <syscall-nr.h>
#include "threads/interrupt.h"
#include "threads/thread.h"
2020-04-28 13:35:26 +00:00
#include <string.h>
2020-05-18 12:57:52 +00:00
#include "userprog/process.h"
#include "threads/vaddr.h"
#include "userprog/pagedir.h"
2020-05-24 14:27:46 +00:00
#include "lib/kernel/hash.h"
#include "filesys/filesys.h"
#include "filesys/file.h"
2020-04-28 13:35:26 +00:00
typedef int (*handler) (uint32_t, uint32_t, uint32_t);
static handler syscall_vec[128];
static int sys_exit (int status);
2020-05-18 12:57:52 +00:00
static int sys_wait (tid_t tid);
static tid_t sys_exec (const char* file_name);
2020-04-28 13:35:26 +00:00
static void syscall_nop(void);
2020-05-24 14:27:46 +00:00
static void sys_halt(void);
bool sys_create(const char* filename, unsigned initial_size);
bool sys_remove(const char* filename);
int sys_open(const char* file);
int sys_filesize(int fd);
void sys_seek(int fd, unsigned position);
unsigned sys_tell(int fd);
void sys_close(int fd);
int sys_read(int fd, void *buffer, unsigned size);
int sys_write(int fd, const void *buffer, unsigned size);
static void syscall_handler (struct intr_frame *);
2020-05-24 14:27:46 +00:00
struct fd_item {
int fd;
struct file* file;
struct hash_elem elem;
};
int next_fd = 3;
struct hash fd_table;
2020-05-25 17:37:51 +00:00
struct lock filesys_lock;
2020-05-24 14:27:46 +00:00
static unsigned item_hash (const struct hash_elem* e, void* aux) {
struct fd_item* i = hash_entry(e, struct fd_item, elem);
return hash_int(i->fd);
}
static bool item_compare(const struct hash_elem* a, const struct hash_elem* b, void* aux) {
struct fd_item *i_a = hash_entry(a, struct fd_item, elem);
struct fd_item *i_b = hash_entry(b, struct fd_item, elem);
return i_a->fd < i_b->fd;
}
void
syscall_init (void)
{
intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall");
2020-04-28 13:35:26 +00:00
memset(syscall_vec, (int)&syscall_nop, 128);
syscall_vec[SYS_EXIT] = (handler)sys_exit;
2020-05-18 12:57:52 +00:00
syscall_vec[SYS_WAIT] = (handler)sys_wait;
syscall_vec[SYS_EXEC] = (handler)sys_exec;
2020-05-24 14:27:46 +00:00
syscall_vec[SYS_HALT] = (handler)sys_halt;
syscall_vec[SYS_CREATE] = (handler)sys_create;
syscall_vec[SYS_REMOVE] = (handler)sys_remove;
syscall_vec[SYS_OPEN] = (handler)sys_open;
syscall_vec[SYS_FILESIZE] = (handler)sys_filesize;
syscall_vec[SYS_SEEK] = (handler)sys_seek;
syscall_vec[SYS_TELL] = (handler)sys_tell;
syscall_vec[SYS_CLOSE] = (handler)sys_close;
syscall_vec[SYS_READ] = (handler)sys_read;
2020-04-28 13:35:26 +00:00
syscall_vec[SYS_WRITE] = (handler)sys_write;
2020-05-24 14:27:46 +00:00
hash_init(&fd_table, item_hash, item_compare, NULL);
2020-05-25 17:37:51 +00:00
lock_init(&filesys_lock);
2020-05-24 14:27:46 +00:00
}
static bool check_ptr(const void* ptr) {
if (ptr == NULL || is_kernel_vaddr(ptr) ||
pagedir_get_page(thread_current()->pagedir, ptr) == NULL) {
sys_exit(-1);
}
return false;
}
static
void sys_halt(void) {
shutdown_power_off();
}
bool sys_create(const char* filename, unsigned initial_size) {
if (check_ptr(filename)) return 0;
2020-05-25 17:37:51 +00:00
lock_acquire (&filesys_lock);
2020-05-24 14:27:46 +00:00
bool return_code = filesys_create(filename, initial_size);
2020-05-25 17:37:51 +00:00
lock_release (&filesys_lock);
2020-05-24 14:27:46 +00:00
return return_code;
}
bool sys_remove(const char* filename) {
if (check_ptr(filename)) return 0;
2020-05-25 17:37:51 +00:00
lock_acquire (&filesys_lock);
2020-05-24 14:27:46 +00:00
bool return_code = filesys_remove(filename);
2020-05-25 17:37:51 +00:00
lock_release (&filesys_lock);
2020-05-24 14:27:46 +00:00
return return_code;
}
int sys_open(const char* file) {
if (check_ptr(file)) return -1;
struct file* file_opened;
struct fd_item* fd = malloc(sizeof(struct fd_item*));
if (!fd) {
return -1;
}
2020-05-25 17:37:51 +00:00
lock_acquire (&filesys_lock);
2020-05-24 14:27:46 +00:00
file_opened = filesys_open(file);
2020-05-25 17:37:51 +00:00
//printf("File opened: %x\n", file_opened);
2020-05-24 14:27:46 +00:00
if (!file_opened) {
free(fd);
2020-05-25 17:37:51 +00:00
lock_release (&filesys_lock);
2020-05-24 14:27:46 +00:00
return -1;
}
2020-05-25 17:37:51 +00:00
fd->file = file_opened;
2020-05-24 14:27:46 +00:00
fd->fd = next_fd++;
2020-05-25 17:37:51 +00:00
//printf("Hash put: %x %d\n", file_opened, fd->fd);
2020-05-24 14:27:46 +00:00
hash_insert(&fd_table, &fd->elem);
2020-05-25 17:37:51 +00:00
lock_release (&filesys_lock);
2020-05-24 14:27:46 +00:00
return fd->fd;
}
int sys_filesize(int fd) {
2020-05-25 17:37:51 +00:00
lock_acquire (&filesys_lock);
2020-05-24 14:27:46 +00:00
struct fd_item i;
i.fd = fd;
2020-05-25 19:18:53 +00:00
struct hash_elem* h = hash_find(&fd_table, &i.elem);
if (h == NULL) sys_exit(-1);
struct fd_item* file_d = hash_entry(h, struct fd_item, elem);
2020-05-24 14:27:46 +00:00
if(file_d == NULL) {
2020-05-25 17:37:51 +00:00
lock_release (&filesys_lock);
2020-05-24 14:27:46 +00:00
return -1;
}
int ret = file_length(file_d->file);
2020-05-25 17:37:51 +00:00
lock_release (&filesys_lock);
2020-05-24 14:27:46 +00:00
return ret;
}
void sys_seek(int fd, unsigned position) {
2020-05-25 17:37:51 +00:00
lock_acquire (&filesys_lock);
2020-05-24 14:27:46 +00:00
struct fd_item i;
i.fd = fd;
2020-05-25 19:18:53 +00:00
struct hash_elem* h = hash_find(&fd_table, &i.elem);
if (h == NULL) sys_exit(-1);
struct fd_item* file_d = hash_entry(h, struct fd_item, elem);
2020-05-24 14:27:46 +00:00
if(file_d && file_d->file) {
file_seek(file_d->file, position);
}
else
return;
2020-05-25 17:37:51 +00:00
lock_release (&filesys_lock);
2020-05-24 14:27:46 +00:00
}
unsigned sys_tell(int fd) {
2020-05-25 17:37:51 +00:00
lock_acquire (&filesys_lock);
2020-05-24 14:27:46 +00:00
struct fd_item i;
i.fd = fd;
2020-05-25 19:18:53 +00:00
struct hash_elem* h = hash_find(&fd_table, &i.elem);
if (h == NULL) sys_exit(-1);
struct fd_item* file_d = hash_entry(h, struct fd_item, elem);
2020-05-24 14:27:46 +00:00
unsigned ret;
if(file_d && file_d->file) {
ret = file_tell(file_d->file);
}
else
ret = -1;
2020-05-25 17:37:51 +00:00
lock_release (&filesys_lock);
2020-05-24 14:27:46 +00:00
return ret;
}
void sys_close(int fd) {
2020-05-25 17:37:51 +00:00
lock_acquire (&filesys_lock);
2020-05-24 14:27:46 +00:00
struct fd_item i;
i.fd = fd;
struct hash_elem* h = hash_find(&fd_table, &i.elem);
if (h == NULL) sys_exit(-1);
struct fd_item* file_d = hash_entry(h, struct fd_item, elem);
2020-05-25 17:37:51 +00:00
//printf("File close id: %x\n", file_d);
2020-05-24 14:27:46 +00:00
if(file_d && file_d->file) {
2020-05-25 17:37:51 +00:00
//printf("File closed: %x\n", file_d->file);
2020-05-24 14:27:46 +00:00
file_close(file_d->file);
hash_delete(&fd_table, &(file_d->elem));
free(file_d);
}
2020-05-25 17:37:51 +00:00
lock_release (&filesys_lock);
2020-05-24 14:27:46 +00:00
}
int sys_read(int fd, void *buffer, unsigned size) {
if (check_ptr(buffer)||check_ptr(buffer+size)) return -1;
2020-05-25 17:37:51 +00:00
lock_acquire (&filesys_lock);
2020-05-24 14:27:46 +00:00
int ret;
if(fd == 0) {
return -1;
} else {
struct fd_item i;
i.fd = fd;
struct hash_elem* h = hash_find(&fd_table, &i.elem);
if (h == NULL) sys_exit(-1);
struct fd_item* file_d = hash_entry(h, struct fd_item, elem);
2020-05-25 17:37:51 +00:00
if (file_d && file_d->file) {
2020-05-24 14:27:46 +00:00
ret = file_read(file_d->file, buffer, size);
2020-05-25 17:37:51 +00:00
} else ret = -1;
2020-05-24 14:27:46 +00:00
}
2020-05-25 17:37:51 +00:00
lock_release (&filesys_lock);
2020-05-24 14:27:46 +00:00
return ret;
}
int sys_write(int fd, const void *buffer, unsigned size) {
2020-05-25 12:00:30 +00:00
unsigned i;
for (i = 0; i <= size; i++) {
if (check_ptr(buffer + size)) return -1;
}
2020-05-24 14:27:46 +00:00
int ret;
2020-05-25 17:37:51 +00:00
if(fd == 1) {
2020-05-24 14:27:46 +00:00
putbuf(buffer, size);
ret = size;
} else {
2020-05-25 17:37:51 +00:00
lock_acquire (&filesys_lock);
2020-05-24 14:27:46 +00:00
struct fd_item i;
i.fd = fd;
struct hash_elem* h = hash_find(&fd_table, &i.elem);
if (h == NULL) sys_exit(-1);
struct fd_item* file_d = hash_entry(h, struct fd_item, elem);
if(file_d && file_d->file) {
ret = file_write(file_d->file, buffer, size);
}
2020-05-25 17:37:51 +00:00
else ret = -1;
lock_release (&filesys_lock);
2020-05-24 14:27:46 +00:00
}
return ret;
2020-04-28 13:35:26 +00:00
}
static void
syscall_nop(void) {
printf("Syscall not implemented");
}
static void
2020-04-28 13:35:26 +00:00
syscall_handler (struct intr_frame *f)
{
2020-04-28 13:35:26 +00:00
handler h;
int *p;
int ret;
p = f->esp;
h = syscall_vec[*p];
ret = h (*(p + 1), *(p + 2), *(p + 3));
f->eax = ret;
}
int
sys_exit (int status)
{
struct thread* t = thread_current();
2020-05-18 12:57:52 +00:00
t->exit_status = status;
2020-05-18 15:12:13 +00:00
thread_exit();
2020-04-28 13:35:26 +00:00
return -1;
2020-05-18 12:57:52 +00:00
}
int
sys_wait (tid_t tid)
{
2020-05-18 15:12:13 +00:00
int status = process_wait(tid);
return status;
2020-05-18 12:57:52 +00:00
}
tid_t
sys_exec (const char* file_name) {
if (file_name == NULL || is_kernel_vaddr(file_name) ||
pagedir_get_page(thread_current()->pagedir, file_name) == NULL) {
return -1;
}
return process_execute(file_name);
2020-04-28 13:35:26 +00:00
}