Merge branch 'BSD-merged' into 'ethan-BSD'

Bring personal branch up to date

See merge request lab2425_autumn/pintos_22!7
This commit is contained in:
Dias Alberto, Ethan
2024-10-17 15:57:03 +00:00
5 changed files with 114 additions and 60 deletions

View File

@@ -199,10 +199,6 @@ static void
timer_interrupt (struct intr_frame *args UNUSED) timer_interrupt (struct intr_frame *args UNUSED)
{ {
ticks++; ticks++;
if (ticks % TIMER_FREQ == 0)
{
calculate_recent_cpu ();
}
for (struct list_elem *e = list_begin (&sleeping_threads); for (struct list_elem *e = list_begin (&sleeping_threads);
e != list_end (&sleeping_threads); e = list_next (e)) e != list_end (&sleeping_threads); e = list_next (e))
{ {
@@ -212,7 +208,6 @@ timer_interrupt (struct intr_frame *args UNUSED)
else else
break; break;
} }
thread_increment_recent_cpu ();
thread_tick (); thread_tick ();
} }

View File

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

View File

@@ -233,6 +233,7 @@ lock_release (struct lock *lock)
lock->holder = NULL; lock->holder = NULL;
sema_up (&lock->semaphore); sema_up (&lock->semaphore);
thread_yield ();
} }
/* Returns true if the current thread holds LOCK, false /* Returns true if the current thread holds LOCK, false

View File

@@ -4,6 +4,7 @@
#include <random.h> #include <random.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "devices/timer.h"
#include "threads/fixed-point.h" #include "threads/fixed-point.h"
#include "threads/flags.h" #include "threads/flags.h"
#include "threads/interrupt.h" #include "threads/interrupt.h"
@@ -50,6 +51,7 @@ struct kernel_thread_frame
static long long idle_ticks; /* # of timer ticks spent idle. */ static long long idle_ticks; /* # of timer ticks spent idle. */
static long long kernel_ticks; /* # of timer ticks in kernel threads. */ static long long kernel_ticks; /* # of timer ticks in kernel threads. */
static long long user_ticks; /* # of timer ticks in user programs. */ static long long user_ticks; /* # of timer ticks in user programs. */
static fp32_t load_avg = { 0 }; /* System load average. */
/* Scheduling. */ /* Scheduling. */
#define TIME_SLICE 4 /* # of timer ticks to give each thread. */ #define TIME_SLICE 4 /* # of timer ticks to give each thread. */
@@ -65,9 +67,14 @@ static void kernel_thread (thread_func *, void *aux);
static void idle (void *aux UNUSED); static void idle (void *aux UNUSED);
static struct thread *running_thread (void); static struct thread *running_thread (void);
static struct thread *next_thread_to_run (void); static struct thread *next_thread_to_run (void);
static void init_thread (struct thread *, const char *name, int priority, fp32_t recent_cpu); static void init_thread (struct thread *, const char *name, int nice,
int priority, fp32_t recent_cpu);
static bool is_thread (struct thread *) UNUSED; static bool is_thread (struct thread *) UNUSED;
static void *alloc_frame (struct thread *, size_t size); 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); static void schedule (void);
void thread_schedule_tail (struct thread *prev); void thread_schedule_tail (struct thread *prev);
static tid_t allocate_tid (void); static tid_t allocate_tid (void);
@@ -97,7 +104,8 @@ thread_init (void)
/* Set up a thread structure for the running thread. */ /* Set up a thread structure for the running thread. */
initial_thread = running_thread (); initial_thread = running_thread ();
fp32_t initial_thread_recent_cpu = { 0 }; fp32_t initial_thread_recent_cpu = { 0 };
init_thread (initial_thread, "main", PRI_DEFAULT, initial_thread_recent_cpu); init_thread (initial_thread, "main", NICE_DEFAULT, PRI_DEFAULT,
initial_thread_recent_cpu);
initial_thread->status = THREAD_RUNNING; initial_thread->status = THREAD_RUNNING;
initial_thread->tid = allocate_tid (); initial_thread->tid = allocate_tid ();
} }
@@ -147,6 +155,28 @@ thread_tick (void)
else else
kernel_ticks++; 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. */ /* Enforce preemption. */
if (++thread_ticks >= TIME_SLICE) if (++thread_ticks >= TIME_SLICE)
intr_yield_on_return (); intr_yield_on_return ();
@@ -194,8 +224,8 @@ thread_create (const char *name, int priority,
return TID_ERROR; return TID_ERROR;
/* Initialize thread. */ /* Initialize thread. */
fp32_t parent_recent_cpu = thread_current ()->recent_cpu; struct thread *pt = thread_current ();
init_thread (t, name, priority, parent_recent_cpu); init_thread (t, name, pt->nice, priority, pt->recent_cpu);
tid = t->tid = allocate_tid (); tid = t->tid = allocate_tid ();
/* Prepare thread for first run by initializing its stack. /* Prepare thread for first run by initializing its stack.
@@ -259,6 +289,9 @@ thread_unblock (struct thread *t)
old_level = intr_disable (); old_level = intr_disable ();
ASSERT (t->status == THREAD_BLOCKED); 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_push_back (&ready_list, &t->elem);
t->status = THREAD_READY; t->status = THREAD_READY;
intr_set_level (old_level); intr_set_level (old_level);
@@ -330,7 +363,13 @@ thread_yield (void)
old_level = intr_disable (); old_level = intr_disable ();
if (cur != idle_thread) 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); list_push_back (&ready_list, &cur->elem);
}
cur->status = THREAD_READY; cur->status = THREAD_READY;
schedule (); schedule ();
intr_set_level (old_level); intr_set_level (old_level);
@@ -357,6 +396,8 @@ thread_foreach (thread_action_func *func, void *aux)
void void
thread_set_priority (int new_priority) thread_set_priority (int new_priority)
{ {
if (thread_mlfqs)
return;
thread_current ()->priority = new_priority; thread_current ()->priority = new_priority;
} }
@@ -367,44 +408,33 @@ thread_get_priority (void)
return thread_current ()->priority; return thread_current ()->priority;
} }
/* Calculates priority for the current thread */ /* Updates recent_cpu for a thread. */
int static void
calculate_priority (void) thread_update_recent_cpu (struct thread *t, void *aux UNUSED)
{ {
/* Not yet implemented */
return 0;
}
void
calculate_recent_cpu (void)
{
struct thread *t = thread_current ();
fp32_t curr_recent_cpu = t->recent_cpu; fp32_t curr_recent_cpu = t->recent_cpu;
fp32_t curr_load_avg = fp_mul_int(thread_get_load_avg (), 2); fp32_t dbl_load_avg = fp_mul_int (load_avg, 2);
fp32_t recent_cpu_coeff = fp_div(curr_load_avg, fp_add_int(curr_load_avg, 1)); fp32_t recent_cpu_coeff
fp32_t new_recent_cpu = fp_add_int(fp_mul(recent_cpu_coeff, curr_recent_cpu), thread_get_nice ()); = fp_div (dbl_load_avg, fp_add_int (dbl_load_avg, 1));
t->recent_cpu = new_recent_cpu; t->recent_cpu
} = fp_add_int (fp_mul (recent_cpu_coeff, curr_recent_cpu), t->nice);
// recent_cpu was updated, update priority.
void t->priority = calculate_bsd_priority (t->recent_cpu, t->nice);
thread_increment_recent_cpu (void)
{
struct thread *t = thread_current ();
if (t == idle_thread)
{
return;
}
fp32_t old_recent_cpu = t->recent_cpu;
old_recent_cpu.raw = old_recent_cpu.raw + 1;
t->recent_cpu = old_recent_cpu;
} }
/* 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) thread_set_nice (int nice)
{ {
thread_current ()->nice = nice; ASSERT (NICE_MIN <= nice && nice <= NICE_MAX);
calculate_priority ();
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 ();
} }
/* Returns the current thread's nice value. */ /* Returns the current thread's nice value. */
@@ -418,8 +448,7 @@ thread_get_nice (void)
int int
thread_get_load_avg (void) thread_get_load_avg (void)
{ {
/* Not yet implemented. */ return fp_round (fp_mul_int (load_avg, 100));
return 0;
} }
/* Returns 100 times the current thread's recent_cpu value. */ /* Returns 100 times the current thread's recent_cpu value. */
@@ -502,7 +531,8 @@ is_thread (struct thread *t)
/* 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, fp32_t recent_cpu) init_thread (struct thread *t, const char *name, int nice, int priority,
fp32_t recent_cpu)
{ {
enum intr_level old_level; enum intr_level old_level;
@@ -514,9 +544,11 @@ init_thread (struct thread *t, const char *name, int priority, fp32_t recent_cpu
t->status = THREAD_BLOCKED; t->status = THREAD_BLOCKED;
strlcpy (t->name, name, sizeof t->name); strlcpy (t->name, name, sizeof t->name);
t->stack = (uint8_t *) t + PGSIZE; t->stack = (uint8_t *) t + PGSIZE;
t->priority = priority; t->priority
t->magic = THREAD_MAGIC; = thread_mlfqs ? calculate_bsd_priority (recent_cpu, nice) : priority;
t->nice = nice;
t->recent_cpu = recent_cpu; t->recent_cpu = recent_cpu;
t->magic = THREAD_MAGIC;
old_level = intr_disable (); old_level = intr_disable ();
list_push_back (&all_list, &t->allelem); list_push_back (&all_list, &t->allelem);
@@ -596,8 +628,30 @@ thread_schedule_tail (struct thread *prev)
} }
} }
/* Schedules a new process. At entry, interrupts must be off and /* Calculates BSD priority for a thread */
the running process's state must have been changed from 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
running to some other state. This function finds another running to some other state. This function finds another
thread to run and switches to it. thread to run and switches to it.

View File

@@ -25,6 +25,10 @@ typedef int tid_t;
#define PRI_DEFAULT 31 /* Default priority. */ #define PRI_DEFAULT 31 /* Default priority. */
#define PRI_MAX 63 /* Highest 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. /* A kernel thread or user process.
Each thread structure is stored in its own 4 kB page. The Each thread structure is stored in its own 4 kB page. The