|
Bullet Collision Detection & Physics Library
|
00001 /* 00002 Bullet Continuous Collision Detection and Physics Library 00003 Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com 00004 00005 This software is provided 'as-is', without any express or implied warranty. 00006 In no event will the authors be held liable for any damages arising from the use of this software. 00007 Permission is granted to anyone to use this software for any purpose, 00008 including commercial applications, and to alter it and redistribute it freely, 00009 subject to the following restrictions: 00010 00011 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 00013 3. This notice may not be removed or altered from any source distribution. 00014 */ 00015 00016 #include "Win32ThreadSupport.h" 00017 00018 #ifdef USE_WIN32_THREADING 00019 00020 #include <windows.h> 00021 00022 #include "SpuCollisionTaskProcess.h" 00023 00024 #include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h" 00025 00026 00027 00030 00033 Win32ThreadSupport::Win32ThreadSupport(const Win32ThreadConstructionInfo & threadConstructionInfo) 00034 { 00035 m_maxNumTasks = threadConstructionInfo.m_numThreads; 00036 startThreads(threadConstructionInfo); 00037 } 00038 00040 Win32ThreadSupport::~Win32ThreadSupport() 00041 { 00042 stopSPU(); 00043 } 00044 00045 00046 00047 00048 #include <stdio.h> 00049 00050 DWORD WINAPI Thread_no_1( LPVOID lpParam ) 00051 { 00052 00053 Win32ThreadSupport::btSpuStatus* status = (Win32ThreadSupport::btSpuStatus*)lpParam; 00054 00055 00056 while (1) 00057 { 00058 WaitForSingleObject(status->m_eventStartHandle,INFINITE); 00059 00060 void* userPtr = status->m_userPtr; 00061 00062 if (userPtr) 00063 { 00064 btAssert(status->m_status); 00065 status->m_userThreadFunc(userPtr,status->m_lsMemory); 00066 status->m_status = 2; 00067 SetEvent(status->m_eventCompletetHandle); 00068 } else 00069 { 00070 //exit Thread 00071 status->m_status = 3; 00072 printf("Thread with taskId %i with handle %p exiting\n",status->m_taskId, status->m_threadHandle); 00073 SetEvent(status->m_eventCompletetHandle); 00074 break; 00075 } 00076 00077 } 00078 00079 printf("Thread TERMINATED\n"); 00080 return 0; 00081 00082 } 00083 00085 void Win32ThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId) 00086 { 00088 00090 00091 00092 00093 switch (uiCommand) 00094 { 00095 case CMD_GATHER_AND_PROCESS_PAIRLIST: 00096 { 00097 00098 00099 //#define SINGLE_THREADED 1 00100 #ifdef SINGLE_THREADED 00101 00102 btSpuStatus& spuStatus = m_activeSpuStatus[0]; 00103 spuStatus.m_userPtr=(void*)uiArgument0; 00104 spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory); 00105 HANDLE handle =0; 00106 #else 00107 00108 00109 btSpuStatus& spuStatus = m_activeSpuStatus[taskId]; 00110 btAssert(taskId>=0); 00111 btAssert(int(taskId)<m_activeSpuStatus.size()); 00112 00113 spuStatus.m_commandId = uiCommand; 00114 spuStatus.m_status = 1; 00115 spuStatus.m_userPtr = (void*)uiArgument0; 00116 00118 SetEvent(spuStatus.m_eventStartHandle); 00119 00120 #endif //CollisionTask_LocalStoreMemory 00121 00122 00123 00124 break; 00125 } 00126 default: 00127 { 00129 btAssert(0); 00130 } 00131 00132 }; 00133 00134 00135 } 00136 00137 00139 void Win32ThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1) 00140 { 00142 00144 00145 00146 btAssert(m_activeSpuStatus.size()); 00147 00148 int last = -1; 00149 #ifndef SINGLE_THREADED 00150 DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, INFINITE); 00151 btAssert(res != WAIT_FAILED); 00152 last = res - WAIT_OBJECT_0; 00153 00154 btSpuStatus& spuStatus = m_activeSpuStatus[last]; 00155 btAssert(spuStatus.m_threadHandle); 00156 btAssert(spuStatus.m_eventCompletetHandle); 00157 00158 //WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE); 00159 btAssert(spuStatus.m_status > 1); 00160 spuStatus.m_status = 0; 00161 00163 btAssert(last>=0); 00164 00165 #else 00166 last=0; 00167 btSpuStatus& spuStatus = m_activeSpuStatus[last]; 00168 #endif //SINGLE_THREADED 00169 00170 00171 00172 *puiArgument0 = spuStatus.m_taskId; 00173 *puiArgument1 = spuStatus.m_status; 00174 00175 00176 } 00177 00178 00180 bool Win32ThreadSupport::isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds) 00181 { 00183 00185 00186 00187 btAssert(m_activeSpuStatus.size()); 00188 00189 int last = -1; 00190 #ifndef SINGLE_THREADED 00191 DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, timeOutInMilliseconds); 00192 00193 if ((res != STATUS_TIMEOUT) && (res != WAIT_FAILED)) 00194 { 00195 00196 btAssert(res != WAIT_FAILED); 00197 last = res - WAIT_OBJECT_0; 00198 00199 btSpuStatus& spuStatus = m_activeSpuStatus[last]; 00200 btAssert(spuStatus.m_threadHandle); 00201 btAssert(spuStatus.m_eventCompletetHandle); 00202 00203 //WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE); 00204 btAssert(spuStatus.m_status > 1); 00205 spuStatus.m_status = 0; 00206 00208 btAssert(last>=0); 00209 00210 #else 00211 last=0; 00212 btSpuStatus& spuStatus = m_activeSpuStatus[last]; 00213 #endif //SINGLE_THREADED 00214 00215 00216 00217 *puiArgument0 = spuStatus.m_taskId; 00218 *puiArgument1 = spuStatus.m_status; 00219 00220 return true; 00221 } 00222 00223 return false; 00224 } 00225 00226 00227 void Win32ThreadSupport::startThreads(const Win32ThreadConstructionInfo& threadConstructionInfo) 00228 { 00229 00230 m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads); 00231 m_completeHandles.resize(threadConstructionInfo.m_numThreads); 00232 00233 m_maxNumTasks = threadConstructionInfo.m_numThreads; 00234 00235 for (int i=0;i<threadConstructionInfo.m_numThreads;i++) 00236 { 00237 printf("starting thread %d\n",i); 00238 00239 btSpuStatus& spuStatus = m_activeSpuStatus[i]; 00240 00241 LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL; 00242 SIZE_T dwStackSize=threadConstructionInfo.m_threadStackSize; 00243 LPTHREAD_START_ROUTINE lpStartAddress=&Thread_no_1; 00244 LPVOID lpParameter=&spuStatus; 00245 DWORD dwCreationFlags=0; 00246 LPDWORD lpThreadId=0; 00247 00248 spuStatus.m_userPtr=0; 00249 00250 sprintf(spuStatus.m_eventStartHandleName,"eventStart%s%d",threadConstructionInfo.m_uniqueName,i); 00251 spuStatus.m_eventStartHandle = CreateEventA (0,false,false,spuStatus.m_eventStartHandleName); 00252 00253 sprintf(spuStatus.m_eventCompletetHandleName,"eventComplete%s%d",threadConstructionInfo.m_uniqueName,i); 00254 spuStatus.m_eventCompletetHandle = CreateEventA (0,false,false,spuStatus.m_eventCompletetHandleName); 00255 00256 m_completeHandles[i] = spuStatus.m_eventCompletetHandle; 00257 00258 HANDLE handle = CreateThread(lpThreadAttributes,dwStackSize,lpStartAddress,lpParameter, dwCreationFlags,lpThreadId); 00259 SetThreadPriority(handle,THREAD_PRIORITY_HIGHEST); 00260 //SetThreadPriority(handle,THREAD_PRIORITY_TIME_CRITICAL); 00261 00262 SetThreadAffinityMask(handle, 1<<i); 00263 00264 spuStatus.m_taskId = i; 00265 spuStatus.m_commandId = 0; 00266 spuStatus.m_status = 0; 00267 spuStatus.m_threadHandle = handle; 00268 spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc(); 00269 spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc; 00270 00271 printf("started thread %d with threadHandle %p\n",i,handle); 00272 00273 } 00274 00275 } 00276 00277 void Win32ThreadSupport::startSPU() 00278 { 00279 } 00280 00281 00283 void Win32ThreadSupport::stopSPU() 00284 { 00285 int i; 00286 for (i=0;i<m_activeSpuStatus.size();i++) 00287 { 00288 btSpuStatus& spuStatus = m_activeSpuStatus[i]; 00289 if (spuStatus.m_status>0) 00290 { 00291 WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE); 00292 } 00293 00294 00295 spuStatus.m_userPtr = 0; 00296 SetEvent(spuStatus.m_eventStartHandle); 00297 WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE); 00298 00299 CloseHandle(spuStatus.m_eventCompletetHandle); 00300 CloseHandle(spuStatus.m_eventStartHandle); 00301 CloseHandle(spuStatus.m_threadHandle); 00302 } 00303 00304 m_activeSpuStatus.clear(); 00305 m_completeHandles.clear(); 00306 00307 } 00308 00309 00310 00311 class btWin32Barrier : public btBarrier 00312 { 00313 private: 00314 CRITICAL_SECTION mExternalCriticalSection; 00315 CRITICAL_SECTION mLocalCriticalSection; 00316 HANDLE mRunEvent,mNotifyEvent; 00317 int mCounter,mEnableCounter; 00318 int mMaxCount; 00319 00320 public: 00321 btWin32Barrier() 00322 { 00323 mCounter = 0; 00324 mMaxCount = 1; 00325 mEnableCounter = 0; 00326 InitializeCriticalSection(&mExternalCriticalSection); 00327 InitializeCriticalSection(&mLocalCriticalSection); 00328 mRunEvent = CreateEvent(NULL,TRUE,FALSE,NULL); 00329 mNotifyEvent = CreateEvent(NULL,TRUE,FALSE,NULL); 00330 } 00331 00332 virtual ~btWin32Barrier() 00333 { 00334 DeleteCriticalSection(&mExternalCriticalSection); 00335 DeleteCriticalSection(&mLocalCriticalSection); 00336 CloseHandle(mRunEvent); 00337 CloseHandle(mNotifyEvent); 00338 } 00339 00340 void sync() 00341 { 00342 int eventId; 00343 00344 EnterCriticalSection(&mExternalCriticalSection); 00345 00346 //PFX_PRINTF("enter taskId %d count %d stage %d phase %d mEnableCounter %d\n",taskId,mCounter,debug&0xff,debug>>16,mEnableCounter); 00347 00348 if(mEnableCounter > 0) { 00349 ResetEvent(mNotifyEvent); 00350 LeaveCriticalSection(&mExternalCriticalSection); 00351 WaitForSingleObject(mNotifyEvent,INFINITE); 00352 EnterCriticalSection(&mExternalCriticalSection); 00353 } 00354 00355 eventId = mCounter; 00356 mCounter++; 00357 00358 if(eventId == mMaxCount-1) { 00359 SetEvent(mRunEvent); 00360 00361 mEnableCounter = mCounter-1; 00362 mCounter = 0; 00363 } 00364 else { 00365 ResetEvent(mRunEvent); 00366 LeaveCriticalSection(&mExternalCriticalSection); 00367 WaitForSingleObject(mRunEvent,INFINITE); 00368 EnterCriticalSection(&mExternalCriticalSection); 00369 mEnableCounter--; 00370 } 00371 00372 if(mEnableCounter == 0) { 00373 SetEvent(mNotifyEvent); 00374 } 00375 00376 //PFX_PRINTF("leave taskId %d count %d stage %d phase %d mEnableCounter %d\n",taskId,mCounter,debug&0xff,debug>>16,mEnableCounter); 00377 00378 LeaveCriticalSection(&mExternalCriticalSection); 00379 } 00380 00381 virtual void setMaxCount(int n) {mMaxCount = n;} 00382 virtual int getMaxCount() {return mMaxCount;} 00383 }; 00384 00385 class btWin32CriticalSection : public btCriticalSection 00386 { 00387 private: 00388 CRITICAL_SECTION mCriticalSection; 00389 00390 public: 00391 btWin32CriticalSection() 00392 { 00393 InitializeCriticalSection(&mCriticalSection); 00394 } 00395 00396 ~btWin32CriticalSection() 00397 { 00398 DeleteCriticalSection(&mCriticalSection); 00399 } 00400 00401 unsigned int getSharedParam(int i) 00402 { 00403 btAssert(i>=0&&i<31); 00404 return mCommonBuff[i+1]; 00405 } 00406 00407 void setSharedParam(int i,unsigned int p) 00408 { 00409 btAssert(i>=0&&i<31); 00410 mCommonBuff[i+1] = p; 00411 } 00412 00413 void lock() 00414 { 00415 EnterCriticalSection(&mCriticalSection); 00416 mCommonBuff[0] = 1; 00417 } 00418 00419 void unlock() 00420 { 00421 mCommonBuff[0] = 0; 00422 LeaveCriticalSection(&mCriticalSection); 00423 } 00424 }; 00425 00426 00427 btBarrier* Win32ThreadSupport::createBarrier() 00428 { 00429 unsigned char* mem = (unsigned char*)btAlignedAlloc(sizeof(btWin32Barrier),16); 00430 btWin32Barrier* barrier = new(mem) btWin32Barrier(); 00431 barrier->setMaxCount(getNumTasks()); 00432 return barrier; 00433 } 00434 00435 btCriticalSection* Win32ThreadSupport::createCriticalSection() 00436 { 00437 unsigned char* mem = (unsigned char*) btAlignedAlloc(sizeof(btWin32CriticalSection),16); 00438 btWin32CriticalSection* cs = new(mem) btWin32CriticalSection(); 00439 return cs; 00440 } 00441 00442 00443 00444 #endif //USE_WIN32_THREADING 00445 00446