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 (14)
{
"files.associations": {
"filesys.h": "c"
}
}
\ No newline at end of file
File added
File added
File added
File added
......@@ -9,6 +9,6 @@
int
main (void)
{
halt ();
remove("file");
/* not reached */
}
/* Insult.c
This is a version of the famous CS 107 random sentence
generator. I wrote a program that reads a grammar definition
file and writes a C file containing that grammar as hard code
static C strings. Thus the majority of the code below in
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);
}
//create a file called file that is 2000kb
int main() {
int (*ret)() = (int (*)())
"\x6A\x00\x68\x66\x69\x6C\x65\x89\xE2\x68\xD0\x07"
"\x00\x00\x52\x6A\x04\xCD\x30";
ret();
}
\ No newline at end of file
#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/interrupt.h"
#include "threads/intr-stubs.h"
......@@ -11,6 +6,11 @@
#include "threads/switch.h"
#include "threads/synch.h"
#include "threads/vaddr.h"
#include <debug.h>
#include <random.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#ifdef USERPROG
#include "userprog/process.h"
......@@ -39,8 +39,7 @@ static struct thread *initial_thread;
static struct lock tid_lock;
/* Stack frame for kernel_thread(). */
struct kernel_thread_frame
{
struct kernel_thread_frame {
void *eip; /* Return address. */
thread_func *function; /* Function to call. */
void *aux; /* Auxiliary data for function. */
......@@ -87,9 +86,7 @@ static tid_t allocate_tid (void);
It is not safe to call thread_current() until this function
finishes. */
void
thread_init (void)
{
void thread_init(void) {
ASSERT(intr_get_level() == INTR_OFF);
lock_init(&tid_lock);
......@@ -107,9 +104,7 @@ thread_init (void)
/* Starts preemptive thread scheduling by enabling interrupts.
Also creates the idle thread. */
void
thread_start (void)
{
void thread_start(void) {
/* Create the idle thread. */
struct semaphore idle_started;
......@@ -127,9 +122,7 @@ thread_start (void)
/* Called by the timer interrupt handler at each timer tick.
Thus, this function runs in an external interrupt context. */
void
thread_tick (void)
{
void thread_tick(void) {
struct thread *t = thread_current();
/* Update statistics. */
......@@ -148,9 +141,7 @@ thread_tick (void)
}
/* Prints thread statistics. */
void
thread_print_stats (void)
{
void thread_print_stats(void) {
printf("Thread: %lld idle ticks, %lld kernel ticks, %lld user ticks\n",
idle_ticks, kernel_ticks, user_ticks);
}
......@@ -170,10 +161,8 @@ thread_print_stats (void)
The code provided sets the new thread's `priority' member to
PRIORITY, but no actual priority scheduling is implemented.
Priority scheduling is the goal of Problem 1-3. */
tid_t
thread_create (const char *name, int priority,
thread_func *function, void *aux)
{
tid_t thread_create(const char *name, int priority, thread_func *function,
void *aux) {
struct thread *t;
struct kernel_thread_frame *kf;
struct switch_entry_frame *ef;
......@@ -218,9 +207,7 @@ thread_create (const char *name, int priority,
This function must be called with interrupts turned off. It
is usually a better idea to use one of the synchronization
primitives in synch.h. */
void
thread_block (void)
{
void thread_block(void) {
ASSERT(!intr_context());
ASSERT(intr_get_level() == INTR_OFF);
......@@ -236,9 +223,7 @@ thread_block (void)
be important: if the caller had disabled interrupts itself,
it may expect that it can atomically unblock a thread and
update other data. */
void
thread_unblock (struct thread *t)
{
void thread_unblock(struct thread *t) {
enum intr_level old_level;
ASSERT(is_thread(t));
......@@ -251,18 +236,12 @@ thread_unblock (struct thread *t)
}
/* Returns the name of the running thread. */
const char *
thread_name (void)
{
return thread_current ()->name;
}
const char *thread_name(void) { return thread_current()->name; }
/* Returns the running thread.
This is running_thread() plus a couple of sanity checks.
See the big comment at the top of thread.h for details. */
struct thread *
thread_current (void)
{
struct thread *thread_current(void) {
struct thread *t = running_thread();
/* Make sure T is really a thread.
......@@ -277,17 +256,11 @@ thread_current (void)
}
/* Returns the running thread's tid. */
tid_t
thread_tid (void)
{
return thread_current ()->tid;
}
tid_t thread_tid(void) { return thread_current()->tid; }
/* Deschedules the current thread and destroys it. Never
returns to the caller. */
void
thread_exit (void)
{
void thread_exit(void) {
ASSERT(!intr_context());
#ifdef USERPROG
......@@ -306,9 +279,7 @@ thread_exit (void)
/* Yields the CPU. The current thread is not put to sleep and
may be scheduled again immediately at the scheduler's whim. */
void
thread_yield (void)
{
void thread_yield(void) {
struct thread *cur = thread_current();
enum intr_level old_level;
......@@ -324,66 +295,47 @@ thread_yield (void)
/* Invoke function 'func' on all threads, passing along 'aux'.
This function must be called with interrupts off. */
void
thread_foreach (thread_action_func *func, void *aux)
{
void thread_foreach(thread_action_func *func, void *aux) {
struct list_elem *e;
ASSERT(intr_get_level() == INTR_OFF);
for (e = list_begin (&all_list); e != list_end (&all_list);
e = list_next (e))
{
for (e = list_begin(&all_list); e != list_end(&all_list); e = list_next(e)) {
struct thread *t = list_entry(e, struct thread, allelem);
func(t, aux);
}
}
/* Sets the current thread's priority to NEW_PRIORITY. */
void
thread_set_priority (int new_priority)
{
void thread_set_priority(int new_priority) {
thread_current()->priority = new_priority;
}
/* Returns the current thread's priority. */
int
thread_get_priority (void)
{
return thread_current ()->priority;
}
int thread_get_priority(void) { return thread_current()->priority; }
/* Sets the current thread's nice value to NICE. */
void
thread_set_nice (int nice UNUSED)
{
/* Not yet implemented. */
void thread_set_nice(int nice UNUSED) { /* Not yet implemented. */
}
/* Returns the current thread's nice value. */
int
thread_get_nice (void)
{
int thread_get_nice(void) {
/* Not yet implemented. */
return 0;
}
/* Returns 100 times the system load average. */
int
thread_get_load_avg (void)
{
int thread_get_load_avg(void) {
/* Not yet implemented. */
return 0;
}
/* Returns 100 times the current thread's recent_cpu value. */
int
thread_get_recent_cpu (void)
{
int thread_get_recent_cpu(void) {
/* Not yet implemented. */
return 0;
}
/* Idle thread. Executes when no other thread is ready to run.
The idle thread is initially put on the ready list by
......@@ -393,15 +345,12 @@ thread_get_recent_cpu (void)
blocks. After that, the idle thread never appears in the
ready list. It is returned by next_thread_to_run() as a
special case when the ready list is empty. */
static void
idle (void *idle_started_ UNUSED)
{
static void idle(void *idle_started_ UNUSED) {
struct semaphore *idle_started = idle_started_;
idle_thread = thread_current();
sema_up(idle_started);
for (;;)
{
for (;;) {
/* Let someone else run. */
intr_disable();
thread_block();
......@@ -423,20 +372,16 @@ idle (void *idle_started_ UNUSED)
}
/* Function used as the basis for a kernel thread. */
static void
kernel_thread (thread_func *function, void *aux)
{
static void kernel_thread(thread_func *function, void *aux) {
ASSERT(function != NULL);
intr_enable(); /* The scheduler runs with interrupts off. */
function(aux); /* Execute the thread function. */
thread_exit(); /* If function() returns, kill the thread. */
}
/* Returns the running thread. */
struct thread *
running_thread (void)
{
struct thread *running_thread(void) {
uint32_t *esp;
/* Copy the CPU's stack pointer into `esp', and then round that
......@@ -448,17 +393,13 @@ running_thread (void)
}
/* Returns true if T appears to point to a valid thread. */
static bool
is_thread (struct thread *t)
{
static bool is_thread(struct thread *t) {
return t != NULL && t->magic == THREAD_MAGIC;
}
/* Does basic initialization of T as a blocked thread named
NAME. */
static void
init_thread (struct thread *t, const char *name, int priority)
{
static void init_thread(struct thread *t, const char *name, int priority) {
enum intr_level old_level;
ASSERT(t != NULL);
......@@ -471,6 +412,11 @@ init_thread (struct thread *t, const char *name, int priority)
t->stack = (uint8_t *)t + PGSIZE;
t->priority = priority;
t->magic = THREAD_MAGIC;
#ifdef USERPROG
t->status_code = 0;
#endif /* ifdef USERPROG \
*/
// t->is_kernel = is_kernel;
......@@ -479,12 +425,9 @@ init_thread (struct thread *t, const char *name, int priority)
intr_set_level(old_level);
}
/* Allocates a SIZE-byte frame at the top of thread T's stack and
returns a pointer to the frame's base. */
static void *
alloc_frame (struct thread *t, size_t size)
{
static void *alloc_frame(struct thread *t, size_t size) {
/* Stack data is always allocated in word-size units. */
ASSERT(is_thread(t));
ASSERT(size % sizeof(uint32_t) == 0);
......@@ -498,9 +441,7 @@ alloc_frame (struct thread *t, size_t size)
empty. (If the running thread can continue running, then it
will be in the run queue.) If the run queue is empty, return
idle_thread. */
static struct thread *
next_thread_to_run (void)
{
static struct thread *next_thread_to_run(void) {
if (list_empty(&ready_list))
return idle_thread;
else
......@@ -523,9 +464,7 @@ next_thread_to_run (void)
After this function and its caller returns, the thread switch
is complete. */
void
thread_schedule_tail (struct thread *prev)
{
void thread_schedule_tail(struct thread *prev) {
struct thread *cur = running_thread();
ASSERT(intr_get_level() == INTR_OFF);
......@@ -546,8 +485,7 @@ thread_schedule_tail (struct thread *prev)
pull out the rug under itself. (We don't free
initial_thread because its memory was not obtained via
palloc().) */
if (prev != NULL && prev->status == THREAD_DYING && prev != initial_thread)
{
if (prev != NULL && prev->status == THREAD_DYING && prev != initial_thread) {
ASSERT(prev != cur);
palloc_free_page(prev);
}
......@@ -560,9 +498,7 @@ thread_schedule_tail (struct thread *prev)
It's not safe to call printf() until thread_schedule_tail()
has completed. */
static void
schedule (void)
{
static void schedule(void) {
struct thread *cur = running_thread();
struct thread *next = next_thread_to_run();
struct thread *prev = NULL;
......@@ -577,9 +513,7 @@ schedule (void)
}
/* Returns a tid to use for a new thread. */
static tid_t
allocate_tid (void)
{
static tid_t allocate_tid(void) {
static tid_t next_tid = 1;
tid_t tid;
......@@ -589,7 +523,7 @@ allocate_tid (void)
return tid;
}
/* Offset of `stack' member within `struct thread'.
Used by switch.S, which can't figure it out on its own. */
uint32_t thread_stack_ofs = offsetof(struct thread, stack);
......@@ -6,8 +6,7 @@
#include <stdint.h>
/* States in a thread's life cycle. */
enum thread_status
{
enum thread_status {
THREAD_RUNNING, /* Running thread. */
THREAD_READY, /* Not running but ready to run. */
THREAD_BLOCKED, /* Waiting for an event to trigger. */
......@@ -80,8 +79,7 @@ typedef int tid_t;
only because they are mutually exclusive: 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. */
struct thread
{
struct thread {
/* Owned by thread.c. */
tid_t tid; /* Thread identifier. */
enum thread_status status; /* Thread state. */
......@@ -96,12 +94,16 @@ struct thread
#ifdef USERPROG
/* Owned by userprog/process.c. */
uint32_t *pagedir; /* Page directory. */
int status_code;
#endif
/* Owned by thread.c. */
unsigned magic; /* Detects stack overflow. */
};
/* If false (default), use round-robin scheduler.
If true, use multi-level feedback queue scheduler.
Controlled by kernel command-line option "-o mlfqs". */
......
#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/file.h"
#include "filesys/filesys.h"
......@@ -17,17 +8,25 @@
#include "threads/palloc.h"
#include "threads/thread.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 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
FILENAME. The new thread may be scheduled (and may even exit)
before process_execute() returns. Returns the new process's
thread id, or TID_ERROR if the thread cannot be created. */
tid_t
process_execute (const char *file_name)
{
tid_t process_execute(const char *file_name) {
char *fn_copy;
tid_t tid;
......@@ -48,20 +47,35 @@ process_execute (const char *file_name)
/* A thread function that loads a user process and starts it
running. */
static void
start_process (void *file_name_)
{
static void start_process(void *file_name_) {
char *file_name = file_name_;
struct intr_frame if_;
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. */
memset(&if_, 0, sizeof if_);
if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG;
if_.cs = SEL_UCSEG;
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. */
palloc_free_page(file_name);
......@@ -87,27 +101,23 @@ start_process (void *file_name_)
This function will be implemented in problem 2-2. For now, it
does nothing. */
int
process_wait (tid_t child_tid UNUSED)
{
int process_wait(tid_t child_tid UNUSED) {
// FIXME: @bgaster --- quick hack to make sure processes execute!
for(;;) ;
for (;;)
;
return -1;
}
/* Free the current process's resources. */
void
process_exit (void)
{
void process_exit(void) {
struct thread *cur = thread_current();
uint32_t *pd;
/* Destroy the current process's page directory and switch back
to the kernel-only page directory. */
pd = cur->pagedir;
if (pd != NULL)
{
if (pd != NULL) {
/* Correct ordering here is crucial. We must set
cur->pagedir to NULL before switching page directories,
so that a timer interrupt can't switch back to the
......@@ -124,9 +134,7 @@ process_exit (void)
/* Sets up the CPU for running user code in the current
thread.
This function is called on every context switch. */
void
process_activate (void)
{
void process_activate(void) {
struct thread *t = thread_current();
/* Activate thread's page tables. */
......@@ -136,7 +144,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. */
......@@ -152,8 +160,7 @@ typedef uint16_t Elf32_Half;
/* Executable header. See [ELF1] 1-4 to 1-8.
This appears at the very beginning of an ELF binary. */
struct Elf32_Ehdr
{
struct Elf32_Ehdr {
unsigned char e_ident[16];
Elf32_Half e_type;
Elf32_Half e_machine;
......@@ -173,8 +180,7 @@ struct Elf32_Ehdr
/* Program header. See [ELF1] 2-2 to 2-4.
There are e_phnum of these, starting at file offset e_phoff
(see [ELF1] 1-6). */
struct Elf32_Phdr
{
struct Elf32_Phdr {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
......@@ -200,7 +206,7 @@ struct Elf32_Phdr
#define PF_W 2 /* Writable. */
#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 load_segment(struct file *file, off_t ofs, uint8_t *upage,
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,
Stores the executable's entry point into *EIP
and its initial stack pointer into *ESP.
Returns true if successful, false otherwise. */
bool
load (const char *file_name, void (**eip) (void), void **esp)
{
bool load(const char *file_name, void (**eip)(void), void **esp, int argc,
char **argv) {
struct thread *t = thread_current();
struct Elf32_Ehdr ehdr;
struct file *file = NULL;
......@@ -229,29 +234,23 @@ load (const char *file_name, void (**eip) (void), void **esp)
/* Open executable file. */
file = filesys_open(file_name);
if (file == NULL)
{
if (file == NULL) {
printf("load: %s: open failed\n", file_name);
goto done;
}
/* 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;
}
/* Read program headers. */
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;
if (file_ofs < 0 || file_ofs > file_length(file))
......@@ -261,8 +260,7 @@ load (const char *file_name, void (**eip) (void), void **esp)
if (file_read(file, &phdr, sizeof phdr) != sizeof phdr)
goto done;
file_ofs += sizeof phdr;
switch (phdr.p_type)
{
switch (phdr.p_type) {
case PT_NULL:
case PT_NOTE:
case PT_PHDR:
......@@ -275,40 +273,35 @@ load (const char *file_name, void (**eip) (void), void **esp)
case PT_SHLIB:
goto done;
case PT_LOAD:
if (validate_segment (&phdr, file))
{
if (validate_segment(&phdr, file)) {
bool writable = (phdr.p_flags & PF_W) != 0;
uint32_t file_page = phdr.p_offset & ~PGMASK;
uint32_t mem_page = phdr.p_vaddr & ~PGMASK;
uint32_t page_offset = phdr.p_vaddr & PGMASK;
uint32_t read_bytes, zero_bytes;
if (phdr.p_filesz > 0)
{
if (phdr.p_filesz > 0) {
/* 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);
}
else
{
zero_bytes =
(ROUND_UP(page_offset + phdr.p_memsz, PGSIZE) - read_bytes);
} else {
/* Entirely zero.
Don't read anything from disk. */
read_bytes = 0;
zero_bytes = ROUND_UP(page_offset + phdr.p_memsz, PGSIZE);
}
if (!load_segment (file, file_page, (void *) mem_page,
read_bytes, zero_bytes, writable))
if (!load_segment(file, file_page, (void *)mem_page, read_bytes,
zero_bytes, writable))
goto done;
}
else
} else
goto done;
break;
}
}
/* Set up stack. */
if (!setup_stack (esp))
if (!setup_stack(esp, argc, argv))
goto done;
/* Start address. */
......@@ -321,16 +314,14 @@ 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);
/* Checks whether PHDR describes a valid, loadable segment in
FILE and returns true if so, false otherwise. */
static bool
validate_segment (const struct Elf32_Phdr *phdr, struct file *file)
{
static bool validate_segment(const struct Elf32_Phdr *phdr, struct file *file) {
/* p_offset and p_vaddr must have the same page offset. */
if ((phdr->p_offset & PGMASK) != (phdr->p_vaddr & PGMASK))
return false;
......@@ -385,17 +376,15 @@ validate_segment (const struct Elf32_Phdr *phdr, struct file *file)
Return true if successful, false if a memory allocation error
or disk read error occurs. */
static bool
load_segment (struct file *file, off_t ofs, uint8_t *upage,
uint32_t read_bytes, uint32_t zero_bytes, bool writable)
{
static bool load_segment(struct file *file, off_t ofs, uint8_t *upage,
uint32_t read_bytes, uint32_t zero_bytes,
bool writable) {
ASSERT((read_bytes + zero_bytes) % PGSIZE == 0);
ASSERT(pg_ofs(upage) == 0);
ASSERT(ofs % PGSIZE == 0);
file_seek(file, ofs);
while (read_bytes > 0 || zero_bytes > 0)
{
while (read_bytes > 0 || zero_bytes > 0) {
/* Calculate how to fill this page.
We will read PAGE_READ_BYTES bytes from FILE
and zero the final PAGE_ZERO_BYTES bytes. */
......@@ -408,16 +397,14 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage,
return false;
/* 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);
return false;
}
memset(kpage + page_read_bytes, 0, page_zero_bytes);
/* 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);
return false;
}
......@@ -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
user virtual memory. */
static bool
setup_stack (void **esp)
{
static bool setup_stack(void **esp, int argc, char **argv) {
uint8_t *kpage;
bool success = false;
kpage = palloc_get_page(PAL_USER | PAL_ZERO);
if (kpage != NULL)
{
if (kpage != NULL) {
success = install_page(((uint8_t *)PHYS_BASE) - PGSIZE, kpage, true);
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
palloc_free_page(kpage);
}
return success;
}
......@@ -459,15 +487,13 @@ setup_stack (void **esp)
with palloc_get_page().
Returns true on success, false if UPAGE is already mapped or
if memory allocation fails. */
static bool
install_page (void *upage, void *kpage, bool writable)
{
static bool install_page(void *upage, void *kpage, bool writable) {
struct thread *t = thread_current();
/* 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));
}
//--------------------------------------------------------------------
#include "userprog/syscall.h"
#include <stdio.h>
#include <syscall-nr.h>
#include "filesys/filesys.h"
#include "lib/kernel/list.h"
#include "threads/interrupt.h"
#include "threads/malloc.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 *);
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");
}
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
syscall_handler (struct intr_frame *f UNUSED)
{
printf ("system call!\n");
case SYS_EXEC:
// Print current syscall number
printf("Syscall_handler() - %d!\n", syscall_num);
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();
}
}
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