Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <stdio.h>
00017 #include "PosixThreadSupport.h"
00018 #ifdef USE_PTHREADS
00019 #include <errno.h>
00020 #include <unistd.h>
00021
00022 #include "SpuCollisionTaskProcess.h"
00023 #include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
00024
00025 #define checkPThreadFunction(returnValue) \
00026 if(0 != returnValue) { \
00027 printf("PThread problem at line %i in file %s: %i %d\n", __LINE__, __FILE__, returnValue, errno); \
00028 }
00029
00030
00031
00032
00033
00034
00035 PosixThreadSupport::PosixThreadSupport(ThreadConstructionInfo& threadConstructionInfo)
00036 {
00037 startThreads(threadConstructionInfo);
00038 }
00039
00040
00041 PosixThreadSupport::~PosixThreadSupport()
00042 {
00043 stopSPU();
00044 }
00045
00046 #if (defined (__APPLE__))
00047 #define NAMED_SEMAPHORES
00048 #endif
00049
00050
00051 static sem_t* mainSemaphore=0;
00052
00053 static sem_t* createSem(const char* baseName)
00054 {
00055 static int semCount = 0;
00056 #ifdef NAMED_SEMAPHORES
00057
00058 char name[32];
00059 snprintf(name, 32, "/%s-%d-%4.4d", baseName, getpid(), semCount++);
00060 sem_t* tempSem = sem_open(name, O_CREAT, 0600, 0);
00061
00062 if (tempSem != reinterpret_cast<sem_t *>(SEM_FAILED))
00063 {
00064
00065 }
00066 else
00067 {
00068
00069 exit(-1);
00070 }
00072 #else
00073 sem_t* tempSem = new sem_t;
00074 checkPThreadFunction(sem_init(tempSem, 0, 0));
00075 #endif
00076 return tempSem;
00077 }
00078
00079 static void destroySem(sem_t* semaphore)
00080 {
00081 #ifdef NAMED_SEMAPHORES
00082 checkPThreadFunction(sem_close(semaphore));
00083 #else
00084 checkPThreadFunction(sem_destroy(semaphore));
00085 delete semaphore;
00086 #endif
00087 }
00088
00089 static void *threadFunction(void *argument)
00090 {
00091
00092 PosixThreadSupport::btSpuStatus* status = (PosixThreadSupport::btSpuStatus*)argument;
00093
00094
00095 while (1)
00096 {
00097 checkPThreadFunction(sem_wait(status->startSemaphore));
00098
00099 void* userPtr = status->m_userPtr;
00100
00101 if (userPtr)
00102 {
00103 btAssert(status->m_status);
00104 status->m_userThreadFunc(userPtr,status->m_lsMemory);
00105 status->m_status = 2;
00106 checkPThreadFunction(sem_post(mainSemaphore));
00107 status->threadUsed++;
00108 } else {
00109
00110 status->m_status = 3;
00111 checkPThreadFunction(sem_post(mainSemaphore));
00112 printf("Thread with taskId %i exiting\n",status->m_taskId);
00113 break;
00114 }
00115
00116 }
00117
00118 printf("Thread TERMINATED\n");
00119 return 0;
00120
00121 }
00122
00124 void PosixThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId)
00125 {
00127
00129
00130
00131
00132 switch (uiCommand)
00133 {
00134 case CMD_GATHER_AND_PROCESS_PAIRLIST:
00135 {
00136 btSpuStatus& spuStatus = m_activeSpuStatus[taskId];
00137 btAssert(taskId >= 0);
00138 btAssert(taskId < m_activeSpuStatus.size());
00139
00140 spuStatus.m_commandId = uiCommand;
00141 spuStatus.m_status = 1;
00142 spuStatus.m_userPtr = (void*)uiArgument0;
00143
00144
00145 checkPThreadFunction(sem_post(spuStatus.startSemaphore));
00146 break;
00147 }
00148 default:
00149 {
00151 btAssert(0);
00152 }
00153
00154 };
00155
00156
00157 }
00158
00159
00161 void PosixThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)
00162 {
00164
00166
00167
00168 btAssert(m_activeSpuStatus.size());
00169
00170
00171 checkPThreadFunction(sem_wait(mainSemaphore));
00172
00173
00174 size_t last = -1;
00175
00176 for(size_t t=0; t < size_t(m_activeSpuStatus.size()); ++t) {
00177 if(2 == m_activeSpuStatus[t].m_status) {
00178 last = t;
00179 break;
00180 }
00181 }
00182
00183 btSpuStatus& spuStatus = m_activeSpuStatus[last];
00184
00185 btAssert(spuStatus.m_status > 1);
00186 spuStatus.m_status = 0;
00187
00188
00189 btAssert(last >= 0);
00190
00191 *puiArgument0 = spuStatus.m_taskId;
00192 *puiArgument1 = spuStatus.m_status;
00193 }
00194
00195
00196
00197 void PosixThreadSupport::startThreads(ThreadConstructionInfo& threadConstructionInfo)
00198 {
00199 printf("%s creating %i threads.\n", __FUNCTION__, threadConstructionInfo.m_numThreads);
00200 m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads);
00201
00202 mainSemaphore = createSem("main");
00203
00204
00205 for (int i=0;i < threadConstructionInfo.m_numThreads;i++)
00206 {
00207 printf("starting thread %d\n",i);
00208
00209 btSpuStatus& spuStatus = m_activeSpuStatus[i];
00210
00211 spuStatus.startSemaphore = createSem("threadLocal");
00212
00213 checkPThreadFunction(pthread_create(&spuStatus.thread, NULL, &threadFunction, (void*)&spuStatus));
00214
00215 spuStatus.m_userPtr=0;
00216
00217 spuStatus.m_taskId = i;
00218 spuStatus.m_commandId = 0;
00219 spuStatus.m_status = 0;
00220 spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc();
00221 spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
00222 spuStatus.threadUsed = 0;
00223
00224 printf("started thread %d \n",i);
00225
00226 }
00227
00228 }
00229
00230 void PosixThreadSupport::startSPU()
00231 {
00232 }
00233
00234
00236 void PosixThreadSupport::stopSPU()
00237 {
00238 for(size_t t=0; t < size_t(m_activeSpuStatus.size()); ++t)
00239 {
00240 btSpuStatus& spuStatus = m_activeSpuStatus[t];
00241 printf("%s: Thread %i used: %ld\n", __FUNCTION__, int(t), spuStatus.threadUsed);
00242
00243 spuStatus.m_userPtr = 0;
00244 checkPThreadFunction(sem_post(spuStatus.startSemaphore));
00245 checkPThreadFunction(sem_wait(mainSemaphore));
00246
00247 printf("destroy semaphore\n");
00248 destroySem(spuStatus.startSemaphore);
00249 printf("semaphore destroyed\n");
00250 checkPThreadFunction(pthread_join(spuStatus.thread,0));
00251
00252 }
00253 printf("destroy main semaphore\n");
00254 destroySem(mainSemaphore);
00255 printf("main semaphore destroyed\n");
00256 m_activeSpuStatus.clear();
00257 }
00258
00259 class PosixCriticalSection : public btCriticalSection
00260 {
00261 pthread_mutex_t m_mutex;
00262
00263 public:
00264 PosixCriticalSection()
00265 {
00266 pthread_mutex_init(&m_mutex, NULL);
00267 }
00268 virtual ~PosixCriticalSection()
00269 {
00270 pthread_mutex_destroy(&m_mutex);
00271 }
00272
00273 ATTRIBUTE_ALIGNED16(unsigned int mCommonBuff[32]);
00274
00275 virtual unsigned int getSharedParam(int i)
00276 {
00277 return mCommonBuff[i];
00278 }
00279 virtual void setSharedParam(int i,unsigned int p)
00280 {
00281 mCommonBuff[i] = p;
00282 }
00283
00284 virtual void lock()
00285 {
00286 pthread_mutex_lock(&m_mutex);
00287 }
00288 virtual void unlock()
00289 {
00290 pthread_mutex_unlock(&m_mutex);
00291 }
00292 };
00293
00294
00295 #if defined(_POSIX_BARRIERS) && (_POSIX_BARRIERS - 20012L) >= 0
00296
00297 class PosixBarrier : public btBarrier
00298 {
00299 pthread_barrier_t m_barr;
00300 int m_numThreads;
00301 public:
00302 PosixBarrier()
00303 :m_numThreads(0) { }
00304 virtual ~PosixBarrier() {
00305 pthread_barrier_destroy(&m_barr);
00306 }
00307
00308 virtual void sync()
00309 {
00310 int rc = pthread_barrier_wait(&m_barr);
00311 if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD)
00312 {
00313 printf("Could not wait on barrier\n");
00314 exit(-1);
00315 }
00316 }
00317 virtual void setMaxCount(int numThreads)
00318 {
00319 int result = pthread_barrier_init(&m_barr, NULL, numThreads);
00320 m_numThreads = numThreads;
00321 btAssert(result==0);
00322 }
00323 virtual int getMaxCount()
00324 {
00325 return m_numThreads;
00326 }
00327 };
00328 #else
00329
00330 class PosixBarrier : public btBarrier
00331 {
00332 pthread_mutex_t m_mutex;
00333 pthread_cond_t m_cond;
00334
00335 int m_numThreads;
00336 int m_called;
00337
00338 public:
00339 PosixBarrier()
00340 :m_numThreads(0)
00341 {
00342 }
00343 virtual ~PosixBarrier()
00344 {
00345 if (m_numThreads>0)
00346 {
00347 pthread_mutex_destroy(&m_mutex);
00348 pthread_cond_destroy(&m_cond);
00349 }
00350 }
00351
00352 virtual void sync()
00353 {
00354 pthread_mutex_lock(&m_mutex);
00355 m_called++;
00356 if (m_called == m_numThreads) {
00357 m_called = 0;
00358 pthread_cond_broadcast(&m_cond);
00359 } else {
00360 pthread_cond_wait(&m_cond,&m_mutex);
00361 }
00362 pthread_mutex_unlock(&m_mutex);
00363
00364 }
00365 virtual void setMaxCount(int numThreads)
00366 {
00367 if (m_numThreads>0)
00368 {
00369 pthread_mutex_destroy(&m_mutex);
00370 pthread_cond_destroy(&m_cond);
00371 }
00372 m_called = 0;
00373 pthread_mutex_init(&m_mutex,NULL);
00374 pthread_cond_init(&m_cond,NULL);
00375 m_numThreads = numThreads;
00376 }
00377 virtual int getMaxCount()
00378 {
00379 return m_numThreads;
00380 }
00381 };
00382
00383 #endif//_POSIX_BARRIERS
00384
00385
00386
00387 btBarrier* PosixThreadSupport::createBarrier()
00388 {
00389 PosixBarrier* barrier = new PosixBarrier();
00390 barrier->setMaxCount(getNumTasks());
00391 return barrier;
00392 }
00393
00394 btCriticalSection* PosixThreadSupport::createCriticalSection()
00395 {
00396 return new PosixCriticalSection();
00397 }
00398
00399 void PosixThreadSupport::deleteBarrier(btBarrier* barrier)
00400 {
00401 delete barrier;
00402 }
00403
00404 void PosixThreadSupport::deleteCriticalSection(btCriticalSection* cs)
00405 {
00406 delete cs;
00407 }
00408 #endif // USE_PTHREADS
00409