CS318 - Pintos
Pintos source browser for JHU CS318 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"
9 #include "threads/intr-stubs.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. */
25 static 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. */
29 static struct list all_list;
30 
31 /** Idle thread. */
32 static struct thread *idle_thread;
33 
34 /** Initial thread, the thread running init.c:main(). */
35 static struct thread *initial_thread;
36 
37 /** Lock used by allocate_tid(). */
38 static 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. */
49 static long long idle_ticks; /**< # of timer ticks spent idle. */
50 static long long kernel_ticks; /**< # of timer ticks in kernel threads. */
51 static 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. */
55 static 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 
62 static void kernel_thread (thread_func *, void *aux);
63 
64 static void idle (void *aux UNUSED);
65 static struct thread *running_thread (void);
66 static struct thread *next_thread_to_run (void);
67 static void init_thread (struct thread *, const char *name, int priority);
68 static bool is_thread (struct thread *) UNUSED;
69 static void *alloc_frame (struct thread *, size_t size);
70 static void schedule (void);
71 void thread_schedule_tail (struct thread *prev);
72 static 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. */
87 void
88 thread_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. */
105 void
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. */
122 void
123 thread_tick (void)
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. */
143 void
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. */
165 tid_t
166 thread_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. */
213 void
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. */
231 void
232 thread_unblock (struct thread *t)
233 {
234  enum intr_level old_level;
235 
236  ASSERT (is_thread (t));
237 
238  old_level = intr_disable ();
239  ASSERT (t->status == THREAD_BLOCKED);
241  t->status = THREAD_READY;
242  intr_set_level (old_level);
243 }
244 
245 /** Returns the name of the running thread. */
246 const char *
247 thread_name (void)
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. */
255 struct 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));
266  ASSERT (t->status == THREAD_RUNNING);
267 
268  return t;
269 }
270 
271 /** Returns the running thread's tid. */
272 tid_t
273 thread_tid (void)
274 {
275  return thread_current ()->tid;
276 }
277 
278 /** Deschedules the current thread and destroys it. Never
279  returns to the caller. */
280 void
281 thread_exit (void)
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. */
301 void
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)
311  list_push_back (&ready_list, &cur->elem);
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. */
319 void
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. */
335 void
336 thread_set_priority (int new_priority)
337 {
338  thread_current ()->priority = new_priority;
339 }
340 
341 /** Returns the current thread's priority. */
342 int
344 {
345  return thread_current ()->priority;
346 }
347 
348 /** Sets the current thread's nice value to NICE. */
349 void
351 {
352  /* Not yet implemented. */
353 }
354 
355 /** Returns the current thread's nice value. */
356 int
358 {
359  /* Not yet implemented. */
360  return 0;
361 }
362 
363 /** Returns 100 times the system load average. */
364 int
366 {
367  /* Not yet implemented. */
368  return 0;
369 }
370 
371 /** Returns 100 times the current thread's recent_cpu value. */
372 int
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. */
388 static void
389 idle (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. */
418 static void
419 kernel_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. */
429 struct 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. */
443 static bool
444 is_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. */
451 static void
452 init_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);
461  t->status = THREAD_BLOCKED;
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. */
474 static void *
475 alloc_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. */
490 static 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. */
515 void
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. */
530  process_activate ();
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. */
552 static void
553 schedule (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);
561  ASSERT (is_thread (next));
562 
563  if (cur != next)
564  prev = switch_threads (cur, next);
565  thread_schedule_tail (prev);
566 }
567 
568 /** Returns a tid to use for a new thread. */
569 static 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. */
switch_threads_frame::eip
void(* eip)(void)
16: Return address.
Definition: switch.h:12
name
char * name[]
Definition: insult.c:47
uint8_t
unsigned char uint8_t
Definition: stdint.h:20
switch_threads_frame::ebp
uint32_t ebp
8: Saved ebp.
Definition: switch.h:10
thread::stack
uint8_t * stack
Saved stack pointer.
Definition: thread.h:89
TIME_SLICE
#define TIME_SLICE
Scheduling.
Definition: thread.c:54
list_elem
Doubly linked list.
Definition: list.h:90
list_entry
#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
lock_release
void lock_release(struct lock *lock)
Releases LOCK, which must be owned by the current thread.
Definition: synch.c:229
thread_tid
tid_t thread_tid(void)
Returns the running thread's tid.
Definition: thread.c:273
PAL_ZERO
Zero page contents.
Definition: palloc.h:10
intr_context
bool intr_context(void)
Returns true during processing of an external interrupt and false at all other times.
Definition: interrupt.c:212
thread_start
void thread_start(void)
Starts preemptive thread scheduling by enabling interrupts.
Definition: thread.c:106
THREAD_READY
Not running but ready to run.
Definition: thread.h:12
kernel_thread_frame::aux
void * aux
Auxiliary data for function.
Definition: thread.c:45
intr_level
intr_level
Interrupts on or off?
Definition: interrupt.h:8
NULL
#define NULL
Definition: stddef.h:4
idle_ticks
static long long idle_ticks
Statistics.
Definition: thread.c:49
pg_round_down
static void * pg_round_down(const void *va)
Round down to nearest page boundary.
Definition: vaddr.h:39
string.h
list_init
void list_init(struct list *list)
Initializes LIST as an empty list.
Definition: list.c:61
thread_ticks
static unsigned thread_ticks
Definition: thread.c:55
alloc_frame
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
lock_init
void lock_init(struct lock *lock)
Initializes LOCK.
Definition: synch.c:176
thread_print_stats
void thread_print_stats(void)
Prints thread statistics.
Definition: thread.c:144
intr_set_level
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
kernel_thread
static void kernel_thread(thread_func *, void *aux)
Function used as the basis for a kernel thread.
Definition: thread.c:419
semaphore
A counting semaphore.
Definition: synch.h:8
UNUSED
#define UNUSED
GCC lets us add "attributes" to functions, function parameters, etc.
Definition: debug.h:7
thread
A kernel thread or user process.
Definition: thread.h:83
THREAD_DYING
About to be destroyed.
Definition: thread.h:14
thread_name
const char * thread_name(void)
Returns the name of the running thread.
Definition: thread.c:247
list_next
struct list_elem * list_next(struct list_elem *elem)
Returns the element after ELEM in its list.
Definition: list.c:82
sema_up
void sema_up(struct semaphore *sema)
Up or "V" operation on a semaphore.
Definition: synch.c:109
thread_current
struct thread * thread_current(void)
Returns the running thread.
Definition: thread.c:256
PGSIZE
#define PGSIZE
Bytes in a page.
Definition: vaddr.h:20
thread::tid
tid_t tid
Thread identifier.
Definition: thread.h:86
palloc_get_page
void * palloc_get_page(enum palloc_flags flags)
Obtains a single free page and returns its kernel virtual address.
Definition: palloc.c:111
kernel_thread_frame::eip
void * eip
Return address.
Definition: thread.c:43
thread_foreach
void thread_foreach(thread_action_func *func, void *aux)
Invoke function 'func' on all threads, passing along 'aux'.
Definition: thread.c:320
thread_block
void thread_block(void)
Puts the current thread to sleep.
Definition: thread.c:214
NOT_REACHED
#define NOT_REACHED()
lib/debug.h
Definition: debug.h:35
all_list
static struct list all_list
List of all processes.
Definition: thread.c:29
thread_action_func
void thread_action_func(struct thread *t, void *aux)
Performs some operation on thread t, given auxiliary data AUX.
Definition: thread.h:130
user_ticks
static long long user_ticks
Definition: thread.c:51
offsetof
#define offsetof(TYPE, MEMBER)
Definition: stddef.h:5
list_remove
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
thread::allelem
struct list_elem allelem
List element for all threads list.
Definition: thread.h:91
random.h
process.h
tid_t
int tid_t
Thread identifier type.
Definition: thread.h:19
thread_get_priority
int thread_get_priority(void)
Returns the current thread's priority.
Definition: thread.c:343
next
static int next(int pos)
Returns the position after POS within an intq.
Definition: intq.c:79
interrupt.h
thread_get_nice
int thread_get_nice(void)
Returns the current thread's nice value.
Definition: thread.c:357
uint32_t
unsigned int uint32_t
Definition: stdint.h:26
thread::status
enum thread_status status
Thread state.
Definition: thread.h:87
initial_thread
static struct thread * initial_thread
Initial thread, the thread running init.c:main().
Definition: thread.c:35
switch_threads_frame
switch_thread()'s stack frame.
Definition: switch.h:6
running_thread
static struct thread * running_thread(void)
Returns the running thread.
Definition: thread.c:430
printf
int printf(const char *format,...)
Writes formatted output to the console.
Definition: stdio.c:79
switch_entry
void switch_entry(void)
intr_get_level
enum intr_level intr_get_level(void)
Returns the current interrupt status.
Definition: interrupt.c:65
ready_list
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
THREAD_RUNNING
Running thread.
Definition: thread.h:11
intr_enable
enum intr_level intr_enable(void)
Enables interrupts and returns the previous interrupt status.
Definition: interrupt.c:88
PRI_MAX
#define PRI_MAX
Highest priority.
Definition: thread.h:25
thread_init
void thread_init(void)
tid_lock
static struct lock tid_lock
Lock used by allocate_tid().
Definition: thread.c:38
sema_down
void sema_down(struct semaphore *sema)
Down or "P" operation on a semaphore.
Definition: synch.c:61
idle
static void idle(void *aux UNUSED)
intr-stubs.h
thread::elem
struct list_elem elem
List element.
Definition: thread.h:94
switch.h
palloc.h
kernel_thread_frame::function
thread_func * function
Function to call.
Definition: thread.c:44
list_end
struct list_elem * list_end(struct list *list)
Returns LIST's tail.
Definition: list.c:94
schedule
static void schedule(void)
Schedules a new process.
Definition: thread.c:553
intr_disable
enum intr_level intr_disable(void)
Disables interrupts and returns the previous interrupt status.
Definition: interrupt.c:104
list_empty
bool list_empty(struct list *list)
Returns true if LIST is empty, false otherwise.
Definition: list.c:310
list_begin
struct list_elem * list_begin(struct list *list)
Returns the beginning of LIST.
Definition: list.c:72
ASSERT
#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
thread::magic
unsigned magic
Detects stack overflow.
Definition: thread.h:102
list_pop_front
struct list_elem * list_pop_front(struct list *list)
Removes the front element from LIST and returns it.
Definition: list.c:260
TID_ERROR
#define TID_ERROR
Error value for tid_t.
Definition: thread.h:20
sema_init
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
switch_entry_frame
Stack frame for switch_entry().
Definition: switch.h:23
intr_yield_on_return
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
thread_exit
void thread_exit(void)
Deschedules the current thread and destroys it.
Definition: thread.c:281
switch_entry_frame::eip
void(* eip)(void)
Definition: switch.h:25
palloc_free_page
void palloc_free_page(void *page)
Frees the page at PAGE.
Definition: palloc.c:146
thread_get_recent_cpu
int thread_get_recent_cpu(void)
Returns 100 times the current thread's recent_cpu value.
Definition: thread.c:373
is_thread
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
thread_schedule_tail
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
PRI_MIN
#define PRI_MIN
Thread priorities.
Definition: thread.h:23
process_activate
void process_activate(void)
Sets up the CPU for running user code in the current thread.
Definition: process.c:123
memset
void * memset(void *dst_, int value, size_t size)
Sets the SIZE bytes in DST to VALUE.
Definition: string.c:279
thread_mlfqs
bool thread_mlfqs
If false (default), use round-robin scheduler.
Definition: thread.c:60
thread_create
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
thread_set_priority
void thread_set_priority(int new_priority)
Sets the current thread's priority to NEW_PRIORITY.
Definition: thread.c:336
THREAD_BLOCKED
Waiting for an event to trigger.
Definition: thread.h:13
thread::name
char name[16]
Name (for debugging purposes).
Definition: thread.h:88
INTR_OFF
Interrupts disabled.
Definition: interrupt.h:10
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Copies string SRC to DST.
Definition: string.c:326
list_push_back
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
thread::priority
int priority
Priority.
Definition: thread.h:90
vaddr.h
thread_unblock
void thread_unblock(struct thread *t)
Transitions a blocked thread T to the ready-to-run state.
Definition: thread.c:232
process_exit
void process_exit(void)
Free the current process's resources.
Definition: process.c:96
flags.h
THREAD_MAGIC
#define THREAD_MAGIC
Random value for struct thread's ‘magic’ member.
Definition: thread.c:21
thread_func
void thread_func(void *aux)
Definition: thread.h:116
idle_thread
static struct thread * idle_thread
Idle thread.
Definition: thread.c:32
init_thread
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
lock_acquire
void lock_acquire(struct lock *lock)
Acquires LOCK, sleeping until it becomes available if necessary.
Definition: synch.c:193
thread_stack_ofs
uint32_t thread_stack_ofs
Offset of ‘stack’ member within ‘struct thread’.
Definition: thread.c:584
switch_threads
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...
synch.h
thread.h
thread_set_nice
void thread_set_nice(int nice UNUSED)
Sets the current thread's nice value to NICE.
Definition: thread.c:350
thread_tick
void thread_tick(void)
Called by the timer interrupt handler at each timer tick.
Definition: thread.c:123
stddef.h
thread_yield
void thread_yield(void)
Yields the CPU.
Definition: thread.c:302
kernel_thread_frame
Stack frame for kernel_thread().
Definition: thread.c:41
lock
Lock.
Definition: synch.h:21
thread_get_load_avg
int thread_get_load_avg(void)
Returns 100 times the system load average.
Definition: thread.c:365
next_thread_to_run
static struct thread * next_thread_to_run(void)
Chooses and returns the next thread to be scheduled.
Definition: thread.c:491
list
List.
Definition: list.h:97
allocate_tid
static tid_t allocate_tid(void)
Returns a tid to use for a new thread.
Definition: thread.c:570
debug.h
PRI_DEFAULT
#define PRI_DEFAULT
Default priority.
Definition: thread.h:24
kernel_ticks
static long long kernel_ticks
Definition: thread.c:50