Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • y2-rhymansaib/pintos_student
1 result
Select Git revision
Show changes
Commits on Source (13)
......@@ -59,7 +59,8 @@ static unsigned thread_ticks; /* # of timer ticks since last yield. */
If true, use multi-level feedback queue scheduler.
Controlled by kernel command-line option "-o mlfqs". */
bool thread_mlfqs;
/* file descriptor lock */
struct lock file_lock;
static void kernel_thread (thread_func *, void *aux);
static void idle (void *aux UNUSED);
......@@ -179,6 +180,7 @@ thread_create (const char *name, int priority,
struct switch_entry_frame *ef;
struct switch_threads_frame *sf;
tid_t tid;
enum intr_level old_level;
ASSERT (function != NULL);
......@@ -191,6 +193,11 @@ thread_create (const char *name, int priority,
init_thread (t, name, priority);
tid = t->tid = allocate_tid ();
/* Prepare thread for first run by initializing its stack.
Do this atomically so intermediate values for the 'stack'
member cannot be observed. */
old_level = intr_disable ();
/* Stack frame for kernel_thread(). */
kf = alloc_frame (t, sizeof *kf);
kf->eip = NULL;
......@@ -206,6 +213,21 @@ thread_create (const char *name, int priority,
sf->eip = switch_entry;
sf->ebp = 0;
intr_set_level (old_level);
/* Set Value */
t->next_fd = 2;
t->file_descriptor = palloc_get_page(0);
if(t->file_descriptor == NULL)
return TID_ERROR;
t->childelem.next = NULL;
t->childelem.prev = NULL;
t->parent_thread = thread_current();
t->load_success = false;
t->process_exit = false;
sema_init(&(t->load_semaphore),0);
sema_init(&(t->exit_semaphore),0);
list_push_back(&(thread_current()->child_list),&(t->childelem));
/* Add to run queue. */
thread_unblock (t);
......
......@@ -83,6 +83,7 @@ typedef int tid_t;
struct thread
{
/* Owned by thread.c. */
struct list_elem childelem;
tid_t tid; /* Thread identifier. */
enum thread_status status; /* Thread state. */
char name[16]; /* Name (for debugging purposes). */
......@@ -96,10 +97,23 @@ struct thread
#ifdef USERPROG
/* Owned by userprog/process.c. */
uint32_t *pagedir; /* Page directory. */
uint8_t *current_esp; /* The current value of the user program’s stack pointer.
A page fault might occur in the kernel, so we might
need to store esp on transition to kernel mode*/
#endif
/* Owned by thread.c. */
unsigned magic; /* Detects stack overflow. */
/* VALUE */
struct file **file_descriptor;
int next_fd;
bool load_success;
bool process_exit;
int process_exit_status;
struct semaphore load_semaphore;
struct semaphore exit_semaphore;
struct thread *parent_thread;
struct list child_list;
};
/* If false (default), use round-robin scheduler.
......
......@@ -21,6 +21,9 @@
static thread_func start_process NO_RETURN;
static bool load(const char *cmdline, void (**eip)(void), void **esp);
#define WORD_SIZE 4
/* Starts a new thread running a user program loaded from
FILENAME. The new thread may be scheduled (and may even exit)
before process_execute() returns. Returns the new process's
......@@ -28,24 +31,104 @@ static bool load (const char *cmdline, void (**eip) (void), void **esp);
tid_t
process_execute(const char *file_name)
{
char *fn_copy;
char *file_copy;
tid_t tid;
char *ptr = NULL;
int file_name_length = strlen(file_name) + 1;
char program[file_name_length];
/* 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)
/* Make a copy of command line. Otherwise there's a race between the caller and load(). */
file_copy = palloc_get_page(0);
if (file_copy == NULL)
return TID_ERROR;
strlcpy (fn_copy, file_name, PGSIZE);
strlcpy(file_copy, file_name, PGSIZE);
/* Parse first argument as program name */
strlcpy(program, file_name, file_name_length);
strtok_r(program, " ", &ptr);
printf("\nProgram name: %s\n\n", program) ;
/* Create a new thread to execute FILE_NAME. */
tid = thread_create (file_name, PRI_DEFAULT, start_process, fn_copy);
tid = thread_create(file_name, PRI_DEFAULT, start_process, file_copy);
if (tid == TID_ERROR)
palloc_free_page (fn_copy);
{
palloc_free_page(file_copy);
}
return tid;
}
/* add file to file descriptor */
int process_add_file(struct file *f)
{
struct file **fd = NULL;
int nextFd;
fd = thread_current()->file_descriptor;
nextFd = thread_current()->next_fd;
if(fd != NULL)
{
fd[nextFd] = f;
thread_current()->next_fd = thread_current()->next_fd+1;
return nextFd;
}
else
{
return -1;
}
}
/* get struct file */
struct file *process_get_file(int fd)
{
struct file *pReturn;
if(fd < thread_current()->next_fd)
{
pReturn = thread_current()->file_descriptor[fd];
return pReturn;
}
else
{
return NULL;
}
}
/* close file function */
void
process_close_file(int fd)
{
struct file *delete_file;
delete_file = process_get_file(fd);
if(delete_file != NULL)
{
file_close(delete_file);
thread_current()->file_descriptor[fd] = NULL;
}
}
/* get_child_process */
struct thread *get_child_process(int pid)
{
struct list *child_list=&(thread_current()->child_list);
struct thread *child_process = NULL;
struct list_elem *element;
/* find child process and return */
for(element=list_begin(child_list); element != list_end(child_list); element=list_next(element))
{
child_process = list_entry(element,struct thread,childelem);
if(child_process->tid == pid)
return child_process;
}
return NULL;
}
/* remove_child_process */
void
remove_child_process(struct thread *cp)
{
if(cp != NULL)
{
list_remove(&(cp->childelem));
palloc_free_page(cp);
}
}
/* A thread function that loads a user process and starts it
running. */
static void
......@@ -54,6 +137,19 @@ start_process (void *file_name_)
char *file_name = file_name_;
struct intr_frame if_;
bool success;
char *parse[250];
char *token;
char *ptr;
int count = 0;
for (token = strtok_r(file_name, " ", &ptr); token != NULL;
token = strtok_r(NULL, " ", &ptr))
{
parse[count] = token;
count++;
printf("\nTokenized Argument: %s\n", parse[count - 1]);
}
printf("\nNumber of tokenized Arguments : %d\n", count);
/* Initialize interrupt frame and load executable. */
memset(&if_, 0, sizeof if_);
......@@ -61,7 +157,12 @@ start_process (void *file_name_)
if_.cs = SEL_UCSEG;
if_.eflags = FLAG_IF | FLAG_MBS;
success = load (file_name, &if_.eip, &if_.esp);
success = load(parse[0], &if_.eip, &if_.esp);
argument_pushing(&parse, count, &if_.esp);
sema_up(&(thread_current()->load_semaphore));
//hex_dump(if_.esp, if_.esp, PHYS_BASE - if_.esp, true);
/* If load failed, quit. */
palloc_free_page(file_name);
......@@ -136,7 +237,7 @@ process_activate (void)
interrupts. */
tss_update();
}
/* We load ELF binaries. The following definitions are taken
from the ELF specification, [ELF1], more-or-less verbatim. */
......@@ -236,13 +337,7 @@ load (const char *file_name, void (**eip) (void), void **esp)
}
/* Read and verify executable header. */
if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr
|| memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7)
|| ehdr.e_type != 2
|| ehdr.e_machine != 3
|| ehdr.e_version != 1
|| ehdr.e_phentsize != sizeof (struct Elf32_Phdr)
|| ehdr.e_phnum > 1024)
if (file_read(file, &ehdr, sizeof ehdr) != sizeof ehdr || memcmp(ehdr.e_ident, "\177ELF\1\1\1", 7) || ehdr.e_type != 2 || ehdr.e_machine != 3 || ehdr.e_version != 1 || ehdr.e_phentsize != sizeof(struct Elf32_Phdr) || ehdr.e_phnum > 1024)
{
printf("load: %s: error loading executable\n", file_name);
goto done;
......@@ -287,8 +382,7 @@ load (const char *file_name, void (**eip) (void), void **esp)
/* Normal segment.
Read initial part from disk and zero the rest. */
read_bytes = page_offset + phdr.p_filesz;
zero_bytes = (ROUND_UP (page_offset + phdr.p_memsz, PGSIZE)
- read_bytes);
zero_bytes = (ROUND_UP(page_offset + phdr.p_memsz, PGSIZE) - read_bytes);
}
else
{
......@@ -321,7 +415,7 @@ load (const char *file_name, void (**eip) (void), void **esp)
file_close(file);
return success;
}
/* load() helpers. */
static bool install_page(void *upage, void *kpage, bool writable);
......@@ -429,6 +523,62 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage,
}
return true;
}
/* References: J,Choi(2014), pintos. Available from: https://github.com/wookayin/pintos [accessed on 23/11/22]*/
void
argument_pushing(char **parse, int count, void **esp)
{
int i, j;
int length = 0; // Argument length
int parse0_address; // First Argument's Adress
int address[count]; // Argument adress
/*Push arguments to stack one by one*/
for (i = count - 1; i > -1; i--)
{
for (j = strlen(parse[i]); j > -1; j--)
{
*esp = *esp - 1;
**(char **)esp = parse[i][j];
length++; /*Count length of arguments we pushed*/
}
/*Store address of argument*/
address[i] = *(unsigned int *)esp;
printf("\nAdress of %d 's argument: %d\n", i + 1, address[i]);
}
printf("\nNumber of arguments pushed onto stack: %d\n", length);
/* Word Allignment*/
for (i = 0; i < 4 - (length % 4); i++)
{
*esp = *esp - 1;
**(uint8_t **)esp = 0;
}
/* Last argument needs to be NULL*/
*esp -= 4;
**(char ***)esp = 0;
/*Push argument adress - Use counter to set **esp */
for (i = count - 1; i >= 0; i--)
{
*esp -= 4;
**(char* **)esp = (char *)address[i];
}
/* Set **argv*/
parse0_address = *(unsigned int *)esp;
*esp -= 4;
**(char* **)esp = (char *)parse0_address;
/* Set counter*/
*esp -= 4;
*(int *)*esp = count;
/*Fake Adress - Set ret*/
*esp -= 4;
*(int *)*esp = 0;
}
/* Create a minimal stack by mapping a zeroed page at the top of
user virtual memory. */
......@@ -442,9 +592,9 @@ setup_stack (void **esp)
if (kpage != NULL)
{
success = install_page(((uint8_t *)PHYS_BASE) - PGSIZE, kpage, true);
if (success) {
if (success)
*esp = PHYS_BASE;
} else
else
palloc_free_page(kpage);
}
return success;
......@@ -466,8 +616,8 @@ install_page (void *upage, void *kpage, bool writable)
/* 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));
return (pagedir_get_page(t->pagedir, upage) == NULL && pagedir_set_page(t->pagedir, upage, kpage, writable));
}
//--------------------------------------------------------------------
......@@ -3,9 +3,20 @@
#include "threads/thread.h"
void argument_pushing(char **parse, int count, void **esp);
struct thread *get_child_process(int pid);
void remove_child_process(struct thread *cp);
int process_add_file(struct file *f);
struct file *process_get_file(int fd);
void process_close_file(int fd);
void process_exit(void);
tid_t process_execute (const char *file_name);
int process_wait (tid_t);
void process_exit (void);
void process_activate (void);
#endif /* userprog/process.h */
#include "userprog/syscall.h"
#include <stdbool.h>
#include <stdio.h>
#include <syscall-nr.h>
#include "threads/interrupt.h"
#include "threads/thread.h"
#include "threads/vaddr.h"
#include <devices/shutdown.h>
#include <filesys/filesys.h>
#include <filesys/file.h>
#include <userprog/process.h>
#include <devices/input.h>
static void syscall_handler (struct intr_frame *);
/*System call initializer*/
void
syscall_init (void)
{
intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall");
}
/*Handler for system commands.*/
static void
syscall_handler (struct intr_frame *f UNUSED)
{
printf ("system call!\n");
int syscall_number;
int argument[5];
void *esp = f->esp;
check_address(esp);
syscall_number = *(int *)esp;
switch (syscall_number) {
case SYS_HALT: // 0
/*Terminate PintOS*/
syscall_halt();
break;
case SYS_EXIT: //1
get_argument(esp,argument,1);
syscall_exit(argument[0]);
break;
case SYS_WAIT: // 2
get_argument(esp,argument,1);
f->eax = syscall_wait(argument[0]);
break;
case SYS_CREATE: // 3
get_argument(esp,argument,2);
check_address((void *)argument[0]);
f->eax = syscall_create((const char *)argument[0],(unsigned)argument[1]);
break;
case SYS_REMOVE: // 4
get_argument(esp,argument,1);
check_address((void *)argument[0]);
f->eax=syscall_remove((const char *)argument[0]);
break;
case SYS_WRITE: //5
get_argument(esp,argument,3);
check_address((void *)argument[1]);
f->eax = syscall_write(argument[0],(void *)argument[1],(unsigned)argument[2]);
break;
/* Unimplemented system calls */
default:
printf("ERROR: system call ( %d ) has not implemented!\n", syscall_number);
/* Terminate. */
syscall_exit(-1);
break;
}
}
/********SYSTEMCALLS********/
/* Halt */
void syscall_halt(void) {
shutdown_power_off(); /* From shutdown.h */
}
/* Exit */
void syscall_exit(int status) {
struct thread *current_process=thread_current();
current_process->process_exit_status = status;
printf("%s: exit(%d)\n",current_process->name,status);
thread_exit();
}
/* Wait */
int syscall_wait(tid_t tid)
{
return process_wait(tid);
}
/* Create File */
bool syscall_create(const char* file_name, unsigned initial_size) {
bool if_created = false;
if( filesys_create(file_name, initial_size)==true){
if_created = true;
}
return if_created;
}
/* Remove File */
bool syscall_remove(const char* file_name) {
bool if_removed = false;
if( filesys_remove(file_name)==true){
if_removed = true;
}
return if_removed;
}
/* write file */
int syscall_write(int fd, void *buffer, unsigned size)
{
int write_size = 0;
struct file *current_file;
if(fd == 1) /*stdout */
{
putbuf((const char *)buffer,size);
write_size = size;
}
else
{
current_file = process_get_file(fd);
if(current_file != NULL)
write_size = file_write(current_file,(const void *)buffer,size);
}
return write_size;
}
/****OTHER FUNCTIONS****/
void
check_address(void *addr)
{
uint32_t address=(unsigned int)addr;
uint32_t lowest=0x8048000;
uint32_t highest=0xc0000000;
if(address >= lowest && address < highest){
return;
}
else{
syscall_exit(-1);
}
}
/* get_argument function */
void
get_argument(void *esp, int *argument, int count)
{
int i;
void *stack_ptr=esp+4;
if(count > 0)
{
for(i=0; i<count; i++){
check_address(stack_ptr);
argument[i] = *(int *)stack_ptr;
stack_ptr = stack_ptr + 4;
}
}
}
\ No newline at end of file
#ifndef USERPROG_SYSCALL_H
#define USERPROG_SYSCALL_H
#include "threads/thread.h"
#include <stdbool.h>
#include <stddef.h>
#include "threads/thread.h"
#include <stdbool.h>
#include <stddef.h>
void syscall_init (void);
void check_address(void *addr);
void get_argument(void *esp, int *arg, int count);
void syscall_halt(void);
void syscall_exit(int status);
int syscall_wait(tid_t tid);
bool syscall_create(const char* file_name, unsigned initial_size);
bool syscall_remove(const char* file_name);
int syscall_write(int fd, void *buffer, unsigned size);
#endif /* userprog/syscall.h */