📄 task.c
字号:
/*
* TOPPERS/JSP Kernel
* Toyohashi Open Platform for Embedded Real-Time Systems/
* Just Standard Profile Kernel
*
* Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
* Toyohashi Univ. of Technology, JAPAN
* Copyright (C) 2005 by Embedded and Real-Time Systems Laboratory
* Graduate School of Information Science, Nagoya Univ., JAPAN
*
* 忋婰挊嶌尃幰偼丆埲壓偺 (1)乣(4) 偺忦審偐丆Free Software Foundation
* 偵傛偭偰岞昞偝傟偰偄傞 GNU General Public License 偺 Version 2 偵婰
* 弎偝傟偰偄傞忦審傪枮偨偡応崌偵尷傝丆杮僜僼僩僂僃傾乮杮僜僼僩僂僃傾
* 傪夵曄偟偨傕偺傪娷傓丏埲壓摨偠乯傪巊梡丒暋惢丒夵曄丒嵞攝晍乮埲壓丆
* 棙梡偲屇傇乯偡傞偙偲傪柍彏偱嫋戻偡傞丏
* (1) 杮僜僼僩僂僃傾傪僜乕僗僐乕僪偺宍偱棙梡偡傞応崌偵偼丆忋婰偺挊嶌
* 尃昞帵丆偙偺棙梡忦審偍傛傃壓婰偺柍曐徹婯掕偑丆偦偺傑傑偺宍偱僜乕
* 僗僐乕僪拞偵娷傑傟偰偄傞偙偲丏
* (2) 杮僜僼僩僂僃傾傪丆儔僀僽儔儕宍幃側偳丆懠偺僜僼僩僂僃傾奐敪偵巊
* 梡偱偒傞宍偱嵞攝晍偡傞応崌偵偼丆嵞攝晍偵敽偆僪僉儏儊儞僩乮棙梡
* 幰儅僯儏傾儖側偳乯偵丆忋婰偺挊嶌尃昞帵丆偙偺棙梡忦審偍傛傃壓婰
* 偺柍曐徹婯掕傪宖嵹偡傞偙偲丏
* (3) 杮僜僼僩僂僃傾傪丆婡婍偵慻傒崬傓側偳丆懠偺僜僼僩僂僃傾奐敪偵巊
* 梡偱偒側偄宍偱嵞攝晍偡傞応崌偵偼丆師偺偄偢傟偐偺忦審傪枮偨偡偙
* 偲丏
* (a) 嵞攝晍偵敽偆僪僉儏儊儞僩乮棙梡幰儅僯儏傾儖側偳乯偵丆忋婰偺挊
* 嶌尃昞帵丆偙偺棙梡忦審偍傛傃壓婰偺柍曐徹婯掕傪宖嵹偡傞偙偲丏
* (b) 嵞攝晍偺宍懺傪丆暿偵掕傔傞曽朄偵傛偭偰丆TOPPERS僾儘僕僃僋僩偵
* 曬崘偡傞偙偲丏
* (4) 杮僜僼僩僂僃傾偺棙梡偵傛傝捈愙揑傑偨偼娫愙揑偵惗偠傞偄偐側傞懝
* 奞偐傜傕丆忋婰挊嶌尃幰偍傛傃TOPPERS僾儘僕僃僋僩傪柶愑偡傞偙偲丏
*
* 杮僜僼僩僂僃傾偼丆柍曐徹偱採嫙偝傟偰偄傞傕偺偱偁傞丏忋婰挊嶌尃幰偍
* 傛傃TOPPERS僾儘僕僃僋僩偼丆杮僜僼僩僂僃傾偵娭偟偰丆偦偺揔梡壜擻惈傕
* 娷傔偰丆偄偐側傞曐徹傕峴傢側偄丏傑偨丆杮僜僼僩僂僃傾偺棙梡偵傛傝捈
* 愙揑傑偨偼娫愙揑偵惗偠偨偄偐側傞懝奞偵娭偟偰傕丆偦偺愑擟傪晧傢側偄丏
*
* @(#) $Id: task.c,v 1.11 2005/11/12 14:55:55 hiro Exp $
*/
/*
* 僞僗僋娗棟儌僕儏乕儖
*/
#include "jsp_kernel.h"
#include "task.h"
#include <cpu_context.h>
#ifdef __tskini
/*
* 幚峴忬懺偺僞僗僋
*/
TCB *runtsk;
/*
* 嵟崅桪愭弴埵偺僞僗僋
*/
TCB *schedtsk;
/*
* 僞僗僋僨傿僗僷僢僠乛僞僗僋椺奜張棟儖乕僠儞婲摦梫媮僼儔僌
*/
BOOL reqflg;
/*
* 僞僗僋僨傿僗僷僢僠嫋壜忬懺
*/
BOOL enadsp;
/*
* 儗僨傿僉儏乕
*/
QUEUE ready_queue[TNUM_TPRI];
/*
* 儗僨傿僉儏乕僒乕僠偺偨傔偺價僢僩儅僢僾
*
* 價僢僩儅僢僾傪 UINT 偱掕媊偟偰偄傞偑丆價僢僩儅僢僾僒乕僠娭悢偱桪愭
* 搙偑16抜奒埲壓偱偁傞偙偲傪壖掕偟偰偄傞丏
*/
UINT ready_primap;
static ID cur_tskid = 0;
/*
* 僞僗僋娗棟儌僕儏乕儖偺弶婜壔
*/
void
task_initialize()
{
UINT i, j;
TCB *tcb;
runtsk = schedtsk = NULL;
reqflg = FALSE;
enadsp = TRUE;
for (i = 0; i < TNUM_TPRI; i++) {
queue_initialize(&(ready_queue[i]));
}
ready_primap = 0;
/*
for (i = 0; i < TNUM_TSK; i++) {
j = INDEX_TSK(torder_table[i]);
tcb = &(tcb_table[j]);
tcb->tinib = &(tinib_table[j]);
tcb->actcnt = FALSE;
make_dormant(tcb);
if ((tcb->tinib->tskatr & TA_ACT) != 0) {
make_active(tcb);
}
}
*/
}
#endif /* __tskini */
/*
* 價僢僩儅僢僾僒乕僠娭悢
*
* bitmap 撪偺 1 偺價僢僩偺撪丆嵟傕壓埵乮塃乯偺傕偺傪僒乕僠偟丆偦偺價
* 僢僩斣崋傪曉偡丏價僢僩斣崋偼丆嵟壓埵價僢僩傪 0 偲偡傞丏bitmap 偵 0
* 傪巜掕偟偰偼側傜側偄丏偙偺娭悢偱偼丆桪愭搙偑16抜奒埲壓偱偁傞偙偲傪
* 壖掕偟丆bitmap 偺壓埵16價僢僩偺傒傪僒乕僠偡傞丏
* 價僢僩僒乕僠柦椷傪帩偮僾儘僙僢僒偱偼丆價僢僩僒乕僠柦椷傪巊偆傛偆偵
* 彂偒捈偟偨曽偑岠棪偑椙偄偩傠偆丏偙偺傛偆側応崌偵偼丆cpu_insn.h 偱
* 價僢僩僒乕僠柦椷傪巊偭偨 bitmap_search 傪掕媊偟丆CPU_BITMAP_SEARCH
* 傪儅僋儘掕媊偡傟偽傛偄丏傑偨丆價僢僩僒乕僠柦椷偺僒乕僠曽岦偑媡側偳
* 偺棟桼偱桪愭搙偲價僢僩偲偺懳墳傪曄峏偟偨偄応崌偵偼丆PRIMAP_BIT 傪
* 儅僋儘掕媊偡傟偽傛偄丏
* 傑偨丆昗弨儔僀僽儔儕偵 ffs 偑偁傞側傜丆師偺傛偆偵掕媊偟偰昗弨儔僀
* 僽儔儕傪巊偭偨曽偑岠棪偑椙偄壜擻惈傕偁傞丏
* #define bitmap_search(bitmap) (ffs(bitmap) - 1)
*/
#ifndef PRIMAP_BIT
#define PRIMAP_BIT(pri) (1u << (pri))
#endif /* PRIMAP_BIT */
#ifndef CPU_BITMAP_SEARCH
static Inline UINT
bitmap_search(UINT bitmap)
{
static const char search_table[] = { 0, 1, 0, 2, 0, 1, 0,
3, 0, 1, 0, 2, 0, 1, 0 };
INT n = 0;
assert((bitmap & 0xffff) != 0);
if ((bitmap & 0x00ff) == 0) {
bitmap >>= 8;
n += 8;
}
if ((bitmap & 0x0f) == 0) {
bitmap >>= 4;
n += 4;
}
return(n + search_table[(bitmap & 0x0f) - 1]);
}
#endif /* CPU_BITMAP_SEARCH */
/*
* 嵟崅桪愭弴埵僞僗僋偺僒乕僠
*/
#ifdef __tsksched
#pragma optimize_for_speed
TCB *
search_schedtsk()
{
UINT schedpri;
schedpri = bitmap_search(ready_primap);
return((TCB *)(ready_queue[schedpri].next));
}
#endif /* __tsksched */
/*
* 幚峴偱偒傞忬懺傊偺堏峴
*
* 嵟崅桪愭弴埵偺僞僗僋傪峏怴偡傞偺偼丆幚峴偱偒傞僞僗僋偑側偐偭偨応崌
* 偲丆tcb 偺桪愭搙偑嵟崅桪愭弴埵偺僞僗僋偺桪愭搙傛傝傕崅偄応崌偱偁傞丏
*/
#ifdef __tskrun
BOOL
make_runnable(TCB *tcb)
{
UINT pri = tcb->priority;
tcb->tstat = TS_RUNNABLE;
LOG_TSKSTAT(tcb);
queue_insert_prev(&(ready_queue[pri]), &(tcb->task_queue));
ready_primap |= PRIMAP_BIT(pri);
if (schedtsk == (TCB *) NULL/* || pri < schedtsk->priority*/) { // Modified by Chen Yi @srf
schedtsk = tcb;
return(enadsp);
}
return(FALSE);
}
#endif /* __tskrun */
/*
* 幚峴偱偒傞忬懺偐傜懠偺忬懺傊偺堏峴
*
* 嵟崅桪愭弴埵偺僞僗僋傪峏怴偡傞偺偼丆tcb 偑嵟崅桪愭弴埵偺僞僗僋偱偁偭
* 偨応崌偱偁傞丏tcb 偲摨偠桪愭搙偺僞僗僋偑懠偵偁傞応崌偼丆tcb 偺師偺
* 僞僗僋偑嵟崅桪愭弴埵偵側傞丏偦偆偱側偄応崌偼丆儗僨傿僉儏乕傪僒乕僠
* 偡傞昁梫偑偁傞丏
*/
#ifdef __tsknrun
BOOL
make_non_runnable(TCB *tcb)
{
UINT pri = tcb->priority;
QUEUE *queue = &(ready_queue[pri]);
queue_delete(&(tcb->task_queue));
if (queue_empty(queue)) {
ready_primap &= ~PRIMAP_BIT(pri);
if (schedtsk == tcb) {
schedtsk = (ready_primap == 0) ? (TCB * ) NULL
: search_schedtsk();
return(enadsp);
}
}
else {
if (schedtsk == tcb) {
schedtsk = (TCB *)(queue->next);
return(enadsp);
}
}
return(FALSE);
}
#endif /* __tsknrun */
/*
* 媥巭忬懺傊偺堏峴
*/
#ifdef __tskdmt
void
make_dormant(TCB *tcb)
{
// tcb->priority = tcb->tinib->ipriority; // It's OK
if(tcb->priority != tcb->tinib->ipriority)
change_priority(tcb, tcb->tinib->ipriority);
tcb->tstat = TS_DORMANT;
tcb->wupcnt = FALSE;
tcb->enatex = FALSE;
tcb->texptn = 0;
create_context(tcb);
LOG_TSKSTAT(tcb);
}
#endif /* __tskdmt */
/*
* 媥巭忬懺偐傜幚峴偱偒傞忬懺傊偺堏峴
*/
#ifdef __tskact
BOOL
make_active(TCB *tcb)
{
// activate_context(tcb);
return(make_runnable(tcb));
}
#endif /* __tskact */
/*
* 幚峴忬懺偺僞僗僋偺廔椆
*/
#ifdef __tskext
void
exit_task()
{
make_non_runnable(runtsk);
make_dormant(runtsk);
if (runtsk->actcnt) {
runtsk->actcnt = FALSE;
make_active(runtsk);
}
exit_to_dispatch();
}
#endif /* __tskext */
static Inline QUEUE* search_node(QUEUE *queue, const QUEUE *entry)
{
QUEUE *p = queue->next;
while(p != queue)
{
if(p == entry)
break;
p = p->next;
}
return p;
}
/*
* 儗僨傿僉儏乕拞偺僞僗僋偺桪愭搙偺曄峏
*
* 嵟崅桪愭弴埵偺僞僗僋傪峏怴偡傞偺偼丆(1) tcb 偑嵟崅桪愭弴埵偺僞僗僋
* 偱偁偭偰丆偦偺桪愭搙傪壓偘偨応崌丆(2) tcb 偑嵟崅桪愭弴埵偺僞僗僋偱
* 偼側偔丆曄峏屻偺桪愭搙偑嵟崅桪愭弴埵偺僞僗僋偺桪愭搙傛傝傕崅偄応崌
* 偱偁傞丏(1) 偺応崌偵偼丆儗僨傿僉儏乕傪僒乕僠偡傞昁梫偑偁傞丏
*/
#ifdef __tskpri
BOOL
change_priority(TCB *tcb, UINT newpri) // Modified by Chen Yi @srf
{
UINT oldpri = tcb->priority;
tcb->priority = newpri;
QUEUE *queue = &ready_queue[oldpri];
if(search_node(queue, (QUEUE*)tcb) == queue) // Current task is not in the queue.
return FALSE;
queue_delete(&(tcb->task_queue));
if (queue_empty(&(ready_queue[oldpri]))) {
ready_primap &= ~PRIMAP_BIT(oldpri);
}
queue_insert_prev(&(ready_queue[newpri]), &(tcb->task_queue));
ready_primap |= PRIMAP_BIT(newpri);
if (schedtsk == tcb) {
if (newpri >= oldpri) {
schedtsk = search_schedtsk();
return(schedtsk != tcb && enadsp);
}
}
else {
if (newpri < schedtsk->priority) {
schedtsk = tcb;
return(enadsp);
}
}
return(FALSE);
}
#endif /* __tskpri */
/*
* 儗僨傿僉儏乕偺夞揮
*
* 嵟崅桪愭弴埵偺僞僗僋傪峏怴偡傞偺偼丆嵟崅桪愭弴埵偺僞僗僋偑僞僗僋僉
* 儏乕偺枛旜偵堏摦偟偨応崌偱偁傞丏
*/
#ifdef __tskrot
BOOL
rotate_ready_queue(UINT pri) // Modified by Chen Yi @srf
{
QUEUE *queue = &(ready_queue[pri]);
QUEUE *entry;
UB nBlkTsks = 0;
if (!(queue_empty(queue)) && queue->next->next != queue)
{
entry = queue_delete_next(queue); // Delete the first node from the queue and return the node.
queue_insert_prev(queue, entry); // Insert the node into the tail of the queue.
if (schedtsk == (TCB *) entry) {
schedtsk = (TCB *)(queue->next);
return(enadsp);
}
}
return(FALSE);
}
#endif /* __tskrot */
void search_dispatch(void)
{
UINT pri = TMAX_TPRI;
QUEUE *queue;
QUEUE *entry;
QUEUE *p;
if(!aTicks[runtsk->tskID])
aTicks[runtsk->tskID] = runtsk->tinib->tskTimeSlice; // Added by Chen Yi @srf
// Time events for a task can be handled here:
do
{
queue = &ready_queue[pri];
p = queue->next; // p points to the current running task
do
{
entry = queue_delete_next(queue); // Delete the first node from the queue and return the node.
queue_insert_prev(queue, entry); // Insert the node into the tail of the queue.
schedtsk = (TCB *)queue->next;
if(schedtsk->tstat == TS_RUNNABLE) // Added by Chen Yi @srf
return;
}
while(queue->next != p);
}
while(pri-- > TMIN_TPRI);
schedtsk = &tcb_table[0];
}
void poll_dispatch(void)
{
UINT pri = TMAX_TPRI;
QUEUE *queue;
QUEUE *entry;
QUEUE *p;
if(--aTicks[runtsk->tskID]) // Added by Chen Yi @srf
{
if(runtsk->tstat == TS_RUNNABLE)
return;
}
if(!aTicks[runtsk->tskID])
aTicks[runtsk->tskID] = runtsk->tinib->tskTimeSlice; // Added by Chen Yi @srf
// Time events for a task can be handled here:
do
{
queue = &ready_queue[pri];
p = queue->next;
do
{
entry = queue_delete_next(queue); // Delete the first node from the queue and return the node.
queue_insert_prev(queue, entry); // Insert the node into the tail of the queue.
schedtsk = (TCB *)(queue->next);
if(schedtsk->tstat == TS_RUNNABLE) // Added by Chen Yi @srf
return;
}
while(queue->next != p);
}
while(pri-- > TMIN_TPRI);
schedtsk = &tcb_table[0];
return;
}
#define SAVE_LP0() \
asm("[--sp] = lc0;"); \
asm("[--sp] = lt0;"); \
asm("[--sp] = lb0;");
#define POP_LP0() \
asm("lb0 = [sp++];"); \
asm("lt0 = [sp++];"); \
asm("lc0 = [sp++];");
void preemption_insert(const ID id)
{
TCB *tcb;
QUEUE *p;
QUEUE *queue = &ready_queue[TMAX_TPRI];
SAVE_LP0();
assert(id >= TMIN_TSKID && id <= tmax_tskid);
tcb = &tcb_table[id];
tcb->priority = TMAX_TPRI;
tcb->tstat = TS_RUNNABLE;
ready_primap |= PRIMAP_BIT(TMAX_TPRI);
p = search_node(queue, (QUEUE*)tcb);
if(p != queue)
queue_delete(p);
queue_insert_next(queue, (QUEUE*)tcb);
p = queue_delete_next(queue); // Delete the first node from the queue and return the node.
queue_insert_prev(queue, p); // Insert the node into the tail of the queue.
schedtsk = (TCB *)(queue->next);
POP_LP0();
}
ID cre_tsk(FP task, SIZE stksz, VP stk, ATR tskatr, UINT priority, UB nTicks)
{
recre_tsk(++cur_tskid, task, stksz, stk, tskatr, priority, nTicks);
return cur_tskid;
}
void recre_tsk(const ID id, FP task, SIZE stksz, VP stk, ATR tskatr, UINT priority, UB nTicks)
{
tinib_table[id].tskatr = tskatr;
tinib_table[id].ipriority = priority;
tinib_table[id].stksz = stksz;
tinib_table[id].stk = stk;
tinib_table[id].task = task;
tinib_table[id].texrtn = NULL;
tinib_table[id].exinf = NULL;
tinib_table[id].tskTimeSlice = nTicks;
tcb_table[id].task_queue.prev = tcb_table[id].task_queue.next = NULL;
tcb_table[id].tstat = TS_DORMANT;
tcb_table[id].tskID = id;
tcb_table[id].tinib = &tinib_table[id];
tcb_table[id].priority = priority;
tcb_table[id].winfo = NULL;
aTicks[id] = nTicks;
}
/*
* 堷悢傑偱掕媊偟偨僞僗僋椺奜張棟儖乕僠儞偺宆
*/
typedef void (*TEXRTN)(TEXPTN texptn, VP_INT exinf);
/*
* 僞僗僋椺奜張棟儖乕僠儞偺屇弌偟
*/
#ifdef __tsktex
void
call_texrtn()
{
TEXPTN texptn;
do {
texptn = runtsk->texptn;
runtsk->enatex = FALSE;
runtsk->texptn = 0;
t_unlock_cpu();
LOG_TEX_ENTER(texptn);
((TEXRTN)(*runtsk->tinib->texrtn))(texptn,
runtsk->tinib->exinf);
LOG_TEX_LEAVE(texptn);
if (!t_sense_lock()) {
t_lock_cpu();
}
} while (runtsk->texptn != 0);
runtsk->enatex = TRUE;
}
/*
* 僞僗僋椺奜張棟儖乕僠儞偺婲摦
*/
#ifndef OMIT_CALLTEX
void
calltex()
{
if (runtsk->enatex && runtsk->texptn != 0) {
call_texrtn();
}
}
#endif /* OMIT_CALLTEX */
#endif /* __tsktex */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -