LCOV - code coverage report
Current view: top level - common - adiag_list.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.5 % 153 140
Test Date: 2026-08-31 10:07:06 Functions: 92.3 % 13 12

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include "adiag_list.h"
      12              : #include "adiag_print.h"
      13              : #include "adiag_utils.h"
      14              : 
      15              : /**
      16              :  * @brief       init circular double linked lists
      17              :  * @param [in]  traList: list holder ptr
      18              :  * @return      AdiagStatus
      19              :  */
      20         6428 : AdiagStatus AdiagListInit(struct AdiagList* traList)
      21              : {
      22         6428 :     AdiagStatus ret = ADIAG_FAILURE;
      23         6428 :     if (traList != NULL) {
      24         6428 :         INIT_LIST_HEAD(&traList->list);
      25         6428 :         traList->cnt = 0;
      26         6428 :         ret = AdiagLockInit(&traList->lock);
      27         6428 :         traList->valid = ((ret == ADIAG_SUCCESS) ? true : false);
      28              :     }
      29              : 
      30         6428 :     return ret;
      31              : }
      32              : 
      33              : /**
      34              :  * @brief       destroy circular doubly linked lists
      35              :  * @param [in]  traList:    list ptr to be destroyed
      36              :  * @return      AdiagStatus
      37              :  */
      38         4890 : AdiagStatus AdiagListDestroy(struct AdiagList* traList)
      39              : {
      40         4890 :     AdiagStatus ret = ADIAG_SUCCESS;
      41              : 
      42         4890 :     if ((traList != NULL) && (traList->valid == true)) {
      43         4400 :         void* data = AdiagListTakeOut(traList);
      44         5637 :         while (data != NULL) {
      45         1237 :             ADIAG_SAFE_FREE(data);
      46         1237 :             data = AdiagListTakeOut(traList);
      47              :         }
      48              : 
      49         4400 :         ret = AdiagLockDestroy(&traList->lock);
      50              :     }
      51              : 
      52         4890 :     return ret;
      53              : }
      54              : 
      55              : /**
      56              :  * @brief       insert new node into list
      57              :  * @param [in]  traList:    list ptr
      58              :  * @param [in]  data:       data to be inserted into list
      59              :  * @return      AdiagStatus
      60              :  */
      61         4813 : AdiagStatus AdiagListInsert(struct AdiagList* traList, void* data)
      62              : {
      63         4813 :     ADIAG_CHK_NULL_PTR(traList, return ADIAG_FAILURE);
      64         4813 :     ADIAG_CHK_NULL_PTR(data, return ADIAG_FAILURE);
      65              : 
      66         4813 :     struct AdiagListNode* node = AdiagMalloc(sizeof(struct AdiagListNode));
      67         4813 :     if (node == NULL) {
      68           64 :         ADIAG_ERR("malloc list node failed.");
      69           64 :         return ADIAG_FAILURE;
      70              :     }
      71              : 
      72         4749 :     INIT_LIST_HEAD(&node->list);
      73         4749 :     node->data = data;
      74              : 
      75         4749 :     (void)AdiagLockGet(&traList->lock);
      76         4749 :     if (traList->cnt < (UINT32_MAX - 1U)) {
      77         4749 :         ListAddBeforeEntry(&node->list, &traList->list);
      78         4749 :         traList->cnt++;
      79         4749 :         (void)AdiagLockRelease(&traList->lock);
      80         4749 :         return ADIAG_SUCCESS;
      81              :     } else {
      82            0 :         AdiagFree(node);
      83            0 :         node = NULL;
      84            0 :         (void)AdiagLockRelease(&traList->lock);
      85            0 :         return ADIAG_FAILURE;
      86              :     }
      87              : }
      88              : 
      89              : /**
      90              :  * @brief       take out oldest node in list and return node data
      91              :  * @param [in]  traList:    list ptr
      92              :  * @return      data ptr which has been taken out
      93              :  */
      94         9404 : void* AdiagListTakeOut(struct AdiagList* traList)
      95              : {
      96         9404 :     ADIAG_CHK_NULL_PTR(traList, return NULL);
      97              : 
      98         9404 :     void* data = NULL;
      99         9404 :     struct AdiagListNode* node = NULL;
     100         9404 :     (void)AdiagLockGet(&traList->lock);
     101         9404 :     if (!ListEmpty(&traList->list)) {
     102         3262 :         node = LIST_FIRST_ENTRY(&traList->list, struct AdiagListNode, list);
     103         3262 :         if (node != NULL) {
     104         3262 :             ListDelEntry(&node->list);
     105         3262 :             traList->cnt--;
     106         3262 :             data = node->data;
     107              :         }
     108              :     }
     109         9404 :     (void)AdiagLockRelease(&traList->lock);
     110              : 
     111         9404 :     ADIAG_SAFE_FREE(node);
     112         9404 :     return (void*)data;
     113              : }
     114              : /**
     115              :  * @brief       apply specified function on every node.
     116              :  * @param [in]  traList:    list ptr
     117              :  * @param [in]  func:       function to be applied
     118              :  * @param [in]  arg:        extra argument for function
     119              :  * @return      NA
     120              :  */
     121          749 : void AdiagListForEachTraverse(struct AdiagList* traList, const AdiagListTraverseFunc func, void* arg)
     122              : {
     123          749 :     if ((traList == NULL) || (func == NULL)) {
     124           44 :         return;
     125              :     }
     126              : 
     127          705 :     struct AdiagListNode* pos = NULL;
     128          705 :     (void)AdiagLockGet(&traList->lock);
     129          746 :     LIST_FOR_EACH_ENTRY(pos, &traList->list, struct AdiagListNode, list) { (void)func(pos->data, arg); }
     130          705 :     (void)AdiagLockRelease(&traList->lock);
     131              : }
     132              : 
     133              : /**
     134              :  * @brief       apply specified function on every node in list without lock.
     135              :  * @param [in]  traList:    list ptr
     136              :  * @param [in]  func:       function to be applied
     137              :  * @param [in]  arg:        extra argument for function
     138              :  * @return      NA
     139              :  */
     140            0 : void AdiagListForEachNolock(struct AdiagList* traList, const AdiagListCmpFunc func, const void* arg)
     141              : {
     142            0 :     if ((traList == NULL) || (func == NULL)) {
     143            0 :         return;
     144              :     }
     145              : 
     146            0 :     const struct AdiagListNode* pos = NULL;
     147              : 
     148            0 :     LIST_FOR_EACH_ENTRY(pos, &traList->list, struct AdiagListNode, list) { (void)func(pos->data, arg); }
     149              : }
     150              : 
     151      2888756 : STATIC INLINE AdiagStatus AdiagListCmpData(const void* nodeData, const void* data)
     152              : {
     153      2888756 :     if (nodeData == data) {
     154      1445732 :         return ADIAG_SUCCESS;
     155              :     }
     156      1443024 :     return ADIAG_FAILURE;
     157              : }
     158              : 
     159      1445754 : void* AdiagListGetNode(struct AdiagList* traList, const void* data)
     160              : {
     161      1445754 :     return AdiagListForEach(traList, AdiagListCmpData, data);
     162              : }
     163              : 
     164              : /**
     165              :  * @brief apply specified function on every node in list.
     166              :  *        return first data that let function return true
     167              :  * @param [in]  traList: list ptr
     168              :  * @param [in]  func: function to be applied
     169              :  * @param [in]  arg: extra argument for function
     170              :  * @return  data which let function return true
     171              :  */
     172      1454760 : void* AdiagListForEach(struct AdiagList* traList, const AdiagListCmpFunc func, const void* arg)
     173              : {
     174      1454760 :     const struct AdiagListNode* pos = NULL;
     175      1454760 :     void* data = NULL;
     176      1454760 :     ADIAG_CHK_NULL_PTR(traList, return NULL);
     177      1454760 :     ADIAG_CHK_NULL_PTR(func, return NULL);
     178              : 
     179      1454760 :     (void)AdiagLockGet(&traList->lock);
     180      2922574 :     LIST_FOR_EACH_ENTRY(pos, &traList->list, struct AdiagListNode, list)
     181              :     {
     182      2920096 :         if (func(pos->data, arg) == ADIAG_SUCCESS) {
     183      1452282 :             data = pos->data;
     184      1452282 :             break;
     185              :         }
     186              :     }
     187      1454760 :     (void)AdiagLockRelease(&traList->lock);
     188      1454760 :     return (void*)data;
     189              : }
     190              : 
     191              : /**
     192              :  * @brief remove the node that has specified data in list, break if found one
     193              :  * @param [in]  traceList: list ptr
     194              :  * @param [in]  data: data to be removed
     195              :  * @return  0 on success, otherwise -1.
     196              :  */
     197         1424 : AdiagStatus AdiagListRemove(struct AdiagList* traceList, void* data)
     198              : {
     199         1424 :     AdiagStatus ret = ADIAG_FAILURE;
     200         1424 :     struct AdiagListNode* node = NULL;
     201         1424 :     struct ListHead* pos = NULL;
     202              : 
     203         1424 :     ADIAG_CHK_NULL_PTR(traceList, return ADIAG_FAILURE);
     204         1424 :     ADIAG_CHK_NULL_PTR(data, return ADIAG_FAILURE);
     205              : 
     206         1424 :     (void)AdiagLockGet(&traceList->lock);
     207         1424 :     if (!ListEmpty(&traceList->list)) {
     208         1891 :         LIST_FOR_EACH(pos, &traceList->list)
     209              :         {
     210         1891 :             node = LIST_ENTRY(pos, struct AdiagListNode, list);
     211         1891 :             if ((node != NULL) && (node->data == data)) {
     212         1424 :                 ListDelEntry(pos);
     213         1424 :                 traceList->cnt--;
     214         1424 :                 AdiagFree(node);
     215         1424 :                 node = NULL;
     216         1424 :                 ret = ADIAG_SUCCESS;
     217         1424 :                 break;
     218              :             }
     219              :         }
     220              :     }
     221         1424 :     (void)AdiagLockRelease(&traceList->lock);
     222              : 
     223         1424 :     return ret;
     224              : }
     225              : 
     226              : /**
     227              :  * @brief remove all the node that has specified data in list
     228              :  * @param [in]  traceList: list ptr
     229              :  * @param [in]  data: data to be removed
     230              :  * @return  0 on success, otherwise -1.
     231              :  */
     232         1262 : AdiagStatus AdiagListRemoveAll(struct AdiagList* traceList, void* data, const AdiagListElemFunc func)
     233              : {
     234         1262 :     AdiagStatus ret = ADIAG_FAILURE;
     235         1262 :     struct AdiagListNode* node = NULL;
     236         1262 :     struct ListHead* pos = NULL;
     237         1262 :     struct ListHead* tmp = NULL;
     238              : 
     239         1262 :     ADIAG_CHK_NULL_PTR(traceList, return ADIAG_FAILURE);
     240         1262 :     ADIAG_CHK_NULL_PTR(data, return ADIAG_FAILURE);
     241              : 
     242         1262 :     (void)AdiagLockGet(&traceList->lock);
     243         1262 :     if (!ListEmpty(&traceList->list)) {
     244           66 :         LIST_FOR_EACH(pos, &traceList->list)
     245              :         {
     246           44 :             node = LIST_ENTRY(pos, struct AdiagListNode, list);
     247           44 :             if ((node != NULL) && (node->data == data)) {
     248           44 :                 tmp = pos->next;
     249           44 :                 ListDelEntry(pos);
     250           44 :                 traceList->cnt--;
     251           44 :                 if (func != NULL) {
     252            0 :                     func(node->data);
     253              :                 }
     254           44 :                 AdiagFree(node);
     255           44 :                 node = NULL;
     256           44 :                 ret = ADIAG_SUCCESS;
     257           44 :                 pos = tmp->prev;
     258              :             }
     259              :         }
     260              :     }
     261         1262 :     (void)AdiagLockRelease(&traceList->lock);
     262              : 
     263         1262 :     return ret;
     264              : }
     265              : 
     266              : /**
     267              :  * @brief move from oldList to new List
     268              :  * @param [in]  oldList: old list to be move from
     269              :  * @param [in]  newList: new list to be move to
     270              :  * @return  NA
     271              :  */
     272            1 : void AdiagListMove(struct AdiagList* oldList, struct AdiagList* newList)
     273              : {
     274            1 :     void* data = NULL;
     275              :     do {
     276            2 :         data = AdiagListTakeOut(oldList);
     277            2 :         if (data == NULL) {
     278            1 :             break;
     279              :         }
     280            1 :         (void)AdiagListInsert(newList, data);
     281              :     } while (true);
     282            1 : }
     283              : 
     284              : /**
     285              :  * @brief clear all the node that match cmpFunc and do otherFunc if not match
     286              :  * @param [in]  traceList: list ptr
     287              :  * @param [in]  cmpFunc: compare function to check if remove or not
     288              :  * @param [in]  arg: argument of compare function
     289              :  * @param [in]  otherFunc: function do if no need to remove
     290              : 
     291              :  * @return  0 on success, otherwise -1.
     292              :  */
     293            1 : AdiagStatus AdiagListClearAndProcessNoLock(
     294              :     struct AdiagList* traceList, const AdiagListCmpFunc cmpFunc, const void* arg, const AdiagListElemFunc otherFunc)
     295              : {
     296            1 :     AdiagStatus ret = ADIAG_FAILURE;
     297            1 :     struct AdiagListNode* node = NULL;
     298            1 :     struct ListHead* pos = NULL;
     299            1 :     struct ListHead* tmp = NULL;
     300            1 :     void* data = NULL;
     301              : 
     302            1 :     ADIAG_CHK_NULL_PTR(traceList, return ADIAG_FAILURE);
     303              : 
     304            1 :     if (!ListEmpty(&traceList->list)) {
     305            2 :         LIST_FOR_EACH(pos, &traceList->list)
     306              :         {
     307            1 :             node = LIST_ENTRY(pos, struct AdiagListNode, list);
     308            1 :             if (node == NULL) {
     309            0 :                 continue;
     310              :             }
     311            1 :             if (cmpFunc(node->data, arg) == ADIAG_SUCCESS) {
     312            1 :                 tmp = pos->next;
     313            1 :                 ListDelEntry(pos);
     314            1 :                 traceList->cnt--;
     315            1 :                 data = (void*)node->data;
     316            1 :                 pos = tmp->prev;
     317            1 :                 ADIAG_SAFE_FREE(node);
     318            1 :                 ADIAG_SAFE_FREE(data);
     319            1 :                 ret = ADIAG_SUCCESS;
     320            0 :             } else if (otherFunc != NULL) {
     321            0 :                 otherFunc(node->data);
     322              :             } else {
     323              :                 ;
     324              :             }
     325              :         }
     326              :     }
     327              : 
     328            1 :     return ret;
     329              : }
        

Generated by: LCOV version 2.0-1