static void *threadFunction(void *argument) { PosixThreadSupport::btSpuStatus* status = (PosixThreadSupport::btSpuStatus*)argument; while (1) { checkPThreadFunction(sem_wait(status->startSemaphore)); void* userPtr = status->m_userPtr; if (userPtr) { btAssert(status->m_status); status->m_userThreadFunc(userPtr,status->m_lsMemory); status->m_status = 2; checkPThreadFunction(sem_post(mainSemaphore)); status->threadUsed++; } else { //exit Thread status->m_status = 3; checkPThreadFunction(sem_post(mainSemaphore)); printf("Thread with taskId %i exiting\n",status->m_taskId); break; } } printf("Thread TERMINATED\n"); return 0; }
///tell the task scheduler we are done with the SPU tasks void b3PosixThreadSupport::stopThreads() { for(size_t t=0; t < size_t(m_activeThreadStatus.size()); ++t) { b3ThreadStatus& spuStatus = m_activeThreadStatus[t]; // printf("%s: Thread %i used: %ld\n", __FUNCTION__, int(t), spuStatus.threadUsed); spuStatus.m_userPtr = 0; checkPThreadFunction(sem_post(spuStatus.startSemaphore)); checkPThreadFunction(sem_wait(m_mainSemaphore)); printf("destroy semaphore\n"); destroySem(spuStatus.startSemaphore); printf("semaphore destroyed\n"); checkPThreadFunction(pthread_join(spuStatus.thread,0)); if (spuStatus.m_lsMemoryReleaseFunc) { spuStatus.m_lsMemoryReleaseFunc( spuStatus.m_lsMemory); } } printf("destroy main semaphore\n"); destroySem(m_mainSemaphore); printf("main semaphore destroyed\n"); m_activeThreadStatus.clear(); }
static void *threadFunction(void *argument) { ChThreadStatePOSIX* status = (ChThreadStatePOSIX*)argument; while (1) { checkPThreadFunction(sem_wait(&status->startSemaphore)); void* userPtr = status->m_userPtr; if (userPtr) { status->m_userThreadFunc(userPtr,status->m_lsMemory); status->m_status = 2; checkPThreadFunction(sem_post(status->mainSemaphore)); //status->threadUsed++; } else { //exit Thread //status->m_status = 3; //??? needed ??? //checkPThreadFunction(sem_post(&this->mainSemaphore)); //??? needed ??? break; } } return 0; }
void ChThreadsPOSIX::makeThreads(ChThreadConstructionInfo& threadConstructionInfo) { m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads); uniqueName = threadConstructionInfo.m_uniqueName; checkPThreadFunction(sem_init(&this->mainSemaphore, 0, 0)); for (int i=0; i < threadConstructionInfo.m_numThreads; i++) { ChThreadStatePOSIX& spuStatus = m_activeSpuStatus[i]; spuStatus.mainSemaphore = &this->mainSemaphore; checkPThreadFunction(sem_init(&spuStatus.startSemaphore, 0, 0)); checkPThreadFunction(pthread_create(&spuStatus.thread, NULL, &threadFunction, (void*)&spuStatus)); spuStatus.m_userPtr=0; spuStatus.m_taskId = i; spuStatus.m_commandId = 0; spuStatus.m_status = 0; spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc(); spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc; spuStatus.threadUsed = 0; } }
static void destroySem(sem_t* semaphore) { #ifdef NAMED_SEMAPHORES checkPThreadFunction(sem_close(semaphore)); #else checkPThreadFunction(sem_destroy(semaphore)); delete semaphore; #endif }
///tell the task scheduler we are done with the SPU tasks void ChThreadsPOSIX::stopSPU() { for(size_t t=0; t < m_activeSpuStatus.size(); ++t) { ChThreadStatePOSIX& spuStatus = m_activeSpuStatus[t]; checkPThreadFunction(sem_destroy(&spuStatus.startSemaphore)); checkPThreadFunction(pthread_cancel(spuStatus.thread)); } checkPThreadFunction(sem_destroy(&this->mainSemaphore)); m_activeSpuStatus.clear(); }
static sem_t* createSem(const char* baseName) { static int semCount = 0; #ifdef NAMED_SEMAPHORES /// Named semaphore begin char name[32]; snprintf(name, 32, "/%s-%d-%4.4d", baseName, getpid(), semCount++); sem_t* tempSem = sem_open(name, O_CREAT, 0600, 0); if (tempSem != reinterpret_cast<sem_t *>(SEM_FAILED)) { // printf("Created \"%s\" Semaphore %p\n", name, tempSem); } else { //printf("Error creating Semaphore %d\n", errno); exit(-1); } /// Named semaphore end #else sem_t* tempSem = new sem_t; checkPThreadFunction(sem_init(tempSem, 0, 0)); #endif return tempSem; }
void PosixThreadSupport::startThreads(ThreadConstructionInfo& threadConstructionInfo) { printf("%s creating %i threads.\n", __FUNCTION__, threadConstructionInfo.m_numThreads); m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads); mainSemaphore = createSem("main"); //checkPThreadFunction(sem_wait(mainSemaphore)); for (int i=0;i < threadConstructionInfo.m_numThreads;i++) { printf("starting thread %d\n",i); btSpuStatus& spuStatus = m_activeSpuStatus[i]; spuStatus.startSemaphore = createSem("threadLocal"); checkPThreadFunction(pthread_create(&spuStatus.thread, NULL, &threadFunction, (void*)&spuStatus)); spuStatus.m_userPtr=0; spuStatus.m_taskId = i; spuStatus.m_commandId = 0; spuStatus.m_status = 0; spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc(); spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc; spuStatus.threadUsed = 0; printf("started thread %d \n",i); } }
///check for messages from SPUs void PosixThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) { ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback' btAssert(m_activeSpuStatus.size()); // wait for any of the threads to finish checkPThreadFunction(sem_wait(mainSemaphore)); // get at least one thread which has finished size_t last = -1; for(size_t t=0; t < size_t(m_activeSpuStatus.size()); ++t) { if(2 == m_activeSpuStatus[t].m_status) { last = t; break; } } btSpuStatus& spuStatus = m_activeSpuStatus[last]; btAssert(spuStatus.m_status > 1); spuStatus.m_status = 0; // need to find an active spu btAssert(last >= 0); *puiArgument0 = spuStatus.m_taskId; *puiArgument1 = spuStatus.m_status; }
///send messages to SPUs void PosixThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId) { /// gMidphaseSPU.sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (uint32_t) &taskDesc); ///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished switch (uiCommand) { case CMD_GATHER_AND_PROCESS_PAIRLIST: { btSpuStatus& spuStatus = m_activeSpuStatus[taskId]; btAssert(taskId >= 0); btAssert(taskId < m_activeSpuStatus.size()); spuStatus.m_commandId = uiCommand; spuStatus.m_status = 1; spuStatus.m_userPtr = (void*)uiArgument0; // fire event to start new task checkPThreadFunction(sem_post(spuStatus.startSemaphore)); break; } default: { ///not implemented btAssert(0); } }; }
///send messages to SPUs void ChThreadsPOSIX::sendRequest(uint32_t uiCommand, void* uiUserPtr, unsigned int threadId)//(uint32_t uiCommand, uint32_t uiArgument0, uint32_t taskId) { ChThreadStatePOSIX& spuStatus = m_activeSpuStatus[threadId]; spuStatus.m_commandId = uiCommand; spuStatus.m_status = 1; spuStatus.m_userPtr = uiUserPtr; // fire event to start new task checkPThreadFunction(sem_post(&spuStatus.startSemaphore)); }
///tell the task scheduler we are done with the SPU tasks void PosixThreadSupport::stopSPU() { for(size_t t=0; t < size_t(m_activeSpuStatus.size()); ++t) { btSpuStatus& spuStatus = m_activeSpuStatus[t]; printf("%s: Thread %i used: %ld\n", __FUNCTION__, int(t), spuStatus.threadUsed); spuStatus.m_userPtr = 0; checkPThreadFunction(sem_post(spuStatus.startSemaphore)); checkPThreadFunction(sem_wait(mainSemaphore)); printf("destroy semaphore\n"); destroySem(spuStatus.startSemaphore); printf("semaphore destroyed\n"); checkPThreadFunction(pthread_cancel(spuStatus.thread)); } printf("destroy main semaphore\n"); destroySem(mainSemaphore); printf("main semaphore destroyed\n"); m_activeSpuStatus.clear(); }