17 #if BT_THREADSAFE && !defined(_WIN32) 
   30 #define _XOPEN_SOURCE 600  //for definition of pthread_barrier_t, see http://pages.cs.wisc.edu/~travitch/pthreads_primer.html 
   31 #endif                     //_XOPEN_SOURCE 
   33 #include <semaphore.h> 
   42 #if __cplusplus >= 201103L 
   46 int btGetNumHardwareThreads()
 
   53 int btGetNumHardwareThreads()
 
   70                 ThreadFunc m_userThreadFunc;
 
   75                 sem_t* startSemaphore;
 
   79                 sem_t* m_mainSemaphore;
 
   80                 unsigned long threadUsed;
 
   84         typedef unsigned long long UINT64;
 
   88         sem_t* m_mainSemaphore;
 
   90         UINT64 m_startedThreadsMask;
 
   91         void startThreads(
const ConstructionInfo& threadInfo);
 
   93         int waitForResponse();
 
   96         btThreadSupportPosix(
const ConstructionInfo& threadConstructionInfo);
 
   97         virtual ~btThreadSupportPosix();
 
  112 #define checkPThreadFunction(returnValue)                                                                 \ 
  113         if (0 != returnValue)                                                                                 \ 
  115                 printf("PThread problem at line %i in file %s: %i %d\n", __LINE__, __FILE__, returnValue, errno); \ 
  121 btThreadSupportPosix::btThreadSupportPosix(
const ConstructionInfo& threadConstructionInfo)
 
  124         startThreads(threadConstructionInfo);
 
  128 btThreadSupportPosix::~btThreadSupportPosix()
 
  135 #if (defined(__APPLE__)) 
  136 #define NAMED_SEMAPHORES 
  139 static sem_t* createSem(
const char* baseName)
 
  141         static int semCount = 0;
 
  142 #ifdef NAMED_SEMAPHORES 
  145         snprintf(name, 32, 
"/%8.s-%4.d-%4.4d", baseName, getpid(), semCount++);
 
  146         sem_t* tempSem = sem_open(name, O_CREAT, 0600, 0);
 
  148         if (tempSem != reinterpret_cast<sem_t*>(SEM_FAILED))
 
  159         sem_t* tempSem = 
new sem_t;
 
  160         checkPThreadFunction(sem_init(tempSem, 0, 0));
 
  165 static void destroySem(sem_t* semaphore)
 
  167 #ifdef NAMED_SEMAPHORES 
  168         checkPThreadFunction(sem_close(semaphore));
 
  170         checkPThreadFunction(sem_destroy(semaphore));
 
  175 static void* threadFunction(
void* argument)
 
  177         btThreadSupportPosix::btThreadStatus* status = (btThreadSupportPosix::btThreadStatus*)argument;
 
  181                 checkPThreadFunction(sem_wait(status->startSemaphore));
 
  182                 void* userPtr = status->m_userPtr;
 
  187                         status->m_userThreadFunc(userPtr);
 
  188                         status->m_cs->lock();
 
  189                         status->m_status = 2;
 
  190                         status->m_cs->unlock();
 
  191                         checkPThreadFunction(sem_post(status->m_mainSemaphore));
 
  192                         status->threadUsed++;
 
  197                         status->m_cs->lock();
 
  198                         status->m_status = 3;
 
  199                         status->m_cs->unlock();
 
  200                         checkPThreadFunction(sem_post(status->m_mainSemaphore));
 
  209 void btThreadSupportPosix::runTask(
int threadIndex, 
void* userData)
 
  212         btThreadStatus& threadStatus = m_activeThreadStatus[threadIndex];
 
  215         threadStatus.m_cs = m_cs;
 
  216         threadStatus.m_commandId = 1;
 
  217         threadStatus.m_status = 1;
 
  218         threadStatus.m_userPtr = userData;
 
  219         m_startedThreadsMask |= UINT64(1) << threadIndex;
 
  222         checkPThreadFunction(sem_post(threadStatus.startSemaphore));
 
  226 int btThreadSupportPosix::waitForResponse()
 
  234         checkPThreadFunction(sem_wait(m_mainSemaphore));
 
  238         for (
size_t t = 0; t < size_t(m_activeThreadStatus.
size()); ++t)
 
  241                 bool hasFinished = (2 == m_activeThreadStatus[t].m_status);
 
  250         btThreadStatus& threadStatus = m_activeThreadStatus[last];
 
  252         btAssert(threadStatus.m_status > 1);
 
  253         threadStatus.m_status = 0;
 
  257         m_startedThreadsMask &= ~(UINT64(1) << last);
 
  262 void btThreadSupportPosix::waitForAllTasks()
 
  264         while (m_startedThreadsMask)
 
  270 void btThreadSupportPosix::startThreads(
const ConstructionInfo& threadConstructionInfo)
 
  272         m_numThreads = btGetNumHardwareThreads() - 1;  
 
  273         m_activeThreadStatus.
resize(m_numThreads);
 
  274         m_startedThreadsMask = 0;
 
  276         m_mainSemaphore = createSem(
"main");
 
  279         for (
int i = 0; i < m_numThreads; i++)
 
  281                 btThreadStatus& threadStatus = m_activeThreadStatus[i];
 
  282                 threadStatus.startSemaphore = createSem(
"threadLocal");
 
  283                 threadStatus.m_userPtr = 0;
 
  284                 threadStatus.m_cs = m_cs;
 
  285                 threadStatus.m_taskId = i;
 
  286                 threadStatus.m_commandId = 0;
 
  287                 threadStatus.m_status = 0;
 
  288                 threadStatus.m_mainSemaphore = m_mainSemaphore;
 
  289                 threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
 
  290                 threadStatus.threadUsed = 0;
 
  291                 checkPThreadFunction(pthread_create(&threadStatus.thread, NULL, &threadFunction, (
void*)&threadStatus));
 
  297 void btThreadSupportPosix::stopThreads()
 
  299         for (
size_t t = 0; t < size_t(m_activeThreadStatus.
size()); ++t)
 
  301                 btThreadStatus& threadStatus = m_activeThreadStatus[t];
 
  303                 threadStatus.m_userPtr = 0;
 
  304                 checkPThreadFunction(sem_post(threadStatus.startSemaphore));
 
  305                 checkPThreadFunction(sem_wait(m_mainSemaphore));
 
  307                 destroySem(threadStatus.startSemaphore);
 
  308                 checkPThreadFunction(pthread_join(threadStatus.thread, 0));
 
  310         destroySem(m_mainSemaphore);
 
  311         m_activeThreadStatus.
clear();
 
  316         pthread_mutex_t m_mutex;
 
  319         btCriticalSectionPosix()
 
  321                 pthread_mutex_init(&m_mutex, NULL);
 
  323         virtual ~btCriticalSectionPosix()
 
  325                 pthread_mutex_destroy(&m_mutex);
 
  330                 pthread_mutex_lock(&m_mutex);
 
  332         virtual void unlock()
 
  334                 pthread_mutex_unlock(&m_mutex);
 
  340         return new btCriticalSectionPosix();
 
  350         return new btThreadSupportPosix(info);
 
  353 #endif  // BT_THREADSAFE && !defined( _WIN32 )