Compare commits

..

10 Commits

5 changed files with 45 additions and 216 deletions

6
.gitignore vendored
View File

@@ -4,6 +4,9 @@
#ignore pdf files (just keep source files)
*.pdf
#ignore shell scripts (only used for testing)
*.sh
#ignore junk files from latex output
*.out
*.log
@@ -24,6 +27,3 @@
*.nav
*.toc
#ignore files from CLion/VSCode IDEs
.idea
.vscode

View File

@@ -1,95 +0,0 @@
#include <stdint.h>
#ifndef FIXED_POINT_H
#define FIXED_POINT_H
typedef struct
{
int32_t raw;
} fp32_t;
/* Fixed Point Arithmetic bit count constants */
#define NUM_FRAC_BITS 14
#define NUM_INT_BITS (31 - NUM_FRAC_BITS)
#define CONVERSION_CONST (1 << NUM_FRAC_BITS) /* f = 2^q, (2^20) */
/* Fixed Point Arithmetic conversion operations */
/* Converts an integer n to a fixed point number */
inline fp32_t
int_to_fp (int32_t n)
{
return (fp32_t){ n * CONVERSION_CONST };
}
/* Handles conversion of fixed point to integer. First version truncates, second one rounds */
inline int32_t
fp_floor (fp32_t x)
{
return x.raw / CONVERSION_CONST;
}
inline int32_t
fp_round (fp32_t x)
{
if (x.raw >= 0)
return (x.raw + CONVERSION_CONST / 2) / CONVERSION_CONST;
else
return (x.raw - CONVERSION_CONST / 2) / CONVERSION_CONST;
}
/* Add two fixed points */
inline fp32_t
fp_add (fp32_t x, fp32_t y)
{
return (fp32_t){ x.raw + y.raw };
}
/* Subtract two fixed points */
inline fp32_t
fp_sub (fp32_t x, fp32_t y)
{
return (fp32_t){ x.raw - y.raw };
}
/* Add fixed point to integer */
inline fp32_t
fp_add_int (fp32_t x, int32_t n)
{
return (fp32_t){ x.raw + n * CONVERSION_CONST };
}
/* Subtract integer from fixed point */
inline fp32_t
fp_sub_int (fp32_t x, int32_t n)
{
return (fp32_t){ x.raw - n * CONVERSION_CONST };
}
/* Multiple two fixed points */
inline fp32_t
fp_mul (fp32_t x, fp32_t y)
{
return (fp32_t){ ((int64_t)x.raw) * y.raw / CONVERSION_CONST };
}
/* Divide two fixed points */
inline fp32_t
fp_div (fp32_t x, fp32_t y)
{
return (fp32_t){ ((int64_t)x.raw) * CONVERSION_CONST / y.raw };
}
/* Multiply fixed point and integer */
inline fp32_t
fp_mul_int (fp32_t x, int32_t n)
{
return (fp32_t){ x.raw * n };
}
/* Divide fixed point by integer */
inline fp32_t
fp_div_int (fp32_t x, int32_t n)
{
return (fp32_t){ x.raw / n };
}
#endif //FIXED_POINT_H

View File

@@ -68,7 +68,8 @@ sema_down (struct semaphore *sema)
old_level = intr_disable ();
while (sema->value == 0)
{
list_push_back (&sema->waiters, &thread_current ()->elem);
list_insert_ordered (&sema->waiters, &thread_current ()->elem,
&thread_priority_greater, NULL);
thread_block ();
}
sema->value--;
@@ -118,6 +119,7 @@ sema_up (struct semaphore *sema)
struct thread, elem));
sema->value++;
intr_set_level (old_level);
thread_yield ();
}
static void sema_test_helper (void *sema_);
@@ -233,7 +235,6 @@ lock_release (struct lock *lock)
lock->holder = NULL;
sema_up (&lock->semaphore);
thread_yield ();
}
/* Returns true if the current thread holds LOCK, false

View File

@@ -4,8 +4,6 @@
#include <random.h>
#include <stdio.h>
#include <string.h>
#include "devices/timer.h"
#include "threads/fixed-point.h"
#include "threads/flags.h"
#include "threads/interrupt.h"
#include "threads/intr-stubs.h"
@@ -51,7 +49,6 @@ struct kernel_thread_frame
static long long idle_ticks; /* # of timer ticks spent idle. */
static long long kernel_ticks; /* # of timer ticks in kernel threads. */
static long long user_ticks; /* # of timer ticks in user programs. */
static fp32_t load_avg = { 0 }; /* System load average. */
/* Scheduling. */
#define TIME_SLICE 4 /* # of timer ticks to give each thread. */
@@ -67,14 +64,9 @@ static void kernel_thread (thread_func *, void *aux);
static void idle (void *aux UNUSED);
static struct thread *running_thread (void);
static struct thread *next_thread_to_run (void);
static void init_thread (struct thread *, const char *name, int nice,
int priority, fp32_t recent_cpu);
static void init_thread (struct thread *, const char *name, int priority);
static bool is_thread (struct thread *) UNUSED;
static void *alloc_frame (struct thread *, size_t size);
static int calculate_bsd_priority (fp32_t recent_cpu, int nice);
static void thread_update_recent_cpu (struct thread *t, void *aux UNUSED);
static bool thread_priority_less (const struct list_elem *a,
const struct list_elem *b, void *aux UNUSED);
static void schedule (void);
void thread_schedule_tail (struct thread *prev);
static tid_t allocate_tid (void);
@@ -103,9 +95,7 @@ thread_init (void)
/* Set up a thread structure for the running thread. */
initial_thread = running_thread ();
fp32_t initial_thread_recent_cpu = { 0 };
init_thread (initial_thread, "main", NICE_DEFAULT, PRI_DEFAULT,
initial_thread_recent_cpu);
init_thread (initial_thread, "main", PRI_DEFAULT);
initial_thread->status = THREAD_RUNNING;
initial_thread->tid = allocate_tid ();
}
@@ -155,28 +145,6 @@ thread_tick (void)
else
kernel_ticks++;
/* Update system load_avg and all threads recent_cpu every second. */
int64_t ticks = timer_ticks ();
if (thread_mlfqs && (ticks % TIMER_FREQ == 0))
{
size_t ready = threads_ready ();
if (t != idle_thread)
ready++;
fp32_t old_coeff = fp_mul (fp_div_int (int_to_fp (59), 60), load_avg);
fp32_t new_coeff = fp_div_int (int_to_fp (ready), 60);
load_avg = fp_add (old_coeff, new_coeff);
thread_foreach (thread_update_recent_cpu, NULL);
}
/* Update current thread's recent_cpu. */
if (thread_mlfqs && (t != idle_thread))
{
t->recent_cpu = fp_add_int (t->recent_cpu, 1);
if (ticks % 4 == 0) // recent_cpu was updated, update priority.
t->priority = calculate_bsd_priority (t->recent_cpu, t->nice);
}
/* Enforce preemption. */
if (++thread_ticks >= TIME_SLICE)
intr_yield_on_return ();
@@ -224,8 +192,7 @@ thread_create (const char *name, int priority,
return TID_ERROR;
/* Initialize thread. */
struct thread *pt = thread_current ();
init_thread (t, name, pt->nice, priority, pt->recent_cpu);
init_thread (t, name, priority);
tid = t->tid = allocate_tid ();
/* Prepare thread for first run by initializing its stack.
@@ -252,6 +219,7 @@ thread_create (const char *name, int priority,
/* Add to run queue. */
thread_unblock (t);
thread_yield ();
return tid;
}
@@ -289,10 +257,7 @@ thread_unblock (struct thread *t)
old_level = intr_disable ();
ASSERT (t->status == THREAD_BLOCKED);
if (thread_mlfqs)
list_insert_ordered (&ready_list, &t->elem, thread_priority_less, NULL);
else
list_push_back (&ready_list, &t->elem);
list_insert_ordered (&ready_list, &t->elem, &thread_priority_greater, NULL);
t->status = THREAD_READY;
intr_set_level (old_level);
}
@@ -362,14 +327,9 @@ thread_yield (void)
ASSERT (!intr_context ());
old_level = intr_disable ();
if (cur != idle_thread)
{
if (thread_mlfqs)
list_insert_ordered (&ready_list, &cur->elem, thread_priority_less,
NULL);
else
list_push_back (&ready_list, &cur->elem);
}
if (cur != idle_thread)
list_insert_ordered (&ready_list, &cur->elem, thread_priority_greater,
NULL);
cur->status = THREAD_READY;
schedule ();
intr_set_level (old_level);
@@ -396,9 +356,12 @@ thread_foreach (thread_action_func *func, void *aux)
void
thread_set_priority (int new_priority)
{
if (thread_mlfqs)
return;
ASSERT (PRI_MIN <= new_priority && new_priority <= PRI_MAX);
int old_priority = thread_get_priority ();
thread_current ()->priority = new_priority;
if (new_priority < old_priority)
thread_yield ();
}
/* Returns the current thread's priority. */
@@ -408,54 +371,35 @@ thread_get_priority (void)
return thread_current ()->priority;
}
/* Updates recent_cpu for a thread. */
static void
thread_update_recent_cpu (struct thread *t, void *aux UNUSED)
{
fp32_t curr_recent_cpu = t->recent_cpu;
fp32_t dbl_load_avg = fp_mul_int (load_avg, 2);
fp32_t recent_cpu_coeff
= fp_div (dbl_load_avg, fp_add_int (dbl_load_avg, 1));
t->recent_cpu
= fp_add_int (fp_mul (recent_cpu_coeff, curr_recent_cpu), t->nice);
// recent_cpu was updated, update priority.
t->priority = calculate_bsd_priority (t->recent_cpu, t->nice);
}
/* Sets the current thread's nice value to NICE. */
void
thread_set_nice (int nice)
thread_set_nice (int nice UNUSED)
{
ASSERT (NICE_MIN <= nice && nice <= NICE_MAX);
struct thread *t = thread_current ();
t->nice = nice;
int priority = calculate_bsd_priority (t->recent_cpu, t->nice);
struct thread *next_t
= list_entry (list_begin (&ready_list), struct thread, elem);
if (priority < next_t->priority)
thread_yield ();
/* Not yet implemented. */
}
/* Returns the current thread's nice value. */
int
thread_get_nice (void)
{
return thread_current ()->nice;
/* Not yet implemented. */
return 0;
}
/* Returns 100 times the system load average. */
int
thread_get_load_avg (void)
{
return fp_round (fp_mul_int (load_avg, 100));
/* Not yet implemented. */
return 0;
}
/* Returns 100 times the current thread's recent_cpu value. */
int
thread_get_recent_cpu (void)
{
return fp_round (fp_mul_int (thread_current ()->recent_cpu, 100));
/* Not yet implemented. */
return 0;
}
/* Idle thread. Executes when no other thread is ready to run.
@@ -531,8 +475,7 @@ is_thread (struct thread *t)
/* Does basic initialization of T as a blocked thread named
NAME. */
static void
init_thread (struct thread *t, const char *name, int nice, int priority,
fp32_t recent_cpu)
init_thread (struct thread *t, const char *name, int priority)
{
enum intr_level old_level;
@@ -544,10 +487,7 @@ init_thread (struct thread *t, const char *name, int nice, int priority,
t->status = THREAD_BLOCKED;
strlcpy (t->name, name, sizeof t->name);
t->stack = (uint8_t *) t + PGSIZE;
t->priority
= thread_mlfqs ? calculate_bsd_priority (recent_cpu, nice) : priority;
t->nice = nice;
t->recent_cpu = recent_cpu;
t->priority = priority;
t->magic = THREAD_MAGIC;
old_level = intr_disable ();
@@ -628,30 +568,8 @@ thread_schedule_tail (struct thread *prev)
}
}
/* Calculates BSD priority for a thread */
static int
calculate_bsd_priority (fp32_t recent_cpu, int nice)
{
int priority = PRI_MAX - (fp_round (recent_cpu) / 4) - (nice * 2);
if (priority < PRI_MIN)
return PRI_MIN;
if (priority > PRI_MAX)
return PRI_MAX;
return priority;
}
/* Returns true if thread a's priority is strictly greater than
thread b's priority. */
static bool
thread_priority_less (const struct list_elem *a, const struct list_elem *b,
void *aux UNUSED)
{
struct thread *ta = list_entry (a, struct thread, elem);
struct thread *tb = list_entry (b, struct thread, elem);
return ta->priority > tb->priority;
}
/* ss's state must have been changed from
/* Schedules a new process. At entry, interrupts must be off and
the running process's state must have been changed from
running to some other state. This function finds another
thread to run and switches to it.
@@ -687,6 +605,17 @@ allocate_tid (void)
return tid;
}
/* Returns true iff the priority of the first list element's thread is greater
than that of the second list element's thread. */
bool
thread_priority_greater (const struct list_elem *a, const struct list_elem *b,
void *aux UNUSED)
{
struct thread *ta = list_entry (a, struct thread, elem);
struct thread *tb = list_entry (b, struct thread, elem);
return ta->priority > tb->priority;
}
/* 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);

View File

@@ -4,7 +4,6 @@
#include <debug.h>
#include <list.h>
#include <stdint.h>
#include "threads/fixed-point.h"
/* States in a thread's life cycle. */
enum thread_status
@@ -25,10 +24,6 @@ typedef int tid_t;
#define PRI_DEFAULT 31 /* Default priority. */
#define PRI_MAX 63 /* Highest priority. */
#define NICE_MIN -20 /* Lowest niceness. */
#define NICE_DEFAULT 0 /* Default niceness. */
#define NICE_MAX 20 /* Highest niceness. */
/* A kernel thread or user process.
Each thread structure is stored in its own 4 kB page. The
@@ -98,10 +93,6 @@ struct thread
/* Shared between thread.c and synch.c. */
struct list_elem elem; /* List element. */
/* MLFQS items */
int nice; /* Nice value for this thread */
fp32_t recent_cpu; /* Amount of time this process received */
#ifdef USERPROG
/* Owned by userprog/process.c. */
uint32_t *pagedir; /* Page directory. */
@@ -148,4 +139,7 @@ void thread_set_nice (int);
int thread_get_recent_cpu (void);
int thread_get_load_avg (void);
/* Returns true iff the priority of the first list element's thread is greater
than that of the second list element's thread. */
list_less_func thread_priority_greater;
#endif /* threads/thread.h */