Project HW #2
This commit is contained in:
parent
7bb6e7cbc0
commit
45efb57647
3 changed files with 124 additions and 64 deletions
|
@ -1,3 +1,6 @@
|
|||
// Author: Claudio Maggioni
|
||||
// Author: Tommaso Rodolfo Masera
|
||||
|
||||
#include "devices/timer.h"
|
||||
#include <debug.h>
|
||||
#include <inttypes.h>
|
||||
|
@ -7,6 +10,8 @@
|
|||
#include "threads/interrupt.h"
|
||||
#include "threads/synch.h"
|
||||
#include "threads/thread.h"
|
||||
#include "threads/malloc.h"
|
||||
#include "../lib/kernel/list.h"
|
||||
|
||||
/* See [8254] for hardware details of the 8254 timer chip. */
|
||||
|
||||
|
@ -89,11 +94,12 @@ timer_elapsed (int64_t then)
|
|||
void
|
||||
timer_sleep (int64_t ticks)
|
||||
{
|
||||
int64_t start = timer_ticks ();
|
||||
if (ticks <= 0)
|
||||
return;
|
||||
|
||||
ASSERT (intr_get_level() == INTR_ON);
|
||||
while (timer_elapsed (start) < ticks)
|
||||
thread_yield ();
|
||||
|
||||
thread_sleep(ticks);
|
||||
}
|
||||
|
||||
/* Sleeps for approximately MS milliseconds. Interrupts must be
|
||||
|
@ -171,6 +177,8 @@ static void
|
|||
timer_interrupt (struct intr_frame *args UNUSED)
|
||||
{
|
||||
ticks++;
|
||||
|
||||
thread_unsleep();
|
||||
thread_tick();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Author: Claudio Maggioni
|
||||
// Author: Tommaso Rodolfo Masera
|
||||
|
||||
#include "threads/thread.h"
|
||||
#include <debug.h>
|
||||
#include <stddef.h>
|
||||
|
@ -11,6 +14,7 @@
|
|||
#include "threads/switch.h"
|
||||
#include "threads/synch.h"
|
||||
#include "threads/vaddr.h"
|
||||
#include "devices/timer.h"
|
||||
#ifdef USERPROG
|
||||
#include "userprog/process.h"
|
||||
#endif
|
||||
|
@ -37,6 +41,8 @@ static struct thread *initial_thread;
|
|||
/* Lock used by allocate_tid(). */
|
||||
static struct lock tid_lock;
|
||||
|
||||
static struct list sleeping;
|
||||
|
||||
/* Stack frame for kernel_thread(). */
|
||||
struct kernel_thread_frame
|
||||
{
|
||||
|
@ -98,6 +104,46 @@ thread_init (void)
|
|||
init_thread (initial_thread, "main", PRI_DEFAULT);
|
||||
initial_thread->status = THREAD_RUNNING;
|
||||
initial_thread->tid = allocate_tid ();
|
||||
|
||||
list_init(&sleeping);
|
||||
}
|
||||
|
||||
static bool
|
||||
earlier_wakeup(const struct list_elem* a, const struct list_elem* b, void* aux UNUSED) {
|
||||
return list_entry(a, struct thread, elem)->wakeup <
|
||||
list_entry(b, struct thread, elem)->wakeup;
|
||||
}
|
||||
|
||||
void
|
||||
thread_sleep(uint64_t ticks) {
|
||||
enum intr_level old_level = intr_disable();
|
||||
struct thread* cur = thread_current();
|
||||
cur->wakeup = timer_ticks() + ticks;
|
||||
// printf("sleeping insert %X\n", cur);
|
||||
list_insert_ordered(&sleeping, &(cur->elem), earlier_wakeup, NULL);
|
||||
thread_block();
|
||||
intr_set_level(old_level);
|
||||
}
|
||||
|
||||
static struct thread* thr(struct list_elem* l) {
|
||||
return list_entry(l, struct thread, elem);
|
||||
}
|
||||
|
||||
void
|
||||
thread_unsleep() {
|
||||
const uint64_t ticks = timer_ticks();
|
||||
enum intr_level old_level = intr_disable();
|
||||
if (!list_empty(&sleeping)) {
|
||||
|
||||
struct list_elem* t = list_begin(&sleeping);
|
||||
while (thr(t)->wakeup <= ticks) {
|
||||
// printf("sleeping remove %X\n", thr(t));
|
||||
struct thread* s = thr(t);
|
||||
t = list_remove(t);
|
||||
thread_unblock(s);
|
||||
}
|
||||
}
|
||||
intr_set_level(old_level);
|
||||
}
|
||||
|
||||
/* Starts preemptive thread scheduling by enabling interrupts.
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Author: Claudio Maggioni
|
||||
// Author: Tommaso Rodolfo Masera
|
||||
|
||||
#ifndef THREADS_THREAD_H
|
||||
#define THREADS_THREAD_H
|
||||
|
||||
|
@ -89,7 +92,7 @@ struct thread
|
|||
uint8_t *stack; /* Saved stack pointer. */
|
||||
int priority; /* Priority. */
|
||||
struct list_elem allelem; /* List element for all threads list. */
|
||||
|
||||
uint64_t wakeup;
|
||||
/* Shared between thread.c and synch.c. */
|
||||
struct list_elem elem; /* List element. */
|
||||
|
||||
|
@ -126,6 +129,9 @@ const char *thread_name (void);
|
|||
void thread_exit (void) NO_RETURN;
|
||||
void thread_yield (void);
|
||||
|
||||
void thread_sleep(uint64_t ticks);
|
||||
void thread_unsleep(void);
|
||||
|
||||
/* Performs some operation on thread t, given auxiliary data AUX. */
|
||||
typedef void thread_action_func (struct thread *t, void *aux);
|
||||
void thread_foreach (thread_action_func *, void *);
|
||||
|
|
Reference in a new issue