-@node Problem 1-2 Join
-@section Problem 1-2: Join
-
-Implement @code{thread_join(tid_t)} in @file{threads/thread.c}. There
-is already a prototype for it in @file{threads/thread.h}, which you
-should not change. This function causes the currently running thread
-to block until the thread whose thread id is passed as an argument
-exits. If @var{A} is the running thread and @var{B} is the argument,
-then we say that ``@var{A} joins @var{B}.''
-
-Incidentally, we don't use @code{struct thread *} as
-@func{thread_join}'s parameter type because a thread pointer is not
-unique over time. That is, when a thread dies, its memory may be,
-whether immediately or much later, reused for another thread. If
-thread A over time had two children B and C that were stored at the
-same address, then @code{thread_join(@var{B})} and
-@code{thread_join(@var{C})} would be ambiguous. Introducing a thread
-id or @dfn{tid}, represented by type @code{tid_t}, that is
-intentionally unique over time solves the problem. The provided code
-uses an @code{int} for @code{tid_t}, but you may decide you prefer to
-use some other type.
-
-The model for @func{thread_join} is the @command{wait} system call
-in Unix-like systems. (Try reading the manpages.) That system call
-can only be used by a parent process to wait for a child's death. You
-should implement @func{thread_join} to have the same restriction.
-That is, a thread may only join its immediate children.
-
-A thread need not ever be joined. Your solution should properly free
-all of a thread's resources, including its @struct{thread},
-whether it is ever joined or not, and regardless of whether the child
-exits before or after its parent. That is, a thread should be freed
-exactly once in all cases.
-
-Joining a given thread is idempotent. That is, joining a thread T
-multiple times is equivalent to joining it once, because T has already
-exited at the time of the later joins. Thus, joins on T after the
-first should return immediately.
-
-Calling @func{thread_join} on an thread that is not the caller's
-child should cause the caller to return immediately.
-
-Consider all the ways a join can occur: nested joins (@var{A} joins
-@var{B}, then @var{B} joins @var{C}), multiple joins (@var{A} joins
-@var{B}, then @var{A} joins @var{C}), and so on. Does your join work
-if @func{thread_join} is called on a thread that has not yet been
-scheduled for the first time? You should handle all of these cases.
-Write test code that demonstrates the cases your join works for.
-Don't overdo the output volume, please!
-
-Be careful to program this function correctly. You will need its
-functionality for project 2.
-
-Once you've implemented @func{thread_join}, define
-@code{THREAD_JOIN_IMPLEMENTED} in @file{constants.h}.
-@xref{Conditional Compilation}, for more information.
-
-@node Problem 1-3 Priority Scheduling
-@section Problem 1-3: Priority Scheduling
-
-Implement priority scheduling in Pintos. Priority scheduling is a key
-building block for real-time systems. Implement functions
-@func{thread_set_priority} to set the priority of the running thread
-and @func{thread_get_priority} to get the running thread's priority.
-(This API only allows a thread to examine and modify its own
-priority.) There are already prototypes for these functions in
-@file{threads/thread.h}, which you should not change.
-
-Thread priority ranges from @code{PRI_MIN} (0) to @code{PRI_MAX} (59).
-The initial thread priority is passed as an argument to
-@func{thread_create}. If there's no reason to choose another
-priority, use @code{PRI_DEFAULT} (29). The @code{PRI_} macros are
-defined in @file{threads/thread.h}, and you should not change their
-values.