怎么补网站漏洞,云设计工具,怎样做科技小制作视频网站,山东省建设工程协会网站任务删除函数 源码1. 进入临界区1.1 第一步1.2 第二步1.3 第三步1.4 第四步 2. 获取待删除任务的任务控制块TCB3. 从就绪/延迟列表中删除任务4. 从事件列表中删除任务5. 如果待删除任务是当前运行的任务6. 如果待删除任务是其它任务7. 退出临界区7.1 第一步7.2 第二步7.3 第三步… 任务删除函数 源码1. 进入临界区1.1 第一步1.2 第二步1.3 第三步1.4 第四步 2. 获取待删除任务的任务控制块TCB3. 从就绪/延迟列表中删除任务4. 从事件列表中删除任务5. 如果待删除任务是当前运行的任务6. 如果待删除任务是其它任务7. 退出临界区7.1 第一步7.2 第二步7.3 第三步7.4 第四步 8. 如果待删除的任务不是当前运行的任务9. 如果待删除的任务不是当前运行的任务 介绍FreeRTOS任务删除函数的执行过程逐行分析源代码。要使用任务删除函数vTaskDelete需要配置宏INCLUDE_vTaskDelete为1。删除任务函数vTaskDelete的参数为待删除任务的任务句柄即任务控制块。当函数参数为NULL时代表删除的是调用函数的任务本身即正在运行的任务。 源码
/* 示例在正在运行的任务中调用任务删除函数。*/
vTaskDelete(NULL); /* 任务删除 */
#if ( INCLUDE_vTaskDelete 1 ) /* 需要INCLUDE_vTaskDelete宏配置为1 */void vTaskDelete( TaskHandle_t xTaskToDelete ) /* 函数参数为待删除任务的任务句柄可以用NULL代替当前任务句柄。 */{TCB_t * pxTCB;taskENTER_CRITICAL(); /* 进入临界区本质是关闭全局中断。 */{/* If null is passed in here then it is the calling task that is* being deleted.* 如果在此处传递NULL则删除的是调用函数的任务本身。*/pxTCB prvGetTCBFromHandle( xTaskToDelete );/* Remove task from the ready/delayed list.* 从就绪/延迟列表中删除任务* 如果删除后列表中没有列表项则uxListRemove返回0*//* 将任务控制块的成员状态列表项xStateListItem从列表中移除 */if( uxListRemove( ( pxTCB-xStateListItem ) ) ( UBaseType_t ) 0 ){taskRESET_READY_PRIORITY( pxTCB-uxPriority );}else{mtCOVERAGE_TEST_MARKER();}/* Is the task waiting on an event also?* 任务是否也在等待事件* 任务控制块的成员xEventListItem是否挂载在其他列表中*/if( listLIST_ITEM_CONTAINER( ( pxTCB-xEventListItem ) ) ! NULL ){/* 将事件列表项从等待事件列表中移出 */( void ) uxListRemove( ( pxTCB-xEventListItem ) );}else{mtCOVERAGE_TEST_MARKER();}/* Increment the uxTaskNumber also so kernel aware debuggers can* detect that the task lists need re-generating. This is done before* portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will* not return.* 同时自增uxTaskNumber以便内核感知调试器可以检测到任务列表需要重新生成。* 这是在portPRE_TASK_DELETE_HOOK之前完成的因为在Windows端口中宏不会返回*/uxTaskNumber; /* 任务列表需要重新生成 *//* 删除的是调用任务本身时 */if( pxTCB pxCurrentTCB ){/* A task is deleting itself. This cannot complete within the* task itself, as a context switch to another task is required.* Place the task in the termination list. The idle task will* check the termination list and free up any memory allocated by* the scheduler for the TCB and stack of the deleted task.* 一个任务正在删除自己。* 这无法在任务本身内完成因为需要切换到另一个任务的上下文。* 将任务放入等待结束列表中。* 空闲任务将检查等待结束列表并释放调度器为准备删除任务分配的TCB和堆栈内存。*/vListInsertEnd( xTasksWaitingTermination, ( pxTCB-xStateListItem ) );/* Increment the ucTasksDeleted variable so the idle task knows* there is a task that has been deleted and that it should therefore* check the xTasksWaitingTermination list.* 递增ucTasksDeleted变量以便空闲任务知道有一个任务已被删除* 因此它应该检查xTasksWaitingTermination列表。*/uxDeletedTasksWaitingCleanUp;/* Call the delete hook before portPRE_TASK_DELETE_HOOK() as* portPRE_TASK_DELETE_HOOK() does not return in the Win32 port.* 在调用portPRE_TASK_delete_hook之前调用delete钩子* 因为portPRE_TAS K_delete_ hook在Win32端口中不返回。*/traceTASK_DELETE( pxTCB );/* The pre-delete hook is primarily for the Windows simulator,* in which Windows specific clean up operations are performed,* after which it is not possible to yield away from this task -* hence xYieldPending is used to latch that a context switch is* required.* 预删除挂钩主要用于Windows模拟器* 在该模拟器中执行特定于Windows的清理操作之后不可能放弃此任务* 因此xYieldPending用于锁定需要进行上下文切换。*/portPRE_TASK_DELETE_HOOK( pxTCB, xYieldPending );}else{--uxCurrentNumberOfTasks; /* 当前任务个数自减一 */traceTASK_DELETE( pxTCB );/* Reset the next expected unblock time in case it referred to* the task that has just been deleted.* 重置下一个预期的解锁时间以防它引用了刚刚被删除的任务*/prvResetNextTaskUnblockTime();}}taskEXIT_CRITICAL(); /* 退出临界区本质是开启全局中断 *//* If the task is not deleting itself, call prvDeleteTCB from outside of* critical section. If a task deletes itself, prvDeleteTCB is called* from prvCheckTasksWaitingTermination which is called from Idle task.* 如果任务不是删除自己请从临界区外部调用prvDeleteTCB。* 如果任务删除自己则从空闲任务调用的prvCheckTasksWaitingTermination中调用prvDeleteTCB删除任务*/if( pxTCB ! pxCurrentTCB ){prvDeleteTCB( pxTCB );}/* Force a reschedule if it is the currently running task that has just* been deleted.* 如果删除的是当前正在运行的任务则强制重新开启一次任务调度*/if( xSchedulerRunning ! pdFALSE ) /* 任务调度器正在运行中 */{if( pxTCB pxCurrentTCB ) /* 删除的是当前正在运行的任务 */{configASSERT( uxSchedulerSuspended 0 );portYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();}}}#endif /* INCLUDE_vTaskDelete */1. 进入临界区
taskENTER_CRITICAL(); /* 进入临界区本质是关闭全局中断。 */1.1 第一步
#define taskENTER_CRITICAL() portENTER_CRITICAL() /* 从任务中进入临界区 */1.2 第二步
#define portENTER_CRITICAL() vPortEnterCritical()1.3 第三步
void vPortEnterCritical( void )
{portDISABLE_INTERRUPTS();ulCriticalNesting;
}1.4 第四步
#define portDISABLE_INTERRUPTS() __asm( setc INTM) /* 关闭全局中断 */2. 获取待删除任务的任务控制块TCB
portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB NULL; /* 指向当前运行的任务控制块。 *//** Several functions take a TaskHandle_t parameter that can optionally be NULL,* where NULL is used to indicate that the handle of the currently executing* task should be used in place of the parameter. This macro simply checks to* see if the parameter is NULL and returns a pointer to the appropriate TCB.* 有几个函数接受一个TaskHandle_t参数该参数可以选择设置为NULL* 其中NULL用于表示使用当前正在执行的任务的句柄来代替该参数。* 此宏只是检查参数是否为NULL并返回指向相应TCB的指针。*/
#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) NULL ) ? pxCurrentTCB : ( pxHandle ) )3. 从就绪/延迟列表中删除任务
/* Remove task from the ready/delayed list.* 从就绪/延迟列表中删除任务* 如果删除后列表中没有列表项则返回0*/
if( uxListRemove( ( pxTCB-xStateListItem ) ) ( UBaseType_t ) 0 )
{taskRESET_READY_PRIORITY( pxTCB-uxPriority );
}
else
{mtCOVERAGE_TEST_MARKER();
}/* 从列表中移除待移除的列表项 */
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{/* The list item knows which list it is in. Obtain the list from the list* item.* 从列表项的成员pxContainer可以知道它在哪个列表中。从列表项中获取列表。* */List_t * const pxList pxItemToRemove-pxContainer;/* 将列表项从列表中移除 */pxItemToRemove-pxNext-pxPrevious pxItemToRemove-pxPrevious;pxItemToRemove-pxPrevious-pxNext pxItemToRemove-pxNext;/* Only used during decision coverage testing.* 仅在决策覆盖率测试期间使用。*/mtCOVERAGE_TEST_DELAY();/* Make sure the index is left pointing to a valid item.* 确保索引指向有效项*/if( pxList-pxIndex pxItemToRemove ) /* 如果列表的列表索引号指向待移除的列表项 */{pxList-pxIndex pxItemToRemove-pxPrevious; /* 将索引号指向待移除列表项的前一个列表项 */}else{mtCOVERAGE_TEST_MARKER();}pxItemToRemove-pxContainer NULL; /* 将待删除列表项的成员pxContainer设置为NULL表示其不属于任何列表 */( pxList-uxNumberOfItems )--; /* 列表的列表项个数减一 */return pxList-uxNumberOfItems; /* 返回列表中剩余的列表项个数 */
}4. 从事件列表中删除任务
/* Is the task waiting on an event also?* 任务是否也在等待事件* 任务控制块的成员xEventListItem是否挂载在其他列表中*/
if( listLIST_ITEM_CONTAINER( ( pxTCB-xEventListItem ) ) ! NULL )
{/* 将事件列表项从等待事件列表中移出 */( void ) uxListRemove( ( pxTCB-xEventListItem ) );
}
else
{mtCOVERAGE_TEST_MARKER();
}/** Return the list a list item is contained within (referenced from).* 返回列表项所挂载的列表** param pxListItem The list item being queried. pxListItem表示正在查询的列表项。* return A pointer to the List_t object that references the pxListItem. 指向挂载pxListItem的List_t对象的指针*/
#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )-pxContainer )5. 如果待删除任务是当前运行的任务
将列表项xStateListItem按尾部插入法挂载到xTasksWaitingTermination列表中变量uxDeletedTasksWaitingCleanUp自增一以供空闲任务使用。
/* 删除的是调用任务本身时 */
if( pxTCB pxCurrentTCB )
{/* A task is deleting itself. This cannot complete within the* task itself, as a context switch to another task is required.* Place the task in the termination list. The idle task will* check the termination list and free up any memory allocated by* the scheduler for the TCB and stack of the deleted task.* 一个任务正在删除自己。* 这无法在当前任务执行内部完成因为还需要切换到另一个任务的上下文。* 因此将待删除任务放入等待结束任务列表中。* 空闲任务将检查等待结束任务列表并释放调度器为待删除任务分配的TCB和堆栈内存。*/vListInsertEnd( xTasksWaitingTermination, ( pxTCB-xStateListItem ) );/* Increment the ucTasksDeleted variable so the idle task knows* there is a task that has been deleted and that it should therefore* check the xTasksWaitingTermination list.* 递增ucTasksDeleted变量以便空闲任务知道有一个任务已被删除* 因此它应该检查xTasksWaitingTermination列表。* */uxDeletedTasksWaitingCleanUp;/* Call the delete hook before portPRE_TASK_DELETE_HOOK() as* portPRE_TASK_DELETE_HOOK() does not return in the Win32 port.* 在调用portPRE_TASK_delete_hook之前调用delete钩子* 因为portPRE_TAS K_delete_ hook在Win32端口中不返回。* */traceTASK_DELETE( pxTCB );/* The pre-delete hook is primarily for the Windows simulator,* in which Windows specific clean up operations are performed,* after which it is not possible to yield away from this task -* hence xYieldPending is used to latch that a context switch is* required.* 预删除挂钩主要用于Windows模拟器* 在该模拟器中执行特定于Windows的清理操作之后不可能放弃此任务* 因此xYieldPending用于锁定需要进行上下文切换。* */portPRE_TASK_DELETE_HOOK( pxTCB, xYieldPending );
}6. 如果待删除任务是其它任务
--uxCurrentNumberOfTasks; /* 当前任务个数自减一 */
traceTASK_DELETE( pxTCB );/* Reset the next expected unblock time in case it referred to* the task that has just been deleted.* 重置下一个预期的解锁时间以防它引用了刚刚被删除的任务即下一个解除等待准备运行的任务就是待删除任务。*/
prvResetNextTaskUnblockTime();/* 重置下一个任务解锁时间 */
static void prvResetNextTaskUnblockTime( void )
{if( listLIST_IS_EMPTY( pxDelayedTaskList ) ! pdFALSE ) /* 延迟任务列表是否为空 */{/* The new current delayed list is empty. Set xNextTaskUnblockTime to* the maximum possible value so it is extremely unlikely that the* if( xTickCount xNextTaskUnblockTime ) test will pass until* there is an item in the delayed list.* 当前新的延迟列表为空。将xNextTaskUnblockTime设置为最大可能值*/xNextTaskUnblockTime portMAX_DELAY;}else{/* The new current delayed list is not empty, get the value of* the item at the head of the delayed list. This is the time at* which the task at the head of the delayed list should be removed* from the Blocked state.* 当前新的延迟列表不为空请获取延迟列表头部项目的值。* 此时应将延迟列表开头的任务从“阻塞”状态中删除。* 即准备让下一个被阻塞的任务开始执行*/xNextTaskUnblockTime listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxDelayedTaskList );}
}/** Access macro to determine if a list contains any items. The macro will* only have the value true if the list is empty.* 访问宏以确定列表是否包含任何列表项。只有当列表为空时宏才会具有值true。*/
#define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )-uxNumberOfItems ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /* Points to the delayed task list currently being used. 指向当前正在使用的延迟任务列表*/#define portMAX_DELAY ( TickType_t ) 0xffffffffUL/** Access macro to retrieve the value of the list item at the head of a given list. * 访问宏以检索给定列表开头的列表项的值*/
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )-xListEnd ).pxNext-xItemValue ) /* 末尾列表项的下一个列表项即为头部列表项。 */PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. 在调度程序启动之前已初始化为portMAX_DELAY*/7. 退出临界区
taskEXIT_CRITICAL(); /* 退出临界区本质是开启全局中断 */7.1 第一步
#define taskEXIT_CRITICAL() portEXIT_CRITICAL()7.2 第二步
#define portEXIT_CRITICAL() vPortExitCritical()7.3 第三步
void vPortExitCritical( void )
{ulCriticalNesting--;if( ulCriticalNesting 0 ){portENABLE_INTERRUPTS();}
}7.4 第四步
#define portENABLE_INTERRUPTS() __asm( clrc INTM) /* 打开全局中断 */8. 如果待删除的任务不是当前运行的任务
/* If the task is not deleting itself, call prvDeleteTCB from outside of* critical section. If a task deletes itself, prvDeleteTCB is called* from prvCheckTasksWaitingTermination which is called from Idle task.* 如果任务不是删除自己请从临界区外部调用prvDeleteTCB。* 如果任务删除自己则从空闲任务调用的prvCheckTasksWaitingTermination中调用prvDeleteTCB删除任务*/
if( pxTCB ! pxCurrentTCB )
{prvDeleteTCB( pxTCB );
}/* 删除任务控制块根据分配内存的方式释放TCB和堆栈内存 */
#if ( INCLUDE_vTaskDelete 1 )static void prvDeleteTCB( TCB_t * pxTCB ){/* This call is required specifically for the TriCore port. It must be* above the vPortFree() calls. The call is also used by ports/demos that* want to allocate and clean RAM statically.* 此调用是TriCore端口特有的。它必须位于vPortFree调用之上。* 该调用也被希望静态分配和清理RAM的端口/演示使用。* */portCLEAN_UP_TCB( pxTCB );#if ( ( configUSE_NEWLIB_REENTRANT 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT 1 ) ){/* Free up the memory allocated for the tasks TLS Block. */configDEINIT_TLS_BLOCK( pxCurrentTCB-xTLSBlock );}#endif#if ( ( configSUPPORT_DYNAMIC_ALLOCATION 1 ) ( configSUPPORT_STATIC_ALLOCATION 0 ) ( portUSING_MPU_WRAPPERS 0 ) ){/* The task can only have been allocated dynamically - free both* the stack and TCB.* 该任务只能是被动态分配需要释放堆栈和TCB* */vPortFreeStack( pxTCB-pxStack );vPortFree( pxTCB );}#elif ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ! 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */{/* The task could have been allocated statically or dynamically, so* check what was statically allocated before trying to free the* memory.* 任务可以静态或动态分配因此在尝试释放内存之前请检查静态分配的内容* */if( pxTCB-ucStaticallyAllocated tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ){/* Both the stack and TCB were allocated dynamically, so both* must be freed.* 堆栈和TCB都是动态分配的因此必须释放它们。* */vPortFreeStack( pxTCB-pxStack );vPortFree( pxTCB );}else if( pxTCB-ucStaticallyAllocated tskSTATICALLY_ALLOCATED_STACK_ONLY ){/* Only the stack was statically allocated, so the TCB is the* only memory that must be freed.* 只有堆栈是静态分配的因此TCB是唯一必须释放的内存。* */vPortFree( pxTCB );}else{/* Neither the stack nor the TCB were allocated dynamically, so* nothing needs to be freed.* 堆栈和TCB都不是动态分配的因此不需要释放任何内容* */configASSERT( pxTCB-ucStaticallyAllocated tskSTATICALLY_ALLOCATED_STACK_AND_TCB );mtCOVERAGE_TEST_MARKER();}}#endif /* configSUPPORT_DYNAMIC_ALLOCATION */}#endif /* INCLUDE_vTaskDelete */9. 如果待删除的任务不是当前运行的任务
/* Force a reschedule if it is the currently running task that has just* been deleted.* 如果删除的是当前正在运行的任务则强制重新开启一次任务调度*/
if( xSchedulerRunning ! pdFALSE ) /* 任务调度器正在运行中 */
{if( pxTCB pxCurrentTCB ) /* 删除的是当前正在运行的任务 */{configASSERT( uxSchedulerSuspended 0 );portYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();}
}PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning pdFALSE;#ifndef portYIELD_WITHIN_API#define portYIELD_WITHIN_API portYIELD
#endif#define portYIELD() do{bYield 1; __asm( INTR INT14);}while(0)