WIP on hw3

This commit is contained in:
Claudio Maggioni 2020-04-13 14:24:44 +02:00
parent 45efb57647
commit c6c8c95690
3 changed files with 292 additions and 42 deletions

View File

@ -0,0 +1,156 @@
/*
* fpr_arith.h
*
* Created on: 20/03/2013
* Author: Eduardo Bezerra - kdubezerra@gmail.com
*/
#ifndef FPR_ARITH_H_
#define FPR_ARITH_H_
/* FIXED POINT REAL
This header contains the definition of the FPReal type, which
is a signed 32 bits integer. It has the following structure:
32 bits:
1 for sign
17 for integer part
14 for fractional part
See section B.6 of Pintos documentation for a detailed explanation:
http://www2.icorsi.ch/mod/resource/view.php?id=91264
*/
/* Fixed-point real type. */
typedef int FPReal;
/* Number of bits reserved for the fractional part. */
#define FRACBITS 14
/* Convert an FPReal to int */
static inline int FPR_TO_INT (FPReal fpr);
/* Convert an int to FPReal */
static inline FPReal INT_TO_FPR (int);
/* Increment an FPReal by 1 */
static inline FPReal FPR_INC (FPReal *);
/* Add two FPReals */
static inline FPReal FPR_ADD_FPR (FPReal, FPReal);
/* Subtract one FPReal from another */
static inline FPReal FPR_SUB_FPR (FPReal, FPReal);
/* Multiply an FPReal by an int */
static inline FPReal FPR_MUL_INT (FPReal, int);
/* Divide an FPReal by an int */
static inline FPReal FPR_DIV_INT (FPReal, int);
/* Add an int to an FPReal */
static inline FPReal FPR_ADD_INT (FPReal, int);
/* Subtract an int from an FPReal */
static inline FPReal FPR_SUB_INT (FPReal, int);
/* Multiply two FPReals */
static inline FPReal FPR_MUL_FPR (FPReal, FPReal);
/* Divide an FPReal by another */
static inline FPReal FPR_DIV_FPR (FPReal, FPReal);
/* Divide two ints and return the real result as an FPReal */
static inline FPReal INT_DIV_INT (int, int);
/* ==================================*/
/* FPReal functions implementations. */
/* Convert an FPReal to int */
static inline int
FPR_TO_INT (FPReal fpr) {
return fpr >> FRACBITS;
}
/* Convert an int to FPReal */
static inline FPReal
INT_TO_FPR (int i) {
return i << FRACBITS;
}
/* Increment an FPReal by 1 */
static inline
FPReal FPR_INC (FPReal * fpr) {
(*fpr) += (1 << FRACBITS);
return *fpr;
}
/* Add two FPReals */
static inline
FPReal FPR_ADD_FPR (FPReal fpr_a, FPReal fpr_b) {
return fpr_a + fpr_b;
}
/* Subtract one FPReal from another */
static inline
FPReal FPR_SUB_FPR (FPReal fpr_a, FPReal fpr_b) {
return fpr_a - fpr_b;
}
/* Multiply an FPReal by an int */
static inline
FPReal FPR_MUL_INT (FPReal fpr_a, int b) {
return fpr_a * b;
}
/* Divide an FPReal by an int */
static inline
FPReal FPR_DIV_INT (FPReal fpr_a, int b) {
return fpr_a / b;
}
/* Add an int to an FPReal */
static inline
FPReal FPR_ADD_INT (FPReal fpr_a, int b) {
return fpr_a + (b << FRACBITS);
}
/* Subtract an int from an FPReal */
static inline
FPReal FPR_SUB_INT (FPReal fpr_a, int b) {
return fpr_a - (b << FRACBITS);
}
/* Multiply two FPReals */
static inline
FPReal FPR_MUL_FPR (FPReal fpr_a, FPReal fpr_b) {
int64_t extended_a = fpr_a;
extended_a *= (int64_t) fpr_b;
extended_a >>= FRACBITS;
return (FPReal) extended_a;
}
/* Divide an FPReal by another */
static inline
FPReal FPR_DIV_FPR (FPReal fpr_a, FPReal fpr_b) {
int64_t extended_a = fpr_a;
extended_a <<= FRACBITS;
extended_a /= (int64_t) fpr_b;
return (FPReal) extended_a;
}
/* Divide two ints and return the real result as an FPReal */
static inline
FPReal INT_DIV_INT (int a, int b) {
int64_t exta = a;
exta <<= FRACBITS;
exta /= b;
return (FPReal) exta;
}
#endif /* FPR_ARITH_H_ */

