Subversion Repositories freemyipod

Rev

Rev 14 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 14 Rev 15
Line 26... Line 26...
26
#include "timer.h"
26
#include "timer.h"
27
#include "panic.h"
27
#include "panic.h"
28
#include "util.h"
28
#include "util.h"
29
 
29
 
30
 
30
 
31
struct scheduler_thread scheduler_threads[MAX_THREADS] IDATA_ATTR;
31
struct scheduler_thread scheduler_threads[MAX_THREADS] IBSS_ATTR;
32
struct scheduler_thread* current_thread IDATA_ATTR;
32
struct scheduler_thread* current_thread IBSS_ATTR;
33
uint32_t last_tick IDATA_ATTR;
33
uint32_t last_tick IBSS_ATTR;
-
 
34
extern struct wakeup dbgwakeup;
34
 
35
 
35
 
36
 
36
void mutex_init(struct mutex* obj)
37
void mutex_init(struct mutex* obj)
37
{
38
{
38
    memset(obj, 0, sizeof(struct mutex));
39
    memset(obj, 0, sizeof(struct mutex));
39
}
40
}
40
 
41
 
41
void mutex_add_to_queue(struct mutex* obj, struct scheduler_thread* thread)
42
void mutex_add_to_queue(struct mutex* obj, struct scheduler_thread* thread)
42
{
43
{
43
    struct scheduler_thread* t;
44
    struct scheduler_thread* t;
44
    if (!obj->waiters || obj->waiters->priority < thread->priority)
45
    if (!obj->waiters || obj->waiters->priority <= thread->priority)
45
    {
46
    {
46
        thread->queue_next = obj->waiters;
47
        thread->queue_next = obj->waiters;
47
        obj->waiters = thread;
48
        obj->waiters = thread;
48
    }
49
    }
49
    else
50
    else
Line 166... Line 167...
166
            current_thread->timeout = timeout;
167
            current_thread->timeout = timeout;
167
            current_thread->blocked_since = USEC_TIMER;
168
            current_thread->blocked_since = USEC_TIMER;
168
            obj->waiter = current_thread;
169
            obj->waiter = current_thread;
169
            leave_critical_section(mode);
170
            leave_critical_section(mode);
170
            context_switch();
171
            context_switch();
-
 
172
            obj->waiter = NULL;
171
            if (!obj->signalled) return THREAD_TIMEOUT;
173
            if (!obj->signalled) return THREAD_TIMEOUT;
172
            obj->signalled = false;
174
            obj->signalled = false;
173
            return THREAD_OK;
175
            return THREAD_OK;
174
        }
176
        }
175
        else ret = THREAD_TIMEOUT;
177
        else ret = THREAD_TIMEOUT;
Line 198... Line 200...
198
    return ret;
200
    return ret;
199
}
201
}
200
 
202
 
201
void sleep(int usecs)
203
void sleep(int usecs)
202
{
204
{
-
 
205
    if (usecs)
-
 
206
    {
203
    uint32_t mode = enter_critical_section();
207
        uint32_t mode = enter_critical_section();
204
    current_thread->state = THREAD_BLOCKED;
208
        current_thread->state = THREAD_BLOCKED;
205
    current_thread->block_type = THREAD_BLOCK_SLEEP;
209
        current_thread->block_type = THREAD_BLOCK_SLEEP;
206
    current_thread->timeout = usecs;
210
        current_thread->timeout = usecs;
207
    current_thread->blocked_since = USEC_TIMER;
211
        current_thread->blocked_since = USEC_TIMER;
208
    leave_critical_section(mode);
212
        leave_critical_section(mode);
-
 
213
    }
209
    context_switch();
214
    context_switch();
210
}
215
}
211
 
216
 
212
void scheduler_init(void)
217
void scheduler_init(void)
213
{
218
{
Line 228... Line 233...
228
    uint32_t usec = USEC_TIMER;
233
    uint32_t usec = USEC_TIMER;
229
    if (current_thread->state == THREAD_RUNNING) current_thread->state = THREAD_READY;
234
    if (current_thread->state == THREAD_RUNNING) current_thread->state = THREAD_READY;
230
    current_thread->cputime_total += usec - current_thread->startusec;
235
    current_thread->cputime_total += usec - current_thread->startusec;
231
    current_thread->cputime_current += usec - current_thread->startusec;
236
    current_thread->cputime_current += usec - current_thread->startusec;
232
    if ((int)current_thread->stack != -1 && *current_thread->stack != 0xaffebeaf)
237
    if ((int)current_thread->stack != -1 && *current_thread->stack != 0xaffebeaf)
-
 
238
    {
-
 
239
        for (i = 0; i < MAX_THREADS; i++)
-
 
240
            if (scheduler_threads[i].type == USER_THREAD)
-
 
241
                scheduler_threads[i].state = THREAD_SUSPENDED;
-
 
242
        current_thread->state = THREAD_DEFUNCT;
233
        panicf(PANIC_KILLPROCESS, "Stack overflow (%s)", current_thread->name);
243
        current_thread->block_type = THREAD_DEFUNCT_STKOV;
-
 
244
        wakeup_signal(&dbgwakeup);
-
 
245
    }
234
 
246
 
235
    if (usec - last_tick > SCHEDULER_TICK)
247
    if (usec - last_tick > SCHEDULER_TICK)
236
    {
248
    {
-
 
249
        last_tick = usec;
237
        for (i = 0; i < MAX_THREADS; i++)
250
        for (i = 0; i < MAX_THREADS; i++)
238
        {
251
        {
239
            scheduler_threads[i].cpuload = scheduler_threads[i].cputime_current / SCHEDULER_TICK;
252
            scheduler_threads[i].cpuload = scheduler_threads[i].cputime_current / SCHEDULER_TICK;
240
            scheduler_threads[i].cputime_current = 0;
253
            scheduler_threads[i].cputime_current = 0;
241
        }
254
        }
Line 266... Line 279...
266
            if (scheduler_threads[i].state == THREAD_READY && scheduler_threads[i].priority)
279
            if (scheduler_threads[i].state == THREAD_READY && scheduler_threads[i].priority)
267
            {
280
            {
268
                score = scheduler_threads[i].cputime_current / scheduler_threads[i].priority;
281
                score = scheduler_threads[i].cputime_current / scheduler_threads[i].priority;
269
                if (score < best)
282
                if (score < best)
270
                {
283
                {
271
                    score = best;
284
                    best = score;
272
                    thread = i;
285
                    thread = i;
273
                }
286
                }
274
            }
287
            }
275
    }
288
    }
276
 
289
 
Line 278... Line 291...
278
    current_thread->state = THREAD_RUNNING;
291
    current_thread->state = THREAD_RUNNING;
279
    current_thread->startusec = USEC_TIMER;
292
    current_thread->startusec = USEC_TIMER;
280
}
293
}
281
 
294
 
282
int thread_create(const char* name, const void* code, void* stack,
295
int thread_create(const char* name, const void* code, void* stack,
283
                  int stacksize, int priority, bool run)
296
                  int stacksize, enum thread_type type, int priority, bool run)
284
{
297
{
285
    int ret = NO_MORE_THREADS;
298
    int ret = NO_MORE_THREADS;
286
    int i;
299
    int i;
287
 
300
 
288
    for (i = 0; i < stacksize >> 2; i ++) ((uint32_t*)stack)[i] = 0xaffebeaf;
301
    for (i = 0; i < stacksize >> 2; i ++) ((uint32_t*)stack)[i] = 0xaffebeaf;
Line 293... Line 306...
293
        if (scheduler_threads[i].state == THREAD_FREE)
306
        if (scheduler_threads[i].state == THREAD_FREE)
294
        {
307
        {
295
            ret = i;
308
            ret = i;
296
            memset(&scheduler_threads[i], 0, sizeof(struct scheduler_thread));
309
            memset(&scheduler_threads[i], 0, sizeof(struct scheduler_thread));
297
            scheduler_threads[i].state = run ? THREAD_READY : THREAD_SUSPENDED;
310
            scheduler_threads[i].state = run ? THREAD_READY : THREAD_SUSPENDED;
-
 
311
            scheduler_threads[i].type = type;
298
            scheduler_threads[i].name = name;
312
            scheduler_threads[i].name = name;
299
            scheduler_threads[i].priority = priority;
313
            scheduler_threads[i].priority = priority;
300
            scheduler_threads[i].cpsr = 0x13;
314
            scheduler_threads[i].cpsr = 0x13;
301
            scheduler_threads[i].regs[15] = (uint32_t)code;
315
            scheduler_threads[i].regs[15] = (uint32_t)code;
302
            scheduler_threads[i].regs[14] = (uint32_t)thread_exit;
316
            scheduler_threads[i].regs[14] = (uint32_t)thread_exit;
Line 324... Line 338...
324
    {
338
    {
325
        if (t->state == THREAD_RUNNING) needsswitch = true;
339
        if (t->state == THREAD_RUNNING) needsswitch = true;
326
        else if (t->state == THREAD_BLOCKED)
340
        else if (t->state == THREAD_BLOCKED)
327
        {
341
        {
328
            if (t->block_type == THREAD_BLOCK_SLEEP)
342
            if (t->block_type == THREAD_BLOCK_SLEEP)
-
 
343
            {
329
                t->timeout -= USEC_TIMER - t->blocked_since;
344
                if (t->timeout != -1) t->timeout -= USEC_TIMER - t->blocked_since;
-
 
345
            }
330
            else if (t->block_type == THREAD_BLOCK_MUTEX)
346
            else if (t->block_type == THREAD_BLOCK_MUTEX)
331
            {
347
            {
332
                mutex_remove_from_queue((struct mutex*)t->blocked_by, t);
348
                mutex_remove_from_queue((struct mutex*)t->blocked_by, t);
333
                t->timeout -= USEC_TIMER - t->blocked_since;
349
                if (t->timeout != -1) t->timeout -= USEC_TIMER - t->blocked_since;
334
            }
350
            }
335
            else if (t->block_type == THREAD_BLOCK_WAKEUP)
351
            else if (t->block_type == THREAD_BLOCK_WAKEUP)
-
 
352
            {
336
                t->timeout -= USEC_TIMER - t->blocked_since;
353
                if (t->timeout != -1) t->timeout -= USEC_TIMER - t->blocked_since;
-
 
354
            }
337
        }
355
        }
338
        t->state = THREAD_SUSPENDED;
356
        t->state = THREAD_SUSPENDED;
339
    }
357
    }
340
 
358
 
341
    leave_critical_section(mode);
359
    leave_critical_section(mode);