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 FPReal load_avg;
/* Stack frame for kernel_thread(). */
struct kernel_thread_frame
{
@ -76,6 +78,9 @@ static void *alloc_frame (struct thread *, size_t size);
static void schedule (void);
void thread_schedule_tail (struct thread *prev);
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
that's currently running into a thread. This can't work in
@ -106,6 +111,7 @@ thread_init (void)
initial_thread->tid = allocate_tid ();
list_init(&sleeping);
load_avg = INT_TO_FPR(0);
}
static bool
@ -163,6 +169,8 @@ thread_start (void)
sema_down (&idle_started);
}
static int tick_count = 0;
/* Called by the timer interrupt handler at each timer tick.
Thus, this function runs in an external interrupt context. */
void
@ -180,11 +188,77 @@ thread_tick (void)
else
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. */
if (++thread_ticks >= TIME_SLICE)
if (thread_ticks >= TIME_SLICE)
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. */
void
thread_print_stats (void)
@ -255,6 +329,8 @@ thread_create (const char *name, int priority,
/* Add to run queue. */
thread_unblock (t);
thread_yield_for_higher_priority();
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. */
void
thread_set_priority (int 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.
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;
}
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
NAME. */
static void
@ -513,7 +566,16 @@ init_thread (struct thread *t, const char *name, int priority)
t->status = THREAD_BLOCKED;
strlcpy (t->name, name, sizeof t->name);
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;
list_push_back (&all_list, &t->allelem);
}
@ -541,8 +603,36 @@ next_thread_to_run (void)
{
if (list_empty (&ready_list))
return idle_thread;
else
return list_entry (list_pop_front (&ready_list), struct thread, elem);
else {
// 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

View file

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