tac0S
Template Affectional Command Operating System
Public Member Functions | Public Attributes | List of all members
Thread Class Reference

The following class defines a "thread control block" – which represents a single thread of execution. More...

#include <thread.h>

Public Member Functions

 Thread (const char *debugName)
 Thread::Thread Initialize a thread control block, so that we can then call Thread::Fork. More...
 
 ~Thread ()
 Thread::~Thread De-allocate a thread. More...
 
void Fork (VoidFunctionPtr func, int arg)
 Thread::Fork Invoke (*func)(arg), allowing caller and callee to execute concurrently. More...
 
void Yield ()
 Thread::Yield Relinquish the CPU if any other thread is ready to run. If so, put the thread on the end of the ready list, so that it will eventually be re-scheduled. More...
 
void Sleep ()
 Thread::Sleep Relinquish the CPU, because the current thread is blocked waiting on a synchronization variable (Semaphore, Lock, or Condition). Eventually, some thread will wake this thread up, and put it back on the ready queue, so that it can be re-scheduled. More...
 
void Finish ()
 Thread::Finish Called by ThreadRoot when a thread is done executing the forked procedure. More...
 
void CheckOverflow ()
 Thread::CheckOverflow Check a thread's stack to see if it has overrun the space that has been allocated for it. If we had a smarter compiler, we wouldn't need to worry about this, but we don't. More...
 
void setStatus (ThreadStatus st)
 Thread::setStatus Set the status as in parameter with debug info. More...
 
const char * getName ()
 
void Print ()
 
void setUserThread (void *userThreadAdress)
 
void * getUserThreadAdress ()
 
ThreadStatus getStatus ()
 
void enterCritique ()
 Thread::enterCritique Get a semaphore for "critic area" code with still having interrupt.
 
void enterCritiqueExt ()
 Thread::enterCritiqueExt From exterior of a thread Get a semaphore for "critic area" code with still having interrupt Basicly stopped the thread when the thread is'nt in critique mode No exit statut for this just exit and call ReadyToRun form the scheduler.
 
void exitCritique ()
 Thread::exitCritique Drop the semaphore for the critique zone of code, see Thread::enterCritique.
 

Public Attributes

bool stopped = false
 
bool inAMutex =false
 

Detailed Description

The following class defines a "thread control block" – which represents a single thread of execution.

Every thread has: an execution stack for activation records ("stackTop" and "stack") space to save CPU registers while not running ("machineState") a "status" (running/ready/blocked)

Some threads also belong to a user address space; threads that only run in the kernel have a NULL address space.

Constructor & Destructor Documentation

Thread::Thread ( const char *  threadName)

Thread::Thread Initialize a thread control block, so that we can then call Thread::Fork.

"threadName" is an arbitrary string, useful for debugging.

Thread::~Thread ( )

Thread::~Thread De-allocate a thread.

NOTE: the current thread cannot delete itself directly, since it is still running on the stack that we need to delete.

NOTE: if this is the main thread, we can't delete the stack because we didn't allocate it – we got it automatically as part of starting up Nachos.

Member Function Documentation

void Thread::CheckOverflow ( )

Thread::CheckOverflow Check a thread's stack to see if it has overrun the space that has been allocated for it. If we had a smarter compiler, we wouldn't need to worry about this, but we don't.

NOTE: Nachos will not catch all stack overflow conditions. In other words, your program may still crash because of an overflow.

If you get bizarre results_test (such as seg faults where there is no code) then you may need to increase the stack size. You can avoid stack overflows by not putting large data structures on the stack. Don't do this: void foo() { int bigArray[10000]; ... }

void Thread::Finish ( )

Thread::Finish Called by ThreadRoot when a thread is done executing the forked procedure.

NOTE: we don't immediately de-allocate the thread data structure or the execution stack, because we're still running in the thread and we're still on the stack! Instead, we set "threadToBeDestroyed", so that Scheduler::Run() will call the destructor, once we're running in the context of a different thread.

NOTE: we disable interrupts, so that we don't get a time slice between setting threadToBeDestroyed, and going to sleep.

void Thread::Fork ( VoidFunctionPtr  func,
int  arg 
)

Thread::Fork Invoke (*func)(arg), allowing caller and callee to execute concurrently.

NOTE: although our definition allows only a single integer argument to be passed to the procedure, it is possible to pass multiple arguments by making them fields of a structure, and passing a pointer to the structure as "arg".

Implemented as the following steps:

  1. Allocate a stack
  2. Initialize the stack so that a call to SWITCH will cause it to run the procedure
  3. Put the thread on the ready queue
Parameters
funcis the procedure to run concurrently.
argis a single argument to be passed to the procedure.
void Thread::setStatus ( ThreadStatus  st)

Thread::setStatus Set the status as in parameter with debug info.

Parameters
ThreadStatusst
void Thread::Sleep ( )

Thread::Sleep Relinquish the CPU, because the current thread is blocked waiting on a synchronization variable (Semaphore, Lock, or Condition). Eventually, some thread will wake this thread up, and put it back on the ready queue, so that it can be re-scheduled.

NOTE: if there are no threads on the ready queue, that means we have no thread to run. "Interrupt::Idle" is called to signify that we should idle the CPU until the next I/O interrupt occurs (the only thing that could cause a thread to become ready to run).

NOTE: we assume interrupts are already disabled, because it is called from the synchronization routines which must disable interrupts for atomicity. We need interrupts off so that there can't be a time slice between pulling the first thread off the ready list, and switching to it.

void Thread::Yield ( )

Thread::Yield Relinquish the CPU if any other thread is ready to run. If so, put the thread on the end of the ready list, so that it will eventually be re-scheduled.

NOTE: returns immediately if no other thread on the ready queue. Otherwise returns when the thread eventually works its way to the front of the ready list and gets re-scheduled.

NOTE: we disable interrupts, so that looking at the thread on the front of the ready list, and switching to it, can be done atomically. On return, we re-set the interrupt level to its original state, in case we are called with interrupts disabled.

Similar to Thread::Sleep(), but a little different.


The documentation for this class was generated from the following files: