Bullet Collision Detection & Physics Library
Win32ThreadSupport.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
16 #include "Win32ThreadSupport.h"
17 
18 #ifdef USE_WIN32_THREADING
19 
20 #include <windows.h>
21 
23 
25 
26 
27 
30 
34 {
35  m_maxNumTasks = threadConstructionInfo.m_numThreads;
36  startThreads(threadConstructionInfo);
37 }
38 
41 {
42  stopSPU();
43 }
44 
45 
46 
47 
48 #include <stdio.h>
49 
50 DWORD WINAPI Thread_no_1( LPVOID lpParam )
51 {
52 
54 
55 
56  while (1)
57  {
58  WaitForSingleObject(status->m_eventStartHandle,INFINITE);
59 
60  void* userPtr = status->m_userPtr;
61 
62  if (userPtr)
63  {
64  btAssert(status->m_status);
65  status->m_userThreadFunc(userPtr,status->m_lsMemory);
66  status->m_status = 2;
67  SetEvent(status->m_eventCompletetHandle);
68  } else
69  {
70  //exit Thread
71  status->m_status = 3;
72  printf("Thread with taskId %i with handle %p exiting\n",status->m_taskId, status->m_threadHandle);
73  SetEvent(status->m_eventCompletetHandle);
74  break;
75  }
76 
77  }
78 
79  printf("Thread TERMINATED\n");
80  return 0;
81 
82 }
83 
85 void Win32ThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId)
86 {
88 
90 
91 
92 
93  switch (uiCommand)
94  {
96  {
97 
98 
99 //#define SINGLE_THREADED 1
100 #ifdef SINGLE_THREADED
101 
102  btSpuStatus& spuStatus = m_activeSpuStatus[0];
103  spuStatus.m_userPtr=(void*)uiArgument0;
104  spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory);
105  HANDLE handle =0;
106 #else
107 
108 
109  btSpuStatus& spuStatus = m_activeSpuStatus[taskId];
110  btAssert(taskId>=0);
111  btAssert(int(taskId)<m_activeSpuStatus.size());
112 
113  spuStatus.m_commandId = uiCommand;
114  spuStatus.m_status = 1;
115  spuStatus.m_userPtr = (void*)uiArgument0;
116 
118  SetEvent(spuStatus.m_eventStartHandle);
119 
120 #endif //CollisionTask_LocalStoreMemory
121 
122 
123 
124  break;
125  }
126  default:
127  {
129  btAssert(0);
130  }
131 
132  };
133 
134 
135 }
136 
137 
139 void Win32ThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)
140 {
142 
144 
145 
146  btAssert(m_activeSpuStatus.size());
147 
148  int last = -1;
149 #ifndef SINGLE_THREADED
150  DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, INFINITE);
151  btAssert(res != WAIT_FAILED);
152  last = res - WAIT_OBJECT_0;
153 
154  btSpuStatus& spuStatus = m_activeSpuStatus[last];
155  btAssert(spuStatus.m_threadHandle);
156  btAssert(spuStatus.m_eventCompletetHandle);
157 
158  //WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
159  btAssert(spuStatus.m_status > 1);
160  spuStatus.m_status = 0;
161 
163  btAssert(last>=0);
164 
165 #else
166  last=0;
167  btSpuStatus& spuStatus = m_activeSpuStatus[last];
168 #endif //SINGLE_THREADED
169 
170 
171 
172  *puiArgument0 = spuStatus.m_taskId;
173  *puiArgument1 = spuStatus.m_status;
174 
175 
176 }
177 
178 
180 bool Win32ThreadSupport::isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds)
181 {
183 
185 
186 
187  btAssert(m_activeSpuStatus.size());
188 
189  int last = -1;
190 #ifndef SINGLE_THREADED
191  DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, timeOutInMilliseconds);
192 
193  if ((res != STATUS_TIMEOUT) && (res != WAIT_FAILED))
194  {
195 
196  btAssert(res != WAIT_FAILED);
197  last = res - WAIT_OBJECT_0;
198 
199  btSpuStatus& spuStatus = m_activeSpuStatus[last];
200  btAssert(spuStatus.m_threadHandle);
201  btAssert(spuStatus.m_eventCompletetHandle);
202 
203  //WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
204  btAssert(spuStatus.m_status > 1);
205  spuStatus.m_status = 0;
206 
208  btAssert(last>=0);
209 
210  #else
211  last=0;
212  btSpuStatus& spuStatus = m_activeSpuStatus[last];
213  #endif //SINGLE_THREADED
214 
215 
216 
217  *puiArgument0 = spuStatus.m_taskId;
218  *puiArgument1 = spuStatus.m_status;
219 
220  return true;
221  }
222 
223  return false;
224 }
225 
226 
228 {
229 
230  m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads);
231  m_completeHandles.resize(threadConstructionInfo.m_numThreads);
232 
233  m_maxNumTasks = threadConstructionInfo.m_numThreads;
234 
235  for (int i=0;i<threadConstructionInfo.m_numThreads;i++)
236  {
237  printf("starting thread %d\n",i);
238 
239  btSpuStatus& spuStatus = m_activeSpuStatus[i];
240 
241  LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL;
242  SIZE_T dwStackSize=threadConstructionInfo.m_threadStackSize;
243  LPTHREAD_START_ROUTINE lpStartAddress=&Thread_no_1;
244  LPVOID lpParameter=&spuStatus;
245  DWORD dwCreationFlags=0;
246  LPDWORD lpThreadId=0;
247 
248  spuStatus.m_userPtr=0;
249 
250  sprintf(spuStatus.m_eventStartHandleName,"eventStart%s%d",threadConstructionInfo.m_uniqueName,i);
251  spuStatus.m_eventStartHandle = CreateEventA (0,false,false,spuStatus.m_eventStartHandleName);
252 
253  sprintf(spuStatus.m_eventCompletetHandleName,"eventComplete%s%d",threadConstructionInfo.m_uniqueName,i);
254  spuStatus.m_eventCompletetHandle = CreateEventA (0,false,false,spuStatus.m_eventCompletetHandleName);
255 
257 
258  HANDLE handle = CreateThread(lpThreadAttributes,dwStackSize,lpStartAddress,lpParameter, dwCreationFlags,lpThreadId);
259  SetThreadPriority(handle,THREAD_PRIORITY_HIGHEST);
260  //SetThreadPriority(handle,THREAD_PRIORITY_TIME_CRITICAL);
261 
262  SetThreadAffinityMask(handle, 1<<i);
263 
264  spuStatus.m_taskId = i;
265  spuStatus.m_commandId = 0;
266  spuStatus.m_status = 0;
267  spuStatus.m_threadHandle = handle;
268  spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc();
269  spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
270 
271  printf("started thread %d with threadHandle %p\n",i,handle);
272 
273  }
274 
275 }
276 
278 {
279 }
280 
281 
284 {
285  int i;
286  for (i=0;i<m_activeSpuStatus.size();i++)
287  {
288  btSpuStatus& spuStatus = m_activeSpuStatus[i];
289  if (spuStatus.m_status>0)
290  {
291  WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
292  }
293 
294 
295  spuStatus.m_userPtr = 0;
296  SetEvent(spuStatus.m_eventStartHandle);
297  WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
298 
299  CloseHandle(spuStatus.m_eventCompletetHandle);
300  CloseHandle(spuStatus.m_eventStartHandle);
301  CloseHandle(spuStatus.m_threadHandle);
302 
303  }
304 
305  m_activeSpuStatus.clear();
307 
308 }
309 
310 
311 
312 class btWin32Barrier : public btBarrier
313 {
314 private:
315  CRITICAL_SECTION mExternalCriticalSection;
316  CRITICAL_SECTION mLocalCriticalSection;
320 
321 public:
323  {
324  mCounter = 0;
325  mMaxCount = 1;
326  mEnableCounter = 0;
327  InitializeCriticalSection(&mExternalCriticalSection);
328  InitializeCriticalSection(&mLocalCriticalSection);
329  mRunEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
330  mNotifyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
331  }
332 
333  virtual ~btWin32Barrier()
334  {
335  DeleteCriticalSection(&mExternalCriticalSection);
336  DeleteCriticalSection(&mLocalCriticalSection);
337  CloseHandle(mRunEvent);
338  CloseHandle(mNotifyEvent);
339  }
340 
341  void sync()
342  {
343  int eventId;
344 
345  EnterCriticalSection(&mExternalCriticalSection);
346 
347  //PFX_PRINTF("enter taskId %d count %d stage %d phase %d mEnableCounter %d\n",taskId,mCounter,debug&0xff,debug>>16,mEnableCounter);
348 
349  if(mEnableCounter > 0) {
350  ResetEvent(mNotifyEvent);
351  LeaveCriticalSection(&mExternalCriticalSection);
352  WaitForSingleObject(mNotifyEvent,INFINITE);
353  EnterCriticalSection(&mExternalCriticalSection);
354  }
355 
356  eventId = mCounter;
357  mCounter++;
358 
359  if(eventId == mMaxCount-1) {
360  SetEvent(mRunEvent);
361 
363  mCounter = 0;
364  }
365  else {
366  ResetEvent(mRunEvent);
367  LeaveCriticalSection(&mExternalCriticalSection);
368  WaitForSingleObject(mRunEvent,INFINITE);
369  EnterCriticalSection(&mExternalCriticalSection);
370  mEnableCounter--;
371  }
372 
373  if(mEnableCounter == 0) {
374  SetEvent(mNotifyEvent);
375  }
376 
377  //PFX_PRINTF("leave taskId %d count %d stage %d phase %d mEnableCounter %d\n",taskId,mCounter,debug&0xff,debug>>16,mEnableCounter);
378 
379  LeaveCriticalSection(&mExternalCriticalSection);
380  }
381 
382  virtual void setMaxCount(int n) {mMaxCount = n;}
383  virtual int getMaxCount() {return mMaxCount;}
384 };
385 
387 {
388 private:
389  CRITICAL_SECTION mCriticalSection;
390 
391 public:
393  {
394  InitializeCriticalSection(&mCriticalSection);
395  }
396 
398  {
399  DeleteCriticalSection(&mCriticalSection);
400  }
401 
402  unsigned int getSharedParam(int i)
403  {
404  btAssert(i>=0&&i<31);
405  return mCommonBuff[i+1];
406  }
407 
408  void setSharedParam(int i,unsigned int p)
409  {
410  btAssert(i>=0&&i<31);
411  mCommonBuff[i+1] = p;
412  }
413 
414  void lock()
415  {
416  EnterCriticalSection(&mCriticalSection);
417  mCommonBuff[0] = 1;
418  }
419 
420  void unlock()
421  {
422  mCommonBuff[0] = 0;
423  LeaveCriticalSection(&mCriticalSection);
424  }
425 };
426 
427 
429 {
430  unsigned char* mem = (unsigned char*)btAlignedAlloc(sizeof(btWin32Barrier),16);
431  btWin32Barrier* barrier = new(mem) btWin32Barrier();
432  barrier->setMaxCount(getNumTasks());
433  return barrier;
434 }
435 
437 {
438  unsigned char* mem = (unsigned char*) btAlignedAlloc(sizeof(btWin32CriticalSection),16);
440  return cs;
441 }
442 
444 {
445  barrier->~btBarrier();
446  btAlignedFree(barrier);
447 }
448 
450 {
451  criticalSection->~btCriticalSection();
452  btAlignedFree(criticalSection);
453 }
454 
455 
456 #endif //USE_WIN32_THREADING
457 
458 
void setSharedParam(int i, unsigned int p)
virtual void startSPU()
start the spus (can be called at the beginning of each frame, to make sure that the right SPU program...
virtual btCriticalSection * createCriticalSection()
unsigned int mCommonBuff[32]
uint32_t ppu_address_t
#define btAssert(x)
Definition: btScalar.h:101
virtual bool isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds)
check for messages from SPUs
DWORD WINAPI Thread_no_1(LPVOID lpParam)
void startThreads(const Win32ThreadConstructionInfo &threadInfo)
Win32ThreadSupport(const Win32ThreadConstructionInfo &threadConstructionInfo)
The number of threads should be equal to the number of available cores.
virtual void stopSPU()
tell the task scheduler we are done with the SPU tasks
virtual void deleteBarrier(btBarrier *barrier)
CRITICAL_SECTION mExternalCriticalSection
void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
int size() const
return the number of elements in the array
placeholder, until libspe2 support is there
#define btAlignedFree(ptr)
CRITICAL_SECTION mCriticalSection
Setup and initialize SPU/CELL/Libspe2.
unsigned int uint32_t
unsigned int getSharedParam(int i)
virtual void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)
check for messages from SPUs
btAlignedObjectArray< btSpuStatus > m_activeSpuStatus
virtual ~Win32ThreadSupport()
cleanup/shutdown Libspe2
virtual int getMaxCount()
virtual btBarrier * createBarrier()
void resize(int newsize, const T &fillData=T())
btAlignedObjectArray< void * > m_completeHandles
#define btAlignedAlloc(size, alignment)
CRITICAL_SECTION mLocalCriticalSection
virtual void setMaxCount(int n)
static void barrier(unsigned int a)
virtual void sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t uiArgument1)
send messages to SPUs
virtual int getNumTasks() const
#define CMD_GATHER_AND_PROCESS_PAIRLIST
virtual void deleteCriticalSection(btCriticalSection *criticalSection)