Bullet Collision Detection & Physics Library
SpuLibspe2Support.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 #ifdef USE_LIBSPE2
17 
18 #include "SpuLibspe2Support.h"
19 
20 
21 
22 
23 //SpuLibspe2Support helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
25 SpuLibspe2Support::SpuLibspe2Support(spe_program_handle_t *speprog, int numThreads)
26 {
27  this->program = speprog;
28  this->numThreads = ((numThreads <= spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, -1)) ? numThreads : spe_cpu_info_get(SPE_COUNT_PHYSICAL_SPES, -1));
29 }
30 
32 SpuLibspe2Support::~SpuLibspe2Support()
33 {
34 
35  stopSPU();
36 }
37 
38 
39 
41 void SpuLibspe2Support::sendRequest(uint32_t uiCommand, uint32_t uiArgument0, uint32_t uiArgument1)
42 {
43  spe_context_ptr_t context;
44 
45  switch (uiCommand)
46  {
48  {
49  //get taskdescription
50  SpuSampleTaskDesc* taskDesc = (SpuSampleTaskDesc*) uiArgument0;
51 
52  btAssert(taskDesc->m_taskId<m_activeSpuStatus.size());
53 
54  //get status of SPU on which task should run
55  btSpuStatus& spuStatus = m_activeSpuStatus[taskDesc->m_taskId];
56 
57  //set data for spuStatus
58  spuStatus.m_commandId = uiCommand;
59  spuStatus.m_status = Spu_Status_Occupied; //set SPU as "occupied"
60  spuStatus.m_taskDesc.p = taskDesc;
61 
62  //get context
63  context = data[taskDesc->m_taskId].context;
64 
65 
66  taskDesc->m_mainMemoryPtr = reinterpret_cast<uint64_t> (spuStatus.m_lsMemory.p);
67 
68 
69  break;
70  }
72  {
73  //get taskdescription
75 
76  btAssert(taskDesc->taskId<m_activeSpuStatus.size());
77 
78  //get status of SPU on which task should run
79  btSpuStatus& spuStatus = m_activeSpuStatus[taskDesc->taskId];
80 
81  //set data for spuStatus
82  spuStatus.m_commandId = uiCommand;
83  spuStatus.m_status = Spu_Status_Occupied; //set SPU as "occupied"
84  spuStatus.m_taskDesc.p = taskDesc;
85 
86  //get context
87  context = data[taskDesc->taskId].context;
88 
89 
90  taskDesc->m_lsMemory = (CollisionTask_LocalStoreMemory*)spuStatus.m_lsMemory.p;
91 
92  break;
93  }
94  default:
95  {
97  btAssert(0);
98  }
99 
100  };
101 
102 
103  //write taskdescription in mailbox
104  unsigned int event = Spu_Mailbox_Event_Task;
105  spe_in_mbox_write(context, &event, 1, SPE_MBOX_ANY_NONBLOCKING);
106 
107 }
108 
110 void SpuLibspe2Support::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)
111 {
113 
115 
116  btAssert(m_activeSpuStatus.size());
117 
118 
119  int last = -1;
120 
121  //find an active spu/thread
122  while(last < 0)
123  {
124  for (int i=0;i<m_activeSpuStatus.size();i++)
125  {
126  if ( m_activeSpuStatus[i].m_status == Spu_Status_Free)
127  {
128  last = i;
129  break;
130  }
131  }
132  if(last < 0)
133  sched_yield();
134  }
135 
136 
137 
138  btSpuStatus& spuStatus = m_activeSpuStatus[last];
139 
141  btAssert(last>=0);
142 
143 
144 
145  *puiArgument0 = spuStatus.m_taskId;
146  *puiArgument1 = spuStatus.m_status;
147 
148 
149 }
150 
151 
152 void SpuLibspe2Support::startSPU()
153 {
154  this->internal_startSPU();
155 }
156 
157 
158 
160 void SpuLibspe2Support::internal_startSPU()
161 {
162  m_activeSpuStatus.resize(numThreads);
163 
164 
165  for (int i=0; i < numThreads; i++)
166  {
167 
168  if(data[i].context == NULL)
169  {
170 
171  /* Create context */
172  if ((data[i].context = spe_context_create(0, NULL)) == NULL)
173  {
174  perror ("Failed creating context");
175  exit(1);
176  }
177 
178  /* Load program into context */
179  if(spe_program_load(data[i].context, this->program))
180  {
181  perror ("Failed loading program");
182  exit(1);
183  }
184 
185  m_activeSpuStatus[i].m_status = Spu_Status_Startup;
186  m_activeSpuStatus[i].m_taskId = i;
187  m_activeSpuStatus[i].m_commandId = 0;
188  m_activeSpuStatus[i].m_lsMemory.p = NULL;
189 
190 
191  data[i].entry = SPE_DEFAULT_ENTRY;
192  data[i].flags = 0;
193  data[i].argp.p = &m_activeSpuStatus[i];
194  data[i].envp.p = NULL;
195 
196  /* Create thread for each SPE context */
197  if (pthread_create(&data[i].pthread, NULL, &ppu_pthread_function, &(data[i]) ))
198  {
199  perror ("Failed creating thread");
200  exit(1);
201  }
202  /*
203  else
204  {
205  printf("started thread %d\n",i);
206  }*/
207  }
208  }
209 
210 
211  for (int i=0; i < numThreads; i++)
212  {
213  if(data[i].context != NULL)
214  {
215  while( m_activeSpuStatus[i].m_status == Spu_Status_Startup)
216  {
217  // wait for spu to set up
218  sched_yield();
219  }
220  printf("Spu %d is ready\n", i);
221  }
222  }
223 }
224 
226 void SpuLibspe2Support::stopSPU()
227 {
228  // wait for all threads to finish
229  int i;
230  for ( i = 0; i < this->numThreads; i++ )
231  {
232 
233  unsigned int event = Spu_Mailbox_Event_Shutdown;
234  spe_context_ptr_t context = data[i].context;
235  spe_in_mbox_write(context, &event, 1, SPE_MBOX_ALL_BLOCKING);
236  pthread_join (data[i].pthread, NULL);
237 
238  }
239  // close SPE program
240  spe_image_close(program);
241  // destroy SPE contexts
242  for ( i = 0; i < this->numThreads; i++ )
243  {
244  if(data[i].context != NULL)
245  {
246  spe_context_destroy (data[i].context);
247  }
248  }
249 
250  m_activeSpuStatus.clear();
251 
252 }
253 
254 
255 
256 #endif //USE_LIBSPE2
257 
struct CollisionTask_LocalStoreMemory * m_lsMemory
unsigned long int uint64_t
Task Description for SPU collision detection.
#define btAssert(x)
Definition: btScalar.h:101
unsigned int uint32_t
uint64_t m_mainMemoryPtr
Definition: SpuSampleTask.h:42
Make sure no destructors are called on this memory.
#define CMD_SAMPLE_TASK_COMMAND
#define CMD_GATHER_AND_PROCESS_PAIRLIST