www.pudn.com > r&s1.10°æ±¾£«Îĵµ.rar > sched.c


/* 
=============================================================================== 
| Copyright (C) 2004 RuanHaiShen, All rights reserved. 
| SUMMARY:  
|   Scheduler implementation. 
| 
| DESCRIPTION: 
|   See http://www.01s.org for documentation, latest information, license  
|   and contact details. 
|   email:ruanhaishen@01s.org 
=============================================================================*/ 
/*===========================================================================*/ 
#include "arch/arch.h" 
#include "inc/queue.h" 
#include "inc/kernel.h" 
#include "inc/memory.h" 
#include "inc/ipc.h" 
#include "inc/kapi.h" 
 
 
queue_t _ready_queue; 
u8      _current_prio; 
u8      _sched_lock; 
 
#ifndef __k_const 
# define __k_const const 
#endif 
 
u8 __k_const _task_map[] = 
    { 
     0xff, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 
    }; 
 
 
void system_init(void) 
{ 
    disable_irq(); 
    _sched_lock = 0xff;  /*to prevent multitasking*/ 
    __ready_que_init(); 
 
    __task_init(); 
#if CFG_MM_EN > 0 
    __mm_init(); 
#endif 
} 
 
 
void system_start(void) 
{ 
    u8 next; 
 
#if CFG_TASK_INFO_EN > 0 
    __usrtask_suspend(); 
#endif 
 
    if (_sched_lock == 0xff) { 
        _sched_lock = 0; 
        __ready_que_get(next); 
        _current_prio = next; 
        __switch_start(_tasks[next].stack); 
    } 
} 
 
 
void __schedule(void) 
{ 
    register u8 current; 
    register u8 next; 
     
    CRITICAL_ENTER; 
    if (_sched_lock == 0) { 
        current = _current_prio; 
        __ready_que_get(next); 
        if (next != current) { 
            hook_schedule(current, next); 
            _current_prio = next; 
            __switch_to(&_tasks[current].stack, _tasks[next].stack); 
        } 
    } 
    CRITICAL_EXIT; 
} 
 
 
#if CFG_IPC_EN > 0  
/*called under critical path*/ 
void __ipc_block(queue_t* q, tick_t ticks) 
{ 
    register u8 current; 
 
    current = _current_prio; 
    _tasks[current].pend_q = q; 
    _tasks[current].delay  = ticks; 
    _tasks[current].state |= STATE_BLOCKED; 
    __ready_que_remove(current); 
    __queue_add((*q), current); 
} 
 
/*called under critical path*/ 
u8 __ipc_resume(queue_t* q) 
{ 
    register u8 next; 
 
    if (queue_if0((*q))) { 
        return NULL_PRIO; 
    } 
 
    __queue_get((*q), next); 
    __queue_remove((*q), next); 
 
    _tasks[next].pend_q = NULL; 
    _tasks[next].state &= ~STATE_BLOCKED; 
    if (!(_tasks[next].state & STATE_SUSPEND)) { 
        __ready_que_add(next); 
    } else { 
        _tasks[next].state |= STATE_PREREADY; 
    } 
    return next; 
} 
 
#if CFG_IPC_TIMEOUT_EN > 0 
/*called under critical path*/ 
void __ipc_timeout(queue_t* q) 
{ 
    register u8 current; 
 
    current = _current_prio; 
    __queue_remove((*q), current); 
    _tasks[current].state &= ~STATE_BLOCKED; 
    _tasks[current].pend_q = NULL; 
} 
#endif 
#endif 
 
/*called under critical path*/ 
void __queue_remove_f(queue_t* q, u8 prio) 
{ 
    __queue_remove((*q), prio); 
} 
 
/*called under critical path*/ 
void __queue_add_f(queue_t* q, u8 prio) 
{ 
    __queue_add((*q), prio); 
} 
 
/*called under critical path*/ 
void __ready_que_move_f(u8 from, u8 to) 
{ 
    __ready_que_move(from, to); 
} 
 
void __memcpy(void* pdest, const void* psrc, u16 size) 
{ 
    for (; size > 0; size--) { 
        *((u8*)pdest)++ = *((u8*)psrc)++; 
    } 
} 
 
void __memclr(void* pdest, u16 size) 
{ 
    for (; size > 0; size--) { 
        *((u8*)pdest)++ = 0; 
    } 
} 
 
void __strcpy(void* pdest, const void* psrc) 
{ 
    while (*(u8*)psrc != 0 ) { 
        *((u8*)pdest)++ = *((u8*)psrc)++; 
    } 
} 
 
 
#if CFG_PRIO_MODE > 1 
/*called under critical path*/ 
bool __prio_if_normal(u8 prio) 
{     
    if (_tasks[prio].state & STATE_READY) { 
        if (prio == _tasks[prio].prio.normal) { 
            return true; 
        } 
    } else if (_tasks[prio].state & STATE_RESERVED) { 
        return true; 
    } 
    return false; 
} 
#endif 
 
/*===========================================================================*/