PKUOS - Pintos
Pintos source browser for PKU Operating System course
thread.c
Go to the documentation of this file.
1#include "threads/thread.h"
2#include <debug.h>
3#include <stddef.h>
4#include <random.h>
5#include <stdio.h>
6#include <string.h>
7#include "threads/flags.h"
8#include "threads/interrupt.h"
10#include "threads/palloc.h"
11#include "threads/switch.h"
12#include "threads/synch.h"
13#include "threads/vaddr.h"
14#ifdef USERPROG
15#include "userprog/process.h"
16#endif
17
18/** Random value for struct thread's `magic' member.
19 Used to detect stack overflow. See the big comment at the top
20 of thread.h for details. */
21#define THREAD_MAGIC 0xcd6abf4b
22
23/** List of processes in THREAD_READY state, that is, processes
24 that are ready to run but not actually running. */
25static struct list ready_list;
26
27/** List of all processes. Processes are added to this list
28 when they are first scheduled and removed when they exit. */
29static struct list all_list;
30
31/** Idle thread. */
32static struct thread *idle_thread;
33
34/** Initial thread, the thread running init.c:main(). */
35static struct thread *initial_thread;
36
37/** Lock used by allocate_tid(). */
38static struct lock tid_lock;
39
40/** Stack frame for kernel_thread(). */
42 {
43 void *eip; /**< Return address. */
44 thread_func *function; /**< Function to call. */
45 void *aux; /**< Auxiliary data for function. */
46 };
47
48/** Statistics. */
49static long long idle_ticks; /**< # of timer ticks spent idle. */
50static long long kernel_ticks; /**< # of timer ticks in kernel threads. */
51static long long user_ticks; /**< # of timer ticks in user programs. */
52
53/** Scheduling. */
54#define TIME_SLICE 4 /**< # of timer ticks to give each thread. */
55static unsigned thread_ticks; /**< # of timer ticks since last yield. */
56
57/** If false (default), use round-robin scheduler.
58 If true, use multi-level feedback queue scheduler.
59 Controlled by kernel command-line option "-o mlfqs". */
61
62static void kernel_thread (thread_func *, void *aux);
63
64static void idle (void *aux UNUSED);
65static struct thread *running_thread (void);
66static struct thread *next_thread_to_run (void);
67static void init_thread (struct thread *, const char *name, int priority);
68static bool is_thread (struct thread *) UNUSED;
69static void *alloc_frame (struct thread *, size_t size);
70static void schedule (void);
71void thread_schedule_tail (struct thread *prev);
72static tid_t allocate_tid (void);
73
74/** Initializes the threading system by transforming the code
75 that's currently running into a thread. This can't work in
76 general and it is possible in this case only because loader.S
77 was careful to put the bottom of the stack at a page boundary.
78
79 Also initializes the run queue and the tid lock.
80
81 After calling this function, be sure to initialize the page
82 allocator before trying to create any threads with
83 thread_create().
84
85 It is not safe to call thread_current() until this function
86 finishes. */
87void
88thread_init (void)
89{
91
95
96 /* Set up a thread structure for the running thread. */
101}
102
103/** Starts preemptive thread scheduling by enabling interrupts.
104 Also creates the idle thread. */
105void
107{
108 /* Create the idle thread. */
109 struct semaphore idle_started;
110 sema_init (&idle_started, 0);
111 thread_create ("idle", PRI_MIN, idle, &idle_started);
112
113 /* Start preemptive thread scheduling. */
114 intr_enable ();
115
116 /* Wait for the idle thread to initialize idle_thread. */
117 sema_down (&idle_started);
118}
119
120/** Called by the timer interrupt handler at each timer tick.
121 Thus, this function runs in an external interrupt context. */
122void
124{
125 struct thread *t = thread_current ();
126
127 /* Update statistics. */
128 if (t == idle_thread)
129 idle_ticks++;
130#ifdef USERPROG
131 else if (t->pagedir != NULL)
132 user_ticks++;
133#endif
134 else
135 kernel_ticks++;
136
137 /* Enforce preemption. */
138 if (++thread_ticks >= TIME_SLICE)
140}
141
142/** Prints thread statistics. */
143void
145{
146 printf ("Thread: %lld idle ticks, %lld kernel ticks, %lld user ticks\n",
148}
149
150/** Creates a new kernel thread named NAME with the given initial
151 PRIORITY, which executes FUNCTION passing AUX as the argument,
152 and adds it to the ready queue. Returns the thread identifier
153 for the new thread, or TID_ERROR if creation fails.
154
155 If thread_start() has been called, then the new thread may be
156 scheduled before thread_create() returns. It could even exit
157 before thread_create() returns. Contrariwise, the original
158 thread may run for any amount of time before the new thread is
159 scheduled. Use a semaphore or some other form of
160 synchronization if you need to ensure ordering.
161
162 The code provided sets the new thread's `priority' member to
163 PRIORITY, but no actual priority scheduling is implemented.
164 Priority scheduling is the goal of Problem 1-3. */
165tid_t
166thread_create (const char *name, int priority,
167 thread_func *function, void *aux)
168{
169 struct thread *t;
170 struct kernel_thread_frame *kf;
171 struct switch_entry_frame *ef;
172 struct switch_threads_frame *sf;
173 tid_t tid;
174
175 ASSERT (function != NULL);
176
177 /* Allocate thread. */
179 if (t == NULL)
180 return TID_ERROR;
181
182 /* Initialize thread. */
183 init_thread (t, name, priority);
184 tid = t->tid = allocate_tid ();
185
186 /* Stack frame for kernel_thread(). */
187 kf = alloc_frame (t, sizeof *kf);
188 kf->eip = NULL;
189 kf->function = function;
190 kf->aux = aux;
191
192 /* Stack frame for switch_entry(). */
193 ef = alloc_frame (t, sizeof *ef);
194 ef->eip = (void (*) (void)) kernel_thread;
195
196 /* Stack frame for switch_threads(). */
197 sf = alloc_frame (t, sizeof *sf);
198 sf->eip = switch_entry;
199 sf->ebp = 0;
200
201 /* Add to run queue. */
202 thread_unblock (t);
203
204 return tid;
205}
206
207/** Puts the current thread to sleep. It will not be scheduled
208 again until awoken by thread_unblock().
209
210 This function must be called with interrupts turned off. It
211 is usually a better idea to use one of the synchronization
212 primitives in synch.h. */
213void
215{
216 ASSERT (!intr_context ());
218
220 schedule ();
221}
222
223/** Transitions a blocked thread T to the ready-to-run state.
224 This is an error if T is not blocked. (Use thread_yield() to
225 make the running thread ready.)
226
227 This function does not preempt the running thread. This can
228 be important: if the caller had disabled interrupts itself,
229 it may expect that it can atomically unblock a thread and
230 update other data. */
231void
233{
234 enum intr_level old_level;
235
236 ASSERT (is_thread (t));
237
238 old_level = intr_disable ();
241 t->status = THREAD_READY;
242 intr_set_level (old_level);
243}
244
245/** Returns the name of the running thread. */
246const char *
248{
249 return thread_current ()->name;
250}
251
252/** Returns the running thread.
253 This is running_thread() plus a couple of sanity checks.
254 See the big comment at the top of thread.h for details. */
255struct thread *
257{
258 struct thread *t = running_thread ();
259
260 /* Make sure T is really a thread.
261 If either of these assertions fire, then your thread may
262 have overflowed its stack. Each thread has less than 4 kB
263 of stack, so a few big automatic arrays or moderate
264 recursion can cause stack overflow. */
265 ASSERT (is_thread (t));
267
268 return t;
269}
270
271/** Returns the running thread's tid. */
272tid_t
274{
275 return thread_current ()->tid;
276}
277
278/** Deschedules the current thread and destroys it. Never
279 returns to the caller. */
280void
282{
283 ASSERT (!intr_context ());
284
285#ifdef USERPROG
286 process_exit ();
287#endif
288
289 /* Remove thread from all threads list, set our status to dying,
290 and schedule another process. That process will destroy us
291 when it calls thread_schedule_tail(). */
292 intr_disable ();
295 schedule ();
296 NOT_REACHED ();
297}
298
299/** Yields the CPU. The current thread is not put to sleep and
300 may be scheduled again immediately at the scheduler's whim. */
301void
303{
304 struct thread *cur = thread_current ();
305 enum intr_level old_level;
306
307 ASSERT (!intr_context ());
308
309 old_level = intr_disable ();
310 if (cur != idle_thread)
312 cur->status = THREAD_READY;
313 schedule ();
314 intr_set_level (old_level);
315}
316
317/** Invoke function 'func' on all threads, passing along 'aux'.
318 This function must be called with interrupts off. */
319void
321{
322 struct list_elem *e;
323
325
326 for (e = list_begin (&all_list); e != list_end (&all_list);
327 e = list_next (e))
328 {
329 struct thread *t = list_entry (e, struct thread, allelem);
330 func (t, aux);
331 }
332}
333
334/** Sets the current thread's priority to NEW_PRIORITY. */
335void
336thread_set_priority (int new_priority)
337{
338 thread_current ()->priority = new_priority;
339}
340
341/** Returns the current thread's priority. */
342int
344{
345 return thread_current ()->priority;
346}
347
348/** Sets the current thread's nice value to NICE. */
349void
351{
352 /* Not yet implemented. */
353}
354
355/** Returns the current thread's nice value. */
356int
358{
359 /* Not yet implemented. */
360 return 0;
361}
362
363/** Returns 100 times the system load average. */
364int
366{
367 /* Not yet implemented. */
368 return 0;
369}
370
371/** Returns 100 times the current thread's recent_cpu value. */
372int
374{
375 /* Not yet implemented. */
376 return 0;
377}
378
379/** Idle thread. Executes when no other thread is ready to run.
380
381 The idle thread is initially put on the ready list by
382 thread_start(). It will be scheduled once initially, at which
383 point it initializes idle_thread, "up"s the semaphore passed
384 to it to enable thread_start() to continue, and immediately
385 blocks. After that, the idle thread never appears in the
386 ready list. It is returned by next_thread_to_run() as a
387 special case when the ready list is empty. */
388static void
389idle (void *idle_started_ UNUSED)
390{
391 struct semaphore *idle_started = idle_started_;
393 sema_up (idle_started);
394
395 for (;;)
396 {
397 /* Let someone else run. */
398 intr_disable ();
399 thread_block ();
400
401 /* Re-enable interrupts and wait for the next one.
402
403 The `sti' instruction disables interrupts until the
404 completion of the next instruction, so these two
405 instructions are executed atomically. This atomicity is
406 important; otherwise, an interrupt could be handled
407 between re-enabling interrupts and waiting for the next
408 one to occur, wasting as much as one clock tick worth of
409 time.
410
411 See [IA32-v2a] "HLT", [IA32-v2b] "STI", and [IA32-v3a]
412 7.11.1 "HLT Instruction". */
413 asm volatile ("sti; hlt" : : : "memory");
414 }
415}
416
417/** Function used as the basis for a kernel thread. */
418static void
419kernel_thread (thread_func *function, void *aux)
420{
421 ASSERT (function != NULL);
422
423 intr_enable (); /**< The scheduler runs with interrupts off. */
424 function (aux); /**< Execute the thread function. */
425 thread_exit (); /**< If function() returns, kill the thread. */
426}
427
428/** Returns the running thread. */
429struct thread *
431{
432 uint32_t *esp;
433
434 /* Copy the CPU's stack pointer into `esp', and then round that
435 down to the start of a page. Because `struct thread' is
436 always at the beginning of a page and the stack pointer is
437 somewhere in the middle, this locates the curent thread. */
438 asm ("mov %%esp, %0" : "=g" (esp));
439 return pg_round_down (esp);
440}
441
442/** Returns true if T appears to point to a valid thread. */
443static bool
444is_thread (struct thread *t)
445{
446 return t != NULL && t->magic == THREAD_MAGIC;
447}
448
449/** Does basic initialization of T as a blocked thread named
450 NAME. */
451static void
452init_thread (struct thread *t, const char *name, int priority)
453{
454 enum intr_level old_level;
455
456 ASSERT (t != NULL);
458 ASSERT (name != NULL);
459
460 memset (t, 0, sizeof *t);
462 strlcpy (t->name, name, sizeof t->name);
463 t->stack = (uint8_t *) t + PGSIZE;
464 t->priority = priority;
465 t->magic = THREAD_MAGIC;
466
467 old_level = intr_disable ();
469 intr_set_level (old_level);
470}
471
472/** Allocates a SIZE-byte frame at the top of thread T's stack and
473 returns a pointer to the frame's base. */
474static void *
475alloc_frame (struct thread *t, size_t size)
476{
477 /* Stack data is always allocated in word-size units. */
478 ASSERT (is_thread (t));
479 ASSERT (size % sizeof (uint32_t) == 0);
480
481 t->stack -= size;
482 return t->stack;
483}
484
485/** Chooses and returns the next thread to be scheduled. Should
486 return a thread from the run queue, unless the run queue is
487 empty. (If the running thread can continue running, then it
488 will be in the run queue.) If the run queue is empty, return
489 idle_thread. */
490static struct thread *
492{
493 if (list_empty (&ready_list))
494 return idle_thread;
495 else
496 return list_entry (list_pop_front (&ready_list), struct thread, elem);
497}
498
499/** Completes a thread switch by activating the new thread's page
500 tables, and, if the previous thread is dying, destroying it.
501
502 At this function's invocation, we just switched from thread
503 PREV, the new thread is already running, and interrupts are
504 still disabled. This function is normally invoked by
505 thread_schedule() as its final action before returning, but
506 the first time a thread is scheduled it is called by
507 switch_entry() (see switch.S).
508
509 It's not safe to call printf() until the thread switch is
510 complete. In practice that means that printf()s should be
511 added at the end of the function.
512
513 After this function and its caller returns, the thread switch
514 is complete. */
515void
517{
518 struct thread *cur = running_thread ();
519
521
522 /* Mark us as running. */
523 cur->status = THREAD_RUNNING;
524
525 /* Start new time slice. */
526 thread_ticks = 0;
527
528#ifdef USERPROG
529 /* Activate the new address space. */
531#endif
532
533 /* If the thread we switched from is dying, destroy its struct
534 thread. This must happen late so that thread_exit() doesn't
535 pull out the rug under itself. (We don't free
536 initial_thread because its memory was not obtained via
537 palloc().) */
538 if (prev != NULL && prev->status == THREAD_DYING && prev != initial_thread)
539 {
540 ASSERT (prev != cur);
541 palloc_free_page (prev);
542 }
543}
544
545/** Schedules a new process. At entry, interrupts must be off and
546 the running process's state must have been changed from
547 running to some other state. This function finds another
548 thread to run and switches to it.
549
550 It's not safe to call printf() until thread_schedule_tail()
551 has completed. */
552static void
553schedule (void)
554{
555 struct thread *cur = running_thread ();
556 struct thread *next = next_thread_to_run ();
557 struct thread *prev = NULL;
558
560 ASSERT (cur->status != THREAD_RUNNING);
562
563 if (cur != next)
564 prev = switch_threads (cur, next);
566}
567
568/** Returns a tid to use for a new thread. */
569static tid_t
571{
572 static tid_t next_tid = 1;
573 tid_t tid;
574
576 tid = next_tid++;
578
579 return tid;
580}
581
582/** Offset of `stack' member within `struct thread'.
583 Used by switch.S, which can't figure it out on its own. */
#define ASSERT(CONDITION)
This is outside the header guard so that debug.h may be included multiple times with different settin...
Definition: debug.h:31
#define NOT_REACHED()
lib/debug.h
Definition: debug.h:35
#define UNUSED
GCC lets us add "attributes" to functions, function parameters, etc.
Definition: debug.h:7
char * name[]
Definition: insult.c:47
void intr_yield_on_return(void)
During processing of an external interrupt, directs the interrupt handler to yield to a new process j...
Definition: interrupt.c:222
enum intr_level intr_enable(void)
Enables interrupts and returns the previous interrupt status.
Definition: interrupt.c:88
bool intr_context(void)
Returns true during processing of an external interrupt and false at all other times.
Definition: interrupt.c:212
enum intr_level intr_disable(void)
Disables interrupts and returns the previous interrupt status.
Definition: interrupt.c:104
enum intr_level intr_get_level(void)
Returns the current interrupt status.
Definition: interrupt.c:65
enum intr_level intr_set_level(enum intr_level level)
Enables or disables interrupts as specified by LEVEL and returns the previous interrupt status.
Definition: interrupt.c:81
intr_level
Interrupts on or off?
Definition: interrupt.h:9
@ INTR_OFF
Interrupts disabled.
Definition: interrupt.h:10
static int next(int pos)
Returns the position after POS within an intq.
Definition: intq.c:79
struct list_elem * list_begin(struct list *list)
Returns the beginning of LIST.
Definition: list.c:72
struct list_elem * list_remove(struct list_elem *elem)
Removes ELEM from its list and returns the element that followed it.
Definition: list.c:249
struct list_elem * list_pop_front(struct list *list)
Removes the front element from LIST and returns it.
Definition: list.c:260
struct list_elem * list_end(struct list *list)
Returns LIST's tail.
Definition: list.c:94
bool list_empty(struct list *list)
Returns true if LIST is empty, false otherwise.
Definition: list.c:310
void list_init(struct list *list)
Initializes LIST as an empty list.
Definition: list.c:61
void list_push_back(struct list *list, struct list_elem *elem)
Inserts ELEM at the end of LIST, so that it becomes the back in LIST.
Definition: list.c:217
struct list_elem * list_next(struct list_elem *elem)
Returns the element after ELEM in its list.
Definition: list.c:82
int printf(const char *format,...)
Writes formatted output to the console.
Definition: stdio.c:79
#define list_entry(LIST_ELEM, STRUCT, MEMBER)
Converts pointer to list element LIST_ELEM into a pointer to the structure that LIST_ELEM is embedded...
Definition: list.h:108
void * palloc_get_page(enum palloc_flags flags)
Obtains a single free page and returns its kernel virtual address.
Definition: palloc.c:111
void palloc_free_page(void *page)
Frees the page at PAGE.
Definition: palloc.c:146
@ PAL_ZERO
Zero page contents.
Definition: palloc.h:10
void process_activate(void)
Sets up the CPU for running user code in the current thread.
Definition: process.c:123
void process_exit(void)
Free the current process's resources.
Definition: process.c:96
#define NULL
Definition: stddef.h:4
#define offsetof(TYPE, MEMBER)
Definition: stddef.h:5
unsigned int uint32_t
Definition: stdint.h:26
unsigned char uint8_t
Definition: stdint.h:20
void * memset(void *dst_, int value, size_t size)
Sets the SIZE bytes in DST to VALUE.
Definition: string.c:279
size_t strlcpy(char *dst, const char *src, size_t size)
Copies string SRC to DST.
Definition: string.c:326
Stack frame for kernel_thread().
Definition: thread.c:42
void * aux
Auxiliary data for function.
Definition: thread.c:45
thread_func * function
Function to call.
Definition: thread.c:44
void * eip
Return address.
Definition: thread.c:43
Doubly linked list.
Definition: list.h:91
List.
Definition: list.h:98
Lock.
Definition: synch.h:22
A counting semaphore.
Definition: synch.h:9
Stack frame for switch_entry().
Definition: switch.h:24
void(* eip)(void)
Definition: switch.h:25
switch_thread()'s stack frame.
Definition: switch.h:7
void(* eip)(void)
16: Return address.
Definition: switch.h:12
uint32_t ebp
8: Saved ebp.
Definition: switch.h:10
A kernel thread or user process.
Definition: thread.h:84
int priority
Priority.
Definition: thread.h:90
uint8_t * stack
Saved stack pointer.
Definition: thread.h:89
struct list_elem allelem
List element for all threads list.
Definition: thread.h:91
unsigned magic
Detects stack overflow.
Definition: thread.h:102
struct list_elem elem
List element.
Definition: thread.h:94
char name[16]
Name (for debugging purposes).
Definition: thread.h:88
tid_t tid
Thread identifier.
Definition: thread.h:86
enum thread_status status
Thread state.
Definition: thread.h:87
struct thread * switch_threads(struct thread *cur, struct thread *next)
Switches from CUR, which must be the running thread, to NEXT, which must also be running switch_threa...
void switch_entry(void)
void lock_release(struct lock *lock)
Releases LOCK, which must be owned by the current thread.
Definition: synch.c:229
void sema_init(struct semaphore *sema, unsigned value)
This file is derived from source code for the Nachos instructional operating system.
Definition: synch.c:45
void sema_up(struct semaphore *sema)
Up or "V" operation on a semaphore.
Definition: synch.c:109
void lock_init(struct lock *lock)
Initializes LOCK.
Definition: synch.c:176
void lock_acquire(struct lock *lock)
Acquires LOCK, sleeping until it becomes available if necessary.
Definition: synch.c:193
void sema_down(struct semaphore *sema)
Down or "P" operation on a semaphore.
Definition: synch.c:61
struct thread * thread_current(void)
Returns the running thread.
Definition: thread.c:256
void thread_start(void)
Starts preemptive thread scheduling by enabling interrupts.
Definition: thread.c:106
void thread_unblock(struct thread *t)
Transitions a blocked thread T to the ready-to-run state.
Definition: thread.c:232
static long long user_ticks
Definition: thread.c:51
static void * alloc_frame(struct thread *t, size_t size)
Allocates a SIZE-byte frame at the top of thread T's stack and returns a pointer to the frame's base.
Definition: thread.c:475
int thread_get_nice(void)
Returns the current thread's nice value.
Definition: thread.c:357
bool thread_mlfqs
If false (default), use round-robin scheduler.
Definition: thread.c:60
static void init_thread(struct thread *, const char *name, int priority)
Does basic initialization of T as a blocked thread named NAME.
Definition: thread.c:452
static tid_t allocate_tid(void)
Returns a tid to use for a new thread.
Definition: thread.c:570
static struct thread * running_thread(void)
Returns the running thread.
Definition: thread.c:430
static long long idle_ticks
Statistics.
Definition: thread.c:49
static struct thread * idle_thread
Idle thread.
Definition: thread.c:32
static void idle(void *aux UNUSED)
uint32_t thread_stack_ofs
Offset of ‘stack’ member within ‘struct thread’.
Definition: thread.c:584
static void schedule(void)
Schedules a new process.
Definition: thread.c:553
static unsigned thread_ticks
Definition: thread.c:55
int thread_get_priority(void)
Returns the current thread's priority.
Definition: thread.c:343
static bool is_thread(struct thread *)
Initializes the threading system by transforming the code that's currently running into a thread.
Definition: thread.c:68
const char * thread_name(void)
Returns the name of the running thread.
Definition: thread.c:247
void thread_exit(void)
Deschedules the current thread and destroys it.
Definition: thread.c:281
static struct list ready_list
List of processes in THREAD_READY state, that is, processes that are ready to run but not actually ru...
Definition: thread.c:25
tid_t thread_create(const char *name, int priority, thread_func *function, void *aux)
Creates a new kernel thread named NAME with the given initial PRIORITY, which executes FUNCTION passi...
Definition: thread.c:166
int thread_get_recent_cpu(void)
Returns 100 times the current thread's recent_cpu value.
Definition: thread.c:373
void thread_set_priority(int new_priority)
Sets the current thread's priority to NEW_PRIORITY.
Definition: thread.c:336
void thread_tick(void)
Called by the timer interrupt handler at each timer tick.
Definition: thread.c:123
static struct list all_list
List of all processes.
Definition: thread.c:29
void thread_yield(void)
Yields the CPU.
Definition: thread.c:302
void thread_set_nice(int nice UNUSED)
Sets the current thread's nice value to NICE.
Definition: thread.c:350
static void kernel_thread(thread_func *, void *aux)
Function used as the basis for a kernel thread.
Definition: thread.c:419
tid_t thread_tid(void)
Returns the running thread's tid.
Definition: thread.c:273
static long long kernel_ticks
Definition: thread.c:50
void thread_schedule_tail(struct thread *prev)
Completes a thread switch by activating the new thread's page tables, and, if the previous thread is ...
Definition: thread.c:516
static struct thread * next_thread_to_run(void)
Chooses and returns the next thread to be scheduled.
Definition: thread.c:491
void thread_block(void)
Puts the current thread to sleep.
Definition: thread.c:214
static struct thread * initial_thread
Initial thread, the thread running init.c:main().
Definition: thread.c:35
#define TIME_SLICE
Scheduling.
Definition: thread.c:54
static struct lock tid_lock
Lock used by allocate_tid().
Definition: thread.c:38
#define THREAD_MAGIC
Random value for struct thread's ‘magic’ member.
Definition: thread.c:21
int thread_get_load_avg(void)
Returns 100 times the system load average.
Definition: thread.c:365
void thread_print_stats(void)
Prints thread statistics.
Definition: thread.c:144
void thread_foreach(thread_action_func *func, void *aux)
Invoke function 'func' on all threads, passing along 'aux'.
Definition: thread.c:320
@ THREAD_BLOCKED
Waiting for an event to trigger.
Definition: thread.h:13
@ THREAD_DYING
About to be destroyed.
Definition: thread.h:14
@ THREAD_RUNNING
Running thread.
Definition: thread.h:11
@ THREAD_READY
Not running but ready to run.
Definition: thread.h:12
void thread_action_func(struct thread *t, void *aux)
Performs some operation on thread t, given auxiliary data AUX.
Definition: thread.h:130
void thread_init(void)
#define PRI_MAX
Highest priority.
Definition: thread.h:25
#define PRI_DEFAULT
Default priority.
Definition: thread.h:24
#define TID_ERROR
Error value for tid_t.
Definition: thread.h:20
int tid_t
Thread identifier type.
Definition: thread.h:19
void thread_func(void *aux)
Definition: thread.h:116
#define PRI_MIN
Thread priorities.
Definition: thread.h:23
static void * pg_round_down(const void *va)
Round down to nearest page boundary.
Definition: vaddr.h:39
#define PGSIZE
Bytes in a page.
Definition: vaddr.h:20