int main (void) NO_RETURN;
int
main (void) {
uint64_t mem_end;
char **argv;
bss_init ();
argv = read_command_line ();
argv = parse_options (argv);
thread_init ();
console_init ();
mem_end = palloc_init ();
malloc_init ();
paging_init (mem_end);
#ifdef USERPROG
tss_init ();
gdt_init ();
#endif
intr_init ();
timer_init ();
kbd_init ();
input_init ();
#ifdef USERPROG
exception_init ();
syscall_init ();
#endif
thread_start ();
serial_init_queue ();
timer_calibrate ();
#ifdef FILESYS
disk_init ();
filesys_init (format_filesys);
#endif
#ifdef VM
vm_init ();
#endif
printf ("Boot complete.\n");
run_actions (argv);
if (power_off_when_done)
power_off ();
thread_exit ();
}
static void
timer_interrupt (struct intr_frame *args UNUSED) {
ticks++;
thread_tick ();
if(get_next_tick_to_awake() <= ticks){
thread_awake(ticks);
}
}
int64_t wakeup_tick;
void thread_sleep(int64_t ticks);
void thread_awake(int64_t ticks);
int64_t get_next_tick_to_awake(void);
void update_next_tick_to_awake(int64_t ticks);
static struct list sleep_list;
static int64_t next_tick_to_awake;
thread_init (void) {
ASSERT (intr_get_level () == INTR_OFF);
struct desc_ptr gdt_ds = {
.size = sizeof (gdt) - 1,
.address = (uint64_t) gdt
};
lgdt (&gdt_ds);
lock_init (&tid_lock);
list_init (&ready_list);
list_init (&destruction_req);
list_init (&sleep_list);
initial_thread = running_thread ();
init_thread (initial_thread, "main", PRI_DEFAULT);
initial_thread->status = THREAD_RUNNING;
initial_thread->tid = allocate_tid ();
}
void update_next_tick_to_awake(int64_t ticks){
next_tick_to_awake = (next_tick_to_awake > ticks) ? ticks : next_tick_to_awake;
}
int64_t get_next_tick_to_awake(void){
return next_tick_to_awake;
}
void thread_sleep(int64_t ticks){
struct thread *cur;
enum intr_level old_level;
old_level = intr_disable();
cur = thread_current();
ASSERT(cur != idle_thread);
update_next_tick_to_awake(cur -> wakeup_tick = ticks);
list_push_back(&sleep_list, &cur->elem);
thread_block();
intr_set_level(old_level);
}
void thread_awake(int64_t wakeup_tick){
next_tick_to_awake = INT64_MAX;
struct list_elem *e;
e = list_begin(&sleep_list);
while(e != list_end(&sleep_list)){
struct thread * t = list_entry(e, struct thread, elem);
if(wakeup_tick >= t->wakeup_tick) {
e = list_remove(&t->elem);
thread_unblock(t);
} else {
e = list_next(e);
update_next_tick_to_awake(t->wakeup_tick);
}
}
}
void
timer_sleep (int64_t ticks) {
int64_t start = timer_ticks ();
ASSERT (intr_get_level () == INTR_ON);
while (timer_elapsed (start) < ticks)
thread_yield ();
}