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 "devices/timer.h"
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
@ -7,6 +10,8 @@
|
||||||
#include "threads/interrupt.h"
|
#include "threads/interrupt.h"
|
||||||
#include "threads/synch.h"
|
#include "threads/synch.h"
|
||||||
#include "threads/thread.h"
|
#include "threads/thread.h"
|
||||||
|
#include "threads/malloc.h"
|
||||||
|
#include "../lib/kernel/list.h"
|
||||||
|
|
||||||
/* See [8254] for hardware details of the 8254 timer chip. */
|
/* See [8254] for hardware details of the 8254 timer chip. */
|
||||||
|
|
||||||
|
@ -89,11 +94,12 @@ timer_elapsed (int64_t then)
|
||||||
void
|
void
|
||||||
timer_sleep (int64_t ticks)
|
timer_sleep (int64_t ticks)
|
||||||
{
|
{
|
||||||
int64_t start = timer_ticks ();
|
if (ticks <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
ASSERT (intr_get_level () == INTR_ON);
|
ASSERT (intr_get_level() == INTR_ON);
|
||||||
while (timer_elapsed (start) < ticks)
|
|
||||||
thread_yield ();
|
thread_sleep(ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sleeps for approximately MS milliseconds. Interrupts must be
|
/* Sleeps for approximately MS milliseconds. Interrupts must be
|
||||||
|
@ -171,7 +177,9 @@ static void
|
||||||
timer_interrupt (struct intr_frame *args UNUSED)
|
timer_interrupt (struct intr_frame *args UNUSED)
|
||||||
{
|
{
|
||||||
ticks++;
|
ticks++;
|
||||||
thread_tick ();
|
|
||||||
|
thread_unsleep();
|
||||||
|
thread_tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true if LOOPS iterations waits for more than one timer
|
/* Returns true if LOOPS iterations waits for more than one timer
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// Author: Claudio Maggioni
|
||||||
|
// Author: Tommaso Rodolfo Masera
|
||||||
|
|
||||||
#include "threads/thread.h"
|
#include "threads/thread.h"
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
@ -11,6 +14,7 @@
|
||||||
#include "threads/switch.h"
|
#include "threads/switch.h"
|
||||||
#include "threads/synch.h"
|
#include "threads/synch.h"
|
||||||
#include "threads/vaddr.h"
|
#include "threads/vaddr.h"
|
||||||
|
#include "devices/timer.h"
|
||||||
#ifdef USERPROG
|
#ifdef USERPROG
|
||||||
#include "userprog/process.h"
|
#include "userprog/process.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,6 +41,8 @@ static struct thread *initial_thread;
|
||||||
/* Lock used by allocate_tid(). */
|
/* Lock used by allocate_tid(). */
|
||||||
static struct lock tid_lock;
|
static struct lock tid_lock;
|
||||||
|
|
||||||
|
static struct list sleeping;
|
||||||
|
|
||||||
/* Stack frame for kernel_thread(). */
|
/* Stack frame for kernel_thread(). */
|
||||||
struct kernel_thread_frame
|
struct kernel_thread_frame
|
||||||
{
|
{
|
||||||
|
@ -98,6 +104,46 @@ thread_init (void)
|
||||||
init_thread (initial_thread, "main", PRI_DEFAULT);
|
init_thread (initial_thread, "main", PRI_DEFAULT);
|
||||||
initial_thread->status = THREAD_RUNNING;
|
initial_thread->status = THREAD_RUNNING;
|
||||||
initial_thread->tid = allocate_tid ();
|
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.
|
/* Starts preemptive thread scheduling by enabling interrupts.
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// Author: Claudio Maggioni
|
||||||
|
// Author: Tommaso Rodolfo Masera
|
||||||
|
|
||||||
#ifndef THREADS_THREAD_H
|
#ifndef THREADS_THREAD_H
|
||||||
#define THREADS_THREAD_H
|
#define THREADS_THREAD_H
|
||||||
|
|
||||||
|
@ -89,7 +92,7 @@ struct thread
|
||||||
uint8_t *stack; /* Saved stack pointer. */
|
uint8_t *stack; /* Saved stack pointer. */
|
||||||
int priority; /* Priority. */
|
int priority; /* Priority. */
|
||||||
struct list_elem allelem; /* List element for all threads list. */
|
struct list_elem allelem; /* List element for all threads list. */
|
||||||
|
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. */
|
||||||
|
|
||||||
|
@ -126,6 +129,9 @@ const char *thread_name (void);
|
||||||
void thread_exit (void) NO_RETURN;
|
void thread_exit (void) NO_RETURN;
|
||||||
void thread_yield (void);
|
void thread_yield (void);
|
||||||
|
|
||||||
|
void thread_sleep(uint64_t ticks);
|
||||||
|
void thread_unsleep(void);
|
||||||
|
|
||||||
/* Performs some operation on thread t, given auxiliary data AUX. */
|
/* Performs some operation on thread t, given auxiliary data AUX. */
|
||||||
typedef void thread_action_func (struct thread *t, void *aux);
|
typedef void thread_action_func (struct thread *t, void *aux);
|
||||||
void thread_foreach (thread_action_func *, void *);
|
void thread_foreach (thread_action_func *, void *);
|
||||||
|
|
Reference in a new issue