00001
00011 #include "myThread.h"
00012 #include <cstdlib>
00013 #include <list>
00014 #include <sys/time.h>
00015 #include <signal.h>
00016
00017
00019
00027 static const std :: size_t maxStackSize = 2000;
00029 typedef unsigned short uInt16;
00031 typedef unsigned int uInt32;
00032
00034
00046 struct Thread
00047 {
00048 ThreadID id;
00049 char stack [ maxStackSize ];
00050
00052
00060 struct Context
00061 {
00062 uInt16 gs;
00063 uInt16 fs;
00064 uInt16 es;
00065 uInt16 ds;
00066 uInt32 edi;
00067 uInt32 esi;
00068 uInt32 ebp;
00069 uInt32 esp;
00070 uInt32 ebx;
00071 uInt32 edx;
00072 uInt32 ecx;
00073 uInt32 eax;
00074 } context;
00075 uInt32 eip;
00076 uInt32 esp;
00077 uInt32 eflags;
00078 };
00079
00081 #define initialTopOfStack context
00083 #define topOfContextStack eip
00085 #define bottomOfContextStack context
00086
00087
00089 static std :: list < Thread > threadList;
00091 static std :: list < Thread > :: iterator threadListIterator;
00093 static Thread currentThread;
00094
00095
00097 static struct itimerval zeroTimer = { { 0 , 0 } , { 0 , 0 } };
00099 static struct itimerval timeSlice = { { 0 , 0 } , { 1 , 10000 } };
00107 #define TimerType ITIMER_VIRTUAL
00109 #define TimerTypeSignal SIGVTALRM
00110
00111
00113 static void saveContext ( int signalNumber );
00115 static std :: list < Thread > :: iterator getNextThread();
00117 extern "C" void threadScheduler();
00119 static void switchToThread ( const std :: list < Thread > :: iterator &nextThread );
00121 static void startTimer ( void );
00122
00123
00137 void
00138 myThread_init()
00139 {
00140
00141 Thread mainThread;
00142
00143
00144 mainThread.id = 0;
00145
00146
00147 threadList.push_back ( mainThread );
00148
00149
00150 threadListIterator = threadList.begin();
00151 currentThread = mainThread;
00152
00153
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
00161 startTimer();
00162 }
00163
00186 void
00187 myThread_create ( StartFunction start )
00188 {
00189
00190 struct itimerval oldTimer;
00191 setitimer ( TimerType , &zeroTimer , &oldTimer );
00192
00193
00194 Thread *newThread = new Thread;
00195
00196 newThread -> id = threadList.size();
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
00217 threadList.push_back ( *newThread );
00218
00219
00220 setitimer ( TimerType , &oldTimer , NULL );
00221
00222
00223 return;
00224 }
00225
00249 void
00250 myThread_exit ( int status )
00251 {
00252
00253
00254 setitimer ( TimerType , &zeroTimer , NULL );
00255
00256
00257 std :: list < Thread > :: iterator nextThread = getNextThread();
00258
00259
00260 if ( nextThread == threadListIterator )
00261 exit ( status );
00262
00263
00264 threadList.erase ( threadListIterator );
00265 threadListIterator = nextThread;
00266 currentThread = *nextThread;
00267
00268
00269 startTimer();
00270
00271
00272 switchToThread ( nextThread );
00273 }
00274
00291 ThreadID
00292 myThread_getID()
00293 {
00294
00295 struct itimerval oldTimer;
00296 setitimer ( TimerType , &zeroTimer , &oldTimer );
00297
00298
00299 ThreadID id = currentThread.id;
00300
00301
00302 setitimer ( TimerType , &oldTimer , NULL );
00303
00304 return id;
00305 }
00306
00325 static void
00326 saveContext ( int signalNumber )
00327 {
00328
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 }
00355
00364 static std :: list < Thread > :: iterator
00365 getNextThread()
00366 {
00367 std :: list < Thread > :: iterator nextThread = threadListIterator;
00368 ++nextThread;
00369
00370
00371 if ( nextThread == threadList.end() )
00372 nextThread = threadList.begin();
00373
00374
00375 return nextThread;
00376 }
00377
00395
00396 extern "C" void
00397 threadScheduler()
00398 {
00399
00400 *threadListIterator = currentThread;
00401
00402
00403 std :: list < Thread > :: iterator nextThread = getNextThread();
00404
00405
00406 threadListIterator = nextThread;
00407 currentThread = *nextThread;
00408
00409
00410 startTimer();
00411
00412
00413 switchToThread ( nextThread );
00414 }
00415
00425 static void
00426 switchToThread ( const std :: list < Thread > :: iterator &nextThread )
00427 {
00428
00429
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
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
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 }
00473
00485 static void
00486 startTimer ( void )
00487 {
00488
00489 sigset_t unblockTimerSignal;
00490 sigemptyset ( &unblockTimerSignal );
00491 sigaddset ( &unblockTimerSignal , TimerTypeSignal );
00492 sigprocmask ( SIG_UNBLOCK , &unblockTimerSignal , NULL );
00493
00494
00495 setitimer ( TimerType , &timeSlice , NULL );
00496 }