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
| Documentation generated on Mon Nov 25 15:25:01 2002 |
Generated with doxygen 1.2.12 by Dimitri van Heesch , 1997-2001 |