/////
Search
📄

Introduction

대부분의 작업은 threads 디렉토리에서 진행하며, 일부는 devices 디렉토리에서 진행
컴파일은 반드시 threads 디렉토리 안에서

배경 : 스레드 이해하기

기본 제공 기능

스레드 생성(thread creation) 및 종료(thread completion)
간단한 스케줄러
동기화 도구들 (세마포어, 락, 조건 변수, 최적화 배리어 등)

스레드 생성 원리

thread_create()를 호출할 때, 실행할 함수 포인터를 인자로 전달
해당 스레드가 처음 스케줄링되면 그 함수의 시작부터 실행
함수가 끝나면 스레드가 종료
각 스레드는 작은 프로그램처럼 동작하며, thread_create()로 전달한 함수가 그 스레드의 main() 과 같음
항상 동시에 단 하나의 스레드만 실행되고, 나머지 스레드는 대기 상태. 스케줄러가 어떤 스레드를 실행할지 결정(실행 가능한 스레드가 없으면 idle() 스레드가 실행됨). 동기화 도구들은 실행 중인 스레드를 대기 상태로 바꾸거나 다른 스레드로 컨텍스트 스위치를 유도. 컨텍스트 스위치 자체는 thread_launch() (threads/thread.c) 안에 구현되어있으며 깊게 이해할 필요 X
각 스레드의 스택은 4KB로 고정되어 있어, 큰 지역 배열(int buf[1000];) 같은 걸 선언하면 스택 오버플로우가 발생 가능.

소스 파일 구조 개요

threads 디렉터리

init.c, init.h
커널 초기화(main 포함)
main() 코드를 읽어보면 어떤 초기화가 이루어지는지 알 수 있음
thread.c, thread.h
스레드 관련 핵심 코드. 대부분의 수정은 여기서 이루어짐
struct thread 구조체는 모든 프로젝트에서 확장·수정하게 됨
palloc.c, palloc.h
페이지 단위(4KB) 메모리 할당기
malloc.c, malloc.h
간단한 malloc/free 구현 (블록 단위 할당기)
interrupt.c, interrupt.h / intr-stubs.S
인터럽트 처리
synch.c, synch.h
세마포어, 락, 조건 변수 구현
이 과제를 포함해 모든 프로젝트에서 많이 쓰게 됨
mmu.c, mmu.h
x86-64 페이지 테이블 관련. Project 3에서 본격적으로 사용

devices 디렉터리

timer.c, timer.h
시스템 타이머 (100Hz 기본). Project 1에서 수정 대상
vga.c, vga.h / serial.c, serial.h
화면 출력, printf 관련 드라이버. 직접 다룰 필요 거의 없음
block.c, block.h / ide.c, partition.c
블록 디바이스 추상화. Project 2 이후 사용
kbd.c, input.c, intq.c
키보드 및 입력 처리
rtc.c, speaker.c, pit.c
실시간 시계, 스피커, 타이머 칩 설정

lib, lib/kernel

표준 C 라이브러리 일부 구현 (string, stdio, stdlib 등)
debug.c : 디버깅용 매크로
random.c : 랜덤 함수
kernel/list.c : 이중 연결 리스트 구현 (Project 1에서 자주 사용됨 → 꼭 읽어보기!)
bitmap, hash : 이후 프로젝트에서 사용

동기화

가장 쉬운 방법은 인터럽트를 꺼서(concurrency 제거) 동기화를 하는 것 → 하지만 권장하지 않음 대신 세마포어, 락, 조건 변수 등을 사용하기
예외
인터럽트 핸들러와 커널 스레드 간 데이터 공유 상황
인터럽트 핸들러는 sleep 불가 → 락 못 씀 따라서 이런 경우는 인터럽트 비활성화 방식 필요
예시
Project 1의 Alarm Clock 과제에서는 타이머 인터럽트에서 sleeping thread를 깨워야 함
핵심 : 인터럽트 끄기는 최소한으로만 사용하기
결론
Project 1에서는 PintOS의 기본 스레드 시스템을 분석하고, Alarm Clock, Priority Scheduling, Priority Donation 같은 기능을 구현하면서 스레드와 동기화의 본질을 배우는 게 목표