00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
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
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
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
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
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
00305 m_activeSpuStatus.clear();
00306 m_completeHandles.clear();
00307
00308 }
00309
00310
00311
00312 class btWin32Barrier : public btBarrier
00313 {
00314 private:
00315 CRITICAL_SECTION mExternalCriticalSection;
00316 CRITICAL_SECTION mLocalCriticalSection;
00317 HANDLE mRunEvent,mNotifyEvent;
00318 int mCounter,mEnableCounter;
00319 int mMaxCount;
00320
00321 public:
00322 btWin32Barrier()
00323 {
00324 mCounter = 0;
00325 mMaxCount = 1;
00326 mEnableCounter = 0;
00327 InitializeCriticalSection(&mExternalCriticalSection);
00328 InitializeCriticalSection(&mLocalCriticalSection);
00329 mRunEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
00330 mNotifyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
00331 }
00332
00333 virtual ~btWin32Barrier()
00334 {
00335 DeleteCriticalSection(&mExternalCriticalSection);
00336 DeleteCriticalSection(&mLocalCriticalSection);
00337 CloseHandle(mRunEvent);
00338 CloseHandle(mNotifyEvent);
00339 }
00340
00341 void sync()
00342 {
00343 int eventId;
00344
00345 EnterCriticalSection(&mExternalCriticalSection);
00346
00347
00348
00349 if(mEnableCounter > 0) {
00350 ResetEvent(mNotifyEvent);
00351 LeaveCriticalSection(&mExternalCriticalSection);
00352 WaitForSingleObject(mNotifyEvent,INFINITE);
00353 EnterCriticalSection(&mExternalCriticalSection);
00354 }
00355
00356 eventId = mCounter;
00357 mCounter++;
00358
00359 if(eventId == mMaxCount-1) {
00360 SetEvent(mRunEvent);
00361
00362 mEnableCounter = mCounter-1;
00363 mCounter = 0;
00364 }
00365 else {
00366 ResetEvent(mRunEvent);
00367 LeaveCriticalSection(&mExternalCriticalSection);
00368 WaitForSingleObject(mRunEvent,INFINITE);
00369 EnterCriticalSection(&mExternalCriticalSection);
00370 mEnableCounter--;
00371 }
00372
00373 if(mEnableCounter == 0) {
00374 SetEvent(mNotifyEvent);
00375 }
00376
00377
00378
00379 LeaveCriticalSection(&mExternalCriticalSection);
00380 }
00381
00382 virtual void setMaxCount(int n) {mMaxCount = n;}
00383 virtual int getMaxCount() {return mMaxCount;}
00384 };
00385
00386 class btWin32CriticalSection : public btCriticalSection
00387 {
00388 private:
00389 CRITICAL_SECTION mCriticalSection;
00390
00391 public:
00392 btWin32CriticalSection()
00393 {
00394 InitializeCriticalSection(&mCriticalSection);
00395 }
00396
00397 ~btWin32CriticalSection()
00398 {
00399 DeleteCriticalSection(&mCriticalSection);
00400 }
00401
00402 unsigned int getSharedParam(int i)
00403 {
00404 btAssert(i>=0&&i<31);
00405 return mCommonBuff[i+1];
00406 }
00407
00408 void setSharedParam(int i,unsigned int p)
00409 {
00410 btAssert(i>=0&&i<31);
00411 mCommonBuff[i+1] = p;
00412 }
00413
00414 void lock()
00415 {
00416 EnterCriticalSection(&mCriticalSection);
00417 mCommonBuff[0] = 1;
00418 }
00419
00420 void unlock()
00421 {
00422 mCommonBuff[0] = 0;
00423 LeaveCriticalSection(&mCriticalSection);
00424 }
00425 };
00426
00427
00428 btBarrier* Win32ThreadSupport::createBarrier()
00429 {
00430 unsigned char* mem = (unsigned char*)btAlignedAlloc(sizeof(btWin32Barrier),16);
00431 btWin32Barrier* barrier = new(mem) btWin32Barrier();
00432 barrier->setMaxCount(getNumTasks());
00433 return barrier;
00434 }
00435
00436 btCriticalSection* Win32ThreadSupport::createCriticalSection()
00437 {
00438 unsigned char* mem = (unsigned char*) btAlignedAlloc(sizeof(btWin32CriticalSection),16);
00439 btWin32CriticalSection* cs = new(mem) btWin32CriticalSection();
00440 return cs;
00441 }
00442
00443 void Win32ThreadSupport::deleteBarrier(btBarrier* barrier)
00444 {
00445 barrier->~btBarrier();
00446 btAlignedFree(barrier);
00447 }
00448
00449 void Win32ThreadSupport::deleteCriticalSection(btCriticalSection* criticalSection)
00450 {
00451 criticalSection->~btCriticalSection();
00452 btAlignedFree(criticalSection);
00453 }
00454
00455
00456 #endif //USE_WIN32_THREADING
00457
00458