LCOV - code coverage report
Current view: top level - common - adiag_list.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 72.9 % 155 113
Test Date: 2026-07-28 10:53:44 Functions: 76.9 % 13 10

            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         5617 : AdiagStatus AdiagListInit(struct AdiagList *traList)
      21              : {
      22         5617 :     AdiagStatus ret = ADIAG_FAILURE;
      23         5617 :     if (traList != NULL) {
      24         5617 :         INIT_LIST_HEAD(&traList->list);
      25         5617 :         traList->cnt = 0;
      26         5617 :         ret = AdiagLockInit(&traList->lock);
      27         5617 :         traList->valid = ((ret == ADIAG_SUCCESS) ? true : false);
      28              :     }
      29              : 
      30         5617 :     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         4350 : AdiagStatus AdiagListDestroy(struct AdiagList *traList)
      39              : {
      40         4350 :     AdiagStatus ret = ADIAG_SUCCESS;
      41              : 
      42         4350 :     if ((traList != NULL) && (traList->valid == true)) {
      43         3898 :         void *data = AdiagListTakeOut(traList);
      44         5034 :         while (data != NULL) {
      45         1136 :             ADIAG_SAFE_FREE(data);
      46         1136 :             data = AdiagListTakeOut(traList);
      47              :         }
      48              : 
      49         3898 :         ret = AdiagLockDestroy(&traList->lock);
      50              :     }
      51              : 
      52         4350 :     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         4292 : AdiagStatus AdiagListInsert(struct AdiagList *traList, void *data)
      62              : {
      63         4292 :     ADIAG_CHK_NULL_PTR(traList, return ADIAG_FAILURE);
      64         4292 :     ADIAG_CHK_NULL_PTR(data, return ADIAG_FAILURE);
      65              : 
      66         4292 :     struct AdiagListNode *node = AdiagMalloc(sizeof(struct AdiagListNode));
      67         4292 :     if (node == NULL) {
      68           56 :         ADIAG_ERR("malloc list node failed.");
      69           56 :         return ADIAG_FAILURE;
      70              :     }
      71              : 
      72         4236 :     INIT_LIST_HEAD(&node->list);
      73         4236 :     node->data = data;
      74              : 
      75         4236 :     (void)AdiagLockGet(&traList->lock);
      76         4236 :     if (traList->cnt < (UINT32_MAX - 1U)) {
      77         4236 :         ListAddBeforeEntry(&node->list, &traList->list);
      78         4236 :         traList->cnt++;
      79         4236 :         (void)AdiagLockRelease(&traList->lock);
      80         4236 :         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         8278 : void *AdiagListTakeOut(struct AdiagList *traList)
      95              : {
      96         8278 :     ADIAG_CHK_NULL_PTR(traList, return NULL);
      97              : 
      98         8278 :     void *data = NULL;
      99         8278 :     struct AdiagListNode *node = NULL;
     100         8278 :     (void)AdiagLockGet(&traList->lock);
     101         8278 :     if (!ListEmpty(&traList->list)) {
     102         2906 :         node = LIST_FIRST_ENTRY(&traList->list, struct AdiagListNode, list);
     103         2906 :         if (node != NULL) {
     104         2906 :             ListDelEntry(&node->list);
     105         2906 :             traList->cnt--;
     106         2906 :             data = node->data;
     107              :         }
     108              :     }
     109         8278 :     (void)AdiagLockRelease(&traList->lock);
     110              : 
     111         8278 :     ADIAG_SAFE_FREE(node);
     112         8278 :     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          595 : void AdiagListForEachTraverse(struct AdiagList *traList, const AdiagListTraverseFunc func, void *arg)
     122              : {
     123          595 :     if ((traList == NULL) || (func == NULL)) {
     124           40 :         return;
     125              :     }
     126              : 
     127          555 :     struct AdiagListNode *pos = NULL;
     128          555 :     (void)AdiagLockGet(&traList->lock);
     129          570 :     LIST_FOR_EACH_ENTRY(pos, &traList->list, struct AdiagListNode, list) {
     130           15 :         (void)func(pos->data, arg);
     131              :     }
     132          555 :     (void)AdiagLockRelease(&traList->lock);
     133              : }
     134              : 
     135              : /**
     136              :  * @brief       apply specified function on every node in list without lock.
     137              :  * @param [in]  traList:    list ptr
     138              :  * @param [in]  func:       function to be applied
     139              :  * @param [in]  arg:        extra argument for function
     140              :  * @return      NA
     141              :  */
     142            0 : void AdiagListForEachNolock(struct AdiagList *traList, const AdiagListCmpFunc func, const void *arg)
     143              : {
     144            0 :     if ((traList == NULL) || (func == NULL)) {
     145            0 :         return;
     146              :     }
     147              : 
     148            0 :     const struct AdiagListNode *pos = NULL;
     149              : 
     150            0 :     LIST_FOR_EACH_ENTRY(pos, &traList->list, struct AdiagListNode, list) {
     151            0 :         (void)func(pos->data, arg);
     152              :     }
     153              : }
     154              : 
     155      2626074 : STATIC INLINE AdiagStatus AdiagListCmpData(const void *nodeData, const void *data)
     156              : {
     157      2626074 :     if (nodeData == data) {
     158      1314234 :         return ADIAG_SUCCESS;
     159              :     }
     160      1311840 :     return ADIAG_FAILURE;
     161              : }
     162              : 
     163      1314254 : void *AdiagListGetNode(struct AdiagList *traList, const void *data)
     164              : {
     165      1314254 :     return AdiagListForEach(traList, AdiagListCmpData, data);
     166              : }
     167              : 
     168              : /**
     169              :  * @brief apply specified function on every node in list.
     170              :  *        return first data that let function return true
     171              :  * @param [in]  traList: list ptr
     172              :  * @param [in]  func: function to be applied
     173              :  * @param [in]  arg: extra argument for function
     174              :  * @return  data which let function return true
     175              :  */
     176      1321898 : void *AdiagListForEach(struct AdiagList *traList, const AdiagListCmpFunc func, const void *arg)
     177              : {
     178      1321898 :     const struct AdiagListNode *pos = NULL;
     179      1321898 :     void *data = NULL;
     180      1321898 :     ADIAG_CHK_NULL_PTR(traList, return NULL);
     181      1321898 :     ADIAG_CHK_NULL_PTR(func, return NULL);
     182              :     
     183      1321898 :     (void)AdiagLockGet(&traList->lock);
     184      2658686 :     LIST_FOR_EACH_ENTRY(pos, &traList->list, struct AdiagListNode, list) {
     185      2656510 :         if (func(pos->data, arg) == ADIAG_SUCCESS) {
     186      1319722 :             data = pos->data;
     187      1319722 :             break;
     188              :         }
     189              :     }
     190      1321898 :     (void)AdiagLockRelease(&traList->lock);
     191      1321898 :     return (void *)data;
     192              : }
     193              : 
     194              : /**
     195              :  * @brief remove the node that has specified data in list, break if found one
     196              :  * @param [in]  traceList: list ptr
     197              :  * @param [in]  data: data to be removed
     198              :  * @return  0 on success, otherwise -1.
     199              :  */
     200         1272 : AdiagStatus AdiagListRemove(struct AdiagList *traceList, void *data)
     201              : {
     202         1272 :     AdiagStatus ret = ADIAG_FAILURE;
     203         1272 :     struct AdiagListNode *node = NULL;
     204         1272 :     struct ListHead *pos = NULL;
     205              : 
     206         1272 :     ADIAG_CHK_NULL_PTR(traceList, return ADIAG_FAILURE);
     207         1272 :     ADIAG_CHK_NULL_PTR(data, return ADIAG_FAILURE);
     208              : 
     209         1272 :     (void)AdiagLockGet(&traceList->lock);
     210         1272 :     if (!ListEmpty(&traceList->list)) {
     211         1697 :         LIST_FOR_EACH(pos, &traceList->list) {
     212         1697 :             node = LIST_ENTRY(pos, struct AdiagListNode, list);
     213         1697 :             if ((node != NULL) && (node->data == data)) {
     214         1272 :                 ListDelEntry(pos);
     215         1272 :                 traceList->cnt--;
     216         1272 :                 AdiagFree(node);
     217         1272 :                 node = NULL;
     218         1272 :                 ret = ADIAG_SUCCESS;
     219         1272 :                 break;
     220              :             }
     221              :         }
     222              :     }
     223         1272 :     (void)AdiagLockRelease(&traceList->lock);
     224              : 
     225         1272 :     return ret;
     226              : }
     227              : 
     228              : /**
     229              :  * @brief remove all the node that has specified data in list
     230              :  * @param [in]  traceList: list ptr
     231              :  * @param [in]  data: data to be removed
     232              :  * @return  0 on success, otherwise -1.
     233              :  */
     234         1124 : AdiagStatus AdiagListRemoveAll(struct AdiagList *traceList, void *data, const AdiagListElemFunc func)
     235              : {
     236         1124 :     AdiagStatus ret = ADIAG_FAILURE;
     237         1124 :     struct AdiagListNode *node = NULL;
     238         1124 :     struct ListHead *pos = NULL;
     239         1124 :     struct ListHead *tmp = NULL;
     240              : 
     241         1124 :     ADIAG_CHK_NULL_PTR(traceList, return ADIAG_FAILURE);
     242         1124 :     ADIAG_CHK_NULL_PTR(data, return ADIAG_FAILURE);
     243              : 
     244         1124 :     (void)AdiagLockGet(&traceList->lock);
     245         1124 :     if (!ListEmpty(&traceList->list)) {
     246           60 :         LIST_FOR_EACH(pos, &traceList->list) {
     247           40 :             node = LIST_ENTRY(pos, struct AdiagListNode, list);
     248           40 :             if ((node != NULL) && (node->data == data)) {
     249           40 :                 tmp = pos->next;
     250           40 :                 ListDelEntry(pos);
     251           40 :                 traceList->cnt--;
     252           40 :                 if (func != NULL) {
     253            0 :                     func(node->data);
     254              :                 }
     255           40 :                 AdiagFree(node);
     256           40 :                 node = NULL;
     257           40 :                 ret = ADIAG_SUCCESS;
     258           40 :                 pos = tmp->prev;
     259              :             }
     260              :         }
     261              :     }
     262         1124 :     (void)AdiagLockRelease(&traceList->lock);
     263              : 
     264         1124 :     return ret;
     265              : }
     266              : 
     267              : /**
     268              :  * @brief move from oldList to new List
     269              :  * @param [in]  oldList: old list to be move from
     270              :  * @param [in]  newList: new list to be move to
     271              :  * @return  NA
     272              :  */
     273            0 : void AdiagListMove(struct AdiagList *oldList, struct AdiagList *newList)
     274              : {
     275            0 :     void *data = NULL;
     276              :     do {
     277            0 :         data = AdiagListTakeOut(oldList);
     278            0 :         if (data == NULL) {
     279            0 :             break;
     280              :         }
     281            0 :         (void)AdiagListInsert(newList, data);
     282              :     } while (true);
     283            0 : }
     284              : 
     285              : /**
     286              :  * @brief clear all the node that match cmpFunc and do otherFunc if not match
     287              :  * @param [in]  traceList: list ptr
     288              :  * @param [in]  cmpFunc: compare function to check if remove or not
     289              :  * @param [in]  arg: argument of compare function
     290              :  * @param [in]  otherFunc: function do if no need to remove
     291              : 
     292              :  * @return  0 on success, otherwise -1.
     293              :  */
     294            0 : AdiagStatus AdiagListClearAndProcessNoLock(struct AdiagList *traceList, const AdiagListCmpFunc cmpFunc, const void *arg,
     295              :     const AdiagListElemFunc otherFunc)
     296              : {
     297            0 :     AdiagStatus ret = ADIAG_FAILURE;
     298            0 :     struct AdiagListNode *node = NULL;
     299            0 :     struct ListHead *pos = NULL;
     300            0 :     struct ListHead *tmp = NULL;
     301            0 :     void *data = NULL;
     302              : 
     303            0 :     ADIAG_CHK_NULL_PTR(traceList, return ADIAG_FAILURE);
     304              : 
     305            0 :     if (!ListEmpty(&traceList->list)) {
     306            0 :         LIST_FOR_EACH(pos, &traceList->list) {
     307            0 :             node = LIST_ENTRY(pos, struct AdiagListNode, list);
     308            0 :             if (node == NULL) {
     309            0 :                 continue;
     310              :             }
     311            0 :             if (cmpFunc(node->data, arg) == ADIAG_SUCCESS) {
     312            0 :                 tmp = pos->next;
     313            0 :                 ListDelEntry(pos);
     314            0 :                 traceList->cnt--;
     315            0 :                 data = (void *)node->data;
     316            0 :                 pos = tmp->prev;
     317            0 :                 ADIAG_SAFE_FREE(node);
     318            0 :                 ADIAG_SAFE_FREE(data);
     319            0 :                 ret = ADIAG_SUCCESS;
     320            0 :             } else if (otherFunc != NULL) {
     321            0 :                 otherFunc(node->data);
     322              :             } else {
     323              :                 ;
     324              :             }
     325              :         }
     326              :     }
     327              : 
     328            0 :     return ret;
     329              : }
        

Generated by: LCOV version 2.0-1