#include "myThread.h"
#include <cstdlib>
#include <list>
#include <sys/time.h>
#include <signal.h>
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< Thread > | threadList |
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). |
Definition in file myThread.cpp.
#define TimerType ITIMER_VIRTUAL |
The Interval Timer used.
Definition at line 107 of file myThread.cpp.
Referenced by myThread_create(), myThread_exit(), myThread_getID(), and startTimer().
static void saveContext | ( | int | signalNumber | ) | [static] |
This function saves the context of the current thread It performs the following steps :
signalNumber | The Timer Signal |
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.
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 :
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.
nextThread | Pointer to the next thread to be executed |
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 :
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 :
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 :
start | The Thread Entry Point |
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 :
status | The Return Status of a Thread |
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 :
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 }
const std :: size_t maxStackSize = 2000 [static] |
Stores the maximum size of the stack for any thread other than the main thread.
Definition at line 27 of file myThread.cpp.