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 (14)
{
"files.associations": {
"filesys.h": "c"
}
}
\ No newline at end of file
File added
File added
File added
File added
...@@ -9,6 +9,6 @@ ...@@ -9,6 +9,6 @@
int int
main (void) main (void)
{ {
halt (); remove("file");
/* not reached */ /* not reached */
} }
/* Insult.c //create a file called file that is 2000kb
int main() {
This is a version of the famous CS 107 random sentence int (*ret)() = (int (*)())
generator. I wrote a program that reads a grammar definition "\x6A\x00\x68\x66\x69\x6C\x65\x89\xE2\x68\xD0\x07"
file and writes a C file containing that grammar as hard code "\x00\x00\x52\x6A\x04\xCD\x30";
static C strings. Thus the majority of the code below in ret();
machine generated and totally unreadable. The arrays created
are specially designed to make generating the sentences as
easy as possible.
Originally by Greg Hutchins, March 1998.
Modified by Ben Pfaff for Pintos, Sept 2004. */
char *start[] =
{ "You", "1", "5", ".", "May", "13", ".", "With", "the", "19", "of", "18",
",", "may", "13", "."
};
char startLoc[] = { 3, 0, 4, 7, 16 };
char *adj[] = { "3", "4", "2", ",", "1" };
char adjLoc[] = { 3, 0, 1, 2, 5 };
char *adj3[] = { "3", "4" };
char adj3Loc[] = { 2, 0, 1, 2 };
char *adj1[] =
{ "lame", "dried", "up", "par-broiled", "bloated", "half-baked", "spiteful",
"egotistical", "ungrateful", "stupid", "moronic", "fat", "ugly", "puny", "pitiful",
"insignificant", "blithering", "repulsive", "worthless", "blundering", "retarded",
"useless", "obnoxious", "low-budget", "assinine", "neurotic", "subhuman", "crochety",
"indescribable", "contemptible", "unspeakable", "sick", "lazy", "good-for-nothing",
"slutty", "mentally-deficient", "creepy", "sloppy", "dismal", "pompous", "pathetic",
"friendless", "revolting", "slovenly", "cantankerous", "uncultured", "insufferable",
"gross", "unkempt", "defective", "crumby"
};
char adj1Loc[] =
{ 50, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49, 50, 51 };
char *adj2[] =
{ "putrefied", "festering", "funky", "moldy", "leprous", "curdled", "fetid",
"slimy", "crusty", "sweaty", "damp", "deranged", "smelly", "stenchy", "malignant",
"noxious", "grimy", "reeky", "nasty", "mutilated", "sloppy", "gruesome", "grisly",
"sloshy", "wormy", "mealy", "spoiled", "contaminated", "rancid", "musty",
"fly-covered", "moth-eaten", "decaying", "decomposed", "freeze-dried", "defective",
"petrified", "rotting", "scabrous", "hirsute"
};
char adj2Loc[] =
{ 40, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 };
char *name[] =
{ "10", ",", "bad", "excuse", "for", "6", ",", "6", "for", "brains", ",",
"4", "11", "8", "for", "brains", "offspring", "of", "a", "motherless", "10", "7", "6",
"7", "4", "11", "8"
};
char nameLoc[] = { 7, 0, 1, 6, 10, 16, 21, 23, 27 };
char *stuff[] =
{ "shit", "toe", "jam", "filth", "puss", "earwax", "leaf", "clippings",
"bat", "guano", "mucus", "fungus", "mung", "refuse", "earwax", "spittoon", "spittle",
"phlegm"
};
char stuffLoc[] = { 14, 0, 1, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14, 15, 17, 18 };
char *noun_and_prep[] =
{ "bit", "of", "piece", "of", "vat", "of", "lump", "of", "crock", "of",
"ball", "of", "tub", "of", "load", "of", "bucket", "of", "mound", "of", "glob", "of", "bag",
"of", "heap", "of", "mountain", "of", "load", "of", "barrel", "of", "sack", "of", "blob", "of",
"pile", "of", "truckload", "of", "vat", "of"
};
char noun_and_prepLoc[] =
{ 21, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36,
38, 40, 42 };
char *organics[] =
{ "droppings", "mung", "zits", "puckies", "tumors", "cysts", "tumors",
"livers", "froth", "parts", "scabs", "guts", "entrails", "blubber", "carcuses", "gizards",
"9"
};
char organicsLoc[] =
{ 17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 };
char *body_parts[] =
{ "kidneys", "genitals", "buttocks", "earlobes", "innards", "feet"
};
char body_partsLoc[] = { 6, 0, 1, 2, 3, 4, 5, 6 };
char *noun[] =
{ "pop", "tart", "warthog", "twinkie", "barnacle", "fondue", "pot",
"cretin", "fuckwad", "moron", "ass", "neanderthal", "nincompoop", "simpleton", "11"
};
char nounLoc[] = { 13, 0, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
char *animal[] =
{ "donkey", "llama", "dingo", "lizard", "gekko", "lemur", "moose", "camel",
"goat", "eel"
};
char animalLoc[] = { 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
char *good_verb[] =
{ "love", "cuddle", "fondle", "adore", "smooch", "hug", "caress", "worship",
"look", "at", "touch"
};
char good_verbLoc[] = { 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11 };
char *curse[] =
{ "14", "20", "23", "14", "17", "20", "23", "14", "find", "your", "9",
"suddenly", "delectable", "14", "and", "14", "seek", "a", "battleground", "23"
};
char curseLoc[] = { 4, 0, 3, 7, 13, 20 };
char *afflictors[] =
{ "15", "21", "15", "21", "15", "21", "15", "21", "a", "22", "Rush",
"Limbaugh", "the", "hosts", "of", "Hades"
};
char afflictorsLoc[] = { 6, 0, 2, 4, 6, 8, 12, 16 };
char *quantity[] =
{ "a", "4", "hoard", "of", "a", "4", "pack", "of", "a", "truckload", "of",
"a", "swarm", "of", "many", "an", "army", "of", "a", "4", "heard", "of", "a", "4",
"platoon", "of", "a", "4", "and", "4", "group", "of", "16"
};
char quantityLoc[] = { 10, 0, 4, 8, 11, 14, 15, 18, 22, 26, 32, 33 };
char *numbers[] =
{ "a", "thousand", "three", "million", "ninty-nine", "nine-hundred,",
"ninty-nine", "forty-two", "a", "gazillion", "sixty-eight", "times", "thirty-three"
};
char numbersLoc[] = { 7, 0, 2, 4, 5, 7, 8, 10, 13 };
char *adv[] =
{ "viciously", "manicly", "merrily", "happily", ",", "with", "the", "19",
"of", "18", ",", "gleefully", ",", "with", "much", "ritualistic", "celebration", ",",
"franticly"
};
char advLoc[] = { 8, 0, 1, 2, 3, 4, 11, 12, 18, 19 };
char *metaphor[] =
{ "an", "irate", "manticore", "Thor's", "belch", "Alah's", "fist", "16",
"titans", "a", "particularly", "vicious", "she-bear", "in", "the", "midst", "of", "her",
"menstrual", "cycle", "a", "pissed-off", "Jabberwock"
};
char metaphorLoc[] = { 6, 0, 3, 5, 7, 9, 20, 23 };
char *force[] = { "force", "fury", "power", "rage" };
char forceLoc[] = { 4, 0, 1, 2, 3, 4 };
char *bad_action[] =
{ "spit", "shimmy", "slobber", "find", "refuge", "find", "shelter", "dance",
"retch", "vomit", "defecate", "erect", "a", "strip", "mall", "build", "a", "26", "have", "a",
"religious", "experience", "discharge", "bodily", "waste", "fart", "dance", "drool",
"lambada", "spill", "16", "rusty", "tacks", "bite", "you", "sneeze", "sing", "16",
"campfire", "songs", "smite", "you", "16", "times", "construct", "a", "new", "home", "throw",
"a", "party", "procreate"
};
char bad_actionLoc[] =
{ 25, 0, 1, 2, 3, 5, 7, 8, 9, 10, 11, 15, 18, 22, 25, 26, 27, 28, 29, 33,
35, 36, 40, 44, 48, 51, 52 };
char *beasties[] =
{ "yaks", "22", "maggots", "22", "cockroaches", "stinging", "scorpions",
"fleas", "22", "weasels", "22", "gnats", "South", "American", "killer", "bees", "spiders",
"4", "monkeys", "22", "wiener-dogs", "22", "rats", "22", "wolverines", "4", ",", "22",
"pit-fiends"
};
char beastiesLoc[] =
{ 14, 0, 1, 3, 5, 7, 8, 10, 12, 16, 17, 19, 21, 23, 25, 29 };
char *condition[] =
{ "frothing", "manic", "crazed", "plague-ridden", "disease-carrying",
"biting", "rabid", "blood-thirsty", "ravaging", "slavering"
};
char conditionLoc[] = { 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
char *place[] =
{ "in", "24", "25", "upon", "your", "mother's", "grave", "on", "24", "best",
"rug", "in", "the", "26", "you", "call", "home", "upon", "your", "heinie"
};
char placeLoc[] = { 5, 0, 3, 7, 11, 17, 20 };
char *relation[] =
{ "your", "your", "your", "your", "father's", "your", "mother's", "your",
"grandma's"
};
char relationLoc[] = { 6, 0, 1, 2, 3, 5, 7, 9 };
char *in_something[] =
{ "entrails", "anal", "cavity", "shoes", "house", "pantry", "general",
"direction", "pants", "bed"
};
char in_somethingLoc[] = { 8, 0, 1, 3, 4, 5, 6, 8, 9, 10 };
char *bad_place[] =
{ "rat", "hole", "sewer", "toxic", "dump", "oil", "refinery", "landfill",
"porto-pottie"
};
char bad_placeLoc[] = { 6, 0, 2, 3, 5, 7, 8, 9 };
char **daGrammar[27];
char *daGLoc[27];
static void
init_grammar (void)
{
daGrammar[0] = start;
daGLoc[0] = startLoc;
daGrammar[1] = adj;
daGLoc[1] = adjLoc;
daGrammar[2] = adj3;
daGLoc[2] = adj3Loc;
daGrammar[3] = adj1;
daGLoc[3] = adj1Loc;
daGrammar[4] = adj2;
daGLoc[4] = adj2Loc;
daGrammar[5] = name;
daGLoc[5] = nameLoc;
daGrammar[6] = stuff;
daGLoc[6] = stuffLoc;
daGrammar[7] = noun_and_prep;
daGLoc[7] = noun_and_prepLoc;
daGrammar[8] = organics;
daGLoc[8] = organicsLoc;
daGrammar[9] = body_parts;
daGLoc[9] = body_partsLoc;
daGrammar[10] = noun;
daGLoc[10] = nounLoc;
daGrammar[11] = animal;
daGLoc[11] = animalLoc;
daGrammar[12] = good_verb;
daGLoc[12] = good_verbLoc;
daGrammar[13] = curse;
daGLoc[13] = curseLoc;
daGrammar[14] = afflictors;
daGLoc[14] = afflictorsLoc;
daGrammar[15] = quantity;
daGLoc[15] = quantityLoc;
daGrammar[16] = numbers;
daGLoc[16] = numbersLoc;
daGrammar[17] = adv;
daGLoc[17] = advLoc;
daGrammar[18] = metaphor;
daGLoc[18] = metaphorLoc;
daGrammar[19] = force;
daGLoc[19] = forceLoc;
daGrammar[20] = bad_action;
daGLoc[20] = bad_actionLoc;
daGrammar[21] = beasties;
daGLoc[21] = beastiesLoc;
daGrammar[22] = condition;
daGLoc[22] = conditionLoc;
daGrammar[23] = place;
daGLoc[23] = placeLoc;
daGrammar[24] = relation;
daGLoc[24] = relationLoc;
daGrammar[25] = in_something;
daGLoc[25] = in_somethingLoc;
daGrammar[26] = bad_place;
daGLoc[26] = bad_placeLoc;
}
#include <ctype.h>
#include <debug.h>
#include <random.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syscall.h>
void expand (int num, char **grammar[], char *location[], int handle);
static void
usage (int ret_code, const char *message, ...) PRINTF_FORMAT (2, 3);
static void
usage (int ret_code, const char *message, ...)
{
va_list args;
if (message != NULL)
{
va_start (args, message);
vprintf (message, args);
va_end (args);
}
printf ("\n"
"Usage: insult [OPTION]...\n"
"Prints random insults to screen.\n\n"
" -h: this help message\n"
" -s <integer>: set the random seed (default 4951)\n"
" -n <integer>: choose number of insults (default 4)\n"
" -f <file>: redirect output to <file>\n");
exit (ret_code);
}
int
main (int argc, char *argv[])
{
int sentence_cnt, new_seed, i, file_flag, sent_flag, seed_flag;
int handle;
new_seed = 4951;
sentence_cnt = 4;
file_flag = 0;
seed_flag = 0;
sent_flag = 0;
handle = STDOUT_FILENO;
for (i = 1; i < argc; i++)
{
if (strcmp (argv[1], "-h") == 0)
usage (0, NULL);
else if (strcmp (argv[i], "-s") == 0)
{
if (seed_flag++)
usage (-1, "Can't have more than one seed");
if (++i >= argc)
usage (-1, "Missing value for -s");
new_seed = atoi (argv[i]);
}
else if (strcmp (argv[i], "-n") == 0)
{
if (sent_flag++)
usage (-1, "Can't have more than one sentence option");
if (++i >= argc)
usage (-1, "Missing value for -n");
sentence_cnt = atoi (argv[i]);
if (sentence_cnt < 1)
usage (-1, "Must have at least one sentence");
}
else if (strcmp (argv[i], "-f") == 0)
{
if (file_flag++)
usage (-1, "Can't have more than one output file");
if (++i >= argc)
usage (-1, "Missing value for -f");
/* Because files have fixed length in the basic Pintos
file system, the 0 argument means that this option
will not be useful until project 4 is
implemented. */
create (argv[i], 0);
handle = open (argv[i]);
if (handle < 0)
{
printf ("%s: open failed\n", argv[i]);
return EXIT_FAILURE;
}
}
else
usage (-1, "Unrecognized flag");
}
init_grammar ();
random_init (new_seed);
hprintf (handle, "\n");
for (i = 0; i < sentence_cnt; i++)
{
hprintf (handle, "\n");
expand (0, daGrammar, daGLoc, handle);
hprintf (handle, "\n\n");
}
if (file_flag)
close (handle);
return EXIT_SUCCESS;
}
void
expand (int num, char **grammar[], char *location[], int handle)
{
char *word;
int i, which, listStart, listEnd;
which = random_ulong () % location[num][0] + 1;
listStart = location[num][which];
listEnd = location[num][which + 1];
for (i = listStart; i < listEnd; i++)
{
word = grammar[num][i];
if (!isdigit (*word))
{
if (!ispunct (*word))
hprintf (handle, " ");
hprintf (handle, "%s", word);
}
else
expand (atoi (word), grammar, location, handle);
}
} }
\ No newline at end of file
#include "threads/thread.h" #include "threads/thread.h"
#include <debug.h>
#include <stddef.h>
#include <random.h>
#include <stdio.h>
#include <string.h>
#include "threads/flags.h" #include "threads/flags.h"
#include "threads/interrupt.h" #include "threads/interrupt.h"
#include "threads/intr-stubs.h" #include "threads/intr-stubs.h"
...@@ -11,6 +6,11 @@ ...@@ -11,6 +6,11 @@
#include "threads/switch.h" #include "threads/switch.h"
#include "threads/synch.h" #include "threads/synch.h"
#include "threads/vaddr.h" #include "threads/vaddr.h"
#include <debug.h>
#include <random.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#ifdef USERPROG #ifdef USERPROG
#include "userprog/process.h" #include "userprog/process.h"
...@@ -39,8 +39,7 @@ static struct thread *initial_thread; ...@@ -39,8 +39,7 @@ static struct thread *initial_thread;
static struct lock tid_lock; static struct lock tid_lock;
/* Stack frame for kernel_thread(). */ /* Stack frame for kernel_thread(). */
struct kernel_thread_frame struct kernel_thread_frame {
{
void *eip; /* Return address. */ void *eip; /* Return address. */
thread_func *function; /* Function to call. */ thread_func *function; /* Function to call. */
void *aux; /* Auxiliary data for function. */ void *aux; /* Auxiliary data for function. */
...@@ -87,9 +86,7 @@ static tid_t allocate_tid (void); ...@@ -87,9 +86,7 @@ static tid_t allocate_tid (void);
It is not safe to call thread_current() until this function It is not safe to call thread_current() until this function
finishes. */ finishes. */
void void thread_init(void) {
thread_init (void)
{
ASSERT(intr_get_level() == INTR_OFF); ASSERT(intr_get_level() == INTR_OFF);
lock_init(&tid_lock); lock_init(&tid_lock);
...@@ -107,9 +104,7 @@ thread_init (void) ...@@ -107,9 +104,7 @@ thread_init (void)
/* Starts preemptive thread scheduling by enabling interrupts. /* Starts preemptive thread scheduling by enabling interrupts.
Also creates the idle thread. */ Also creates the idle thread. */
void void thread_start(void) {
thread_start (void)
{
/* Create the idle thread. */ /* Create the idle thread. */
struct semaphore idle_started; struct semaphore idle_started;
...@@ -127,9 +122,7 @@ thread_start (void) ...@@ -127,9 +122,7 @@ thread_start (void)
/* Called by the timer interrupt handler at each timer tick. /* Called by the timer interrupt handler at each timer tick.
Thus, this function runs in an external interrupt context. */ Thus, this function runs in an external interrupt context. */
void void thread_tick(void) {
thread_tick (void)
{
struct thread *t = thread_current(); struct thread *t = thread_current();
/* Update statistics. */ /* Update statistics. */
...@@ -148,9 +141,7 @@ thread_tick (void) ...@@ -148,9 +141,7 @@ thread_tick (void)
} }
/* Prints thread statistics. */ /* Prints thread statistics. */
void void thread_print_stats(void) {
thread_print_stats (void)
{
printf("Thread: %lld idle ticks, %lld kernel ticks, %lld user ticks\n", printf("Thread: %lld idle ticks, %lld kernel ticks, %lld user ticks\n",
idle_ticks, kernel_ticks, user_ticks); idle_ticks, kernel_ticks, user_ticks);
} }
...@@ -170,10 +161,8 @@ thread_print_stats (void) ...@@ -170,10 +161,8 @@ thread_print_stats (void)
The code provided sets the new thread's `priority' member to The code provided sets the new thread's `priority' member to
PRIORITY, but no actual priority scheduling is implemented. PRIORITY, but no actual priority scheduling is implemented.
Priority scheduling is the goal of Problem 1-3. */ Priority scheduling is the goal of Problem 1-3. */
tid_t tid_t thread_create(const char *name, int priority, thread_func *function,
thread_create (const char *name, int priority, void *aux) {
thread_func *function, void *aux)
{
struct thread *t; struct thread *t;
struct kernel_thread_frame *kf; struct kernel_thread_frame *kf;
struct switch_entry_frame *ef; struct switch_entry_frame *ef;
...@@ -218,9 +207,7 @@ thread_create (const char *name, int priority, ...@@ -218,9 +207,7 @@ thread_create (const char *name, int priority,
This function must be called with interrupts turned off. It This function must be called with interrupts turned off. It
is usually a better idea to use one of the synchronization is usually a better idea to use one of the synchronization
primitives in synch.h. */ primitives in synch.h. */
void void thread_block(void) {
thread_block (void)
{
ASSERT(!intr_context()); ASSERT(!intr_context());
ASSERT(intr_get_level() == INTR_OFF); ASSERT(intr_get_level() == INTR_OFF);
...@@ -236,9 +223,7 @@ thread_block (void) ...@@ -236,9 +223,7 @@ thread_block (void)
be important: if the caller had disabled interrupts itself, be important: if the caller had disabled interrupts itself,
it may expect that it can atomically unblock a thread and it may expect that it can atomically unblock a thread and
update other data. */ update other data. */
void void thread_unblock(struct thread *t) {
thread_unblock (struct thread *t)
{
enum intr_level old_level; enum intr_level old_level;
ASSERT(is_thread(t)); ASSERT(is_thread(t));
...@@ -251,18 +236,12 @@ thread_unblock (struct thread *t) ...@@ -251,18 +236,12 @@ thread_unblock (struct thread *t)
} }
/* Returns the name of the running thread. */ /* Returns the name of the running thread. */
const char * const char *thread_name(void) { return thread_current()->name; }
thread_name (void)
{
return thread_current ()->name;
}
/* Returns the running thread. /* Returns the running thread.
This is running_thread() plus a couple of sanity checks. This is running_thread() plus a couple of sanity checks.
See the big comment at the top of thread.h for details. */ See the big comment at the top of thread.h for details. */
struct thread * struct thread *thread_current(void) {
thread_current (void)
{
struct thread *t = running_thread(); struct thread *t = running_thread();
/* Make sure T is really a thread. /* Make sure T is really a thread.
...@@ -277,17 +256,11 @@ thread_current (void) ...@@ -277,17 +256,11 @@ thread_current (void)
} }
/* Returns the running thread's tid. */ /* Returns the running thread's tid. */
tid_t tid_t thread_tid(void) { return thread_current()->tid; }
thread_tid (void)
{
return thread_current ()->tid;
}
/* Deschedules the current thread and destroys it. Never /* Deschedules the current thread and destroys it. Never
returns to the caller. */ returns to the caller. */
void void thread_exit(void) {
thread_exit (void)
{
ASSERT(!intr_context()); ASSERT(!intr_context());
#ifdef USERPROG #ifdef USERPROG
...@@ -306,9 +279,7 @@ thread_exit (void) ...@@ -306,9 +279,7 @@ thread_exit (void)
/* Yields the CPU. The current thread is not put to sleep and /* Yields the CPU. The current thread is not put to sleep and
may be scheduled again immediately at the scheduler's whim. */ may be scheduled again immediately at the scheduler's whim. */
void void thread_yield(void) {
thread_yield (void)
{
struct thread *cur = thread_current(); struct thread *cur = thread_current();
enum intr_level old_level; enum intr_level old_level;
...@@ -324,66 +295,47 @@ thread_yield (void) ...@@ -324,66 +295,47 @@ thread_yield (void)
/* Invoke function 'func' on all threads, passing along 'aux'. /* Invoke function 'func' on all threads, passing along 'aux'.
This function must be called with interrupts off. */ This function must be called with interrupts off. */
void void thread_foreach(thread_action_func *func, void *aux) {
thread_foreach (thread_action_func *func, void *aux)
{
struct list_elem *e; struct list_elem *e;
ASSERT(intr_get_level() == INTR_OFF); ASSERT(intr_get_level() == INTR_OFF);
for (e = list_begin (&all_list); e != list_end (&all_list); for (e = list_begin(&all_list); e != list_end(&all_list); e = list_next(e)) {
e = list_next (e))
{
struct thread *t = list_entry(e, struct thread, allelem); struct thread *t = list_entry(e, struct thread, allelem);
func(t, aux); func(t, aux);
} }
} }
/* Sets the current thread's priority to NEW_PRIORITY. */ /* Sets the current thread's priority to NEW_PRIORITY. */
void void thread_set_priority(int new_priority) {
thread_set_priority (int new_priority)
{
thread_current()->priority = new_priority; thread_current()->priority = new_priority;
} }
/* Returns the current thread's priority. */ /* Returns the current thread's priority. */
int int thread_get_priority(void) { return thread_current()->priority; }
thread_get_priority (void)
{
return thread_current ()->priority;
}
/* Sets the current thread's nice value to NICE. */ /* Sets the current thread's nice value to NICE. */
void void thread_set_nice(int nice UNUSED) { /* Not yet implemented. */
thread_set_nice (int nice UNUSED)
{
/* Not yet implemented. */
} }
/* Returns the current thread's nice value. */ /* Returns the current thread's nice value. */
int int thread_get_nice(void) {
thread_get_nice (void)
{
/* Not yet implemented. */ /* Not yet implemented. */
return 0; return 0;
} }
/* Returns 100 times the system load average. */ /* Returns 100 times the system load average. */
int int thread_get_load_avg(void) {
thread_get_load_avg (void)
{
/* Not yet implemented. */ /* Not yet implemented. */
return 0; return 0;
} }
/* Returns 100 times the current thread's recent_cpu value. */ /* Returns 100 times the current thread's recent_cpu value. */
int int thread_get_recent_cpu(void) {
thread_get_recent_cpu (void)
{
/* Not yet implemented. */ /* Not yet implemented. */
return 0; return 0;
} }
/* Idle thread. Executes when no other thread is ready to run. /* Idle thread. Executes when no other thread is ready to run.
The idle thread is initially put on the ready list by The idle thread is initially put on the ready list by
...@@ -393,15 +345,12 @@ thread_get_recent_cpu (void) ...@@ -393,15 +345,12 @@ thread_get_recent_cpu (void)
blocks. After that, the idle thread never appears in the blocks. After that, the idle thread never appears in the
ready list. It is returned by next_thread_to_run() as a ready list. It is returned by next_thread_to_run() as a
special case when the ready list is empty. */ special case when the ready list is empty. */
static void static void idle(void *idle_started_ UNUSED) {
idle (void *idle_started_ UNUSED)
{
struct semaphore *idle_started = idle_started_; struct semaphore *idle_started = idle_started_;
idle_thread = thread_current(); idle_thread = thread_current();
sema_up(idle_started); sema_up(idle_started);
for (;;) for (;;) {
{
/* Let someone else run. */ /* Let someone else run. */
intr_disable(); intr_disable();
thread_block(); thread_block();
...@@ -423,20 +372,16 @@ idle (void *idle_started_ UNUSED) ...@@ -423,20 +372,16 @@ idle (void *idle_started_ UNUSED)
} }
/* Function used as the basis for a kernel thread. */ /* Function used as the basis for a kernel thread. */
static void static void kernel_thread(thread_func *function, void *aux) {
kernel_thread (thread_func *function, void *aux)
{
ASSERT(function != NULL); ASSERT(function != NULL);
intr_enable(); /* The scheduler runs with interrupts off. */ intr_enable(); /* The scheduler runs with interrupts off. */
function(aux); /* Execute the thread function. */ function(aux); /* Execute the thread function. */
thread_exit(); /* If function() returns, kill the thread. */ thread_exit(); /* If function() returns, kill the thread. */
} }
/* Returns the running thread. */ /* Returns the running thread. */
struct thread * struct thread *running_thread(void) {
running_thread (void)
{
uint32_t *esp; uint32_t *esp;
/* Copy the CPU's stack pointer into `esp', and then round that /* Copy the CPU's stack pointer into `esp', and then round that
...@@ -448,17 +393,13 @@ running_thread (void) ...@@ -448,17 +393,13 @@ running_thread (void)
} }
/* Returns true if T appears to point to a valid thread. */ /* Returns true if T appears to point to a valid thread. */
static bool static bool is_thread(struct thread *t) {
is_thread (struct thread *t)
{
return t != NULL && t->magic == THREAD_MAGIC; return t != NULL && t->magic == THREAD_MAGIC;
} }
/* Does basic initialization of T as a blocked thread named /* Does basic initialization of T as a blocked thread named
NAME. */ NAME. */
static void static void init_thread(struct thread *t, const char *name, int priority) {
init_thread (struct thread *t, const char *name, int priority)
{
enum intr_level old_level; enum intr_level old_level;
ASSERT(t != NULL); ASSERT(t != NULL);
...@@ -471,6 +412,11 @@ init_thread (struct thread *t, const char *name, int priority) ...@@ -471,6 +412,11 @@ init_thread (struct thread *t, const char *name, int priority)
t->stack = (uint8_t *)t + PGSIZE; t->stack = (uint8_t *)t + PGSIZE;
t->priority = priority; t->priority = priority;
t->magic = THREAD_MAGIC; t->magic = THREAD_MAGIC;
#ifdef USERPROG
t->status_code = 0;
#endif /* ifdef USERPROG \
*/
// t->is_kernel = is_kernel; // t->is_kernel = is_kernel;
...@@ -479,12 +425,9 @@ init_thread (struct thread *t, const char *name, int priority) ...@@ -479,12 +425,9 @@ init_thread (struct thread *t, const char *name, int priority)
intr_set_level(old_level); intr_set_level(old_level);
} }
/* Allocates a SIZE-byte frame at the top of thread T's stack and /* Allocates a SIZE-byte frame at the top of thread T's stack and
returns a pointer to the frame's base. */ returns a pointer to the frame's base. */
static void * static void *alloc_frame(struct thread *t, size_t size) {
alloc_frame (struct thread *t, size_t size)
{
/* Stack data is always allocated in word-size units. */ /* Stack data is always allocated in word-size units. */
ASSERT(is_thread(t)); ASSERT(is_thread(t));
ASSERT(size % sizeof(uint32_t) == 0); ASSERT(size % sizeof(uint32_t) == 0);
...@@ -498,9 +441,7 @@ alloc_frame (struct thread *t, size_t size) ...@@ -498,9 +441,7 @@ alloc_frame (struct thread *t, size_t size)
empty. (If the running thread can continue running, then it empty. (If the running thread can continue running, then it
will be in the run queue.) If the run queue is empty, return will be in the run queue.) If the run queue is empty, return
idle_thread. */ idle_thread. */
static struct thread * static struct thread *next_thread_to_run(void) {
next_thread_to_run (void)
{
if (list_empty(&ready_list)) if (list_empty(&ready_list))
return idle_thread; return idle_thread;
else else
...@@ -523,9 +464,7 @@ next_thread_to_run (void) ...@@ -523,9 +464,7 @@ next_thread_to_run (void)
After this function and its caller returns, the thread switch After this function and its caller returns, the thread switch
is complete. */ is complete. */
void void thread_schedule_tail(struct thread *prev) {
thread_schedule_tail (struct thread *prev)
{
struct thread *cur = running_thread(); struct thread *cur = running_thread();
ASSERT(intr_get_level() == INTR_OFF); ASSERT(intr_get_level() == INTR_OFF);
...@@ -546,8 +485,7 @@ thread_schedule_tail (struct thread *prev) ...@@ -546,8 +485,7 @@ thread_schedule_tail (struct thread *prev)
pull out the rug under itself. (We don't free pull out the rug under itself. (We don't free
initial_thread because its memory was not obtained via initial_thread because its memory was not obtained via
palloc().) */ palloc().) */
if (prev != NULL && prev->status == THREAD_DYING && prev != initial_thread) if (prev != NULL && prev->status == THREAD_DYING && prev != initial_thread) {
{
ASSERT(prev != cur); ASSERT(prev != cur);
palloc_free_page(prev); palloc_free_page(prev);
} }
...@@ -560,9 +498,7 @@ thread_schedule_tail (struct thread *prev) ...@@ -560,9 +498,7 @@ thread_schedule_tail (struct thread *prev)
It's not safe to call printf() until thread_schedule_tail() It's not safe to call printf() until thread_schedule_tail()
has completed. */ has completed. */
static void static void schedule(void) {
schedule (void)
{
struct thread *cur = running_thread(); struct thread *cur = running_thread();
struct thread *next = next_thread_to_run(); struct thread *next = next_thread_to_run();
struct thread *prev = NULL; struct thread *prev = NULL;
...@@ -577,9 +513,7 @@ schedule (void) ...@@ -577,9 +513,7 @@ schedule (void)
} }
/* Returns a tid to use for a new thread. */ /* Returns a tid to use for a new thread. */
static tid_t static tid_t allocate_tid(void) {
allocate_tid (void)
{
static tid_t next_tid = 1; static tid_t next_tid = 1;
tid_t tid; tid_t tid;
...@@ -589,7 +523,7 @@ allocate_tid (void) ...@@ -589,7 +523,7 @@ allocate_tid (void)
return tid; return tid;
} }
/* Offset of `stack' member within `struct thread'. /* Offset of `stack' member within `struct thread'.
Used by switch.S, which can't figure it out on its own. */ Used by switch.S, which can't figure it out on its own. */
uint32_t thread_stack_ofs = offsetof(struct thread, stack); uint32_t thread_stack_ofs = offsetof(struct thread, stack);
...@@ -6,8 +6,7 @@ ...@@ -6,8 +6,7 @@
#include <stdint.h> #include <stdint.h>
/* States in a thread's life cycle. */ /* States in a thread's life cycle. */
enum thread_status enum thread_status {
{
THREAD_RUNNING, /* Running thread. */ THREAD_RUNNING, /* Running thread. */
THREAD_READY, /* Not running but ready to run. */ THREAD_READY, /* Not running but ready to run. */
THREAD_BLOCKED, /* Waiting for an event to trigger. */ THREAD_BLOCKED, /* Waiting for an event to trigger. */
...@@ -80,8 +79,7 @@ typedef int tid_t; ...@@ -80,8 +79,7 @@ typedef int tid_t;
only because they are mutually exclusive: only a thread in the only because they are mutually exclusive: only a thread in the
ready state is on the run queue, whereas only a thread in the ready state is on the run queue, whereas only a thread in the
blocked state is on a semaphore wait list. */ blocked state is on a semaphore wait list. */
struct thread struct thread {
{
/* Owned by thread.c. */ /* Owned by thread.c. */
tid_t tid; /* Thread identifier. */ tid_t tid; /* Thread identifier. */
enum thread_status status; /* Thread state. */ enum thread_status status; /* Thread state. */
...@@ -96,12 +94,16 @@ struct thread ...@@ -96,12 +94,16 @@ 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. */
int status_code;
#endif #endif
/* Owned by thread.c. */ /* Owned by thread.c. */
unsigned magic; /* Detects stack overflow. */ unsigned magic; /* Detects stack overflow. */
}; };
/* If false (default), use round-robin scheduler. /* If false (default), use round-robin scheduler.
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". */
......
#include "userprog/process.h" #include "userprog/process.h"
#include <debug.h>
#include <inttypes.h>
#include <round.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "userprog/gdt.h"
#include "userprog/pagedir.h"
#include "userprog/tss.h"
#include "filesys/directory.h" #include "filesys/directory.h"
#include "filesys/file.h" #include "filesys/file.h"
#include "filesys/filesys.h" #include "filesys/filesys.h"
...@@ -17,17 +8,25 @@ ...@@ -17,17 +8,25 @@
#include "threads/palloc.h" #include "threads/palloc.h"
#include "threads/thread.h" #include "threads/thread.h"
#include "threads/vaddr.h" #include "threads/vaddr.h"
#include "userprog/gdt.h"
#include "userprog/pagedir.h"
#include "userprog/tss.h"
#include <debug.h>
#include <inttypes.h>
#include <round.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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, int argc,
char **argv);
/* 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
thread id, or TID_ERROR if the thread cannot be created. */ thread id, or TID_ERROR if the thread cannot be created. */
tid_t tid_t process_execute(const char *file_name) {
process_execute (const char *file_name)
{
char *fn_copy; char *fn_copy;
tid_t tid; tid_t tid;
...@@ -48,20 +47,35 @@ process_execute (const char *file_name) ...@@ -48,20 +47,35 @@ process_execute (const char *file_name)
/* 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 start_process(void *file_name_) {
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;
// Run strtok_r to find correct file_name
// Declare argument vector and argument count
char **argv[255];
int argc = 0; // Initialize with 1
char *token;
char *save_ptr;
// Argv[0] is the file name e.g. 'echo' in 'echo x y z'
argv[argc++] = strtok_r(file_name, " ", &save_ptr);
// While loop to fill argument vector with arguments e.g. 'x y z' in 'echo x y
// z'
while ((token = strtok_r(NULL, " ", &save_ptr)) != NULL) {
argv[argc++] = token;
}
/* Initialize interrupt frame and load executable. */ /* Initialize interrupt frame and load executable. */
memset(&if_, 0, sizeof if_); memset(&if_, 0, sizeof if_);
if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG; if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG;
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(file_name, &if_.eip, &if_.esp, argc, argv);
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);
...@@ -87,27 +101,23 @@ start_process (void *file_name_) ...@@ -87,27 +101,23 @@ start_process (void *file_name_)
This function will be implemented in problem 2-2. For now, it This function will be implemented in problem 2-2. For now, it
does nothing. */ does nothing. */
int int process_wait(tid_t child_tid UNUSED) {
process_wait (tid_t child_tid UNUSED)
{
// FIXME: @bgaster --- quick hack to make sure processes execute! // FIXME: @bgaster --- quick hack to make sure processes execute!
for(;;) ; for (;;)
;
return -1; return -1;
} }
/* Free the current process's resources. */ /* Free the current process's resources. */
void void process_exit(void) {
process_exit (void)
{
struct thread *cur = thread_current(); struct thread *cur = thread_current();
uint32_t *pd; uint32_t *pd;
/* Destroy the current process's page directory and switch back /* Destroy the current process's page directory and switch back
to the kernel-only page directory. */ to the kernel-only page directory. */
pd = cur->pagedir; pd = cur->pagedir;
if (pd != NULL) if (pd != NULL) {
{
/* Correct ordering here is crucial. We must set /* Correct ordering here is crucial. We must set
cur->pagedir to NULL before switching page directories, cur->pagedir to NULL before switching page directories,
so that a timer interrupt can't switch back to the so that a timer interrupt can't switch back to the
...@@ -124,9 +134,7 @@ process_exit (void) ...@@ -124,9 +134,7 @@ process_exit (void)
/* Sets up the CPU for running user code in the current /* Sets up the CPU for running user code in the current
thread. thread.
This function is called on every context switch. */ This function is called on every context switch. */
void void process_activate(void) {
process_activate (void)
{
struct thread *t = thread_current(); struct thread *t = thread_current();
/* Activate thread's page tables. */ /* Activate thread's page tables. */
...@@ -136,7 +144,7 @@ process_activate (void) ...@@ -136,7 +144,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. */
...@@ -152,8 +160,7 @@ typedef uint16_t Elf32_Half; ...@@ -152,8 +160,7 @@ typedef uint16_t Elf32_Half;
/* Executable header. See [ELF1] 1-4 to 1-8. /* Executable header. See [ELF1] 1-4 to 1-8.
This appears at the very beginning of an ELF binary. */ This appears at the very beginning of an ELF binary. */
struct Elf32_Ehdr struct Elf32_Ehdr {
{
unsigned char e_ident[16]; unsigned char e_ident[16];
Elf32_Half e_type; Elf32_Half e_type;
Elf32_Half e_machine; Elf32_Half e_machine;
...@@ -173,8 +180,7 @@ struct Elf32_Ehdr ...@@ -173,8 +180,7 @@ struct Elf32_Ehdr
/* Program header. See [ELF1] 2-2 to 2-4. /* Program header. See [ELF1] 2-2 to 2-4.
There are e_phnum of these, starting at file offset e_phoff There are e_phnum of these, starting at file offset e_phoff
(see [ELF1] 1-6). */ (see [ELF1] 1-6). */
struct Elf32_Phdr struct Elf32_Phdr {
{
Elf32_Word p_type; Elf32_Word p_type;
Elf32_Off p_offset; Elf32_Off p_offset;
Elf32_Addr p_vaddr; Elf32_Addr p_vaddr;
...@@ -200,7 +206,7 @@ struct Elf32_Phdr ...@@ -200,7 +206,7 @@ struct Elf32_Phdr
#define PF_W 2 /* Writable. */ #define PF_W 2 /* Writable. */
#define PF_R 4 /* Readable. */ #define PF_R 4 /* Readable. */
static bool setup_stack (void **esp); static bool setup_stack(void **esp, int argc, char **argv);
static bool validate_segment(const struct Elf32_Phdr *, struct file *); static bool validate_segment(const struct Elf32_Phdr *, struct file *);
static bool load_segment(struct file *file, off_t ofs, uint8_t *upage, static bool load_segment(struct file *file, off_t ofs, uint8_t *upage,
uint32_t read_bytes, uint32_t zero_bytes, uint32_t read_bytes, uint32_t zero_bytes,
...@@ -210,9 +216,8 @@ static bool load_segment (struct file *file, off_t ofs, uint8_t *upage, ...@@ -210,9 +216,8 @@ static bool load_segment (struct file *file, off_t ofs, uint8_t *upage,
Stores the executable's entry point into *EIP Stores the executable's entry point into *EIP
and its initial stack pointer into *ESP. and its initial stack pointer into *ESP.
Returns true if successful, false otherwise. */ Returns true if successful, false otherwise. */
bool bool load(const char *file_name, void (**eip)(void), void **esp, int argc,
load (const char *file_name, void (**eip) (void), void **esp) char **argv) {
{
struct thread *t = thread_current(); struct thread *t = thread_current();
struct Elf32_Ehdr ehdr; struct Elf32_Ehdr ehdr;
struct file *file = NULL; struct file *file = NULL;
...@@ -229,29 +234,23 @@ load (const char *file_name, void (**eip) (void), void **esp) ...@@ -229,29 +234,23 @@ load (const char *file_name, void (**eip) (void), void **esp)
/* Open executable file. */ /* Open executable file. */
file = filesys_open(file_name); file = filesys_open(file_name);
if (file == NULL) if (file == NULL) {
{
printf("load: %s: open failed\n", file_name); printf("load: %s: open failed\n", file_name);
goto done; goto done;
} }
/* 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) memcmp(ehdr.e_ident, "\177ELF\1\1\1", 7) || ehdr.e_type != 2 ||
|| ehdr.e_type != 2 ehdr.e_machine != 3 || ehdr.e_version != 1 ||
|| ehdr.e_machine != 3 ehdr.e_phentsize != sizeof(struct Elf32_Phdr) || ehdr.e_phnum > 1024) {
|| 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;
} }
/* Read program headers. */ /* Read program headers. */
file_ofs = ehdr.e_phoff; file_ofs = ehdr.e_phoff;
for (i = 0; i < ehdr.e_phnum; i++) for (i = 0; i < ehdr.e_phnum; i++) {
{
struct Elf32_Phdr phdr; struct Elf32_Phdr phdr;
if (file_ofs < 0 || file_ofs > file_length(file)) if (file_ofs < 0 || file_ofs > file_length(file))
...@@ -261,8 +260,7 @@ load (const char *file_name, void (**eip) (void), void **esp) ...@@ -261,8 +260,7 @@ load (const char *file_name, void (**eip) (void), void **esp)
if (file_read(file, &phdr, sizeof phdr) != sizeof phdr) if (file_read(file, &phdr, sizeof phdr) != sizeof phdr)
goto done; goto done;
file_ofs += sizeof phdr; file_ofs += sizeof phdr;
switch (phdr.p_type) switch (phdr.p_type) {
{
case PT_NULL: case PT_NULL:
case PT_NOTE: case PT_NOTE:
case PT_PHDR: case PT_PHDR:
...@@ -275,40 +273,35 @@ load (const char *file_name, void (**eip) (void), void **esp) ...@@ -275,40 +273,35 @@ load (const char *file_name, void (**eip) (void), void **esp)
case PT_SHLIB: case PT_SHLIB:
goto done; goto done;
case PT_LOAD: case PT_LOAD:
if (validate_segment (&phdr, file)) if (validate_segment(&phdr, file)) {
{
bool writable = (phdr.p_flags & PF_W) != 0; bool writable = (phdr.p_flags & PF_W) != 0;
uint32_t file_page = phdr.p_offset & ~PGMASK; uint32_t file_page = phdr.p_offset & ~PGMASK;
uint32_t mem_page = phdr.p_vaddr & ~PGMASK; uint32_t mem_page = phdr.p_vaddr & ~PGMASK;
uint32_t page_offset = phdr.p_vaddr & PGMASK; uint32_t page_offset = phdr.p_vaddr & PGMASK;
uint32_t read_bytes, zero_bytes; uint32_t read_bytes, zero_bytes;
if (phdr.p_filesz > 0) if (phdr.p_filesz > 0) {
{
/* 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 =
- read_bytes); (ROUND_UP(page_offset + phdr.p_memsz, PGSIZE) - read_bytes);
} } else {
else
{
/* Entirely zero. /* Entirely zero.
Don't read anything from disk. */ Don't read anything from disk. */
read_bytes = 0; read_bytes = 0;
zero_bytes = ROUND_UP(page_offset + phdr.p_memsz, PGSIZE); zero_bytes = ROUND_UP(page_offset + phdr.p_memsz, PGSIZE);
} }
if (!load_segment (file, file_page, (void *) mem_page, if (!load_segment(file, file_page, (void *)mem_page, read_bytes,
read_bytes, zero_bytes, writable)) zero_bytes, writable))
goto done; goto done;
} } else
else
goto done; goto done;
break; break;
} }
} }
/* Set up stack. */ /* Set up stack. */
if (!setup_stack (esp)) if (!setup_stack(esp, argc, argv))
goto done; goto done;
/* Start address. */ /* Start address. */
...@@ -321,16 +314,14 @@ load (const char *file_name, void (**eip) (void), void **esp) ...@@ -321,16 +314,14 @@ 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);
/* Checks whether PHDR describes a valid, loadable segment in /* Checks whether PHDR describes a valid, loadable segment in
FILE and returns true if so, false otherwise. */ FILE and returns true if so, false otherwise. */
static bool static bool validate_segment(const struct Elf32_Phdr *phdr, struct file *file) {
validate_segment (const struct Elf32_Phdr *phdr, struct file *file)
{
/* p_offset and p_vaddr must have the same page offset. */ /* p_offset and p_vaddr must have the same page offset. */
if ((phdr->p_offset & PGMASK) != (phdr->p_vaddr & PGMASK)) if ((phdr->p_offset & PGMASK) != (phdr->p_vaddr & PGMASK))
return false; return false;
...@@ -385,17 +376,15 @@ validate_segment (const struct Elf32_Phdr *phdr, struct file *file) ...@@ -385,17 +376,15 @@ validate_segment (const struct Elf32_Phdr *phdr, struct file *file)
Return true if successful, false if a memory allocation error Return true if successful, false if a memory allocation error
or disk read error occurs. */ or disk read error occurs. */
static bool static bool load_segment(struct file *file, off_t ofs, uint8_t *upage,
load_segment (struct file *file, off_t ofs, uint8_t *upage, uint32_t read_bytes, uint32_t zero_bytes,
uint32_t read_bytes, uint32_t zero_bytes, bool writable) bool writable) {
{
ASSERT((read_bytes + zero_bytes) % PGSIZE == 0); ASSERT((read_bytes + zero_bytes) % PGSIZE == 0);
ASSERT(pg_ofs(upage) == 0); ASSERT(pg_ofs(upage) == 0);
ASSERT(ofs % PGSIZE == 0); ASSERT(ofs % PGSIZE == 0);
file_seek(file, ofs); file_seek(file, ofs);
while (read_bytes > 0 || zero_bytes > 0) while (read_bytes > 0 || zero_bytes > 0) {
{
/* Calculate how to fill this page. /* Calculate how to fill this page.
We will read PAGE_READ_BYTES bytes from FILE We will read PAGE_READ_BYTES bytes from FILE
and zero the final PAGE_ZERO_BYTES bytes. */ and zero the final PAGE_ZERO_BYTES bytes. */
...@@ -408,16 +397,14 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage, ...@@ -408,16 +397,14 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage,
return false; return false;
/* Load this page. */ /* Load this page. */
if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes) if (file_read(file, kpage, page_read_bytes) != (int)page_read_bytes) {
{
palloc_free_page(kpage); palloc_free_page(kpage);
return false; return false;
} }
memset(kpage + page_read_bytes, 0, page_zero_bytes); memset(kpage + page_read_bytes, 0, page_zero_bytes);
/* Add the page to the process's address space. */ /* Add the page to the process's address space. */
if (!install_page (upage, kpage, writable)) if (!install_page(upage, kpage, writable)) {
{
palloc_free_page(kpage); palloc_free_page(kpage);
return false; return false;
} }
...@@ -432,21 +419,62 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage, ...@@ -432,21 +419,62 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage,
/* 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. */
static bool static bool setup_stack(void **esp, int argc, char **argv) {
setup_stack (void **esp)
{
uint8_t *kpage; uint8_t *kpage;
bool success = false; bool success = false;
kpage = palloc_get_page(PAL_USER | PAL_ZERO); kpage = palloc_get_page(PAL_USER | PAL_ZERO);
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; // -12 "hack" removed as argument passing implemented
int i = argc;
//***************************
uint32_t *arr[argc]; // Pointer to arguments in the stack
while (--i >= 0) {
*esp = *esp - (strlen(argv[i]) + 1); // Add + 1 for null terminator
arr[i] = (uint32_t *)*esp;
// memcpy (destination, source, size);
memcpy(*esp, argv[i], strlen(argv[i]) + 1);
}
// Word alignment using modulus
int alignment = (uint32_t)*esp % 4;
// If alignment needed move esp
if (alignment > 0) {
*esp = *esp - alignment;
// memset(* to the block of memory to fill, value to be set, number of
// bytes to be set)
memset(*esp, 0, alignment);
}
// In C the size of each constant character e.g. 'x' is equal to 4
// esp - 4 move position in the stack
*esp = *esp - 4;
(*(uint8_t *)(*esp)) = 0; // Add a sentinel for termination
i = argc;
// Address pointing to each argument written to the stack
while (--i >= 0) {
*esp = *esp - 4;
(*(uint32_t **)(*esp)) = arr[i];
}
*esp = *esp - 4;
// Write address of argv[0]
(*(uintptr_t **)(*esp)) = (*esp + 4);
*esp = *esp - 4;
// Write the number of arguments to the stack
*(int *)(*esp) = argc;
*esp = *esp - 4;
// Write 0 for return address
(*(int *)(*esp)) = 0;
} else } else
palloc_free_page(kpage); palloc_free_page(kpage);
} }
return success; return success;
} }
...@@ -459,15 +487,13 @@ setup_stack (void **esp) ...@@ -459,15 +487,13 @@ setup_stack (void **esp)
with palloc_get_page(). with palloc_get_page().
Returns true on success, false if UPAGE is already mapped or Returns true on success, false if UPAGE is already mapped or
if memory allocation fails. */ if memory allocation fails. */
static bool static bool install_page(void *upage, void *kpage, bool writable) {
install_page (void *upage, void *kpage, bool writable)
{
struct thread *t = thread_current(); struct thread *t = thread_current();
/* 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));
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
#include "userprog/syscall.h" #include "userprog/syscall.h"
#include <stdio.h> #include "filesys/filesys.h"
#include <syscall-nr.h> #include "lib/kernel/list.h"
#include "threads/interrupt.h" #include "threads/interrupt.h"
#include "threads/malloc.h"
#include "threads/thread.h" #include "threads/thread.h"
#include "userprog/process.h"
#include <stdio.h>
#include <string.h>
#include <syscall-nr.h>
static void syscall_handler(struct intr_frame *); static void syscall_handler(struct intr_frame *);
bool create(const char *file, unsigned initial_size);
tid_t exec(const char *cmd_line);
void
syscall_init (void) void syscall_init(void) {
{
intr_register_int(0x30, 3, INTR_ON, syscall_handler, "syscall"); intr_register_int(0x30, 3, INTR_ON, syscall_handler, "syscall");
} }
static void syscall_handler(struct intr_frame *f) {
// Get the syscall number from the stack
int syscall_num = *(int *)f->esp;
switch (syscall_num) {
case SYS_REMOVE:
// Print current syscall number
printf("Syscall_handler() - %d!\n", syscall_num);
filesys_remove(*(char **)(f->esp + 4));
printf(*(char **)(f->esp + 4));
break;
static void case SYS_EXEC:
syscall_handler (struct intr_frame *f UNUSED) // Print current syscall number
{ printf("Syscall_handler() - %d!\n", syscall_num);
printf ("system call!\n"); printf("SYS_CALL : EXEC \n");
exec(*(char **)(f->esp + 4));
break;
case SYS_CREATE:
// Print current syscall number
printf("Syscall_handler() - %d!\n", syscall_num);
create(*(int *)(f->esp + 4), (unsigned)*(int *)(f->esp + 8));
break;
default:
thread_exit(); thread_exit();
} }
}
tid_t exec(const char *cmd_line) {
// showing the arg/process in the command line
printf(" \ncmd_line : '%s'\n", cmd_line);
// executing whatever in cmd_line then return to the process id
tid_t pid = process_execute(cmd_line);
return pid;
}
bool create(const char *file, unsigned initial_size) {
// This creates a new file but doesn't open it
printf("File named '%s' created\n", file);
return filesys_create(file, initial_size);
}
\ No newline at end of file