📄 os_task.c
字号:
* task is being deleted, the current task would not be able to be rescheduled because it
* is removed from the ready list. Incrementing the nesting counter prevents another task
* from being schedule. This means that an ISR would return to the current task which is
* being deleted. The rest of the deletion would thus be able to be completed.
*********************************************************************************************************
*/
/*$PAGE*/
#if OS_TASK_DEL_EN > 0
INT8U OSTaskDel(INT8U prio)
{
#if OS_EVENT_EN
OS_EVENT *pevent;
#endif
#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
OS_FLAG_NODE *pnode;
#endif
OS_TCB *ptcb;
INT8U y;
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
if (OSIntNesting > 0)
{
/* See if trying to delete from ISR */
return (OS_ERR_TASK_DEL_ISR);
}
if (prio == OS_TASK_IDLE_PRIO)
{
/* Not allowed to delete idle task */
return (OS_ERR_TASK_DEL_IDLE);
}
#if OS_ARG_CHK_EN > 0
if (prio >= OS_LOWEST_PRIO)
{
/* Task priority valid ? */
if (prio != OS_PRIO_SELF)
{
return (OS_ERR_PRIO_INVALID);
}
}
#endif
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF)
{
/* See if requesting to delete self */
prio = OSTCBCur->OSTCBPrio; /* Set priority to delete to current */
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *) 0)
{
/* Task to delete must exist */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST);
}
if (ptcb == OS_TCB_RESERVED)
{
/* Must not be assigned to Mutex */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_DEL);
}
y = ptcb->OSTCBY;
OSRdyTbl[y] &= ~ptcb->OSTCBBitX;
if (OSRdyTbl[y] == 0)
{
/* Make task not ready */
OSRdyGrp &= ~ptcb->OSTCBBitY;
}
#if OS_EVENT_EN
pevent = ptcb->OSTCBEventPtr;
if (pevent != (OS_EVENT *) 0)
{
/* If task is waiting on event */
pevent->OSEventTbl[y] &= ~ptcb->OSTCBBitX;
if (pevent->OSEventTbl[y] == 0)
{
/* ... remove task from ... */
pevent->OSEventGrp &= ~ptcb->OSTCBBitY; /* ... event ctrl block */
}
}
#endif
#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
pnode = ptcb->OSTCBFlagNode;
if (pnode != (OS_FLAG_NODE *) 0)
{
/* If task is waiting on event flag */
OS_FlagUnlink(pnode); /* Remove from wait list */
}
#endif
ptcb->OSTCBDly = 0; /* Prevent OSTimeTick() from updating */
ptcb->OSTCBStat = OS_STAT_RDY; /* Prevent task from being resumed */
ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
if (OSLockNesting < 255u)
{
/* Make sure we don't context switch */
OSLockNesting++;
}
OS_EXIT_CRITICAL(); /* Enabling INT. ignores next instruc. */
OS_Dummy(); /* ... Dummy ensures that INTs will be */
OS_ENTER_CRITICAL(); /* ... disabled HERE! */
if (OSLockNesting > 0)
{
/* Remove context switch lock */
OSLockNesting--;
}
OSTaskDelHook(ptcb); /* Call user defined hook */
OSTaskCtr--; /* One less task being managed */
OSTCBPrioTbl[prio] = (OS_TCB *) 0; /* Clear old priority entry */
if (ptcb->OSTCBPrev == (OS_TCB *) 0)
{
/* Remove from TCB chain */
ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *) 0;
OSTCBList = ptcb->OSTCBNext;
}
else
{
ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
}
ptcb->OSTCBNext = OSTCBFreeList; /* Return TCB to free TCB list */
OSTCBFreeList = ptcb;
#if OS_TASK_NAME_SIZE > 1
ptcb->OSTCBTaskName[0] = '?'; /* Unknown name */
ptcb->OSTCBTaskName[1] = OS_ASCII_NUL;
#endif
OS_EXIT_CRITICAL();
if (OSRunning == OS_TRUE)
{
OS_Sched(); /* Find new highest priority task */
}
return (OS_ERR_NONE);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* REQUEST THAT A TASK DELETE ITSELF
*
* Description: This function is used to:
* a) notify a task to delete itself.
* b) to see if a task requested that the current task delete itself.
* This function is a little tricky to understand. Basically, you have a task that needs
* to be deleted however, this task has resources that it has allocated (memory buffers,
* semaphores, mailboxes, queues etc.). The task cannot be deleted otherwise these
* resources would not be freed. The requesting task calls OSTaskDelReq() to indicate that
* the task needs to be deleted. Deleting of the task is however, deferred to the task to
* be deleted. For example, suppose that task #10 needs to be deleted. The requesting task
* example, task #5, would call OSTaskDelReq(10). When task #10 gets to execute, it calls
* this function by specifying OS_PRIO_SELF and monitors the returned value. If the return
* value is OS_ERR_TASK_DEL_REQ, another task requested a task delete. Task #10 would look like
* this:
*
* void Task(void *p_arg)
* {
* .
* .
* while (1) {
* OSTimeDly(1);
* if (OSTaskDelReq(OS_PRIO_SELF) == OS_ERR_TASK_DEL_REQ) {
* Release any owned resources;
* De-allocate any dynamic memory;
* OSTaskDel(OS_PRIO_SELF);
* }
* }
* }
*
* Arguments : prio is the priority of the task to request the delete from
*
* Returns : OS_ERR_NONE if the task exist and the request has been registered
* OS_ERR_TASK_NOT_EXIST if the task has been deleted. This allows the caller to know whether
* the request has been executed.
* OS_ERR_TASK_DEL if the task is assigned to a Mutex.
* OS_ERR_TASK_DEL_IDLE if you requested to delete uC/OS-II's idle task
* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed
* (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
* OS_ERR_TASK_DEL_REQ if a task (possibly another task) requested that the running task be
* deleted.
*********************************************************************************************************
*/
/*$PAGE*/
#if OS_TASK_DEL_EN > 0
INT8U OSTaskDelReq(INT8U prio)
{
INT8U stat;
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
if (prio == OS_TASK_IDLE_PRIO)
{
/* Not allowed to delete idle task */
return (OS_ERR_TASK_DEL_IDLE);
}
#if OS_ARG_CHK_EN > 0
if (prio >= OS_LOWEST_PRIO)
{
/* Task priority valid ? */
if (prio != OS_PRIO_SELF)
{
return (OS_ERR_PRIO_INVALID);
}
}
#endif
if (prio == OS_PRIO_SELF)
{
/* See if a task is requesting to ... */
OS_ENTER_CRITICAL(); /* ... this task to delete itself */
stat = OSTCBCur->OSTCBDelReq; /* Return request status to caller */
OS_EXIT_CRITICAL();
return (stat);
}
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *) 0)
{
/* Task to delete must exist */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST); /* Task must already be deleted */
}
if (ptcb == OS_TCB_RESERVED)
{
/* Must NOT be assigned to a Mutex */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_DEL);
}
ptcb->OSTCBDelReq = OS_ERR_TASK_DEL_REQ; /* Set flag indicating task to be DEL. */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* GET THE NAME OF A TASK
*
* Description: This function is called to obtain the name of a task.
*
* Arguments : prio is the priority of the task that you want to obtain the name from.
*
* pname is a pointer to an ASCII string that will receive the name of the task. The
* string must be able to hold at least OS_TASK_NAME_SIZE characters.
*
* perr is a pointer to an error code that can contain one of the following values:
*
* OS_ERR_NONE if the requested task is resumed
* OS_ERR_TASK_NOT_EXIST if the task has not been created or is assigned to a Mutex
* OS_ERR_PRIO_INVALID if you specified an invalid priority:
* A higher value than the idle task or not OS_PRIO_SELF.
* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname'
* OS_ERR_NAME_GET_ISR You called this function from an ISR
*
*
* Returns : The length of the string or 0 if the task does not exist.
*********************************************************************************************************
*/
#if OS_TASK_NAME_SIZE > 1
INT8U OSTaskNameGet(INT8U prio, INT8U *pname, INT8U *perr)
{
OS_TCB *ptcb;
INT8U len;
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
#if OS_ARG_CHK_EN > 0
if (perr == (INT8U *) 0)
{
/* Validate 'perr' */
return (0);
}
if (prio > OS_LOWEST_PRIO)
{
/* Task priority valid ? */
if (prio != OS_PRIO_SELF)
{
*perr = OS_ERR_PRIO_INVALID; /* No */
return (0);
}
}
if (pname == (INT8U *) 0)
{
/* Is 'pname' a NULL pointer? */
*perr = OS_ERR_PNAME_NULL; /* Yes */
return (0);
}
#endif
if (OSIntNesting > 0)
{
/* See if trying to call from an ISR */
*perr = OS_ERR_NAME_GET_ISR;
return (0);
}
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF)
{
/* See if caller desires it's own name */
prio = OSTCBCur->OSTCBPrio;
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *) 0)
{
/* Does task exist? */
OS_EXIT_CRITICAL(); /* No */
*perr = OS_ERR_TASK_NOT_EXIST;
return (0);
}
if (ptcb == OS_TCB_RESERVED)
{
/* Task assigned to a Mutex? */
OS_EXIT_CRITICAL(); /* Yes */
*perr = OS_ERR_TASK_NOT_EXIST;
return (0);
}
len = OS_StrCopy(pname, ptcb->OSTCBTaskName); /* Yes, copy name from TCB */
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return (len);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* ASSIGN A NAME TO A TASK
*
* Description: This function is used to set the name of a task.
*
* Arguments : prio is the priority of the task that you want the assign a name to.
*
* pname is a pointer to an ASCII string that contains the name of the task. The ASCII
* string must be NUL terminated.
*
* perr is a pointer to an error code that can contain one of the following values:
*
* OS_ERR_NONE if the requested task is resumed
* OS_ERR_TASK_NOT_EXIST if the task has not been created or is assigned to a Mutex
* OS_ERR_TASK_NAME_TOO_LONG if the name you are giving to the task exceeds the
* storage capacity of a task name as specified by
* OS_TASK_NAME_SIZE.
* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname'
* OS_ERR_PRIO_INVALID if you specified an invalid priority:
* A higher value than the idle task or not OS_PRIO_SELF.
* OS_ERR_NAME_SET_ISR if you called this function from an ISR
*
* Returns : None
*********************************************************************************************************
*/
#if OS_TASK_NAME_SIZE > 1
void OSTaskNameSet(INT8U prio, INT8U *pname, INT8U *perr)
{
INT8U len;
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0;
#endif
#if OS_ARG_CHK_EN > 0
if (perr == (INT8U *) 0)
{
/* Validate 'perr' */
return;
}
if (prio > OS_LOWEST_PRIO)
{
/* Task priority valid ? */
if (prio != OS_PRIO_SELF)
{
*perr = OS_ERR_PRIO_INVALID; /* No */
return;
}
}
if (pname == (INT8U *) 0)
{
/* Is 'pname' a NULL pointer? */
*perr = OS_ERR_PNAME_NULL; /* Yes */
return;
}
#endif
if (OSIntNesting > 0)
{
/* See if trying to call from an ISR */
*perr = OS_ERR_NAME_SET_ISR;
return;
}
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF)
{
/* See if caller desires to set it's own name */
prio = OSTCBCur->OSTCBPrio;
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *) 0)
{
/* Does task exist? */
OS_EXIT_CRITICAL(); /* No */
*perr = OS_ERR_TASK_NOT_EXIST;
return;
}
if (ptcb == OS_TCB_RESERVED)
{
/* Task assigned to a Mutex? */
OS_EXIT_CRITICAL(); /* Yes */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -