Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/bullet/BulletMultiThreaded/Win32ThreadSupport.cpp @ 1963

Last change on this file since 1963 was 1963, checked in by rgrieder, 16 years ago

Added Bullet physics engine.

  • Property svn:eol-style set to native
File size: 6.8 KB
Line 
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2007 Erwin Coumans  http://bulletphysics.com
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. 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
22#include "SpuCollisionTaskProcess.h"
23
24#include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
25
26
27
28///The number of threads should be equal to the number of available cores
29///Todo: each worker should be linked to a single core, using SetThreadIdealProcessor.
30
31///Win32ThreadSupport helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
32///Setup and initialize SPU/CELL/Libspe2
33Win32ThreadSupport::Win32ThreadSupport(const Win32ThreadConstructionInfo & threadConstructionInfo)
34{
35        startThreads(threadConstructionInfo);
36}
37
38///cleanup/shutdown Libspe2
39Win32ThreadSupport::~Win32ThreadSupport()
40{
41        stopSPU();
42}
43
44
45
46
47#include <stdio.h>
48
49DWORD WINAPI Thread_no_1( LPVOID lpParam ) 
50{
51
52        Win32ThreadSupport::btSpuStatus* status = (Win32ThreadSupport::btSpuStatus*)lpParam;
53
54       
55        while (1)
56        {
57                WaitForSingleObject(status->m_eventStartHandle,INFINITE);
58               
59                void* userPtr = status->m_userPtr;
60
61                if (userPtr)
62                {
63                        btAssert(status->m_status);
64                        status->m_userThreadFunc(userPtr,status->m_lsMemory);
65                        status->m_status = 2;
66                        SetEvent(status->m_eventCompletetHandle);
67                } else
68                {
69                        //exit Thread
70                        status->m_status = 3;
71                        SetEvent(status->m_eventCompletetHandle);
72                        printf("Thread with taskId %i with handle %i exiting\n",status->m_taskId, status->m_threadHandle);
73                        break;
74                }
75               
76        }
77
78        printf("Thread TERMINATED\n");
79        return 0;
80
81}
82
83///send messages to SPUs
84void Win32ThreadSupport::sendRequest(uint32_t uiCommand, uint32_t uiArgument0, uint32_t taskId)
85{
86        ///     gMidphaseSPU.sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (uint32_t) &taskDesc);
87       
88        ///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished
89       
90
91
92        switch (uiCommand)
93        {
94        case    CMD_GATHER_AND_PROCESS_PAIRLIST:
95                {
96
97
98//#define SINGLE_THREADED 1
99#ifdef SINGLE_THREADED
100
101                        btSpuStatus&    spuStatus = m_activeSpuStatus[0];
102                        spuStatus.m_userPtr=(void*)uiArgument0;
103                        spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory);
104                        HANDLE handle =0;
105#else
106
107
108                        btSpuStatus&    spuStatus = m_activeSpuStatus[taskId];
109                        btAssert(taskId>=0);
110                        btAssert(taskId<m_activeSpuStatus.size());
111
112                        spuStatus.m_commandId = uiCommand;
113                        spuStatus.m_status = 1;
114                        spuStatus.m_userPtr = (void*)uiArgument0;
115
116                        ///fire event to start new task
117                        SetEvent(spuStatus.m_eventStartHandle);
118
119#endif //CollisionTask_LocalStoreMemory
120
121                       
122
123                        break;
124                }
125        default:
126                {
127                        ///not implemented
128                        btAssert(0);
129                }
130
131        };
132
133
134}
135
136
137///check for messages from SPUs
138void Win32ThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)
139{
140        ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response
141       
142        ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback'
143
144
145        btAssert(m_activeSpuStatus.size());
146
147        int last = -1;
148#ifndef SINGLE_THREADED
149        DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, INFINITE);
150        btAssert(res != WAIT_FAILED);
151        last = res - WAIT_OBJECT_0;
152
153        btSpuStatus& spuStatus = m_activeSpuStatus[last];
154        btAssert(spuStatus.m_threadHandle);
155        btAssert(spuStatus.m_eventCompletetHandle);
156
157        //WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
158        btAssert(spuStatus.m_status > 1);
159        spuStatus.m_status = 0;
160
161        ///need to find an active spu
162        btAssert(last>=0);
163
164#else
165        last=0;
166        btSpuStatus& spuStatus = m_activeSpuStatus[last];
167#endif //SINGLE_THREADED
168
169       
170
171        *puiArgument0 = spuStatus.m_taskId;
172        *puiArgument1 = spuStatus.m_status;
173
174
175}
176
177
178
179void Win32ThreadSupport::startThreads(const Win32ThreadConstructionInfo& threadConstructionInfo)
180{
181
182        m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads);
183        m_completeHandles.resize(threadConstructionInfo.m_numThreads);
184
185        for (int i=0;i<threadConstructionInfo.m_numThreads;i++)
186        {
187                printf("starting thread %d\n",i);
188
189                btSpuStatus&    spuStatus = m_activeSpuStatus[i];
190
191                LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL;
192                SIZE_T dwStackSize=threadConstructionInfo.m_threadStackSize;
193                LPTHREAD_START_ROUTINE lpStartAddress=&Thread_no_1;
194                LPVOID lpParameter=&spuStatus;
195                DWORD dwCreationFlags=0;
196                LPDWORD lpThreadId=0;
197
198                spuStatus.m_userPtr=0;
199
200                sprintf(spuStatus.m_eventStartHandleName,"eventStart%s%d",threadConstructionInfo.m_uniqueName,i);
201                spuStatus.m_eventStartHandle = CreateEvent(0,false,false,spuStatus.m_eventStartHandleName);
202
203                sprintf(spuStatus.m_eventCompletetHandleName,"eventComplete%s%d",threadConstructionInfo.m_uniqueName,i);
204                spuStatus.m_eventCompletetHandle = CreateEvent(0,false,false,spuStatus.m_eventCompletetHandleName);
205
206                m_completeHandles[i] = spuStatus.m_eventCompletetHandle;
207
208                HANDLE handle = CreateThread(lpThreadAttributes,dwStackSize,lpStartAddress,lpParameter, dwCreationFlags,lpThreadId);
209                SetThreadPriority(handle,THREAD_PRIORITY_HIGHEST);
210                //SetThreadPriority(handle,THREAD_PRIORITY_TIME_CRITICAL);
211
212                SetThreadAffinityMask(handle, 1<<i);
213
214                spuStatus.m_taskId = i;
215                spuStatus.m_commandId = 0;
216                spuStatus.m_status = 0;
217                spuStatus.m_threadHandle = handle;
218                spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc();
219                spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
220
221                printf("started thread %d with threadHandle %d\n",i,handle);
222               
223        }
224
225}
226
227void Win32ThreadSupport::startSPU()
228{
229}
230
231
232///tell the task scheduler we are done with the SPU tasks
233void Win32ThreadSupport::stopSPU()
234{
235        int i;
236        for (i=0;i<m_activeSpuStatus.size();i++)
237        {
238                btSpuStatus& spuStatus = m_activeSpuStatus[i];
239                if (spuStatus.m_status>0)
240                {
241                        WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
242                }
243               
244
245                spuStatus.m_userPtr = 0;
246                SetEvent(spuStatus.m_eventStartHandle);
247                WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
248
249                CloseHandle(spuStatus.m_eventCompletetHandle);
250                CloseHandle(spuStatus.m_eventStartHandle);
251                CloseHandle(spuStatus.m_threadHandle);
252        }
253
254        m_activeSpuStatus.clear();
255        m_completeHandles.clear();
256
257}
258
259#endif //USE_WIN32_THREADING
Note: See TracBrowser for help on using the repository browser.