15
#include "mrses_ppu.h"
19
# include "mrses_spu.h"
21
extern spe_program_handle_t mrses_spe;
22
#endif /* HW_HAVE_SPU */
25
#define MUTEX_INIT(ctx, name) \
26
if (!err) err = pthread_mutex_init(&ctx->name##_mutex, NULL);
28
#define MUTEX_FREE(ctx, name) \
29
pthread_mutex_destroy(&ctx->name##_mutex);
31
#define COND_INIT(ctx, name) \
32
MUTEX_INIT(ctx, name##_cond) \
34
err = pthread_cond_init(&ctx->name##_cond, NULL); \
35
if (err) { MUTEX_FREE(ctx, name##_cond) } \
38
#define COND_FREE(ctx, name) \
39
pthread_cond_destroy(&ctx->name##_cond); \
40
MUTEX_FREE(ctx, name##_cond)
42
HWRunFunction ppu_run[] = {
43
(HWRunFunction)mrses_ppu_run,
44
(HWRunFunction)mrses_ppu_iterate,
49
HWRunFunction spu_run[] = {
50
(HWRunFunction)mrses_spu_run,
51
(HWRunFunction)mrses_spu_iterate,
54
#endif /* HW_HAVE_SPU */
56
HWSched hw_sched_create() {
66
spe_context_ptr_t spe;
67
#endif /* HW_HAVE_SPU */
69
ctx = (HWSched)malloc(sizeof(HWSchedS));
70
if (!ctx) return NULL;
72
memset(ctx, 0, sizeof(HWSchedS));
76
MUTEX_INIT(ctx, data);
78
COND_INIT(ctx, compl);
80
MUTEX_FREE(ctx, data);
85
COND_FREE(ctx, compl);
86
MUTEX_FREE(ctx, data);
92
fprintf(stderr, "Error initializing conditions and mutexes, errnon: %i\n", errno);
93
hw_sched_destroy(ctx);
98
err = sched_getaffinity(getpid(), sizeof(mask), &mask);
101
ppu_count = CPU_COUNT(&mask);
103
for (ppu_count = 0; ppu_count < CPU_SETSIZE; ppu_count++) {
104
if (!CPU_ISSET(ppu_count, &mask)) break;
109
if (ppu_count > HW_MAX_PPU) ppu_count = HW_MAX_PPU;
110
#endif /* HW_MAX_PPU */
113
for (i = 0; i < ppu_count; i++) {
114
ctx->thread[ctx->n_threads] = hw_thread_create(ctx, ctx->n_threads, NULL, ppu_run, NULL);
115
if (ctx->thread[ctx->n_threads]) ++ctx->n_threads;
119
spu_count = spe_cpu_info_get(SPE_COUNT_USABLE_SPES, -1);
120
if ((spu_count + ctx->n_threads) > HW_MAX_THREADS) spu_count = HW_MAX_THREADS - ctx->n_threads;
123
if (spu_count > HW_MAX_SPU) spu_count = HW_MAX_SPU;
124
#endif /* HW_MAX_SPU */
126
for (i = 0; i < spu_count; i++) {
127
spe = spe_context_create (0, NULL);
129
reportError("Failed to create SPE context");
130
hw_sched_destroy(ctx);
134
err = spe_program_load (spe, &mrses_spe);
136
reportError("Failed to load program into the SPE, error: %i", err);
140
ctx->thread[ctx->n_threads] = hw_thread_create(ctx, ctx->n_threads, spe, spu_run, (HWFreeFunction)spe_context_destroy);
141
if (ctx->thread[ctx->n_threads]) ++ctx->n_threads;
144
reportMessage("ppu: %i, spu: %i", ppu_count, spu_count);
145
#else /* HW_HAVE_SPU */
146
reportMessage("threads: %i", ppu_count);
147
#endif /* HW_HAVE_SPU */
153
static int hw_sched_wait_threads(HWSched ctx) {
156
hw_sched_lock(ctx, compl_cond);
157
while (i < ctx->n_threads) {
158
for (; i < ctx->n_threads; i++) {
159
if (ctx->thread[i]->status == HW_THREAD_STATUS_INIT) {
160
hw_sched_wait(ctx, compl);
166
hw_sched_unlock(ctx, compl_cond);
173
void hw_sched_destroy(HWSched ctx) {
176
if (ctx->n_threads > 0) {
178
hw_sched_wait_threads(ctx);
182
hw_sched_lock(ctx, job_cond);
183
hw_sched_broadcast(ctx, job);
184
hw_sched_unlock(ctx, job_cond);
186
for (i = 0; i < ctx->n_threads; i++) {
187
hw_thread_destroy(ctx->thread[i]);
191
if (ctx->sync_init) {
193
COND_FREE(ctx, compl);
194
MUTEX_FREE(ctx, data);
200
int hw_sched_set_sequential_mode(HWSched ctx, int *n_blocks, int *cur_block) {
201
ctx->mode = HW_SCHED_MODE_SEQUENTIAL;
202
ctx->n_blocks = n_blocks;
203
ctx->cur_block = cur_block;
208
int hw_sched_get_chunk(HWSched ctx, int thread_id) {
212
case HW_SCHED_MODE_PREALLOCATED:
213
if (ctx->thread[thread_id]->status == HW_THREAD_STATUS_IDLE) {
218
case HW_SCHED_MODE_SEQUENTIAL:
219
hw_sched_lock(ctx, data);
220
block = *ctx->cur_block;
221
if (block < *ctx->n_blocks) {
222
*ctx->cur_block = *ctx->cur_block + 1;
226
hw_sched_unlock(ctx, data);
236
int hw_sched_schedule_task(HWSched ctx, void *appctx, int entry) {
238
hw_sched_wait_threads(ctx);
244
hw_sched_lock(ctx, compl_cond);
246
hw_sched_lock(ctx, job_cond);
247
hw_sched_broadcast(ctx, job);
248
hw_sched_unlock(ctx, job_cond);
253
int hw_sched_wait_task(HWSched ctx) {
256
while (i < ctx->n_threads) {
257
for (; i < ctx->n_threads; i++) {
258
if (ctx->thread[i]->status == HW_THREAD_STATUS_DONE) {
259
ctx->thread[i]->status = HW_THREAD_STATUS_IDLE;
261
hw_sched_wait(ctx, compl);
271
//wait all threads set running mode
274
hw_sched_wait(ctx, compl);
277
for (i = 0; i < ctx->n_threads; i++) {
278
if (ctx->thread[i]->status) {
279
if (ctx->thread[i]->status == HW_THREAD_STATUS_DONE) {
280
ctx->thread[i]->status = HW_THREAD_STATUS_IDLE;
290
hw_sched_unlock(ctx, compl_cond);