pintos os 코드정리

Matthew Woo·2021년 10월 1일
0
/* Pintos main program. */
// main
int main (void) NO_RETURN;

/* Pintos main program. */
int
main (void) {
	uint64_t mem_end;
	char **argv;

	/* Clear BSS and get machine's RAM size. */
	bss_init ();

	/* Break command line into arguments and parse options. */
	argv = read_command_line ();
	argv = parse_options (argv);

	/* Initialize ourselves as a thread so we can use locks,
	   then enable console locking. */
	thread_init ();
	console_init ();

	/* Initialize memory system. */
	mem_end = palloc_init ();
	malloc_init ();
	paging_init (mem_end);

#ifdef USERPROG
	tss_init ();
	gdt_init ();
#endif

	/* Initialize interrupt handlers. */
	intr_init ();
	timer_init ();
	kbd_init ();
	input_init ();
#ifdef USERPROG
	exception_init ();
	syscall_init ();
#endif
	/* Start thread scheduler and enable interrupts. */
	thread_start ();
	serial_init_queue ();
	timer_calibrate ();

#ifdef FILESYS
	/* Initialize file system. */
	disk_init ();
	filesys_init (format_filesys);
#endif

#ifdef VM
	vm_init ();
#endif

	printf ("Boot complete.\n");

	/* Run actions specified on kernel command line. */
	run_actions (argv);

	/* Finish up. */
	if (power_off_when_done)
		power_off ();
	thread_exit ();
}


/* timer.c */
/* Timer interrupt handler. */
static void
timer_interrupt (struct intr_frame *args UNUSED) {
	ticks++;
	thread_tick ();

	/* 매 tick akek sleep queue 에서 깨어날 thead가 는지 홧인하여, 깨우는 함수를 호출하도록 함*/
	if(get_next_tick_to_awake() <= ticks){
		thread_awake(ticks);
	}
}

// include/threads/thread.h

/* 깨어나야 할 tick을 저장 할 변수 추가*/
int64_t wakeup_tick; 

//스레드를 ticks시각까지 재우는 함수.
void thread_sleep(int64_t ticks);
//푹 자고 있는 스레드 중에 깨어날 시각이 ticks시각이 지난 애들을 모조리 깨우는 함수
void thread_awake(int64_t ticks);

// 가장 먼저 일어나야할 스레드가 일어날 시각을 반환함
int64_t get_next_tick_to_awake(void);
// 가장 먼저 일어날 스레드가 일어날 시각을 업데이트함
void update_next_tick_to_awake(int64_t ticks);


// threads/thread.c 
static struct list sleep_list;	/* 잠자는 애들을 모아둘 공간을 마련함 */
static int64_t next_tick_to_awake;	/* 가장 먼저 일어날 애가 일어날 시각을 저장할 변수 */

thread_init (void) {
	ASSERT (intr_get_level () == INTR_OFF);
	/* Reload the temporal gdt for the kernel
	 * This gdt does not include the user context.
	 * The kernel will rebuild the gdt with user context, in gdt_init (). */
	struct desc_ptr gdt_ds = {
		.size = sizeof (gdt) - 1,
		.address = (uint64_t) gdt
	};
	lgdt (&gdt_ds);
	/* Init the globla thread context */
	lock_init (&tid_lock);
	list_init (&ready_list);
	list_init (&destruction_req);
	list_init (&sleep_list);	/* sleep list 이걸 추가하였음 */

	/* Set up a thread structure for the running thread. */
	initial_thread = running_thread ();
	init_thread (initial_thread, "main", PRI_DEFAULT);
	initial_thread->status = THREAD_RUNNING;
	initial_thread->tid = allocate_tid ();
}

// 가장 먼저 일어나야할 thread가 일어날 시간을 반환함
void update_next_tick_to_awake(int64_t ticks){
	/* next_tick_to_awake 가 깨워야 할 스레드의 깨어날 tick 값 중 가장 작은  tick을 갖도록 업데이트 */
	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;
}

// 스레드를 ticks 시각 까지 재우는 함수
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);	// idle 스레드는 sleep 되지 않아야 함

	// awake 함수가 실헹되어야 할 tick 값을 update
	update_next_tick_to_awake(cur -> wakeup_tick = ticks);

	/* 현재 스레드를 슬립 큐에 삽입한 후에 스케줄한다. */
	list_push_back(&sleep_list, &cur->elem);

	// 이 스레드를 블락하고 다시 스케쥴될 때 까지 블락 상태로 대기
	thread_block();

	/* 인터럽트를 다시 받아들이도록 수정 */
	intr_set_level(old_level);
}

/* 자고 있는 스레드 중에 깨어날 시각이 tick 시각이 지난 애들을 모조리 깨우는 함수 */
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);
		}
	}

}

// devices/timer.c
/* Suspends execution for approximately TICKS timer ticks. */
void
timer_sleep (int64_t ticks) {
	int64_t start = timer_ticks ();

	ASSERT (intr_get_level () == INTR_ON);  /*  INTR_ON means Interrupts enabled. */
	while (timer_elapsed (start) < ticks)
		thread_yield (); // <= 다음 thread에게 실행권한 넘기는건가..?
		
	// thread_sleep(start + ticks);
}
profile
Code Everyday

0개의 댓글