/* * FreeRTOS Kernel V10.5.1 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * SPDX-License-Identifier: MIT * */ #include /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining * all the API functions to use the MPU wrappers. That should only be done when * task.h is included from an application file. */ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE #include "FreeRTOS.h" #include "list.h" /* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be * defined for the header files above, but not in this file, in order to * generate the correct privileged Vs unprivileged linkage and placement. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ void vListInitialise(List_t * const pxList) { /* The list structure contains a list item which is used to mark the * end of the list. To initialise the list the list end is inserted * as the only list entry. */ pxList->pxIndex = (ListItem_t *) &(pxList->xListEnd); listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE(&(pxList->xListEnd)); /* The list end value is the highest possible value in the list to * ensure it remains at the end of the list. */ pxList->xListEnd.xItemValue = portMAX_DELAY; /* The list end next and previous pointers point to itself so we know * when the list is empty. */ pxList->xListEnd.pxNext = (ListItem_t *) &(pxList->xListEnd); pxList->xListEnd.pxPrevious = (ListItem_t *) &(pxList->xListEnd); /* Initialize the remaining fields of xListEnd when it is a proper ListItem_t */ #if (configUSE_MINI_LIST_ITEM == 0) { pxList->xListEnd.pvOwner = NULL; pxList->xListEnd.pxContainer = NULL; listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE(&(pxList->xListEnd)); } #endif pxList->uxNumberOfItems = (UBaseType_t)0U; /* Write known values into the list if * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ listSET_LIST_INTEGRITY_CHECK_1_VALUE(pxList); listSET_LIST_INTEGRITY_CHECK_2_VALUE(pxList); } void vListInitialiseItem(ListItem_t * const pxItem) { /* Make sure the list item is not recorded as being on a list. */ pxItem->pxContainer = NULL; /* Write known values into the list item if * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE(pxItem); listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE(pxItem); } /** * pxNewListItem插入到链表的尾部 */ void vListInsertEnd(List_t * const pxList, ListItem_t * const pxNewListItem) { ListItem_t * const pxIndex = pxList->pxIndex; /* Only effective when configASSERT() is also defined, these tests may catch * the list data structures being overwritten in memory. They will not catch * data errors caused by incorrect configuration or use of FreeRTOS. */ listTEST_LIST_INTEGRITY(pxList); listTEST_LIST_ITEM_INTEGRITY(pxNewListItem); /* Insert a new list item into pxList, but rather than sort the list, * makes the new list item the last item to be removed by a call to * listGET_OWNER_OF_NEXT_ENTRY(). */ pxNewListItem->pxNext = pxIndex; pxNewListItem->pxPrevious = pxIndex->pxPrevious; /* Only used during decision coverage testing. */ mtCOVERAGE_TEST_DELAY(); pxIndex->pxPrevious->pxNext = pxNewListItem; pxIndex->pxPrevious = pxNewListItem; /* Remember which list the item is in. */ pxNewListItem->pxContainer = pxList; (pxList->uxNumberOfItems)++; } /** * 将pxNewListItem插入到pxList升序链表 * xItemValue为键值,元素从小到大排列 */ void vListInsert(List_t * const pxList, ListItem_t * const pxNewListItem) { ListItem_t * pxIterator; const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; /* Only effective when configASSERT() is also defined, these tests may catch * the list data structures being overwritten in memory. They will not catch * data errors caused by incorrect configuration or use of FreeRTOS. */ listTEST_LIST_INTEGRITY(pxList); listTEST_LIST_ITEM_INTEGRITY(pxNewListItem); /* Insert the new list item into the list, sorted in xItemValue order. * * If the list already contains a list item with the same item value then the * new list item should be placed after it. This ensures that TCBs which are * stored in ready lists (all of which have the same xItemValue value) get a * share of the CPU. However, if the xItemValue is the same as the back marker * the iteration loop below will not end. Therefore the value is checked * first, and the algorithm slightly modified if necessary. */ if(xValueOfInsertion == portMAX_DELAY) { pxIterator = pxList->xListEnd.pxPrevious; } else { /* 遍历找到链表插入的位置 */ pxIterator = (ListItem_t *) &(pxList->xListEnd); while (pxIterator->pxNext->xItemValue <= xValueOfInsertion) pxIterator = pxIterator->pxNext; } pxNewListItem->pxNext = pxIterator->pxNext; pxNewListItem->pxNext->pxPrevious = pxNewListItem; pxNewListItem->pxPrevious = pxIterator; pxIterator->pxNext = pxNewListItem; /* Remember which list the item is in. This allows fast removal of the * item later. */ pxNewListItem->pxContainer = pxList; (pxList->uxNumberOfItems)++; } /** * 删除pxItemToRemove节点 */ UBaseType_t uxListRemove(ListItem_t * const pxItemToRemove) { /* The list item knows which list it is in. Obtain the list from the list * item. * 找到节点所在的链表 */ 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; } pxItemToRemove->pxContainer = NULL; (pxList->uxNumberOfItems)--; /* 返回剩余节点数 */ return pxList->uxNumberOfItems; }