https://github.com/wookayin/pintos/blob/master/src/threads/thread.h
| ifndef THREADS_THREAD_H | |
| THREADS_THREAD_H | |
| > | |
| > | |
| > | |
| ifdef VM | |
| endif | |
| */ | |
| enum thread_status | |
| { | |
| */ | |
| */ | |
| */ | |
| */ | |
| }; | |
| /* Thread identifier type. | |
| */ | |
| tid_t; | |
| */ | |
| */ | |
| */ | |
| */ | |
| */ | |
| /* A kernel thread or user process. | |
| Each thread structure is stored in its own 4 kB page. The | |
| thread structure itself sits at the very bottom of the page | |
| (at offset 0). The rest of the page is reserved for the | |
| thread's kernel stack, which grows downward from the top of | |
| the page (at offset 4 kB). Here's an illustration: | |
| 4 kB +---------------------------------+ | |
| | kernel stack | | |
| | | | | |
| | | | | |
| | V | | |
| | grows downward | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| +---------------------------------+ | |
| | magic | | |
| | : | | |
| | : | | |
| | name | | |
| | status | | |
| 0 kB +---------------------------------+ | |
| The upshot of this is twofold: | |
| 1. First, `struct thread' must not be allowed to grow too | |
| big. If it does, then there will not be enough room for | |
| the kernel stack. Our base `struct thread' is only a | |
| few bytes in size. It probably should stay well under 1 | |
| kB. | |
| 2. Second, kernel stacks must not be allowed to grow too | |
| large. If a stack overflows, it will corrupt the thread | |
| state. Thus, kernel functions should not allocate large | |
| structures or arrays as non-static local variables. Use | |
| dynamic allocation with malloc() or palloc_get_page() | |
| instead. | |
| The first symptom of either of these problems will probably be | |
| an assertion failure in thread_current(), which checks that | |
| the `magic' member of the running thread's `struct thread' is | |
| set to THREAD_MAGIC. Stack overflow will normally change this | |
| */ | |
| /* The `elem' member has a dual purpose. It can be an element in | |
| the run queue (thread.c), or it can be an element in a | |
| semaphore wait list (synch.c). It can be used these two ways | |
| only because they are mutually exclusive: only a thread in the | |
| ready state is on the run queue, whereas only a thread in the | |
| */ | |
| struct thread | |
| { | |
| */ | |
| */ | |
| */ | |
| */ | |
| */ | |
| */ | |
| */ | |
| */ | |
| */ | |
| */ | |
| */ | |
| */ | |
| // needed for priority donations | |
| */ | |
| */ | |
| ifdef USERPROG | |
| */ | |
| */ | |
| // Project 2: file descriptors and process table | |
| */ | |
| */ | |
| /* List of children processes of this thread, | |
| */ | |
| */ | |
| */ | |
| /* The current value of the user program’s stack pointer. | |
| A page fault might occur in the kernel, so we might | |
| */ | |
| endif | |
| ifdef VM | |
| // Project 3: Supplemental page table. | |
| */ | |
| // Project 3: Memory Mapped Files. | |
| */ | |
| endif | |
| // Project 4: CWD. | |
| struct dir *cwd; | |
| */ | |
| */ | |
| }; | |
| /* If false (default), use round-robin scheduler. | |
| If true, use multi-level feedback queue scheduler. | |
| */ | |
| bool thread_mlfqs; | |
| void); | |
| void); | |
| int64_t tick); | |
| void); | |
| void *aux); | |
| void *); | |
| void); | |
| struct thread *); | |
| int64_t wake_tick); | |
| void); | |
| void); | |
| void); | |
| void) NO_RETURN; | |
| void); | |
| */ | |
| void *aux); | |
| void *); | |
| void); | |
| int); | |
| int priority); | |
| void); | |
| int); | |
| void); | |
| void); | |
| */ |