174
pintos-env/pintos/threads/thread.c Executable file → Normal file
View File

@ -43,6 +43,8 @@ static struct lock tid_lock;
static struct list sleeping; static struct list sleeping;
static FPReal load_avg;
/* Stack frame for kernel_thread(). */ /* Stack frame for kernel_thread(). */
struct kernel_thread_frame struct kernel_thread_frame
{ {
@ -76,6 +78,9 @@ static void *alloc_frame (struct thread *, size_t size);
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);
void thread_yield_for_higher_priority(void);
static void compute_mlfqs_priority(struct thread* t);
bool comp_priority(struct list_elem *, struct list_elem *, void *);
/* Initializes the threading system by transforming the code /* Initializes the threading system by transforming the code
that's currently running into a thread. This can't work in that's currently running into a thread. This can't work in
@ -106,6 +111,7 @@ thread_init (void)
initial_thread->tid = allocate_tid (); initial_thread->tid = allocate_tid ();
list_init(&sleeping); list_init(&sleeping);
load_avg = INT_TO_FPR(0);
} }
static bool static bool
@ -163,6 +169,8 @@ thread_start (void)
sema_down (&idle_started); sema_down (&idle_started);
} }
static int tick_count = 0;
/* 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
@ -180,11 +188,77 @@ thread_tick (void)
else else
kernel_ticks++; kernel_ticks++;
++thread_ticks;
++tick_count;
if (thread_mlfqs) {
if (thread_ticks % 4 == 0) {
compute_mlfqs_priority(t);
}
t->recent_cpu = FPR_ADD_INT(t->recent_cpu, 1);
if (tick_count >= TIMER_FREQ) { // this is true every second
tick_count = 0;
int thr_running = thread_current() == idle_thread ? 0 : 1;
thr_running += list_size(&ready_list);
load_avg = FPR_ADD_FPR(
FPR_MUL_FPR(INT_DIV_INT(59, 60), load_avg),
FPR_MUL_INT(INT_DIV_INT(1, 60), thr_running));
FPReal dag = FPR_MUL_INT(load_avg, 2);
t->recent_cpu = FPR_MUL_FPR(t->recent_cpu,
FPR_DIV_FPR(dag, FPR_ADD_INT(dag, 1))) + INT_TO_FPR(t->nice);
if (t->recent_cpu > INT_TO_FPR(100)) {
t->recent_cpu = INT_TO_FPR(100);
} else if (t->recent_cpu < INT_TO_FPR(0)) {
t->recent_cpu = INT_TO_FPR(0);
}
printf("recent_cpu: %d\n", t->recent_cpu);
//printf("load_avg: %d - threads_ready: %d\n", load_avg, thr_running);
}
}
/* Enforce preemption. */ /* Enforce preemption. */
if (++thread_ticks >= TIME_SLICE) if (thread_ticks >= TIME_SLICE)
intr_yield_on_return (); intr_yield_on_return ();
} }
int
thread_get_nice (void)
{
return thread_current()->nice;
}
void
thread_set_nice (int nice)
{
struct thread* t = thread_current();
enum intr_level old_level = intr_disable();
t->nice = nice > 20 || nice < -20 ? 0 : nice;
compute_mlfqs_priority(t);
intr_set_level(old_level);
thread_yield_for_higher_priority();
}
int
thread_get_recent_cpu (void)
{
return FPR_TO_INT(FPR_MUL_INT(thread_current()->recent_cpu, 100));
}
int
thread_get_load_avg (void)
{
return FPR_TO_INT(FPR_MUL_INT(load_avg, 100));
}
/* Prints thread statistics. */ /* Prints thread statistics. */
void void
thread_print_stats (void) thread_print_stats (void)
@ -255,6 +329,8 @@ thread_create (const char *name, int priority,
/* Add to run queue. */ /* Add to run queue. */
thread_unblock (t); thread_unblock (t);
thread_yield_for_higher_priority();
return tid; return tid;
} }
@ -385,51 +461,19 @@ thread_foreach (thread_action_func *func, void *aux)
} }
} }
int
thread_get_priority (void) {
return thread_current()->priority;
}
/* 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;
thread_yield_for_higher_priority();
} }
/* Returns the current thread's 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. */
}
/* Returns the current thread's nice value. */
int
thread_get_nice (void)
{
/* Not yet implemented. */
return 0;
}
/* Returns 100 times the system load average. */
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)
{
/* Not yet implemented. */
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
@ -500,6 +544,15 @@ is_thread (struct thread *t)
return t != NULL && t->magic == THREAD_MAGIC; return t != NULL && t->magic == THREAD_MAGIC;
} }
static void
compute_mlfqs_priority(struct thread* t) {
t->priority = PRI_MAX - FPR_TO_INT(FPR_DIV_INT(t->recent_cpu, 4))
- (t->nice * 2);
if (t->priority < PRI_MIN) t->priority = PRI_MIN;
else if (t->priority > PRI_MAX) t->priority = PRI_MAX;
}
/* 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
@ -513,7 +566,16 @@ init_thread (struct thread *t, const char *name, int priority)
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;
if (thread_mlfqs) {
t->nice_init = priority > 20 || priority < 20 ? 0 : priority;
t->nice = t->nice_init;
t->recent_cpu = 0;
compute_mlfqs_priority(t);
} else {
t->priority = priority;
}
t->magic = THREAD_MAGIC; t->magic = THREAD_MAGIC;
list_push_back (&all_list, &t->allelem); list_push_back (&all_list, &t->allelem);
} }
@ -541,8 +603,36 @@ next_thread_to_run (void)
{ {
if (list_empty (&ready_list)) if (list_empty (&ready_list))
return idle_thread; return idle_thread;
else else {
return list_entry (list_pop_front (&ready_list), struct thread, elem); // return list_entry (list_pop_front (&ready_list), struct thread, elem);
struct list_elem * th_max_elem = list_max(&ready_list, comp_priority, NULL);
struct thread * th_max = list_entry(th_max_elem, struct thread, elem);
list_remove(th_max_elem);
return th_max;
}
}
bool comp_priority(struct list_elem * a, struct list_elem * b, void *aux) {
struct thread * at = list_entry(a, struct thread, elem);
struct thread * bt = list_entry(b, struct thread, elem);
return at -> priority < bt -> priority;
}
void thread_yield_for_higher_priority(void) {
enum intr_level old_level = intr_disable();
if (!list_empty(&ready_list)) {
struct list_elem * th_max_elem = list_max(&ready_list, comp_priority, NULL);
struct thread * th_max = list_entry(th_max_elem, struct thread, elem);
struct thread * th_cur = thread_current();
if (th_cur -> priority < th_max -> priority)
thread_yield();
}
intr_set_level(old_level);
} }
/* Completes a thread switch by activating the new thread's page /* Completes a thread switch by activating the new thread's page

View File

@ -7,6 +7,7 @@
#include <debug.h> #include <debug.h>
#include <list.h> #include <list.h>
#include <stdint.h> #include <stdint.h>
#include "threads/fpr_arith.h"
/* States in a thread's life cycle. */ /* States in a thread's life cycle. */
enum thread_status enum thread_status
@ -95,6 +96,9 @@ struct thread
uint64_t wakeup; uint64_t wakeup;
/* Shared between thread.c and synch.c. */ /* Shared between thread.c and synch.c. */
struct list_elem elem; /* List element. */ struct list_elem elem; /* List element. */
int nice;
int nice_init;
FPReal recent_cpu;
#ifdef USERPROG #ifdef USERPROG
/* Owned by userprog/process.c. */ /* Owned by userprog/process.c. */