📄 pg_task.c
字号:
///////////////////////////////////////////////////////////////
//
//
// PGOS : A Portable,Configable Embedded System Kernel
//
//
//
// This is an open source project under GPL lincence
//
// Version 0.9.0 ---- Development Snopshot
//
// File name : pg_task.c : Task functions implemention
// History :
//
// 2005-07-24 First build by X.K. @ PGOS Team
// 2005-08-09 Fix a bug in pgos_tk_cre
// 2005-08-09 Upgrade for programming style
// 2005-08-21 Fix a bug in pgos_tk_switch
// Note :
// pgos_tk_remove still has a little bug need to fix
/////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include "pgos.h"
/******************************
TK_SWITCH() is a macro here.
And in your porting code ,
it also must be a MACRO .
******************************/
#define TK_SWITCH() __asm("break")
pgTASKLIST* task_freelist ; // points to the task pre lists
pgTASKLIST* task_list ; // points to the task lists tail
pgTASKLIST* task_list_head ; // points to the task lists head
pgTASKSEARCH* task_table ; // task entry table
extern pgTASK* task_nxt ; // task which is next to run
pgTASK* task_cur ; // task which is current running
extern pgTASK* task_prv ; // task which is last run
BYTE task_cur_id ; // current running task id
BYTE task_cur_prio ; // current running task prio
BYTE task_nxt_id ; // next run task id
BYTE task_nxt_prio ; // next run task prio
BYTE tasknum ; // total number of the task(s)
extern BYTE schedular ;
extern BYTE pgos_running ;
#if PG_SCH_ROUNDROBIN == 1
DWORD maxtime ;
#endif
#if PG_STAT_SUPPORT == 1
extern DWORD task_sw ;
#endif
#if PG_TASK_BASIC_SUPPORT == 1
////////////////////////////////////////////////////
//
//pgos_tk_cre
//
// Create a task and insert it to the task list .
// if successful,returns PGOS_SUCCESS
//
////////////////////////////////////////////////////
PGOS_STATUS pgos_tk_cre( VOID ( *task )(), BYTE prio, REGSZ* stk, BYTE* id )
{
pgTASK* Task ;
pgos_int_disable() ;
if( tasknum == MAXTASK )
return PGOS_FAIL_OV ; // task too many
// Alloc memory for task
if( task_freelist->next == NULL )
return PGOS_FAIL_MEM ;
stk = pgos_tk_initstk( stk,task ) ;
if( task_list == NULL )
{
task_list = task_freelist ;
task_list_head = task_list ;
}
else
{
task_list->next = task_freelist ;
task_list = task_list->next ;
}
task_freelist = task_freelist->next ;
task_list->next = NULL ;
Task = task_list->pTask ;
// Initliaze the task
Task->pgSP = stk ;
Task->id = tasknum ;
*id = tasknum ;
tasknum ++ ;
Task->prio = prio ;
Task->state = PG_READY ;
Task->delay = 0 ;
#if PG_MSG_SUPPORT == 1
Task->pgMessage->uflag = MSG_NEW ;
Task->pgMessage->rflag = MSG_NO_READ ;
Task->pgMessage->m_msg = PGOS_MMSG_Create ;
Task->pgMessage->From = MSG_PGOS_SEND ;
Task->pgMessage->To = MSG_TASK_RECV | Task->id ;
#if PG_DRV_SUPPORT == 1
pgos_call_drv( SYS_MSG_S, ( void * )Task->pgMessage ) ;
#endif // end of PG_DRV_SUPPORT
#endif // end of PG_MSG_SUPPORT
#if PG_SCH_ROUNDROBIN == 1
Task->runtime = 0 ;
#endif
pgos_tk_insert( Task ) ;
#if PG_DRV_SUPPORT == 1
pgos_call_drv( SYS_TK_C, NULL ) ;
#endif
if( pgos_running == 1 )
{
pgos_int_enable() ;
if( prio > task_cur_prio )
{
pgos_tk_switch() ;
}
else
{
return PGOS_SUCCESS ;
}
}
return PGOS_SUCCESS ;
}
////////////////////////////////////////////////////////
//
//pgos_tk_sleep
//
// Make a task sleep .
//
////////////////////////////////////////////////////////
PGOS_STATUS pgos_tk_sleep( BYTE id, WORD time )
{
pgTASK* pTask ;
pgos_int_disable() ;
pTask = pgos_tk_lookup( id ) ;
if( !pTask )
{
pgos_int_enable() ;
return PGOS_FAIL_NM ;
}
pTask->state = PG_SLEEP ;
pTask->delay = time ;
if( id == task_cur_id )
{
pgos_tk_switch() ;
}
pgos_int_enable() ;
return PGOS_SUCCESS ;
}
////////////////////////////////////////////////////////
//
//pgos_tk_wakeup
//
// Wakeup a task .
//
/////////////////////////////////////////////////////////
PGOS_STATUS pgos_tk_wakeup( BYTE id )
{
pgTASK* pTask ;
pgos_int_disable() ;
pTask = pgos_tk_lookup( id ) ;
if( !pTask || pTask->state != PG_SLEEP )
{
pgos_int_enable() ;
return PGOS_FAIL_NM ;
}
pTask->state = PG_READY ;
pTask->delay = 0 ;
if( pTask->prio > task_cur_prio )
{
task_cur->state = PG_READY ;
pgos_tk_switch() ;
}
pgos_int_enable() ;
return PGOS_SUCCESS ;
}
PGOS_STATUS pgos_tk_suspend( BYTE id )
{
pgTASK* pTask ;
pgos_int_disable() ;
pTask = pgos_tk_lookup( id ) ;
if( !pTask )
{
pgos_int_enable() ;
return PGOS_FAIL_NM ;
}
pTask->state = PG_SUSPEND ;
if( id == task_cur_id )
{
pgos_tk_switch() ;
}
pgos_int_enable() ;
return PGOS_SUCCESS ;
}
PGOS_STATUS pgos_tk_resume( BYTE id )
{
pgTASK* pTask ;
pgos_int_disable() ;
pTask = pgos_tk_lookup( id ) ;
if( !pTask )
{
pgos_int_enable() ;
return PGOS_FAIL_NM ;
}
pTask->state = PG_READY ;
if( pTask->prio > task_cur_prio )
{
task_cur->state = PG_READY ;
pgos_tk_switch() ;
}
pgos_int_enable() ;
return PGOS_SUCCESS ;
}
PGOS_STATUS pgos_tk_remove( BYTE id )
{
pgTASK* pTask = NULL ;
pgTASKLIST* pListNext = NULL ;
pgTASKLIST* pListPrv = NULL ;
pgTASKLIST* pList = NULL ;
pgos_int_disable() ;
pTask = pgos_tk_lookup( id ) ;
if( !pTask )
return PGOS_FAIL_NM ;
pList = task_list_head ;
if( pTask->id == task_cur_id )
return PGOS_FAIL_NM ;
if( pTask == pList->pTask )
{
if( pList->next == NULL )
{
free( pTask->pgSP ) ;
free( pTask ) ;
free( pList ) ;
#if PG_DRV_SUPPORT == 1
pgos_call_drv( SYS_TK_R, NULL ) ;
#endif
// Even the idle task is removed
for( ;; ) ;
}
else
{
pListNext = pList->next ;
free( pTask->pgSP ) ;
free( pTask ) ;
free( pList ) ;
task_list_head = pListNext ;
}
pgos_int_enable() ;
#if PG_DRV_SUPPORT == 1
pgos_call_drv( SYS_TK_R, NULL ) ;
#endif
return PGOS_SUCCESS ;
}
pListPrv = pList ;
for( ; pList ; pList = pList->next )
{
if( pList->pTask == pTask )
{
if( pList->next->next != NULL )
{
pListNext = pList->next->next ;
free( pTask->pgSP ) ;
free( pTask ) ;
pListPrv->next = pListNext ;
free( pList ) ;
}
else
{
free( pTask->pgSP ) ;
free( pTask ) ;
pListPrv->next = NULL ;
free( pList ) ;
}
#if PG_DRV_SUPPORT == 1
pgos_call_drv( SYS_TK_R, NULL ) ;
#endif
pgos_int_enable() ;
return PGOS_SUCCESS ;
}
pListPrv = pList ;
}
pgos_int_enable() ;
return PGOS_FAIL_NM ;
}
pgTASK* pgos_tk_lookup( BYTE id )
{
if( id <= tasknum )
return *(&task_table[ id ].pTask) ;
return NULL ;
}
pgTASK* pgos_tk_alloc()
{
pgTASK* pTask ;
pTask = ( pgTASK* )malloc( sizeof( pgTASK ) ) ;
if( !pTask )
return NULL ;
#if PG_MSG_SUPPORT == 1
pTask->pgMessage = ( pgMSG * )malloc( sizeof( pgMSG ) ) ;
if( !pTask->pgMessage )
return NULL ;
#endif
return pTask ;
}
pgTASKLIST* pgos_tk_listalloc()
{
pgTASKLIST* pList ;
pList = ( pgTASKLIST* )malloc( sizeof( pgTASKLIST ) ) ;
if( !pList )
return NULL ;
pList->pTask = pgos_tk_alloc() ;
if( !pList->pTask )
return NULL ;
return pList ;
}
pgTASKLIST* pgos_tk_inilist()
{
BYTE index ;
pgTASKLIST* list ;
pgTASKLIST* list_head ;
list = pgos_tk_listalloc() ;
if( !list )
return NULL ;
list_head = list ;
for( index = 0 ;index < MAXTASK ;index ++ )
{
list->next = pgos_tk_listalloc() ;
if( !list->next )
return NULL ;
list = list->next ;
list->next = NULL ;
}
task_list = NULL ;
task_list_head = NULL ;
tasknum = 0 ;
return list_head ;
}
PGOS_STATUS pgos_tk_initab( )
{
task_table = ( pgTASKSEARCH * )malloc( sizeof( pgTASKSEARCH ) * MAXTASK ) ;
if( !task_table )
return PGOS_FAIL_MEM ;
return PGOS_SUCCESS ;
}
VOID pgos_tk_insert( pgTASK* pTask )
{
pgos_int_disable() ;
task_table[ pTask->id ].pTask = pTask ;
pgos_int_enable() ;
}
VOID pgos_tk_switch()
{
pgTASKLIST* tlist = NULL ;
// If the schedular is locked
if( schedular == PG_SCH_LOCK ) return ;
tlist = task_list_head ;
task_nxt = tlist->pTask ;
task_nxt_prio = task_nxt->prio ;
for( ; tlist ; tlist = tlist->next )
{
if( tlist->pTask->state == PG_READY )
{
if( task_nxt_prio < tlist->pTask->prio )
{
task_nxt_prio = tlist->pTask->prio ;
task_nxt = tlist->pTask ;
}
}
}
#if PG_SCH_ROUNDROBIN == 1
task_cur->runtime = 0 ;
#endif
task_prv = task_cur ;
task_cur = task_nxt ;
task_cur_id = task_nxt->id ;
task_cur_prio = task_nxt_prio ;
task_nxt->state = PG_RUN ;
#if PG_STAT_SUPPORT == 1
task_sw ++ ;
#endif
#if PG_DRV_SUPPORT == 1
pgos_call_drv( SYS_TK_SW, NULL ) ;
#endif
TK_SWITCH() ;
}
#endif // TASK_BASIC_SUPPORT
#if PG_TASK_ADV_SUPPORT == 1
VOID pgos_tk_resumeall()
{
pgTASK* pTask ;
pgTASKLIST* pList = task_list_head ;
pgos_int_disable() ;
task_nxt_prio = pList->pTask->prio ;
for( ; pList ; pList = pList->next )
{
pTask = pList->pTask ;
if( pTask->state == PG_SUSPEND )
{
pTask->state = PG_READY ;
if( pTask->prio > task_nxt_prio )
task_nxt_prio = pTask->prio ;
}
}
if( task_nxt_prio != task_cur_prio )
{
task_cur->state = PG_READY ;
pgos_tk_switch() ;
}
pgos_int_enable() ;
}
BYTE pgos_tk_getnum()
{
return tasknum - 1 ;
}
BYTE pgos_tk_getcurid( )
{
return task_cur_id ;
}
BYTE pgos_tk_getkmax()
{
return MAXTASK ;
}
VOID pgos_tk_sleep_sec( WORD sec )
{
pgos_tk_sleep( task_cur_id, 200 * sec ) ;
}
#endif // TASK_ADV_SUPPORT
#if PG_MSG_SUPPORT == 1
PGOS_STATUS pgos_tk_sendmsg( BYTE id, WORD m_msg, WORD s_msg )
{
pgTASK* pTask ;
pgMSG* pMsg ;
pgos_int_disable() ;
pTask = pgos_tk_lookup( id ) ;
if( !pTask )
{
pgos_int_enable() ;
return PGOS_FAIL_NM ;
}
pMsg = pTask->pgMessage ;
#if PG_MESSAGE_UNBLK == 1
if( pMsg->rflag == MSG_NO_READ )
{
pgos_tk_sleep( task_cur_id,10 ) ;
if( pMsg->rflag == MSG_NO_READ )
{
pgos_int_enable() ;
return PGOS_FAIL_NM ;
}
}
#else
#if PG_MESSAGE_BLOCK == 1
while( pMsg->rflag == MSG_READ_OK )
{
pgos_tk_sleep( task_cur_id,10 ) ;
}
#else
#error Error in PG_CFG.H ........
#endif // end of BLOCK mode
#endif // end of UNBLK Mode
pMsg->uflag = MSG_NEW ;
pMsg->rflag = MSG_NO_READ ;
pMsg->m_msg = m_msg ;
pMsg->s_msg = s_msg ;
pMsg->From = MSG_TASK_SEND | ( WORD )task_cur_id ;
pMsg->To = MSG_TASK_RECV | ( WORD )id ;
#if PG_DRV_SUPPORT == 1
pgos_call_drv( SYS_MSG_S, ( void * )pMsg ) ;
#endif
pgos_int_enable() ;
return PGOS_SUCCESS ;
}
PGOS_STATUS pgos_tk_getmsg( WORD* m_msg, WORD* s_msg, WORD* Sender )
{
pgMSG* pMsg ;
pgos_int_disable() ;
pMsg = task_cur->pgMessage ;
#if PG_MESSAGE_UNBLK == 1
if( pMsg->uflag == MSG_OLD )
{
pgos_tk_sleep( task_cur_id,10 ) ;
if( pMsg->uflag == MSG_OLD )
{
pgos_int_enable() ;
return PGOS_FAIL_NM ;
}
}
#else
#if PG_MESSAGE_BLOCK == 1
while( pMsg->uflag == MSG_NEW && pMsg->rflag == MSG_NO_READ )
{
pgos_tk_sleep( task_cur_id,10 ) ;
}
#else
#error Error in PG_CFG.H............
#endif // end of BLOCK Mode
#endif // end of UNBLK Mode
*m_msg = pMsg->m_msg ;
*s_msg = pMsg->s_msg ;
*Sender = pMsg->From ;
pMsg->uflag = MSG_OLD ;
pMsg->rflag = MSG_READ_OK ;
#if PG_DRV_SUPPORT == 1
pgos_call_drv( SYS_MSG_R, ( void * )pMsg ) ;
#endif
pgos_int_enable() ;
return PGOS_SUCCESS ;
}
BOOL pgos_tk_isnewmsg()
{
pgTASK* pTask ;
BOOL Ret ;
pgos_int_disable() ;
pTask = pgos_tk_lookup( task_cur_id ) ;
if( pTask->pgMessage->uflag == MSG_NEW )
{
Ret = TRUE ;
}
else
{
Ret = FALSE ;
}
pgos_int_enable() ;
return Ret ;
}
#endif
#if PG_SCH_ROUNDROBIN == 1
VOID pgos_tk_setruntime( DWORD time )
{
if( time == 0 )
maxtime = MAX_DEF_TIME ;
else
maxtime = time ;
}
#endif
BOOL pgos_tk_basic()
{
#if PG_TASK_BASIC_SUPPORT == 1
return TRUE ;
#else
return FALSE ;
#endif
}
BOOL pgos_tk_adv()
{
#if PG_TASK_ADV_SUPPORT == 1
return TRUE ;
#else
return FALSE ;
#endif
}
BOOL pgos_tk_msg()
{
#if PG_MSG_SUPPORT == 1
return TRUE ;
#else
return FALSE ;
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -