⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 task.c

📁 日本著名的的嵌入式实时操作系统T-Kernel的源码及用户手册。
💻 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.c (T-Kernel/OS) *	Task Control */#include "kernel.h"#include "task.h"#include "wait.h"#include "ready_queue.h"#include "cpu_task.h"#include "tkdev_timer.h"#include "check.h"/* * Task dispatch disable state */#ifdef USE_DISPATCH_DISABLEDEXPORT BOOL	dispatch_disabled;#endif/* * Task execution control  */EXPORT TCB	*ctxtsk;	/* Task in execution */EXPORT TCB	*schedtsk;	/* Task which should be executed */EXPORT RDYQUE	ready_queue;	/* Ready queue *//* * Task control information */EXPORT TCB	*tcb_table;	/* Task control block */EXPORT QUEUE	free_tcb;	/* FreeQue */EXPORT ID	max_tskid;	/* Maximum task ID */EXPORT INT	default_sstksz;	/* Default system stack size */EXPORT INT	svc_call_limit;	/* Protect level of system call *//* * TCB Initialization */EXPORT ER task_initialize( void ){	INT	i;	TCB	*tcb;	ID	tskid;	/* Get system information */	i = _tk_get_cfn("TMaxTskId", &max_tskid, 1);	if ( i < 1 || NUM_TSKID < 1 ) return E_SYS;	i = _tk_get_cfn("TSysStkSz", &default_sstksz, 1);	if ( i < 1 || default_sstksz < MIN_SYS_STACK_SIZE ) return E_SYS;	i = _tk_get_cfn("TSVCLimit", &svc_call_limit, 1);	if ( i < 1 || svc_call_limit < 0 || svc_call_limit > 3 ) return E_SYS;	/* Allocate TCB area */	tcb_table = Imalloc(NUM_TSKID * sizeof(TCB));	if ( tcb_table == NULL ) return E_NOMEM;	/* Initialize task execution control information */	ctxtsk = schedtsk = NULL;	ready_queue_initialize(&ready_queue);#ifdef USE_DISPATCH_DISABLED	dispatch_disabled = 0;#endif	/* Register all TCBs onto FreeQue */	QueInit(&free_tcb);	for ( tcb = tcb_table, i = 0; i < NUM_TSKID; tcb++, i++ ) {		tskid = ID_TSK(i);		tcb->tskid = tskid;		tcb->state = TS_NONEXIST;#ifdef NUM_PORID		tcb->wrdvno = (UH)tskid;#endif		InitSVCLOCK(&tcb->svclock);		tcb->svclocked = NULL;		QueInsert(&tcb->tskque, &free_tcb);	}	return E_OK;}/* * Prepare task execution. */EXPORT void make_dormant( TCB *tcb ){	/* Initialize variables which should be reset at DORMANT state */	tcb->state    = TS_DORMANT;	tcb->priority = tcb->bpriority = tcb->ipriority;	tcb->sysmode  = tcb->isysmode;	tcb->wupcnt   = 0;	tcb->suscnt   = 0;	tcb->waitmask = 0;	tcb->nodiswai  = FALSE;	tcb->klockwait = FALSE;	tcb->klocked   = FALSE;	tcb->slicetime = 0;	tcb->stime = 0;	tcb->utime = 0;#ifdef NUM_MTXID	tcb->mtxlist = NULL;#endif	tcb->tskevt = 0;	tcb->texhdr   = NULL; /* Undefined task exception handler */	tcb->texmask  = 0;	tcb->pendtex  = 0;	tcb->exectex  = 0;	tcb->texflg   = 0;	tcb->execssid = 0;	/* Set context to start task */	setup_context(tcb);}/* ------------------------------------------------------------------------ *//* * Scheduling by time slice *	Add TIMER_PERIOD to the 'tcb' task's continuous execution *	time counter, and then if the counter exceeds the maximum *	continuation time, put the task at the end of the ready queue. */EXPORT TCB* time_slice_schedule( TCB *tcb ){	if ( tcb != NULL && tcb->slicetime > 0 ) {		tcb->slicecnt += TIMER_PERIOD;		if ( tcb->slicecnt > tcb->slicetime ) {			tcb = ready_queue_move_last(&ready_queue, tcb);		}	}	return tcb; /* New head task */}/* * Reselect task to execute *	Set 'schedtsk' to the head task at the ready queue. */Inline void reschedule( void ){	TCB	*toptsk;	toptsk = ready_queue_top(&ready_queue);	if ( schedtsk != toptsk ) {		/*		 * When the state becomes RUN to READY,		 * execute the time slice scheduling.		 */		if ( schedtsk == ctxtsk ) {			time_slice_schedule(schedtsk);		}		schedtsk = toptsk;		dispatch_request();	}}/* * Set task to READY state. *	Update the task state and insert in the ready queue. If necessary,  *	update 'schedtsk' and request to start task dispatcher.  */EXPORT void make_ready( TCB *tcb ){	tcb->state = TS_READY;	if ( ready_queue_insert(&ready_queue, tcb) ) {		/*		 * When the state becomes RUN to READY,		 * execute the time slice scheduling.		 */		if ( schedtsk == ctxtsk ) {			time_slice_schedule(schedtsk);		}		schedtsk = tcb;		dispatch_request();	}}/* * Set task to non-executable state. *	Delete the task from the ready queue. *	If the deleted task is 'schedtsk', set 'schedtsk' to the *	highest priority task in the ready queue.  *	'tcb' task must be READY. */EXPORT void make_non_ready( TCB *tcb ){	ready_queue_delete(&ready_queue, tcb);	if ( schedtsk == tcb ) {		schedtsk = ready_queue_top(&ready_queue);		dispatch_request();	}}/* * Change task priority. */EXPORT void change_task_priority( TCB *tcb, INT priority ){	INT	oldpri;	if ( tcb->state == TS_READY ) {		/*		 * When deleting a task from the ready queue, 		 * a value in the 'priority' field in TCB is needed. 		 * Therefore you need to delete the task from the		 * ready queue before changing 'tcb->priority.'		 */		ready_queue_delete(&ready_queue, tcb);		tcb->priority = priority;		ready_queue_insert(&ready_queue, tcb);		reschedule();	} else {		oldpri = tcb->priority;		tcb->priority = priority;		/* If the hook routine at the task priority change is defined,		   execute it */		if ( (tcb->state & TS_WAIT) != 0		  && tcb->wspec->chg_pri_hook) {			(*tcb->wspec->chg_pri_hook)(tcb, oldpri);		}	}}/* * Rotate ready queue. */EXPORT void rotate_ready_queue( INT priority ){	ready_queue_rotate(&ready_queue, priority);	reschedule();}/* * Rotate the ready queue including the highest priority task. */EXPORT void rotate_ready_queue_run(){	if ( schedtsk != NULL ) {		ready_queue_rotate(&ready_queue,				ready_queue_top_priority(&ready_queue));		reschedule();	}}/* ------------------------------------------------------------------------ *//* *	Debug support function */#if USE_DBGSPT/* * Refer ready queue */SYSCALL INT _td_rdy_que( PRI pri, ID list[], INT nent ){	QUEUE	*q, *tskque;	INT	n = 0;	CHECK_PRI(pri);	BEGIN_DISABLE_INTERRUPT;	tskque = &ready_queue.tskque[int_priority(pri)];	for ( q = tskque->next; q != tskque; q = q->next ) {		if ( n++ < nent ) {			*list++ = ((TCB*)q)->tskid;		}	}	END_DISABLE_INTERRUPT;	return n;}#endif /* USE_DBGSPT */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -