[Krafton Jungle] PintOS 2.0.0
크래프톤 정글 PintOS
 
Loading...
Searching...
No Matches
thread.h File Reference
#include <debug.h>
#include <list.h>
#include <stdint.h>
#include "threads/interrupt.h"
#include "threads/synch.h"
Include dependency graph for thread.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  thread
 

Macros

#define USERPROG
 
#define VM
 
#define TID_ERROR   ((tid_t) -1) /* Error value for tid_t. */
 
#define PRI_MIN   0 /* Lowest priority. */
 
#define PRI_DEFAULT   31 /* Default priority. */
 
#define PRI_MAX   63 /* Highest priority. */
 
#define FDT_PAGES   3
 
#define FDCOUNT_LIMIT   FDT_PAGES *(1<<9)
 

Typedefs

typedef int tid_t
 
typedef void thread_func(void *aux)
 

Enumerations

enum  thread_status { THREAD_RUNNING , THREAD_READY , THREAD_BLOCKED , THREAD_DYING }
 

Functions

void thread_init (void)
 
void thread_start (void)
 
void thread_tick (void)
 
void thread_print_stats (void)
 
tid_t thread_create (const char *name, int priority, thread_func *, void *)
 
void thread_block (void)
 
void thread_unblock (struct thread *)
 
struct threadthread_current (void)
 
tid_t thread_tid (void)
 
const char * thread_name (void)
 
void thread_exit (void) NO_RETURN
 
void thread_yield (void)
 
int thread_get_priority (void)
 
void thread_set_priority (int)
 
int thread_get_nice (void)
 
void thread_set_nice (int)
 
int thread_get_recent_cpu (void)
 
int thread_get_load_avg (void)
 
void do_iret (struct intr_frame *tf)
 
int64_t get_global_ticks (void)
 
void set_global_ticks (int64_t ticks)
 
void thread_awake (int64_t ticks)
 
void thread_sleep (int64_t ticks)
 
bool cmp_priority (const struct list_elem *a, const struct list_elem *b, void *aux UNUSED)
 

Variables

bool thread_mlfqs
 

Macro Definition Documentation

◆ FDCOUNT_LIMIT

#define FDCOUNT_LIMIT   FDT_PAGES *(1<<9)

◆ FDT_PAGES

#define FDT_PAGES   3

◆ PRI_DEFAULT

#define PRI_DEFAULT   31 /* Default priority. */

◆ PRI_MAX

#define PRI_MAX   63 /* Highest priority. */

◆ PRI_MIN

#define PRI_MIN   0 /* Lowest priority. */

◆ TID_ERROR

#define TID_ERROR   ((tid_t) -1) /* Error value for tid_t. */

◆ USERPROG

#define USERPROG

◆ VM

#define VM

Typedef Documentation

◆ thread_func

typedef void thread_func(void *aux)

◆ tid_t

typedef int tid_t

Enumeration Type Documentation

◆ thread_status

Enumerator
THREAD_RUNNING 
THREAD_READY 
THREAD_BLOCKED 
THREAD_DYING 
16 {
17 THREAD_RUNNING, /* Running thread. */
18 THREAD_READY, /* Not running but ready to run. */
19 THREAD_BLOCKED, /* Waiting for an event to trigger. */
20 THREAD_DYING /* About to be destroyed. */
21};
@ THREAD_BLOCKED
Definition: thread.h:19
@ THREAD_DYING
Definition: thread.h:20
@ THREAD_RUNNING
Definition: thread.h:17
@ THREAD_READY
Definition: thread.h:18

Function Documentation

◆ cmp_priority()

bool cmp_priority ( const struct list_elem a,
const struct list_elem b,
void *aux  UNUSED 
)
449 {
450 return list_entry(a, struct thread, elem) -> priority \
451 > list_entry(b, struct thread, elem) -> priority ? \
452 1 : 0;
453}
#define list_entry(LIST_ELEM, STRUCT, MEMBER)
Definition: list.h:103
Definition: thread.h:100
Here is the caller graph for this function:

◆ do_iret()

void do_iret ( struct intr_frame tf)
577 {
578 __asm __volatile(
579 "movq %0, %%rsp\n"
580 "movq 0(%%rsp),%%r15\n"
581 "movq 8(%%rsp),%%r14\n"
582 "movq 16(%%rsp),%%r13\n"
583 "movq 24(%%rsp),%%r12\n"
584 "movq 32(%%rsp),%%r11\n"
585 "movq 40(%%rsp),%%r10\n"
586 "movq 48(%%rsp),%%r9\n"
587 "movq 56(%%rsp),%%r8\n"
588 "movq 64(%%rsp),%%rsi\n"
589 "movq 72(%%rsp),%%rdi\n"
590 "movq 80(%%rsp),%%rbp\n"
591 "movq 88(%%rsp),%%rdx\n"
592 "movq 96(%%rsp),%%rcx\n"
593 "movq 104(%%rsp),%%rbx\n"
594 "movq 112(%%rsp),%%rax\n"
595 "addq $120,%%rsp\n"
596 "movw 8(%%rsp),%%ds\n"
597 "movw (%%rsp),%%es\n"
598 "addq $32, %%rsp\n"
599 "iretq"
600 : : "g" ((uint64_t) tf) : "memory");
601}
__asm __volatile("wrmsr" ::"c"(ecx), "d"(edx), "a"(eax))
unsigned long long int uint64_t
Definition: stdint.h:29
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_global_ticks()

int64_t get_global_ticks ( void  )
390 {
391 return global_ticks;
392}
static int64_t global_ticks
Definition: thread.c:48
Here is the caller graph for this function:

◆ set_global_ticks()

void set_global_ticks ( int64_t  ticks)
397 {
398 if (ticks < global_ticks) {
400 }
401}
static int64_t ticks
Definition: timer.c:22
Here is the caller graph for this function:

◆ thread_awake()

void thread_awake ( int64_t  ticks)
405 {
406 struct list_elem *curr = list_begin(&sleep_list);
407 set_global_ticks(INT64_MAX); // 기존 글로벌 틱으로 비교하면 초기화되지 않음
408 struct thread *curr_thread;
409 while (curr != list_end(&sleep_list)){ // 전체 순회
410 curr_thread = list_entry(curr, struct thread, elem);
411 if (curr_thread -> wakeup_tick <= ticks) {
412 curr = list_remove(curr); // curr을 슬립 리스트에서 뻄
413 thread_unblock(curr_thread); // curr을 레디 상태로 만듦(unblocked)
414 } else {
415 set_global_ticks(curr_thread -> wakeup_tick);
416 // 슬립 리스트에서 현재 깨어나야하는 시간이 ticks 보다 클때, 디음 루틴을 위해 글로벌 틱을 재설정한다.
417 curr = curr -> next;
418 }
419 }
420}
static int next(int pos)
Definition: intq.c:74
struct list_elem * list_begin(struct list *)
Definition: list.c:68
struct list_elem * list_remove(struct list_elem *)
Definition: list.c:241
struct list_elem * list_end(struct list *)
Definition: list.c:88
#define INT64_MAX
Definition: stdint.h:17
Definition: list.h:87
int64_t wakeup_tick
Definition: thread.h:109
struct list_elem elem
Definition: thread.h:112
void thread_unblock(struct thread *t)
Definition: thread.c:275
static struct list sleep_list
Definition: thread.c:32
void set_global_ticks(int64_t ticks)
Definition: thread.c:397
Here is the call graph for this function:
Here is the caller graph for this function:

◆ thread_block()

void thread_block ( void  )
258 {
259 ASSERT (!intr_context ());
262 schedule ();
263}
#define ASSERT(CONDITION)
Definition: debug.h:30
bool intr_context(void)
Definition: interrupt.c:258
@ INTR_OFF
Definition: interrupt.h:9
enum intr_level intr_get_level(void)
Definition: interrupt.c:115
enum thread_status status
Definition: thread.h:103
struct thread * thread_current(void)
Definition: thread.c:301
static void schedule(void)
Definition: thread.c:691
Here is the call graph for this function:
Here is the caller graph for this function:

◆ thread_create()

