/ani/mrses

To get this branch, use:
bzr branch http://suren.me/webbzr/ani/mrses

« back to all changes in this revision

Viewing changes to cell/hw_sched.c

  • Committer: Suren A. Chilingaryan
  • Date: 2010-04-28 04:30:08 UTC
  • Revision ID: csa@dside.dyndns.org-20100428043008-vd9z0nso9axezvlp
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define _GNU_SOURCE
 
2
 
 
3
#include <stdio.h>
 
4
#include <stdlib.h>
 
5
#include <string.h>
 
6
#include <sys/types.h>
 
7
#include <unistd.h>
 
8
#include <sched.h>
 
9
#include <pthread.h>
 
10
#include <errno.h>
 
11
 
 
12
#include "msg.h"
 
13
#include "hw_sched.h"
 
14
 
 
15
#include "mrses_ppu.h"
 
16
 
 
17
#ifdef HW_HAVE_SPU
 
18
# include <libspe2.h>
 
19
# include "mrses_spu.h"
 
20
 
 
21
extern spe_program_handle_t mrses_spe;
 
22
#endif /* HW_HAVE_SPU */
 
23
 
 
24
 
 
25
#define MUTEX_INIT(ctx, name) \
 
26
    if (!err) err = pthread_mutex_init(&ctx->name##_mutex, NULL);
 
27
    
 
28
#define MUTEX_FREE(ctx, name) \
 
29
    pthread_mutex_destroy(&ctx->name##_mutex);
 
30
 
 
31
#define COND_INIT(ctx, name) \
 
32
    MUTEX_INIT(ctx, name##_cond) \
 
33
    if (!err) { \
 
34
        err = pthread_cond_init(&ctx->name##_cond, NULL); \
 
35
        if (err) { MUTEX_FREE(ctx, name##_cond) } \
 
36
    }
 
37
 
 
38
#define COND_FREE(ctx, name) \
 
39
    pthread_cond_destroy(&ctx->name##_cond); \
 
40
    MUTEX_FREE(ctx, name##_cond)
 
41
 
 
42
HWRunFunction ppu_run[] = {
 
43
    (HWRunFunction)mrses_ppu_run,
 
44
    (HWRunFunction)mrses_ppu_iterate,
 
45
    NULL
 
46
};
 
47
 
 
48
#ifdef HW_HAVE_SPU
 
49
HWRunFunction spu_run[] = {
 
50
    (HWRunFunction)mrses_spu_run,
 
51
    (HWRunFunction)mrses_spu_iterate,
 
52
    NULL
 
53
};
 
54
#endif /* HW_HAVE_SPU */
 
55
 
 
56
HWSched hw_sched_create() {
 
57
    int i;
 
58
    int err = 0;
 
59
    cpu_set_t mask;
 
60
 
 
61
    int ppu_count;
 
62
    HWSched ctx;
 
63
    
 
64
#ifdef HW_HAVE_SPU
 
65
    int spu_count;
 
66
    spe_context_ptr_t spe;
 
67
#endif /* HW_HAVE_SPU */
 
68
 
 
69
    ctx = (HWSched)malloc(sizeof(HWSchedS));
 
70
    if (!ctx) return NULL;
 
71
 
 
72
    memset(ctx, 0, sizeof(HWSchedS));
 
73
 
 
74
    ctx->status = 1;
 
75
 
 
76
    MUTEX_INIT(ctx, data);
 
77
 
 
78
    COND_INIT(ctx, compl);
 
79
    if (err) {
 
80
        MUTEX_FREE(ctx, data);
 
81
    }
 
82
 
 
83
    COND_INIT(ctx, job);
 
84
    if (err) {
 
85
        COND_FREE(ctx, compl);
 
86
        MUTEX_FREE(ctx, data);
 
87
    } else {
 
88
        ctx->sync_init = 1;
 
89
    }
 
90
    
 
91
    if (err) {
 
92
        fprintf(stderr, "Error initializing conditions and mutexes, errnon: %i\n", errno);
 
93
        hw_sched_destroy(ctx);
 
94
        return NULL;
 
95
    }
 
96
 
 
97
 
 
98
    err = sched_getaffinity(getpid(), sizeof(mask), &mask);
 
99
 
 
100
#ifdef CPU_COUNT
 
101
    ppu_count = CPU_COUNT(&mask);
 
102
#else
 
103
    for (ppu_count = 0; ppu_count < CPU_SETSIZE; ppu_count++) {
 
104
        if (!CPU_ISSET(ppu_count, &mask)) break;
 
105
    }
 
106
#endif
 
107
 
 
108
#ifdef HW_MAX_PPU
 
109
    if (ppu_count > HW_MAX_PPU) ppu_count = HW_MAX_PPU;
 
110
#endif /* HW_MAX_PPU */
 
111
 
 
112
    ctx->n_threads = 0;
 
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;
 
116
    }
 
117
    
 
118
#ifdef HW_HAVE_SPU
 
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;
 
121
 
 
122
#ifdef HW_MAX_SPU
 
123
    if (spu_count > HW_MAX_SPU) spu_count = HW_MAX_SPU;
 
124
#endif /* HW_MAX_SPU */
 
125
 
 
126
    for (i = 0; i < spu_count; i++) {
 
127
        spe = spe_context_create (0, NULL);
 
128
        if (spe == NULL) {
 
129
            reportError("Failed to create SPE context");
 
130
            hw_sched_destroy(ctx);
 
131
            return NULL;
 
132
        }
 
133
        
 
134
        err = spe_program_load (spe, &mrses_spe);
 
135
        if (err) {
 
136
            reportError("Failed to load program into the SPE, error: %i", err);
 
137
            return NULL;
 
138
        }
 
139
 
 
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;
 
142
    }
 
143
 
 
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 */
 
148
 
 
149
 
 
150
    return ctx;
 
151
}
 
152
 
 
153
static int hw_sched_wait_threads(HWSched ctx) {
 
154
    int i = 0;
 
155
    
 
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);
 
161
                break;
 
162
            }
 
163
        }
 
164
        
 
165
    }
 
166
    hw_sched_unlock(ctx, compl_cond);
 
167
    
 
168
    ctx->started = 1;
 
169
 
 
170
    return 0;
 
171
}
 
172
 
 
173
void hw_sched_destroy(HWSched ctx) {
 
174
    int i;
 
175
 
 
176
    if (ctx->n_threads > 0) {
 
177
        if (!ctx->started) {
 
178
            hw_sched_wait_threads(ctx);
 
179
        }
 
180
 
 
181
        ctx->status = 0;
 
182
        hw_sched_lock(ctx, job_cond);
 
183
        hw_sched_broadcast(ctx, job);
 
184
        hw_sched_unlock(ctx, job_cond);
 
185
    
 
186
        for (i = 0; i < ctx->n_threads; i++) {
 
187
            hw_thread_destroy(ctx->thread[i]);
 
188
        }
 
189
    }
 
190
 
 
191
    if (ctx->sync_init) {
 
192
        COND_FREE(ctx, job);
 
193
        COND_FREE(ctx, compl);
 
194
        MUTEX_FREE(ctx, data);
 
195
    }
 
196
 
 
197
    free(ctx);
 
198
}
 
199
 
 
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;
 
204
    
 
205
    return 0;
 
206
}
 
207
 
 
208
int hw_sched_get_chunk(HWSched ctx, int thread_id) {
 
209
    int block;
 
210
 
 
211
    switch (ctx->mode) {
 
212
        case HW_SCHED_MODE_PREALLOCATED:
 
213
            if (ctx->thread[thread_id]->status == HW_THREAD_STATUS_IDLE) {
 
214
                return thread_id;
 
215
            } else {
 
216
                return -1;
 
217
            }
 
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;
 
223
            } else {
 
224
                block = -1;
 
225
            }
 
226
            hw_sched_unlock(ctx, data);
 
227
            return block;
 
228
        default:
 
229
            return -1;
 
230
    }
 
231
 
 
232
    return -1;
 
233
}
 
234
 
 
235
    
 
236
int hw_sched_schedule_task(HWSched ctx, void *appctx, int entry) {
 
237
    if (!ctx->started) {
 
238
        hw_sched_wait_threads(ctx);
 
239
    }
 
240
    
 
241
    ctx->ctx = appctx;
 
242
    ctx->entry = entry;
 
243
    
 
244
    hw_sched_lock(ctx, compl_cond);
 
245
 
 
246
    hw_sched_lock(ctx, job_cond);
 
247
    hw_sched_broadcast(ctx, job);
 
248
    hw_sched_unlock(ctx, job_cond);
 
249
 
 
250
    return 0;
 
251
}
 
252
 
 
253
int hw_sched_wait_task(HWSched ctx) {
 
254
    int i = 0;
 
255
 
 
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;
 
260
            } else {
 
261
                hw_sched_wait(ctx, compl);
 
262
                break;
 
263
            }
 
264
        }
 
265
        
 
266
    }
 
267
 
 
268
/*        
 
269
    int i, running = 1;
 
270
 
 
271
        //wait all threads set running mode
 
272
 
 
273
    while (running) {
 
274
        hw_sched_wait(ctx, compl);
 
275
        
 
276
        running = 0;
 
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;
 
281
                } else {
 
282
                    running = 1;
 
283
                    break;
 
284
                }
 
285
            }
 
286
        }
 
287
    }
 
288
*/
 
289
 
 
290
    hw_sched_unlock(ctx, compl_cond);
 
291
 
 
292
 
 
293
    return 0;
 
294
}