Skip to content

Commit

Permalink
Merge pull request #2 from SWJungle4A/opjoobecmp
Browse files Browse the repository at this point in the history
TEAM 1 - PINTOS PROJECT 1
  • Loading branch information
opjoobe authored May 26, 2022
2 parents 2408338 + 04b4bb9 commit a432fd1
Show file tree
Hide file tree
Showing 6 changed files with 462 additions and 30 deletions.
23 changes: 20 additions & 3 deletions devices/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,15 @@ timer_elapsed (int64_t then) {
/* Suspends execution for approximately TICKS timer ticks. */
void
timer_sleep (int64_t ticks) {
int64_t start = timer_ticks ();
int64_t start = timer_ticks (); // current time (in ticks : 1ms)

ASSERT (intr_get_level () == INTR_ON);
while (timer_elapsed (start) < ticks)
thread_yield ();
/* busy waiting */
// while (timer_elapsed (start) < ticks)
// thread_yield ();
/* sleep & awake */
// if (timer_elapsed(start) < ticks)
thread_sleep(start+ticks); // alarm-multiple 관련 변경 // current time + ticks(required) = time to be awaken => local ticks
}

/* Suspends execution for approximately MS milliseconds. */
Expand Down Expand Up @@ -126,6 +130,19 @@ static void
timer_interrupt (struct intr_frame *args UNUSED) {
ticks++;
thread_tick ();
if (thread_mlfqs){
mlfqs_increment();
if (timer_ticks() % 4 == 0){
mlfqs_priority(thread_current());
if (timer_ticks() % TIMER_FREQ == 0){
mlfqs_load_avg();
mlfqs_recalc();
}
}
}
/* per every tick(1ms), check if there are any threads to be awaken */
if(get_next_tick_to_awake() <= ticks) // if the first candidate of sleep list needds to be awaken (== if there's at least 1 thread to be awaken)
thread_awake(ticks); // alarm-multiple 관련 변경 // by calling thread_awake(), check every threads in the sleep list and wakeup if necessary
}

/* Returns true if LOOPS iterations waits for more than one timer
Expand Down
73 changes: 73 additions & 0 deletions include/threads/fixed_point.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#define F (1 << 14) //fixed point 1 (in 17.14 format)
#define INT_MAX ((1 << 31) - 1)
#define INT_MIN (-(1 << 31))

/* x and y denote fixed_point numbers in 17.14 format
* n is an integer
* int = integer
* fp = fixed point numbers
*/

/* Prototypes */
int int_to_fp(int n);
int fp_to_int_round(int x);
int fp_to_int(int x);
int add_fp(int x, int y);
int add_mixed(int x, int n);
int sub_fp(int x, int y);
int sub_mixed(int x, int n);
int mult_fp(int x, int y);
int mult_mixed(int x, int y);
int div_fp(int x, int y);
int div_mixed(int x, int n);

/* convert int to fp */
int int_to_fp (int n) {
return n * F;
}

/* convert fp to int (rounding toward zero) */
int fp_to_int (int x) {
return x / F;
}

/* convert fp to int (rounding to nearest int) */
int fp_to_int_round (int x) {
if (x >= 0) return (x + F / 2) / F;
else return (x - F / 2) / F;
}

/* fp + fp */
int add_fp (int x, int y) {
return x + y;
}

/* fp - fp */
int sub_fp (int x, int y) {
return x - y;
}

/* */
int add_mixed (int x, int n) {
return x + n * F;
}

int sub_mixed (int x, int n) {
return x - n * F;
}

int mult_fp (int x, int y) {
return ((int64_t) x) * y / F;
}

int mult_mixed (int x, int n) {
return x * n;
}

int div_fp (int x, int y) {
return ((int64_t) x) * F / y;
}

int div_mixed (int x, int n) {
return x / n;
}
3 changes: 3 additions & 0 deletions include/threads/synch.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ void cond_wait (struct condition *, struct lock *);
void cond_signal (struct condition *, struct lock *);
void cond_broadcast (struct condition *, struct lock *);

/* priority-sema,condvar 관련 변경 */
bool cmp_sem_priority (const struct list_elem *a, const struct list_elem *b, void *aux);

/* Optimization barrier.
*
* The compiler will not reorder operations across an
Expand Down
35 changes: 34 additions & 1 deletion include/threads/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,17 @@ struct thread {
enum thread_status status; /* Thread state. */
char name[16]; /* Name (for debugging purposes). */
int priority; /* Priority. */

/* Shared between thread.c and synch.c. */
struct list_elem elem; /* List element. */
struct list_elem all_elem; /* List element for all_list */ // 변경사항


int init_priority; /* default priority (to initialize after return donated priority) */ // priority-donate 관련 변경
struct lock *wait_on_lock; /* Address of lock that this thread is waiting for */ // priority-donate 관련 변경
struct list donations; /* donors list (multiple donation) */ //priority-donate 관련 변경
struct list_elem donation_elem; /* multiple donation case */ //priority-donate 관련 변경
int nice; /* nice value of thread */// 변경사항
int recent_cpu; /* recent_cpu which estimates how much CPU time earned recently */// 변경사항

#ifdef USERPROG
/* Owned by userprog/process.c. */
Expand All @@ -107,6 +115,7 @@ struct thread {
/* Owned by thread.c. */
struct intr_frame tf; /* Information for switching */
unsigned magic; /* Detects stack overflow. */
int64_t wakeup_tick; /* Local ticks (minimum ticks required before awakened ) */ /* alarm-multiple 관련 변경 */
};

/* If false (default), use round-robin scheduler.
Expand Down Expand Up @@ -143,4 +152,28 @@ int thread_get_load_avg (void);

void do_iret (struct intr_frame *tf);

/* alarm-multiple 관련 변경 */
void thread_sleep(int64_t ticks);
void thread_awake(int64_t ticks);
void update_next_tick_to_awake(int64_t ticks);
int64_t get_next_tick_to_awake(void);

/* alarm-priority, priority-fifo/preempt 관련 변경 */
void check_curr_max_priority(void);
bool cmp_priority(const struct list_elem *a, const struct list_elem *b, void *aux UNUSED);

/* priority-donate 관련 변경 */
void donate_priority(void);
void remove_donors_on_released_lock(struct lock *lock);
void refresh_priority(void);
bool cmp_donation_priority(const struct list_elem *a, const struct list_elem *b, void *aux);

/* 변경사항 */
void mlfqs_priority (struct thread *t);
void mlfqs_recent_cpu (struct thread *t);
void mlfqs_load_avg (void);
void mlfqs_increment (void);
void mlfqs_recalc(void);


#endif /* threads/thread.h */
73 changes: 56 additions & 17 deletions threads/synch.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ sema_init (struct semaphore *sema, unsigned value) {
interrupts disabled, but if it sleeps then the next scheduled
thread will probably turn interrupts back on. This is
sema_down function. */
/* priority-sema,condvar 관련 변경 */
void
sema_down (struct semaphore *sema) {
enum intr_level old_level;
Expand All @@ -66,7 +67,8 @@ sema_down (struct semaphore *sema) {

old_level = intr_disable ();
while (sema->value == 0) {
list_push_back (&sema->waiters, &thread_current ()->elem);
// list_push_back (&sema->waiters, &thread_current ()->elem);
list_insert_ordered(&sema->waiters, &thread_current()->elem, cmp_priority, NULL); // priority-sema,condvar 관련 변경 // instead Round-Robin scheduling, insert into waiters list based on priority.
thread_block ();
}
sema->value--;
Expand Down Expand Up @@ -102,17 +104,20 @@ sema_try_down (struct semaphore *sema) {
and wakes up one thread of those waiting for SEMA, if any.
This function may be called from an interrupt handler. */
/* priority-sema,condvar 관련 변경 */
void
sema_up (struct semaphore *sema) {
enum intr_level old_level;

ASSERT (sema != NULL);

old_level = intr_disable ();
if (!list_empty (&sema->waiters))
thread_unblock (list_entry (list_pop_front (&sema->waiters),
struct thread, elem));
if (!list_empty (&sema->waiters)){
list_sort (&sema->waiters, cmp_priority, NULL); //priority-sema,condvar 관련 변경 // there might be some priority changes while waiting for the sema, therefore sort the waiters list again
thread_unblock (list_entry (list_pop_front (&sema->waiters), struct thread, elem));
}
sema->value++;
check_curr_max_priority(); // priority-sema,condvar 관련 변경 // there's a new UNBLOCKED thread, so let's check if the current thread is still the thread with highest priority. if not, yield !
intr_set_level (old_level);
}

Expand Down Expand Up @@ -182,14 +187,24 @@ lock_init (struct lock *lock) {
interrupt handler. This function may be called with
interrupts disabled, but interrupts will be turned back on if
we need to sleep. */

/* priority-donate 관련 변경 */
void
lock_acquire (struct lock *lock) {
struct thread *curr = thread_current();
ASSERT (lock != NULL);
ASSERT (!intr_context ());
ASSERT (!lock_held_by_current_thread (lock));

ASSERT (!lock_held_by_current_thread (lock)); // no recursive acquisition (cannot acquire lock while already holding the same lock)
if(!thread_mlfqs){
if (lock->holder){ // if holder of the target lock exists, (already held by other thread)
curr->wait_on_lock = lock; // save the target lock's address on current holder's wait_on_lock field.
list_insert_ordered(&lock->holder->donations, &curr->donation_elem, cmp_donation_priority, NULL); // insert current thread's donation_elem into lock holder's donations list
donate_priority();
}
}
sema_down (&lock->semaphore);
lock->holder = thread_current ();
curr->wait_on_lock = NULL; // after acquired the lock, set NULL on wait_on_lock field
lock->holder = curr;
}

/* Tries to acquires LOCK and returns true if successful or false
Expand All @@ -205,8 +220,8 @@ lock_try_acquire (struct lock *lock) {
ASSERT (lock != NULL);
ASSERT (!lock_held_by_current_thread (lock));

success = sema_try_down (&lock->semaphore);
if (success)
success = sema_try_down (&lock->semaphore); // sucess = true(acquire successed) or false(acquire failed)
if (success) // if sucess = true
lock->holder = thread_current ();
return success;
}
Expand All @@ -217,13 +232,18 @@ lock_try_acquire (struct lock *lock) {
An interrupt handler cannot acquire a lock, so it does not
make sense to try to release a lock within an interrupt
handler. */

/* priority-donate 관련 변경 */
void
lock_release (struct lock *lock) {
ASSERT (lock != NULL);
ASSERT (lock_held_by_current_thread (lock));

lock->holder = NULL;
sema_up (&lock->semaphore);
ASSERT (lock_held_by_current_thread (lock)); // check if current thread is the lock holder
lock->holder = NULL; // make lock's holder field NULL. time to release
if (!thread_mlfqs){
remove_donors_on_released_lock(lock); // remove the donors on released lock from current thread's donations
refresh_priority(); // refresh current thread's priority
}
sema_up (&lock->semaphore); // allow other threads to acquire that lock, by sema up
}

/* Returns true if the current thread holds LOCK, false
Expand Down Expand Up @@ -272,6 +292,7 @@ cond_init (struct condition *cond) {
interrupt handler. This function may be called with
interrupts disabled, but interrupts will be turned back on if
we need to sleep. */
/* priority-sema,condvar 관련 변경 */
void
cond_wait (struct condition *cond, struct lock *lock) {
struct semaphore_elem waiter;
Expand All @@ -282,7 +303,8 @@ cond_wait (struct condition *cond, struct lock *lock) {
ASSERT (lock_held_by_current_thread (lock));

sema_init (&waiter.semaphore, 0);
list_push_back (&cond->waiters, &waiter.elem);
// list_push_back (&cond->waiters, &waiter.elem);
list_insert_ordered (&cond->waiters, &waiter.elem, cmp_sem_priority, NULL); // priority-sema,condvar 관련 변경 // instead Round-Robin scheduling, insert into waiters list based on priority.
lock_release (lock);
sema_down (&waiter.semaphore);
lock_acquire (lock);
Expand All @@ -295,16 +317,18 @@ cond_wait (struct condition *cond, struct lock *lock) {
An interrupt handler cannot acquire a lock, so it does not
make sense to try to signal a condition variable within an
interrupt handler. */
/* priority-sema,condvar 관련 변경 */
void
cond_signal (struct condition *cond, struct lock *lock UNUSED) {
ASSERT (cond != NULL);
ASSERT (lock != NULL);
ASSERT (!intr_context ());
ASSERT (lock_held_by_current_thread (lock));

if (!list_empty (&cond->waiters))
sema_up (&list_entry (list_pop_front (&cond->waiters),
struct semaphore_elem, elem)->semaphore);
if (!list_empty (&cond->waiters)){
list_sort (&cond->waiters, cmp_sem_priority, NULL); // priority-sema,condvar 관련 변경 (추가사항) // there might be some priority changes while waiting for the condvar, therefore sort the waiters list again
sema_up (&list_entry (list_pop_front (&cond->waiters), struct semaphore_elem, elem)->semaphore);
}
}

/* Wakes up all threads, if any, waiting on COND (protected by
Expand All @@ -321,3 +345,18 @@ cond_broadcast (struct condition *cond, struct lock *lock) {
while (!list_empty (&cond->waiters))
cond_signal (cond, lock);
}

/* priority-sema,condvar 관련 변경 */
/* Sort the condvar's waiters list which is the list of semaphores waiting for the condvar, based on the priority of thread (the first one in the semaphore's waiters list) */
bool cmp_sem_priority (const struct list_elem *a, const struct list_elem *b, void *aux){
struct semaphore_elem *sema_a = list_entry(a, struct semaphore_elem, elem);
struct semaphore_elem *sema_b = list_entry(b, struct semaphore_elem, elem);
struct list *sema_a_waiters = &(sema_a->semaphore.waiters);
struct list *sema_b_waiters = &(sema_b->semaphore.waiters);
struct thread *sema_a_waiters_front = list_entry(list_begin(sema_a_waiters), struct thread, elem);
struct thread *sema_b_waiters_front = list_entry(list_begin(sema_b_waiters), struct thread, elem);
if (sema_a_waiters_front->priority > sema_b_waiters_front->priority)
return true;
else
return false;
}
Loading

0 comments on commit a432fd1

Please sign in to comment.