tid_t thread_create ( const char *  name,
int  priority,
thread_func function,
void *  aux 
)
197 {
198 struct thread *t;
199 tid_t tid;
200
201 ASSERT (function != NULL);
202
203 /* Allocate thread. */
205 if (t == NULL)
206 return TID_ERROR;
207
208 /* Initialize thread. */
210 tid = t->tid = allocate_tid ();
211
212 /*------------------------- [P2] System Call --------------------------*/
214 if (t->fdt == NULL) {
215 return TID_ERROR;
216 }
217 t->next_fd = 2; // 0 : stdin, 1 : stdout
218 t->fdt[0] = 1; // STDIN_FILENO -> dummy value
219 t->fdt[1] = 2; // STDOUT_FILENO -> dummy value
220
221/*------------------------- [P2] System Call - Thread --------------------------*/
222 /* 현재 스레드의 자식 리스트에 새로 생성한 스레드 추가 */
223 struct thread *curr = thread_current();
225
226 /* Call the kernel_thread if it scheduled.
227 * Note) rdi is 1st argument, and rsi is 2nd argument. */
229 t->tf.R.rdi = (uint64_t) function;
230 t->tf.R.rsi = (uint64_t) aux;
231 t->tf.ds = SEL_KDSEG;
232 t->tf.es = SEL_KDSEG;
233 t->tf.ss = SEL_KDSEG;
234 t->tf.cs = SEL_KCSEG;
235 t->tf.eflags = FLAG_IF;
236
237 /*------------------------- [P1] Priority Scheduling --------------------------*/
238 /* Add to run queue. */
239 thread_unblock (t); // ready_list 에 새로 넣은 스레드
240
241 if (thread_get_priority() < priority) { //1. 현재 실행중인 스레드와 새로 추가하려는 스레드 비교
242 if (intr_context())
244 else
245 thread_yield(); //2. 만약 새로 추가하려는 스레드가 현재 실행중인 스레드보다 우선순위가 높으면 CPU를 선점한다.
246 }
247 return tid;
248}
#define FLAG_IF
Definition: flags.h:6
void intr_yield_on_return(void)
Definition: interrupt.c:269
void list_push_back(struct list *, struct list_elem *)
Definition: list.c:202
#define SEL_KDSEG
Definition: loader.h:37
#define SEL_KCSEG
Definition: loader.h:36
@ PAL_ZERO
Definition: palloc.h:10
void * palloc_get_page(enum palloc_flags)
Definition: palloc.c:301
void * palloc_get_multiple(enum palloc_flags, size_t page_cnt)
Definition: palloc.c:263
#define NULL
Definition: stddef.h:4
uint64_t uintptr_t
Definition: stdint.h:36
uint64_t rdi
Definition: interrupt.h:29
uint64_t rsi
Definition: interrupt.h:28
uint16_t ss
Definition: interrupt.h:61
uintptr_t rip
Definition: interrupt.h:55
uint16_t es
Definition: interrupt.h:41
uint16_t ds
Definition: interrupt.h:44
uint16_t cs
Definition: interrupt.h:56
uint64_t eflags
Definition: interrupt.h:59
struct gp_registers R
Definition: interrupt.h:40
struct list_elem child_elem
Definition: thread.h:128
int priority
Definition: thread.h:105
int next_fd
Definition: thread.h:123
char name[16]
Definition: thread.h:104
tid_t tid
Definition: thread.h:102
struct intr_frame tf
Definition: thread.h:150
struct file ** fdt
Definition: thread.h:122
struct list child_list
Definition: thread.h:127
static void kernel_thread(thread_func *, void *aux)
Definition: thread.c:521
static tid_t allocate_tid(void)
Definition: thread.c:730
int thread_get_priority(void)
Definition: thread.c:441
void thread_yield(void)
Definition: thread.c:343
static void init_thread(struct thread *, const char *name, int priority)
Definition: thread.c:534
#define FDT_PAGES
Definition: thread.h:34
#define TID_ERROR
Definition: thread.h:26
int tid_t
Definition: thread.h:25
Here is the call graph for this function:
Here is the caller graph for this function:

◆ thread_current()

struct thread * thread_current ( void  )
301 {
302 struct thread *t = running_thread ();
303
304 /* Make sure T is really a thread.
305 If either of these assertions fire, then your thread may
306 have overflowed its stack. Each thread has less than 4 kB
307 of stack, so a few big automatic arrays or moderate
308 recursion can cause stack overflow. */
309 ASSERT (is_thread (t));
311
312 return t;
313}
#define is_thread(t)
Definition: thread.c:81
#define running_thread()
Definition: thread.c:88

◆ thread_exit()

void thread_exit ( void  )
325 {
326 ASSERT (!intr_context ());
327 struct thread *curr = thread_current (); // 현재 스레드의 포인터
328
329#ifdef USERPROG
330 process_exit ();
331#endif
332
333 /* Just set our status to dying and schedule another process.
334 We will be destroyed during the call to schedule_tail(). */
335 intr_disable ();
337 NOT_REACHED ();
338}
#define NOT_REACHED()
Definition: debug.h:34
enum intr_level intr_disable(void)
Definition: interrupt.c:151
void process_exit(void)
Definition: process.c:328
static void do_schedule(int status)
Definition: thread.c:678
Here is the call graph for this function:
Here is the caller graph for this function:

◆ thread_get_load_avg()

int thread_get_load_avg ( void  )
470 {
471 /* TODO: Your implementation goes here */
472 return 0;
473}

◆ thread_get_nice()

int thread_get_nice ( void  )
463 {
464 /* TODO: Your implementation goes here */
465 return 0;
466}

◆ thread_get_priority()

int thread_get_priority ( void  )
441 {
442 return thread_current ()->priority;
443}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ thread_get_recent_cpu()

int thread_get_recent_cpu ( void  )
477 {
478 /* TODO: Your implementation goes here */
479 return 0;
480}

◆ thread_init()

void thread_init ( void  )
110 {
111 printf("thread init\n");
113
114 /* Reload the temporal gdt for the kernel
115 * This gdt does not include the user context.
116 * The kernel will rebuild the gdt with user context, in gdt_init (). */
117 struct desc_ptr gdt_ds = {
118 .size = sizeof (gdt) - 1,
119 .address = (uint64_t) gdt
120 };
121 lgdt (&gdt_ds);
122
123 /*------------------------- [P1] Alarm Clock --------------------------*/
124 /* Init the globla thread context */
127 list_init (&sleep_list); // sleep_list를 초기화 한다.
129
130 /* Set up a thread structure for the running thread. */
135}
struct desc_ptr gdt_ds
Definition: gdt.c:75
void list_init(struct list *)
Definition: list.c:58
uint64_t address
Definition: mmu.h:1
int printf(const char *,...) PRINTF_FORMAT(1
Definition: mmu.h:30
uint16_t size
Definition: mmu.h:31
void lock_init(struct lock *)
Definition: synch.c:186
static struct list ready_list
Definition: thread.c:29
static struct list destruction_req
Definition: thread.c:44
static uint64_t gdt[3]
Definition: thread.c:94
static struct thread * initial_thread
Definition: thread.c:38
static struct lock tid_lock
Definition: thread.c:41
#define PRI_DEFAULT
Definition: thread.h:30
Here is the call graph for this function:
Here is the caller graph for this function:

◆ thread_name()

const char * thread_name ( void  )
293 {
294 return thread_current ()->name;
295}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ thread_print_stats()

void thread_print_stats ( void  )
176 {
177 printf ("Thread: %lld idle ticks, %lld kernel ticks, %lld user ticks\n",
179}
static long long user_ticks
Definition: thread.c:53
static long long idle_ticks
Definition: thread.c:51
static long long kernel_ticks
Definition: thread.c:52
Here is the call graph for this function:
Here is the caller graph for this function:

◆ thread_set_nice()

void thread_set_nice ( int  )

◆ thread_set_priority()

void thread_set_priority ( int  new_priority)
426 {
427 thread_current ()->priority_base = new_priority;
429
430 if (thread_get_priority () < list_entry (list_begin (&ready_list), struct thread, elem)->priority) {
431 if (intr_context())
433 else
434 thread_yield ();
435 }
436}
int priority_base
Definition: thread.h:107
void refresh_priority(void)
Definition: synch.c:304
Here is the call graph for this function:

◆ thread_sleep()

void thread_sleep ( int64_t  ticks)
365 { // ticks : 해당 스레드가 깨어나야 할 절대적인 시간 (eg. 12:05)
366 struct thread *curr = thread_current (); // 현재 스레드의 포인터
367 enum intr_level old_level; // 이전 상태
368
369 ASSERT (!intr_context ());
370
371 old_level = intr_disable (); // 인터럽터를 비활성화 시킨다.
372 if (curr != idle_thread) // 현재 스레드가 유휴 스레드가 아니면 sleep_list의 맨 뒤로 넣는다.
373 {
374 curr -> wakeup_tick = ticks; // 깨워야할 시간으로 새로 받은 인자를 넣는다.
375 list_push_back (&sleep_list, &curr->elem); // 현재 스레드를 레디리스트의 맨 뒤로 삽입한다.
376 // curr -> status = THREAD_BLOCKED;
377
379 }
380
381 /* 스레드의 상태를 BLOCKED로 전환하고 컨텍스트 스위치(schedule())를 수행한다. */
382 thread_block();
383 // do_schedule (THREAD_BLOCKED); (= thread_block)
384 intr_set_level (old_level); // 이후 다시 인터럽터를 활성화한다.
385}
enum intr_level intr_set_level(enum intr_level)
Definition: interrupt.c:130
intr_level
Definition: interrupt.h:8
static struct thread * idle_thread
Definition: thread.c:35
void thread_block(void)
Definition: thread.c:258
Here is the call graph for this function:
Here is the caller graph for this function:

◆ thread_start()

void thread_start ( void  )
140 {
141 /* Create the idle thread. */
142 struct semaphore idle_started;
143 sema_init (&idle_started, 0);
144 thread_create ("idle", PRI_MIN, idle, &idle_started);
145
146 /* Start preemptive thread scheduling. */
147 intr_enable ();
148
149 /* Wait for the idle thread to initialize idle_thread. */
150 sema_down (&idle_started);
151}
enum intr_level intr_enable(void)
Definition: interrupt.c:136
Definition: synch.h:8
void sema_down(struct semaphore *)
Definition: synch.c:68
void sema_init(struct semaphore *, unsigned value)
Definition: synch.c:52
static void idle(void *aux UNUSED)
tid_t thread_create(const char *name, int priority, thread_func *function, void *aux)
Definition: thread.c:197
#define PRI_MIN
Definition: thread.h:29
Here is the call graph for this function:
Here is the caller graph for this function:

◆ thread_tick()

void thread_tick ( void  )
156 {
157 struct thread *t = thread_current ();
158
159 /* Update statistics. */
160 if (t == idle_thread)
161 idle_ticks++;
162#ifdef USERPROG
163 else if (t->pml4 != NULL)
164 user_ticks++;
165#endif
166 else
167 kernel_ticks++;
168
169 /* Enforce preemption. */
170 if (++thread_ticks >= TIME_SLICE)
172}
uint64_t * pml4
Definition: thread.h:121
static unsigned thread_ticks
Definition: thread.c:57
#define TIME_SLICE
Definition: thread.c:56
Here is the call graph for this function:
Here is the caller graph for this function:

◆ thread_tid()

tid_t thread_tid ( void  )
317 {
318 return thread_current ()->tid;
319}
Here is the call graph for this function:

◆ thread_unblock()

void thread_unblock ( struct thread t)
275 {
276 enum intr_level old_level;
277
278 ASSERT (is_thread (t));
279
280 old_level = intr_disable ();
282 /*------------------------- [P1] Priority Scheduling --------------------------*/
283 /* origin code
284 list_push_back (&ready_list, &t->elem);
285 */
286 list_insert_ordered(&ready_list, &t -> elem, cmp_priority, NULL); // 정렬된 상태로 스레드가 삽입되도록 한다.
287 t->status = THREAD_READY;
288 intr_set_level (old_level);
289}
void list_insert_ordered(struct list *, struct list_elem *, list_less_func *, void *aux)
Definition: list.c:419
bool cmp_priority(const struct list_elem *a, const struct list_elem *b, void *aux UNUSED)
Definition: thread.c:449
Here is the call graph for this function:
Here is the caller graph for this function:

◆ thread_yield()

void thread_yield ( void  )
343 {
344 struct thread *curr = thread_current (); // 현재 스레드의 포인터
345 enum intr_level old_level;
346
347 ASSERT (!intr_context ());
348
349 old_level = intr_disable (); // 인터럽터를 비활성화한다.
350 if (curr != idle_thread) { // 현재 스레드가 유휴 스레드가 아니면 리스트의 맨 뒤로 넣는다.
351 /*------------------------- [P1] Alarm Clock --------------------------*/
352 /* origin code
353 list_push_back (&ready_list, &curr->elem); // 현재 스레드를 레디리스트의 맨 뒤로 삽입한다.
354 */
355 /*------------------------- [P1] Priority Scheduling --------------------------*/
356 list_insert_ordered(&ready_list, &curr -> elem, cmp_priority, NULL); // 정렬된 상태로 스레드가 삽입되도록 한다.
357 }
358 do_schedule (THREAD_READY); // ready 상태로 전환하고 컨텍스트 스위칭을 한다.
359 intr_set_level (old_level); // 이후 다시 이전 상태로 되돌린다.
360}
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ thread_mlfqs

bool thread_mlfqs
extern