📄 task_manage.c
字号:
/* *---------------------------------------------------------------------- * T-Kernel * * Copyright (C) 2004 by Ken Sakamura. All rights reserved. * T-Kernel is distributed under the T-License. *---------------------------------------------------------------------- * * Version: 1.01.00 * Released by T-Engine Forum(http://www.t-engine.org) at 2004/6/28. * *---------------------------------------------------------------------- *//* * task_manage.c (T-Kernel/OS) * Task Management Function */#include "kernel.h"#include "task.h"#include "wait.h"#include "check.h"#include "cpu_task.h"#include <tm/tmonitor.h>/* * Create task */SYSCALL ID _tk_cre_tsk P1( T_CTSK *pk_ctsk ){ const ATR VALID_TSKATR = { /* Valid value of task attribute */ TA_HLNG |TA_SSTKSZ |TA_USERSTACK |TA_TASKSPACE |TA_RESID |TA_RNG3 |TA_FPU |TA_COP0 |TA_COP1 |TA_COP2 |TA_COP3 |TA_GP#if USE_OBJECT_NAME |TA_DSNAME#endif }; TCB *tcb; INT stksz, sstksz, sysmode, resid; VP stack, sstack; ER ercd; CHECK_RSATR(pk_ctsk->tskatr, VALID_TSKATR); CHECK_PRI(pk_ctsk->itskpri); CHECK_NOCOP(pk_ctsk->tskatr);#ifdef USE_SINGLE_STACK CHECK_NOSPT((pk_ctsk->tskatr & TA_USERSTACK) == 0);#endif#ifdef CHK_PAR if ( (pk_ctsk->tskatr & TA_USERSTACK) != 0 ) { CHECK_PAR((pk_ctsk->tskatr & TA_RNG3) != TA_RNG0); CHECK_PAR(pk_ctsk->stksz == 0); } else { CHECK_PAR(pk_ctsk->stksz >= 0); } if ( (pk_ctsk->tskatr & TA_TASKSPACE) != 0 ) { CHECK_PAR(pk_ctsk->lsid >= 0 && pk_ctsk->lsid <= MAX_LSID); }#endif if ( (pk_ctsk->tskatr & TA_RESID) != 0 ) { CHECK_RESID(pk_ctsk->resid); resid = pk_ctsk->resid; } else { resid = SYS_RESID; /* System resource group */ } if ( (pk_ctsk->tskatr & TA_SSTKSZ) != 0 ) { CHECK_PAR(pk_ctsk->sstksz >= MIN_SYS_STACK_SIZE); sstksz = pk_ctsk->sstksz; } else { sstksz = default_sstksz; } if ( (pk_ctsk->tskatr & TA_RNG3) == TA_RNG0 ) { sysmode = 1; sstksz += pk_ctsk->stksz; stksz = 0; } else { sysmode = 0;#ifdef USE_SINGLE_STACK sstksz += pk_ctsk->stksz; stksz = 0;#else stksz = pk_ctsk->stksz;#endif } /* Adjust stack size by 8 bytes */ sstksz = (sstksz + 7) / 8 * 8; stksz = (stksz + 7) / 8 * 8; /* Allocate system stack area */ sstack = IAmalloc(sstksz, TA_RNG0); if ( sstack == NULL ) return E_NOMEM; if ( stksz > 0 ) { /* Allocate user stack area */ stack = IAmalloc(stksz, pk_ctsk->tskatr); if ( stack == NULL ) { IAfree(sstack, TA_RNG0); return E_NOMEM; } } BEGIN_CRITICAL_SECTION; /* Get control block from FreeQue */ tcb = (TCB*)QueRemoveNext(&free_tcb); if ( tcb == NULL ) { ercd = E_LIMIT; goto error_exit; } /* Initialize control block */ tcb->exinf = pk_ctsk->exinf; tcb->tskatr = pk_ctsk->tskatr; tcb->task = pk_ctsk->task; tcb->ipriority = int_priority(pk_ctsk->itskpri); tcb->resid = resid; tcb->stksz = stksz; tcb->sstksz = sstksz;#if USE_OBJECT_NAME if ( (pk_ctsk->tskatr & TA_DSNAME) != 0 ) { strncpy(tcb->name, pk_ctsk->dsname, OBJECT_NAME_LENGTH); }#endif#if TA_GP /* Set global pointer */ if ( (pk_ctsk->tskatr & TA_GP) != 0 ) gp = pk_ctsk->gp; tcb->gp = gp;#endif /* Set stack pointer */ if ( stksz > 0 ) { tcb->istack = (VB*)stack + stksz; } else { tcb->istack = pk_ctsk->stkptr; } tcb->isstack = (VB*)sstack + sstksz - RESERVE_SSTACK(tcb->tskatr); /* Set initial value of task operation mode */ tcb->isysmode = sysmode; tcb->sysmode = sysmode; /* Set initial value of task space */ if ( (pk_ctsk->tskatr & TA_TASKSPACE) != 0 ) { tcb->tskctxb.uatb = pk_ctsk->uatb; tcb->tskctxb.lsid = pk_ctsk->lsid; } else { tcb->tskctxb.uatb = NULL; tcb->tskctxb.lsid = 0; /* No task eigenspace */ } /* make it to DORMANT state */ make_dormant(tcb); ercd = tcb->tskid; error_exit: END_CRITICAL_SECTION; if ( ercd < E_OK ) { IAfree(sstack, TA_RNG0); if ( stksz > 0 ) IAfree(stack, pk_ctsk->tskatr); } return ercd;}/* * Task deletion * Call from critical section */LOCAL void _del_tsk( TCB *tcb ){ VP stack; /* Free system stack */ stack = (VB*)tcb->isstack + RESERVE_SSTACK(tcb->tskatr) - tcb->sstksz; IAfree(stack, TA_RNG0); if ( tcb->stksz > 0 ) { /* Free user stack */ stack = (VB*)tcb->istack - tcb->stksz; IAfree(stack, tcb->tskatr); } /* Return control block to FreeQue */ QueInsert(&tcb->tskque, &free_tcb); tcb->state = TS_NONEXIST;}/* * Delete task */SYSCALL ER _tk_del_tsk( ID tskid ){ TCB *tcb; TSTAT state; ER ercd = E_OK; CHECK_TSKID(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; state = tcb->state; if ( state != TS_DORMANT ) { ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; } else { _del_tsk(tcb); } END_CRITICAL_SECTION; return ercd;}/* ------------------------------------------------------------------------ *//* * Start task */SYSCALL ER _tk_sta_tsk( ID tskid, INT stacd ){ TCB *tcb; TSTAT state; ER ercd = E_OK; CHECK_TSKID(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; state = tcb->state; if ( state != TS_DORMANT ) { ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; } else { setup_stacd(tcb, stacd); make_ready(tcb); } END_CRITICAL_SECTION; return ercd;}/* * Task finalization * Call from critical section */LOCAL void _ter_tsk( TCB *tcb ){ TSTAT state; if ( tcb->svclocked != NULL ) { /* Unlock all extended SVC locks */ AllUnlockSVC(tcb); } state = tcb->state; if ( state == TS_READY ) { make_non_ready(tcb); } else if ( (state & TS_WAIT) != 0 ) { wait_cancel(tcb); if ( tcb->wspec->rel_wai_hook != NULL ) { (*tcb->wspec->rel_wai_hook)(tcb); } }#ifdef NUM_MTXID /* signal mutex */ signal_all_mutex(tcb);#endif cleanup_context(tcb);}/* * End its own task */SYSCALL void _tk_ext_tsk( void ){#ifdef DORMANT_STACK_SIZE /* To avoid destroying stack used in 'make_dormant', allocate the dummy area on the stack. */ volatile VB _dummy[DORMANT_STACK_SIZE];#endif /* Check context error */#ifdef CHK_CTX2 if ( in_indp() ) {#ifndef NO_KERNEL_MESSAGE tm_putstring("tk_ext_tsk was called in the task independent\n");#endif tm_monitor(); /* To monitor */ }#endif#ifdef CHK_CTX1 if ( in_ddsp() ) {#ifndef NO_KERNEL_MESSAGE tm_putstring("tk_ext_tsk was called in the dispatch disabled\n");#endif }#endif DISABLE_INTERRUPT; _ter_tsk(ctxtsk); make_dormant(ctxtsk); force_dispatch(); /* No return */#ifdef DORMANT_STACK_SIZE /* for WARNING */ _dummy[0] = 0;#endif}/* * End and delete its own task */SYSCALL void _tk_exd_tsk( void ){ /* Check context error */#ifdef CHK_CTX2 if ( in_indp() ) {#ifndef NO_KERNEL_MESSAGE tm_putstring("tk_exd_tsk was called in the task independent\n");#endif tm_monitor(); /* To monitor */ }#endif#ifdef CHK_CTX1 if ( in_ddsp() ) {#ifndef NO_KERNEL_MESSAGE tm_putstring("tk_exd_tsk was called in the dispatch disabled\n");#endif }#endif DISABLE_INTERRUPT; _ter_tsk(ctxtsk); _del_tsk(ctxtsk); force_dispatch(); /* No return */}/* * Termination of other task */SYSCALL ER _tk_ter_tsk( ID tskid ){ TCB *tcb; TSTAT state; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_NONSELF(tskid); CHECK_INTSK(); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; state = tcb->state; if ( !task_alive(state) ) { ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; } else if ( tcb->klocked ) { /* Normally, it does not become this state. * When the state is page-in wait in the virtual memory * system and when triying to terminate any task, * it becomes this state. */ ercd = E_OBJ; } else { _ter_tsk(tcb); make_dormant(tcb); } END_CRITICAL_SECTION; return ercd;}/* ------------------------------------------------------------------------ *//* * Change task priority */SYSCALL ER _tk_chg_pri( ID tskid, PRI tskpri ){ TCB *tcb; INT priority; ER ercd; CHECK_TSKID_SELF(tskid); CHECK_PRI_INI(tskpri); tcb = get_tcb_self(tskid); BEGIN_CRITICAL_SECTION; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; goto error_exit; } /* Converiosn priority to internal expression */ if ( tskpri == TPRI_INI ) { priority = tcb->ipriority; } else { priority = int_priority(tskpri); }#ifdef NUM_MTXID /* Mutex priority change limit */ ercd = chg_pri_mutex(tcb, priority); if ( ercd < E_OK ) goto error_exit; tcb->bpriority = priority; priority = ercd;#else tcb->bpriority = priority;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -