Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

PsnMultiThreadedScheduler.cxx

Go to the documentation of this file.
00001 /*
00002  * This file is part of openMask © INRIA, CNRS, Universite de Rennes 1 1993-2002, thereinafter the Software
00003  * 
00004  * The Software has been developped within the Siames Project. 
00005  * INRIA, the University of Rennes 1 and CNRS jointly hold intellectual property rights
00006  * 
00007  * The Software has been registered with the Agence pour la Protection des
00008  * Programmes (APP) under registration number IDDN.FR.001.510008.00.S.P.2001.000.41200
00009  *  
00010  * This file may be distributed under the terms of the Q Public License
00011  * version 1.0 as defined by Trolltech AS of Norway and appearing in the file
00012  * LICENSE.QPL included in the packaging of this file.
00013  *
00014  * Licensees holding valid specific licenses issued by INRIA, CNRS or Université de Rennes 1 
00015  * for the software may use this file in accordance with that specific license
00016  *
00017  */
00018 #include "PsnMultiThreadedScheduler.h"
00019 
00020 #include "PsnFrameScheduler.h"
00021 #include "PsnBenchScheduler.h"
00022 #include "PsnBarrier.h"
00023 #include "PsController.h"
00024 #include "PsDuplicatedObject.h"
00025 #include "PsnThreadMemoryManager.h"
00026 #include "PsnDescriptorMemoryManager.h"
00027 #include "PsnNew.h"
00028 #include "PsnSystemMemoryManager.h"
00029 #include <unistd.h>
00030 
00031 PsnMultiThreadedScheduler::PsnMultiThreadedScheduler (unsigned int numberOfSteps, unsigned int numberOfThreads, bool createThreadAndLocalSchedulers ) :
00032    PsnScheduler(numberOfSteps),
00033    _numberOfThreads(numberOfThreads),
00034    _currentStep ( 0 ),
00035    _nextThreadForScheduling ( 0 )
00036 {
00037 
00038    _barrier = new PsnBarrier ( _numberOfThreads + 1) ;
00039 
00040    _threadIds = new pthread_t [ _numberOfThreads ] ;
00041 
00042    //onlu used when profiling
00043    _profilingTimer = new itimerval  [ _numberOfThreads ] ;
00044 
00045    _threadData = new vector <pair<PsnScheduler *, unsigned int> * > ( _numberOfThreads ) ;
00046 
00047    for (int i = 0 ; i < _numberOfThreads ; i++ ) 
00048       {
00049          (*_threadData)[i] = new pair<PsnScheduler *, unsigned int> (this, i) ;
00050 
00051          // get the data associated to the timer used for profiling
00052          getitimer(ITIMER_PROF, &(_profilingTimer[i] ));
00053       }
00054 
00055 
00056    _localSchedulers = new vector <PsnScheduler *> ( _numberOfThreads ) ;
00057 
00058    int ret;
00059 
00060 #ifdef _SGI
00061    //for better use of the cpus available
00062    pthread_setconcurrency(_numberOfThreads) ;
00063 #endif
00064 
00065    if ( createThreadAndLocalSchedulers )
00066       {
00067          
00068          _duplicatedObjectScheduler = new PsnFrameScheduler( numberOfSteps ) ;
00069          
00070          for (int i = 0 ; i < _numberOfThreads ; i++ ) 
00071             {
00072                (*_localSchedulers)[i] = new PsnFrameScheduler( numberOfSteps ) ;
00073             }
00074             
00075          for (int i = 0 ; i < _numberOfThreads ; i++ ) 
00076             {
00077                ret = pthread_create( & (_threadIds [i]), 
00078                                      0,
00079                                      (void *(*)(void *))_threadContainer,
00080                                      (*_threadData)[i]);
00081                if (ret) 
00082                   {
00083                      PsController::error("Thread creation impossible") ;
00084                   }
00085                
00086             }
00087       }
00088 }
00089 
00090 
00091 PsnMultiThreadedScheduler::~PsnMultiThreadedScheduler() {
00092    
00093 
00094    for (int i = 0 ; i < _numberOfThreads ; i++ ) {
00095       
00096       delete (*_localSchedulers)[i] ;
00097       
00098       delete (*_threadData)[i] ;
00099 
00100    }
00101 
00102    delete _profilingTimer ;
00103 
00104    delete _localSchedulers ;
00105 
00106    delete _barrier ;
00107 
00108    delete [] _threadIds ;
00109 
00110    delete _threadData ;
00111 
00112    delete _duplicatedObjectScheduler ;
00113 }
00114 
00115 
00116 
00117 void PsnMultiThreadedScheduler::runStep (unsigned int which) 
00118 {
00119 
00120    _currentStep = which ;
00121 
00122    _duplicatedObjectScheduler->runStep (which) ;
00123 
00124 #if defined (_DEBUGSCHEDULER)   
00125    cerr<<"Execution par block pour debug "<<endl;
00126    for ( int i = 0 ; i < _numberOfThreads ; i++ ) {
00127       cerr<<"Lot "<<i<<" ***********************************"<<endl;
00128       (*_localSchedulers)[ i ]->runStep (which) ;
00129    }
00130 #else
00131    // let the thread do their work
00132    _barrier->Sync() ;
00133 
00134 
00135    // wait for the threads to finish their work
00136    _barrier->Sync() ;
00137    //let the controller do it's work
00138 
00139    //purge the memory manager from memory that couldn't be freed efficiently
00140    PsnThreadMemoryManager::freeLeakedMemoryBlocks() ;
00141 #endif
00142 }
00143 
00144 
00145 
00146 void PsnMultiThreadedScheduler::addToScheduable (PsnReferenceObjectHandle * ref, unsigned int when, unsigned int whichThread) {
00147    //cerr<<"PsnMultiThreadedScheduler::addToScheduable"<<((PsnReferenceObjectHandle *)ref)->objetSimul()->Nom()<<endl;
00148    if (dynamic_cast<const PsDuplicatedObject *>(&((PsnReferenceObjectHandle *)ref)->getSimulatedObject())) {
00149       _duplicatedObjectScheduler->addToScheduable ( ref , when ) ;
00150    }
00151    else {
00152       (*_localSchedulers)[ whichThread ] -> addToScheduable( ref , when ) ;
00153    }
00154 
00155 }
00156 
00157 
00158 
00159 void PsnMultiThreadedScheduler::addToScheduable (PsnReferenceObjectHandle * ref, unsigned int when) {
00160    //cerr<<"PsnMultiThreadedScheduler::addToScheduable "<<((PsnReferenceObjectHandle *)ref)->objetSimul()->Nom()<<endl;
00161 
00162    if (dynamic_cast<const PsDuplicatedObject *>(&((PsnReferenceObjectHandle *)ref)->getSimulatedObject())) {
00163       _duplicatedObjectScheduler->addToScheduable ( ref , when ) ;
00164    }
00165    else {
00166       assert ( ref != NULL ) ;
00167       assert ( ref->getSimulatedObject().getFather () != NULL );
00168       map<PsnReferenceObjectHandle *, unsigned int>::iterator i = _whichThread.find((PsnReferenceObjectHandle *)ref->getSimulatedObject().getFather()->getObjectHandle() ) ;
00169       if ( i==_whichThread.end() ){
00170          
00171          (*_localSchedulers)[ _nextThreadForScheduling ] -> addToScheduable( ref , when ) ;
00172 #ifdef _DEBUGSCHEDULER
00173          cout<<ref->getSimulatedObject().getObjectDescriptor().getName()<< " goes to thread "<<_nextThreadForScheduling<<endl;
00174 #endif
00175          _whichThread [ ref ] = _nextThreadForScheduling ;
00176 
00177          _nextThreadForScheduling = ( _nextThreadForScheduling + 1 ) % _numberOfThreads ;
00178          
00179       }
00180       else {//schedule on the same thread as ref's father
00181          
00182          (*_localSchedulers)[ (*i).second ] -> addToScheduable( ref , when ) ;
00183 #ifdef _DEBUGSCHEDULER
00184          cout<<ref->getSimulatedObject().getObjectDescriptor().getName()<< " goes to thread "<<(*i).second<<endl;
00185 #endif
00186          
00187          _whichThread [ ref ] = (*i).second ;
00188          
00189       }
00190    }
00191 }
00192 
00193 
00194  
00195 void PsnMultiThreadedScheduler::removeFromScheduable (PsnReferenceObjectHandle * ref) {
00196 
00197    if (dynamic_cast<const PsDuplicatedObject *>(&((PsnReferenceObjectHandle *)ref)->getSimulatedObject())) {
00198       _duplicatedObjectScheduler->removeFromScheduable ( ref ) ;
00199    }
00200    else {
00201       (*_localSchedulers) [ _whichThread [ ref ] ] ->removeFromScheduable (ref ) ;
00202    }
00203 }
00204 
00205 
00206 
00207 void PsnMultiThreadedScheduler::schedule(PsnReferenceObjectHandle * ref) {
00208 
00209    if (dynamic_cast<const PsDuplicatedObject *>(&((PsnReferenceObjectHandle *)ref)->getSimulatedObject())) {
00210       _duplicatedObjectScheduler->schedule ( ref ) ;
00211    }
00212    else {
00213       (*_localSchedulers) [ _whichThread [ ref ] ] -> schedule (ref) ;
00214    }
00215 }
00216 
00217 
00218 
00219 void PsnMultiThreadedScheduler::unschedule(PsnReferenceObjectHandle * ref) {
00220 
00221    if (dynamic_cast<const PsDuplicatedObject *>(&((PsnReferenceObjectHandle *)ref)->getSimulatedObject())) {
00222       _duplicatedObjectScheduler->unschedule ( ref ) ;
00223    }
00224    else {
00225       (*_localSchedulers) [ _whichThread [ ref ] ] -> unschedule (ref) ;
00226    }
00227 }
00228 
00229 
00230 
00231 void * PsnMultiThreadedScheduler::_threadContainer (void * myThreadData) 
00232 {
00233    // install the memory managers
00234    HeapStackTop systemMemoryManager ( HeapStackTop::getSystemMemoryManager() ) ;
00235   
00236    PsnMemoryManager * currentMemoryManager = HeapStackTop::getSystemMemoryManager() ;
00237 
00238    assert ( currentMemoryManager != 0 ) ;
00239 
00240    size_t initialAllocatatedMemory = 1024 * 1024 ;
00241 
00242    void * startMemory = currentMemoryManager->allocateSizeRemembered ( initialAllocatatedMemory ) ;
00243 
00244    PsnDescriptorMemoryManager * descriptorMemoryManager = new PsnDescriptorMemoryManager ( *currentMemoryManager ) ;
00245 
00246    descriptorMemoryManager->init() ;
00247    
00248    PsnThreadMemoryManager * memoryManagerForThisThread ;
00249    
00250    memoryManagerForThisThread = new PsnThreadMemoryManager ( startMemory, 
00251                                                              initialAllocatatedMemory,
00252                                                              *currentMemoryManager,
00253                                                              *descriptorMemoryManager ) ;
00254    memoryManagerForThisThread -> init() ;
00255 
00256    HeapStackTop allocationContextForThisThread ( memoryManagerForThisThread ) ;
00257 
00258 
00259    // get the data specific to this thread
00260    pair<PsnMultiThreadedScheduler *, unsigned int> * threadData = ( pair<PsnMultiThreadedScheduler *, unsigned int> * ) myThreadData ;
00261 
00262    // get the eventual profiler to profile this thread
00263    setitimer(ITIMER_PROF, &(( * threadData ).first->_profilingTimer[( * threadData ).second]), NULL);
00264 
00265    cerr<<"Thread now profiled ?"<<endl;
00266 
00267    ( * threadData ).first->run( ( * threadData ).second ) ;
00268 
00269    return threadData ;
00270 }
00271 
00272 
00273 void PsnMultiThreadedScheduler::run( unsigned int whichFrameScheduler ) 
00274 {
00275 
00276    while ( true ) {
00277       
00278       _barrier->Sync() ;
00279       
00280 
00281       (*_localSchedulers)[ whichFrameScheduler ]->runStep ( _currentStep ) ;
00282 
00283 
00284       _barrier->Sync() ;
00285 
00286 
00287    }
00288 }
00289 
00290 
00291 
00292 
00293 
00294 

logo OpenMask

Documentation generated on Mon Nov 25 15:25:01 2002

Generated with doxygen 1.2.12 by Dimitri van Heesch ,   1997-2001