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
  • master
1 result

Target

Select target project
  • y2-rhymansaib/pintos_student
1 result
Select Git revision
  • master
1 result
Show changes
Commits on Source (13)
...@@ -59,7 +59,8 @@ static unsigned thread_ticks; /* # of timer ticks since last yield. */ ...@@ -59,7 +59,8 @@ static unsigned thread_ticks; /* # of timer ticks since last yield. */
If true, use multi-level feedback queue scheduler. If true, use multi-level feedback queue scheduler.
Controlled by kernel command-line option "-o mlfqs". */ Controlled by kernel command-line option "-o mlfqs". */
bool thread_mlfqs; bool thread_mlfqs;
/* file descriptor lock */
struct lock file_lock;
static void kernel_thread (thread_func *, void *aux); static void kernel_thread (thread_func *, void *aux);
static void idle (void *aux UNUSED); static void idle (void *aux UNUSED);
...@@ -179,6 +180,7 @@ thread_create (const char *name, int priority, ...@@ -179,6 +180,7 @@ thread_create (const char *name, int priority,
struct switch_entry_frame *ef; struct switch_entry_frame *ef;
struct switch_threads_frame *sf; struct switch_threads_frame *sf;
tid_t tid; tid_t tid;
enum intr_level old_level;
ASSERT (function != NULL); ASSERT (function != NULL);
...@@ -191,6 +193,11 @@ thread_create (const char *name, int priority, ...@@ -191,6 +193,11 @@ thread_create (const char *name, int priority,
init_thread (t, name, priority); init_thread (t, name, priority);
tid = t->tid = allocate_tid (); 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(). */ /* Stack frame for kernel_thread(). */
kf = alloc_frame (t, sizeof *kf); kf = alloc_frame (t, sizeof *kf);
kf->eip = NULL; kf->eip = NULL;
...@@ -206,6 +213,21 @@ thread_create (const char *name, int priority, ...@@ -206,6 +213,21 @@ thread_create (const char *name, int priority,
sf->eip = switch_entry; sf->eip = switch_entry;
sf->ebp = 0; 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. */ /* Add to run queue. */
thread_unblock (t); thread_unblock (t);
......
...@@ -83,6 +83,7 @@ typedef int tid_t; ...@@ -83,6 +83,7 @@ typedef int tid_t;
struct thread struct thread
{ {
/* Owned by thread.c. */ /* Owned by thread.c. */
struct list_elem childelem;
tid_t tid; /* Thread identifier. */ tid_t tid; /* Thread identifier. */
enum thread_status status; /* Thread state. */ enum thread_status status; /* Thread state. */
char name[16]; /* Name (for debugging purposes). */ char name[16]; /* Name (for debugging purposes). */
...@@ -96,10 +97,23 @@ struct thread ...@@ -96,10 +97,23 @@ struct thread
#ifdef USERPROG #ifdef USERPROG
/* Owned by userprog/process.c. */ /* Owned by userprog/process.c. */
uint32_t *pagedir; /* Page directory. */ 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 #endif
/* Owned by thread.c. */ /* Owned by thread.c. */
unsigned magic; /* Detects stack overflow. */ 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. /* If false (default), use round-robin scheduler.
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
static thread_func start_process 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 *cmdline, void (**eip)(void), void **esp);
#define WORD_SIZE 4
/* Starts a new thread running a user program loaded from /* Starts a new thread running a user program loaded from
FILENAME. The new thread may be scheduled (and may even exit) FILENAME. The new thread may be scheduled (and may even exit)
before process_execute() returns. Returns the new process's before process_execute() returns. Returns the new process's
...@@ -28,24 +31,104 @@ static bool load (const char *cmdline, void (**eip) (void), void **esp); ...@@ -28,24 +31,104 @@ static bool load (const char *cmdline, void (**eip) (void), void **esp);
tid_t tid_t
process_execute(const char *file_name) process_execute(const char *file_name)
{ {
char *fn_copy; char *file_copy;
tid_t tid; 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. /* Make a copy of command line. Otherwise there's a race between the caller and load(). */
Otherwise there's a race between the caller and load(). */ file_copy = palloc_get_page(0);
fn_copy = palloc_get_page (0); if (file_copy == NULL)
if (fn_copy == NULL)
return TID_ERROR; 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. */ /* 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) if (tid == TID_ERROR)
palloc_free_page (fn_copy); {
palloc_free_page(file_copy);
}
return tid; 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 /* A thread function that loads a user process and starts it
running. */ running. */
static void static void
...@@ -54,6 +137,19 @@ start_process (void *file_name_) ...@@ -54,6 +137,19 @@ start_process (void *file_name_)
char *file_name = file_name_; char *file_name = file_name_;
struct intr_frame if_; struct intr_frame if_;
bool success; 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. */ /* Initialize interrupt frame and load executable. */
memset(&if_, 0, sizeof if_); memset(&if_, 0, sizeof if_);
...@@ -61,7 +157,12 @@ start_process (void *file_name_) ...@@ -61,7 +157,12 @@ start_process (void *file_name_)
if_.cs = SEL_UCSEG; if_.cs = SEL_UCSEG;
if_.eflags = FLAG_IF | FLAG_MBS; 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. */ /* If load failed, quit. */
palloc_free_page(file_name); palloc_free_page(file_name);
...@@ -136,7 +237,7 @@ process_activate (void) ...@@ -136,7 +237,7 @@ process_activate (void)
interrupts. */ interrupts. */
tss_update(); tss_update();
} }
/* We load ELF binaries. The following definitions are taken /* We load ELF binaries. The following definitions are taken
from the ELF specification, [ELF1], more-or-less verbatim. */ from the ELF specification, [ELF1], more-or-less verbatim. */
...@@ -236,13 +337,7 @@ load (const char *file_name, void (**eip) (void), void **esp) ...@@ -236,13 +337,7 @@ load (const char *file_name, void (**eip) (void), void **esp)
} }
/* Read and verify executable header. */ /* Read and verify executable header. */
if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr 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)
|| 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); printf("load: %s: error loading executable\n", file_name);
goto done; goto done;
...@@ -287,8 +382,7 @@ load (const char *file_name, void (**eip) (void), void **esp) ...@@ -287,8 +382,7 @@ load (const char *file_name, void (**eip) (void), void **esp)
/* Normal segment. /* Normal segment.
Read initial part from disk and zero the rest. */ Read initial part from disk and zero the rest. */
read_bytes = page_offset + phdr.p_filesz; read_bytes = page_offset + phdr.p_filesz;
zero_bytes = (ROUND_UP (page_offset + phdr.p_memsz, PGSIZE) zero_bytes = (ROUND_UP(page_offset + phdr.p_memsz, PGSIZE) - read_bytes);
- read_bytes);
} }
else else
{ {
...@@ -321,7 +415,7 @@ load (const char *file_name, void (**eip) (void), void **esp) ...@@ -321,7 +415,7 @@ load (const char *file_name, void (**eip) (void), void **esp)
file_close(file); file_close(file);
return success; return success;
} }
/* load() helpers. */ /* load() helpers. */
static bool install_page(void *upage, void *kpage, bool writable); 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, ...@@ -429,6 +523,62 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage,
} }
return true; 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 /* Create a minimal stack by mapping a zeroed page at the top of
user virtual memory. */ user virtual memory. */
...@@ -442,9 +592,9 @@ setup_stack (void **esp) ...@@ -442,9 +592,9 @@ setup_stack (void **esp)
if (kpage != NULL) if (kpage != NULL)
{ {
success = install_page(((uint8_t *)PHYS_BASE) - PGSIZE, kpage, true); success = install_page(((uint8_t *)PHYS_BASE) - PGSIZE, kpage, true);
if (success) { if (success)
*esp = PHYS_BASE; *esp = PHYS_BASE;
} else else
palloc_free_page(kpage); palloc_free_page(kpage);
} }
return success; return success;
...@@ -466,8 +616,8 @@ install_page (void *upage, void *kpage, bool writable) ...@@ -466,8 +616,8 @@ install_page (void *upage, void *kpage, bool writable)
/* Verify that there's not already a page at that virtual /* Verify that there's not already a page at that virtual
address, then map our page there. */ address, then map our page there. */
return (pagedir_get_page (t->pagedir, upage) == NULL return (pagedir_get_page(t->pagedir, upage) == NULL && pagedir_set_page(t->pagedir, upage, kpage, writable));
&& pagedir_set_page (t->pagedir, upage, kpage, writable));
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
...@@ -3,9 +3,20 @@ ...@@ -3,9 +3,20 @@
#include "threads/thread.h" #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); tid_t process_execute (const char *file_name);
int process_wait (tid_t); int process_wait (tid_t);
void process_exit (void); void process_exit (void);
void process_activate (void); void process_activate (void);
#endif /* userprog/process.h */ #endif /* userprog/process.h */
#include "userprog/syscall.h" #include "userprog/syscall.h"
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <syscall-nr.h> #include <syscall-nr.h>
#include "threads/interrupt.h" #include "threads/interrupt.h"
#include "threads/thread.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 *); static void syscall_handler (struct intr_frame *);
/*System call initializer*/
void void
syscall_init (void) syscall_init (void)
{ {
intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall"); intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall");
} }
/*Handler for system commands.*/
static void static void
syscall_handler (struct intr_frame *f UNUSED) 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(); 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 #ifndef USERPROG_SYSCALL_H
#define 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 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 */ #endif /* userprog/syscall.h */