μC/OS-II—Task management 1 (os_task.c)

Directory

  • task management
    • Task creation
    • Task creation (extension)
    • Task deletion
      • Implementation principle
    • Request to delete Task

Task management

Task creation

#if OS_TASK_CREATE_EN > 0u
INT8U OSTaskCreate (void (*task) (void *p_arg),
void *p_arg,
OS_STK *ptos,
INT8U prio)
{<!-- -->
OS_STK *psp;
INT8U err;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
\t
if (OSSafetyCriticalStartFlag == OS_TRUE)
{<!-- -->
OS_SAFETY_CRITICAL_EXCEPTION();
return (OS_ERR_ILLEGAL_CREATE_RUN_TIME);
}
\t
#endif
#if OS_ARG_CHK_EN > 0u
\t
if (prio > OS_LOWEST_PRIO) /* Make sure priority is within allowable range */
{<!-- -->
return (OS_ERR_PRIO_INVALID);
}
\t
#endif
OS_ENTER_CRITICAL();
\t
if (OSIntNesting > 0u) /* Make sure we don't create the task from within an ISR */
{<!-- -->
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_CREATE_ISR);
}
\t
if (OSTCBPrioTbl[prio] == (OS_TCB *)0) /* Make sure task doesn't already exist at this priority */
{<!-- -->
OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */
/* ... the same thing until task is created. */
OS_EXIT_CRITICAL();
psp = OSTaskStkInit (task, p_arg, ptos, 0u); /* Initialize the task's stack */
err = OS_TCBInit (prio, psp, (OS_STK *)0, 0u, 0u, (void *)0, 0u);
\t\t
if (err == OS_ERR_NONE)
{<!-- -->
if (OSRunning == OS_TRUE) /* Find highest priority task if multitasking has started */
{<!-- -->
OS_Sched();
}
}
\t\t
else
{<!-- -->
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */
OS_EXIT_CRITICAL();
}
\t\t
return (err);
}
\t
OS_EXIT_CRITICAL();
return (OS_ERR_PRIO_EXIST);
}
#endif

Task creation (extension)

#if OS_TASK_CREATE_EXT_EN > 0u
INT8U OSTaskCreateExt (void (*task) (void *p_arg),
void *p_arg,
OS_STK *ptos,
INT8U prio,
INT16Uid,
OS_STK *pbos,
INT32U stk_size,
void *pext,
INT16U opt)
{<!-- -->
OS_STK *psp;
INT8U err;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
\t
if (OSSafetyCriticalStartFlag == OS_TRUE)
{<!-- -->
OS_SAFETY_CRITICAL_EXCEPTION();
return (OS_ERR_ILLEGAL_CREATE_RUN_TIME);
}
\t
#endif
#if OS_ARG_CHK_EN > 0u
\t
if (prio > OS_LOWEST_PRIO) /* Make sure priority is within allowable range */
{<!-- -->
return (OS_ERR_PRIO_INVALID);
}
\t
#endif
OS_ENTER_CRITICAL();
\t
if (OSIntNesting > 0u) /* Make sure we don't create the task from within an ISR */
{<!-- -->
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_CREATE_ISR);
}
\t
if (OSTCBPrioTbl[prio] == (OS_TCB *)0) /* Make sure task doesn't already exist at this priority */
{<!-- -->
OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */
/* ... the same thing until task is created. */
OS_EXIT_CRITICAL();
#if (OS_TASK_STAT_STK_CHK_EN > 0u)
OS_TaskStkClr (pbos, stk_size, opt); /* Clear the task stack (if needed) */
#endif
psp = OSTaskStkInit (task, p_arg, ptos, opt); /* Initialize the task's stack */
err = OS_TCBInit (prio, psp, pbos, id, stk_size, pext, opt);
\t\t
if (err == OS_ERR_NONE)
{<!-- -->
if (OSRunning == OS_TRUE) /* Find HPT if multitasking has started */
{<!-- -->
OS_Sched();
}
}
\t\t
else
{<!-- -->
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Make this priority avail. to others */
OS_EXIT_CRITICAL();
}
\t\t
return (err);
}
\t
OS_EXIT_CRITICAL();
return (OS_ERR_PRIO_EXIST);
}
#endif

Task deletion

Implementation principle

  • In ucos2, the task deletion is generally: the task deletes itself, because if A deletes B, the memory resources occupied by B will not be released.
  • If A wants to delete B, it needs to: First call OSTaskDelReq (B’s priority) to request task B to delete itself; B Check through OSTaskDelReq (INT8U prio) function Whether there are other tasks requesting to delete itself, if so, use the OSTaskDel (INT8U prio) function to delete itself.
#if OS_TASK_DEL_EN > 0u
INT8U OSTaskDel (INT8U prio)
{<!-- -->
#if (OS_FLAG_EN > 0u) & amp; & amp; (OS_MAX_FLAGS > 0u)
OS_FLAG_NODE *pnode;
#endif
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
\t
if (OSIntNesting > 0u) /* See if trying to delete from ISR */
{<!-- -->
return (OS_ERR_TASK_DEL_ISR);
}
\t
if (prio == OS_TASK_IDLE_PRIO) /* Not allowed to delete idle task */
{<!-- -->
return (OS_ERR_TASK_DEL_IDLE);
}
\t
#if OS_ARG_CHK_EN > 0u
\t
if (prio >= OS_LOWEST_PRIO) /* Task priority valid? */
{<!-- -->
if (prio != OS_PRIO_SELF)
{<!-- -->
return (OS_ERR_PRIO_INVALID);
}
}
\t
#endif
/*$PAGE*/
OS_ENTER_CRITICAL();
\t
if (prio == OS_PRIO_SELF) /* See if requesting to delete self */
{<!-- -->
prio = OSTCBCur->OSTCBPrio; /* Set priority to delete to current */
}
\t
ptcb = OSTCBPrioTbl[prio];
\t
if (ptcb == (OS_TCB *)0) /* Task to delete must exist */
{<!-- -->
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST);
}
\t
if (ptcb == OS_TCB_RESERVED) /* Must not be assigned to Mutex */
{<!-- -->
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_DEL);
}
\t
OSRdyTbl[ptcb->OSTCBY] & amp;= (OS_PRIO)~ptcb->OSTCBBitX;
\t
if (OSRdyTbl[ptcb->OSTCBY] == 0u) /* Make task not ready */
{<!-- -->
OSRdyGrp & amp;= (OS_PRIO)~ptcb->OSTCBBitY;
}
\t
#if (OS_EVENT_EN)
\t
if (ptcb->OSTCBEventPtr != (OS_EVENT *)0)
{<!-- -->
OS_EventTaskRemove (ptcb, ptcb->OSTCBEventPtr); /* Remove this task from any event wait list */
}
\t
#if (OS_EVENT_MULTI_EN > 0u)
\t
if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) /* Remove this task from any events' wait lists*/
{<!-- -->
OS_EventTaskRemoveMulti (ptcb, ptcb->OSTCBEventMultiPtr);
}
\t
#endif
#endif
#if (OS_FLAG_EN > 0u) & amp; & amp; (OS_MAX_FLAGS > 0u)
pnode = ptcb->OSTCBFlagNode;
\t
if (pnode != (OS_FLAG_NODE *)0) /* If task is waiting on event flag */
{<!-- -->
OS_FlagUnlink (pnode); /* Remove from wait list */
}
\t
#endif
ptcb->OSTCBDly = 0u; /* Prevent OSTimeTick() from updating */
ptcb->OSTCBStat = OS_STAT_RDY; /* Prevent task from being resumed */
ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
\t
if (OSLockNesting < 255u) /* Make sure we don't context switch */
{<!-- -->
OSLockNesting + + ;
}
\t
OS_EXIT_CRITICAL(); /* Enabling INT. ignores next instruc. */
OS_Dummy(); /* ... Dummy ensures that INTs will be */
OS_ENTER_CRITICAL(); /* ... disabled HERE! */
\t
if (OSLockNesting > 0u) /* Remove context switch lock */
{<!-- -->
OSLockNesting--;
}
\t
OSTaskDelHook (ptcb); /* Call user defined hook */
OSTaskCtr--; /* One less task being managed */
OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Clear old priority entry */
\t
if (ptcb->OSTCBPrev == (OS_TCB *)0) /* Remove from TCB chain */
{<!-- -->
ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0;
OSTCBList = ptcb->OSTCBNext;
}
\t
else
{<!-- -->
ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
}
\t
ptcb->OSTCBNext = OSTCBFreeList; /* Return TCB to free TCB list */
OSTCBFreeList = ptcb;
#if OS_TASK_NAME_EN > 0u
ptcb->OSTCBTaskName = (INT8U *) (void *)"?";
#endif
OS_EXIT_CRITICAL();
\t
if (OSRunning == OS_TRUE)
{<!-- -->
OS_Sched(); /* Find new highest priority task */
}
\t
return (OS_ERR_NONE);
}

Request to delete Task

#if OS_TASK_DEL_EN > 0u
INT8U OSTaskDelReq (INT8U prio)
{<!-- -->
INT8Ustat;
OS_TCB *ptcb;
#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr = 0u;
#endif
\t
if (prio == OS_TASK_IDLE_PRIO) /* Not allowed to delete idle task */
{<!-- -->
return (OS_ERR_TASK_DEL_IDLE);
}
\t
#if OS_ARG_CHK_EN > 0u
\t
if (prio >= OS_LOWEST_PRIO) /* Task priority valid? */
{<!-- -->
if (prio != OS_PRIO_SELF)
{<!-- -->
return (OS_ERR_PRIO_INVALID);
}
}
\t
#endif
\t
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);
}
\t
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio];
\t
if (ptcb == (OS_TCB *)0) /* Task to delete must exist */
{<!-- -->
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST); /* Task must already be deleted */
}
\t
if (ptcb == OS_TCB_RESERVED) /* Must NOT be assigned to a Mutex */
{<!-- -->
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_DEL);
}
\t
ptcb->OSTCBDelReq = OS_ERR_TASK_DEL_REQ; /* Set flag indicating task to be DEL. */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
}
#endif