myThread.cpp File Reference

MyThread Library Source Code. More...

#include "myThread.h"
#include <cstdlib>
#include <list>
#include <sys/time.h>
#include <signal.h>

Include dependency graph for myThread.cpp:

Go to the source code of this file.

Classes

struct  Thread
 Main Thread Data Structure. More...
struct  Thread::Context
 Thread Context Data Structure. More...

Defines

#define initialTopOfStack   context
 Reference to the initial top of a thread's stack.
#define topOfContextStack   eip
 Reference to the Top of the 'Context' Stack.
#define bottomOfContextStack   context
 Reference to the Bottom of the 'Context' Stack.
#define TimerType   ITIMER_VIRTUAL
#define TimerTypeSignal   SIGVTALRM
 The Interval Timer Signal.

Typedefs

typedef unsigned short uInt16
 Unsigned 16-bit Integer.
typedef unsigned int uInt32
 Unsigned 32-bit Integer.

Functions

static void saveContext (int signalNumber)
 Saves the context of the thread.
static std::list< Thread >
::iterator 
getNextThread ()
 Scheduling Policy : Returns the next thread to be executed.
void threadScheduler ()
 Schedules the next thread.
static void switchToThread (const std::list< Thread >::iterator &nextThread)
 Switches to the specified thread.
static void startTimer (void)
 Starts the interval timer.
void myThread_init ()
 To initialise the threading library.
void myThread_create (StartFunction start)
 To create a new thread.
void myThread_exit (int status)
 To exit a thread.
ThreadID myThread_getID ()
 To get the current running thread's ID.

Variables

static const std::size_t maxStackSize = 2000
 Maximum Stack size.
static std::list< ThreadthreadList
 List of all Threads.
static std::list< Thread >
::iterator 
threadListIterator
 Pointer to the current running thread.
static Thread currentThread
 Stores the current running thread.
static struct itimerval zeroTimer = { { 0 , 0 } , { 0 , 0 } }
 Required to switch off the timer.
static struct itimerval timeSlice = { { 0 , 0 } , { 1 , 10000 } }
 Time Slice given to each thread (1sec 10 ms).


Detailed Description

This contains the implementation of the threading functions, internal thread data structures, and helper functions.

Definition in file myThread.cpp.


Define Documentation

#define TimerType   ITIMER_VIRTUAL

The Interval Timer used.

Note:
Using the Virtual timer simplifies the context switching (we don't have to take care of interrupted system calls)

Definition at line 107 of file myThread.cpp.

Referenced by myThread_create(), myThread_exit(), myThread_getID(), and startTimer().


Function Documentation

static void saveContext ( int  signalNumber  )  [static]

This function saves the context of the current thread It performs the following steps :

  1. Stores the values of all registers in currentThread (using inline assembly)
  2. Calls the threadScheduler
Parameters:
signalNumber The Timer Signal
Returns:
Does not return
Note:
The Timer Signal gets masked when this signal handler is invoked, hence it should be unmasked at a later point

Definition at line 326 of file myThread.cpp.

References Thread::context, Thread::Context::ds, Thread::eflags, Thread::eip, Thread::Context::es, Thread::esp, Thread::Context::fs, and Thread::Context::gs.

Referenced by myThread_init().

00327 {
00328   // Save the context (including the return address)...
00329   asm volatile ( "movl   %%ebp , %%esp    \n\t"
00330                  "popl   %%ebp            \n\t"
00331                  "popl   %0               \n\t"
00332                  "movl   %%esp , %1       \n\t"
00333                  "pushfl                  \n\t"
00334                  "popl   %2               \n\t"
00335                  "leal   %7    , %%esp    \n\t"
00336                  "pushal                  \n\t"
00337                  "movl   %8    , %%esp    \n\t"
00338                  "movw   %%ds  , %%ax     \n\t"
00339                  "movw   %%ax  , %3       \n\t"
00340                  "movw   %%es  , %%ax     \n\t"
00341                  "movw   %%ax  , %4       \n\t"
00342                  "movw   %%fs  , %%ax     \n\t"
00343                  "movw   %%ax  , %5       \n\t"
00344                  "movw   %%gs  , %%ax     \n\t"
00345                  "movw   %%ax  , %6       \n\t"
00346                  "call   threadScheduler  \n\t"
00347                  : "=m" ( currentThread.eip )        , "=m" ( currentThread.esp ) ,
00348                    "=m" ( currentThread.eflags )     ,
00349                    "=m" ( currentThread.context.ds ) , "=m" ( currentThread.context.es ) ,
00350                    "=m" ( currentThread.context.fs ) , "=m" ( currentThread.context.gs )
00351                  : "m" ( currentThread.topOfContextStack ) , "m" ( currentThread.esp )
00352                  : "%esp" , "%eax"
00353                  );
00354 }

static std::list< Thread >::iterator getNextThread (  )  [static]

This function decides the Scheduling Policy. Here, a round-robin policy has been used.

Returns:
A pointer to the next thread to be executed

Definition at line 365 of file myThread.cpp.

References threadList, and threadListIterator.

Referenced by myThread_exit(), and threadScheduler().

00366 {
00367   std :: list < Thread > :: iterator nextThread = threadListIterator;
00368   ++nextThread;
00369 
00370   // Round Robin scheduling...
00371   if ( nextThread == threadList.end() )
00372     nextThread = threadList.begin();
00373 
00374   // This may be the same as currentThread...
00375   return nextThread;
00376 }

void threadScheduler (  ) 

This function switches to the next thread to be executed. It performs the following steps :

  1. Gets the next thread to be executed by calling getNextThread()
  2. Restarts the timer
  3. Switches to the next thread by calling switchToThread()
Returns:
Does not return
Note:
  • The Timer Signal gets unmasked in the function call startTimer()
  • The linkage is specified as extern "C" to make the function easier to invoke using the function's name in the inline assembly

Definition at line 397 of file myThread.cpp.

References getNextThread(), startTimer(), switchToThread(), and threadListIterator.

00398 {
00399   // Save the context into the thread list...
00400   *threadListIterator = currentThread;
00401 
00402   // Choose another thread to run (timer is already off)...
00403   std :: list < Thread > :: iterator nextThread = getNextThread();
00404 
00405   // Make currentThread store the next thread to be run...
00406   threadListIterator = nextThread;
00407   currentThread = *nextThread;
00408 
00409   // Reset the timer...
00410   startTimer();
00411 
00412   // Switch to the next thread...
00413   switchToThread ( nextThread );
00414 }

static void switchToThread ( const std::list< Thread >::iterator &  nextThread  )  [static]

This function restores the context of the next thread to be executed.

Parameters:
nextThread Pointer to the next thread to be executed
Returns:
Does not return

Definition at line 426 of file myThread.cpp.

Referenced by myThread_exit(), and threadScheduler().

00427 {
00428   // Jump to the next thread after switching the context...
00429   // Also, push the new eip on the stack before doing a 'ret'...
00430   uInt32 eax = nextThread -> context.eax , ebx = nextThread -> context.ebx ,
00431          ecx = nextThread -> context.ecx , edx = nextThread -> context.edx ,
00432          esi = nextThread -> context.esi , edi = nextThread -> context.edi ,
00433          ebp = nextThread -> context.ebp , esp = nextThread -> esp ,
00434          eip = nextThread -> eip         , eflags = nextThread -> eflags;
00435   uInt16 ds = nextThread -> context.ds , es = nextThread -> context.es ,
00436          fs = nextThread -> context.fs , gs = nextThread -> context.gs;
00437 
00438   asm volatile ( "movl   %0   , %%esp \n\t"
00439                  "pushl  %1           \n\t"
00440                  "pushl  %2           \n\t"
00441                  "popfl               \n\t"
00442                  "movl   %4   , %%ebx \n\t"
00443                  "movl   %5   , %%ecx \n\t"
00444                  "movl   %6   , %%edx \n\t"
00445                  // Don't modify EBP here, gcc uses it to access local variables
00446                  "movl   %8   , %%esi \n\t"
00447                  "movl   %9   , %%edi \n\t"
00448                  "movw   %10  , %%ax  \n\t"
00449                  "movw   %%ax , %%ds  \n\t"
00450                  "movw   %11  , %%ax  \n\t"
00451                  "movw   %%ax , %%es  \n\t"
00452                  "movw   %12  , %%ax  \n\t"
00453                  "movw   %%ax , %%fs  \n\t"
00454                  "movw   %13  , %%ax  \n\t"
00455                  "movw   %%ax , %%gs  \n\t"
00456                  "movl   %3   , %%eax \n\t"
00457                  // Change EBP at the end
00458                  "movl   %7   , %%ebp \n\t"
00459                  "ret                 \n\t"
00460                  :
00461                  : "m" ( esp )    , "m" ( eip ) ,
00462                    "m" ( eflags ) ,
00463                    "m" ( eax )    , "m" ( ebx ) ,
00464                    "m" ( ecx )    , "m" ( edx ) ,
00465                    "m" ( ebp )    ,
00466                    "m" ( esi )    , "m" ( edi ) ,
00467                    "m" ( ds  )    , "m" ( es  ) ,
00468                    "m" ( fs  )    , "m" ( gs  )
00469                  : "%eax" , "%ebx" , "%ecx" , "%edx" ,
00470                    "%esi" , "%edi" , "%esp"
00471                  );
00472 }

static void startTimer ( void   )  [static]

This function restarts the Timer. It performs the following steps :

  1. Unmasks (unblocks) the Timer Signal
  2. Resets the timer to the timeSlice
Returns:
Returns Nothing

Definition at line 486 of file myThread.cpp.

References TimerType, TimerTypeSignal, and timeSlice.

Referenced by myThread_exit(), myThread_init(), and threadScheduler().

00487 {
00488   // Unblock the TimerTypeSignal...
00489   sigset_t unblockTimerSignal;
00490   sigemptyset ( &unblockTimerSignal );
00491   sigaddset ( &unblockTimerSignal , TimerTypeSignal );
00492   sigprocmask ( SIG_UNBLOCK , &unblockTimerSignal , NULL );
00493 
00494   // Start the timer...
00495   setitimer ( TimerType , &timeSlice , NULL );
00496 }

void myThread_init (  ) 

This function initialises the thread library. It performs the following steps :

  1. Creates a Thread data structure for the main thread and puts it in the thread list
  2. Registers the signal handler saveContext() to catch the Timer signal
  3. Starts the Interval Timer
Returns:
Returns Nothing

Definition at line 138 of file myThread.cpp.

References Thread::id, saveContext(), startTimer(), threadList, threadListIterator, and TimerTypeSignal.

00139 {
00140   // Create an entry for the main thread...
00141   Thread mainThread;
00142   // A special ID = 0 for the main thread...
00143   // The main thread does not have a separate stack like the other threads...
00144   mainThread.id = 0;
00145 
00146   // Insert the main thread into the list of threads...
00147   threadList.push_back ( mainThread );
00148 
00149   // Set the current thread to this main thread...
00150   threadListIterator = threadList.begin();
00151   currentThread = mainThread;
00152 
00153   // Register the signal handling routine...
00154   struct sigaction action;
00155   action.sa_handler = saveContext;
00156   sigemptyset ( &action.sa_mask );
00157   action.sa_flags = 0;
00158   sigaction ( TimerTypeSignal , &action , NULL );
00159 
00160   // Start the Timer...
00161   startTimer();
00162 }

void myThread_create ( StartFunction  start  ) 

This function creates a new thread It performs the following steps :

  1. Switches off the Timer
  2. Fills in a new Thread Data Structure, and appends it to the end of the thread list
  3. Restarts the Interval Timer
Parameters:
start The Thread Entry Point
Returns:
Returns Nothing
Note:
This function can be used in any thread to create new threads. However, there is no concept of thread parent and child.
Bug:
The Thread ID assigned may not be unique

Definition at line 187 of file myThread.cpp.

References initialTopOfStack, threadList, TimerType, and zeroTimer.

00188 {
00189   // Switch off the timer...
00190   struct itimerval oldTimer;
00191   setitimer ( TimerType , &zeroTimer , &oldTimer );
00192 
00193   // Create a new thread...
00194   Thread *newThread = new Thread;            // How to deallocate ???????
00195   // Note : This method will not produce unique thread IDs...
00196   newThread -> id = threadList.size();       // we may run out of thread IDs...
00197   newThread -> esp = reinterpret_cast < uInt32 > ( &newThread -> initialTopOfStack );
00198   newThread -> eip = reinterpret_cast < uInt32 > ( start );
00199   asm volatile ( "movw   %%ds , %%ax \n\t"
00200                  "movw   %%ax , %0   \n\t"
00201                  "movw   %%es , %%ax \n\t"
00202                  "movw   %%ax , %1   \n\t"
00203                  "movw   %%fs , %%ax \n\t"
00204                  "movw   %%ax , %2   \n\t"
00205                  "movw   %%gs , %%ax \n\t"
00206                  "movw   %%ax , %3   \n\t"
00207                  "pushfl             \n\t"
00208                  "popl   %4          \n\t"
00209                  : "=m" ( newThread -> context.ds ) , "=m" ( newThread -> context.es ) ,
00210                    "=m" ( newThread -> context.fs ) , "=m" ( newThread -> context.gs ) ,
00211                    "=m" ( newThread -> eflags )
00212                  :
00213                  : "%ax"
00214                  );
00215 
00216   // Insert it into the list...
00217   threadList.push_back ( *newThread );
00218 
00219   // Set the timer to what it was...
00220   setitimer ( TimerType , &oldTimer , NULL );
00221 
00222   // Return to the current thread...
00223   return;
00224 }

void myThread_exit ( int  status  ) 

This function terminates a thread It performs the following steps :

  1. Switches off the Timer
  2. Gets the next thread to be run
  3. Removes the current thread from the list
  4. Restarts the Interval Timer
  5. Switches to the next thread
Parameters:
status The Return Status of a Thread
Returns:
Does not return
Note:
All threads (other than the main thread) should call this function before exiting
Todo:
Record the return status of the thread in some way

Definition at line 250 of file myThread.cpp.

References getNextThread(), startTimer(), switchToThread(), threadList, threadListIterator, TimerType, and zeroTimer.

00251 {
00252   // Status is ignored...
00253   // Switch off the timer...
00254   setitimer ( TimerType , &zeroTimer , NULL );
00255 
00256   // Keep the next thread ready...
00257   std :: list < Thread > :: iterator nextThread = getNextThread();
00258 
00259   // If this is the last thread, then simply exit...
00260   if ( nextThread == threadListIterator )
00261     exit ( status );
00262 
00263   // Remove the thread from the list...
00264   threadList.erase ( threadListIterator );
00265   threadListIterator = nextThread;
00266   currentThread = *nextThread;
00267 
00268   // Reset the timer...
00269   startTimer();
00270 
00271   // Switch to next thread...
00272   switchToThread ( nextThread );
00273 }

ThreadID myThread_getID (  ) 

This function returns the current running thread's ID It performs the following steps :

  1. Switches off the Timer
  2. Gets the current thread ID
  3. Switches the timer back on
Returns:
The current executing thread's ID
Remarks:
The Timer is switched off before accessing the thread list, but this may not really be required

Definition at line 292 of file myThread.cpp.

References Thread::id, TimerType, and zeroTimer.

00293 {
00294   // Switch off the timer...
00295   struct itimerval oldTimer;
00296   setitimer ( TimerType , &zeroTimer , &oldTimer );
00297 
00298   // Get the current thread ID...
00299   ThreadID id = currentThread.id;
00300 
00301   // Set the timer to what it was...
00302   setitimer ( TimerType , &oldTimer , NULL );
00303 
00304   return id;
00305 }


Variable Documentation

const std :: size_t maxStackSize = 2000 [static]

Stores the maximum size of the stack for any thread other than the main thread.

Note:
Stack Size should be large enough for lots of nested function calls, especially in the STL library

Definition at line 27 of file myThread.cpp.


Generated on Fri Sep 18 20:32:22 2009 for "MyThread Library" by  doxygen 1.5.5