LCOV - code coverage report
Current view: top level - atrace/trace_server/session_mgr - trace_session_mgr.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.8 % 183 168
Test Date: 2026-07-28 10:53:44 Functions: 100.0 % 15 15

            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              : #include "trace_session_mgr.h"
      11              : #include "adiag_lock.h"
      12              : #include "adiag_print.h"
      13              : #include "trace_system_api.h"
      14              : #include "trace_adx_api.h"
      15              : #include "ascend_hal.h"
      16              : 
      17              : #define MAX_DEV_NUM                 64
      18              : 
      19              : STATIC SessionNode *g_sessionPidDevIdList = NULL;
      20              : STATIC SessionNode *g_sessionPidDevIdDeletedList = NULL;
      21              : STATIC AdiagLock g_sessionLock = TRACE_MUTEX_INITIALIZER;
      22              : 
      23        41876 : void TraceServerSessionLock(void)
      24              : {
      25        41876 :     (void)AdiagLockGet(&g_sessionLock);
      26        41876 : }
      27              : 
      28        41876 : void TraceServerSessionUnlock(void)
      29              : {
      30        41876 :     (void)AdiagLockRelease(&g_sessionLock);
      31        41876 : }
      32              : 
      33           34 : TraStatus TraceServerSessionInit(void)
      34              : {
      35           34 :     return AdiagLockInit(&g_sessionLock);
      36              : }
      37              : 
      38           88 : STATIC void TraceServerListExit(SessionNode *list)
      39              : {
      40           88 :     SessionNode *node = NULL;
      41          104 :     while (list != NULL) {
      42           16 :         node = list;
      43           16 :         list = list->next;
      44           16 :         TraceQueueFree(node->queue);
      45           16 :         ADIAG_SAFE_FREE(node->queue);
      46           16 :         TraceAdxDestroyCommHandle(node->handle);
      47           16 :         ADIAG_SAFE_FREE(node);
      48              :     }
      49           88 : }
      50              :  
      51           44 : void TraceServerSessionExit(void)
      52              : {
      53           44 :     TraceServerSessionLock();
      54           44 :     TraceServerListExit(g_sessionPidDevIdList);
      55           44 :     g_sessionPidDevIdList = NULL;
      56           44 :     TraceServerListExit(g_sessionPidDevIdDeletedList);
      57           44 :     g_sessionPidDevIdDeletedList = NULL;
      58           44 :     TraceServerSessionUnlock();
      59           44 :     AdiagLockDestroy(&g_sessionLock);
      60           44 : }
      61              : 
      62           61 : STATIC SessionNode* TraceServerPopDeletedSessionNode(void)
      63              : {
      64           61 :     SessionNode *tmp = g_sessionPidDevIdDeletedList;
      65           61 :     if (tmp != NULL) {
      66           31 :         g_sessionPidDevIdDeletedList = NULL;
      67              :     }
      68           61 :     return tmp;
      69              : }
      70              : 
      71           69 : STATIC void TraceServerPushDeletedSessionNode(SessionNode *node)
      72              : {
      73           69 :     if (node == NULL) {
      74           32 :         return;
      75              :     }
      76           37 :     if (g_sessionPidDevIdDeletedList == NULL) {
      77           36 :         g_sessionPidDevIdDeletedList = node;
      78           36 :         return;
      79              :     }
      80            1 :     if (node->next != NULL) {
      81              :         // if node is list, insert to global list tail
      82            0 :         SessionNode *tmp = g_sessionPidDevIdDeletedList;
      83            0 :         while (tmp->next != NULL) {
      84            0 :             tmp = tmp->next;
      85              :         }
      86            0 :         tmp->next = node;
      87              :     } else {
      88              :         // if node is single, insert to global list head
      89            1 :         node->next = g_sessionPidDevIdDeletedList;
      90            1 :         g_sessionPidDevIdDeletedList = node;
      91              :     }
      92              : }
      93              : 
      94              : /**
      95              :  * @brief       handle deleted session list node, if node is timeout, free it.
      96              :  * @param [in]  func:         handle function
      97              :  * @return      NA
      98              :  */
      99           61 : void TraceServerHandleDeletedSessionNode(TraceSeverSendDataFunc func)
     100              : {
     101              :     // pop all session nodes which will be deleted
     102           61 :     TraceServerSessionLock();
     103           61 :     SessionNode *sessionNode = TraceServerPopDeletedSessionNode();
     104           61 :     SessionNode *pre = NULL;
     105           61 :     SessionNode *head = sessionNode;
     106          122 :     while (sessionNode != NULL) {
     107              :         // traverse each node
     108           61 :         sessionNode->timeout -= SESSION_TIME_INTERVAL;
     109           61 :         g_sessionPidDevIdDeletedList = sessionNode;
     110           61 :         func(sessionNode, DELETED_SESSION_LIST);
     111           61 :         g_sessionPidDevIdDeletedList = NULL;
     112           61 :         if (sessionNode->timeout <= 0) {
     113            3 :             ADIAG_RUN_INF("session node is timeout, pid = %d.", sessionNode->pid);
     114              :             // session node is timeout, the timeout value is notified by client (libascend_trace.so)
     115              :             // delete node from list
     116            3 :             SessionNode *tmp = sessionNode->next;
     117            3 :             if (pre == NULL) {
     118            3 :                 head = sessionNode->next;
     119              :             } else {
     120            0 :                 pre->next = sessionNode->next;
     121              :             }
     122              :             // free log node
     123            3 :             TraceQueueFree(sessionNode->queue);
     124            3 :             ADIAG_SAFE_FREE(sessionNode->queue);
     125            3 :             TraceAdxDestroyCommHandle(sessionNode->handle);
     126            3 :             ADIAG_SAFE_FREE(sessionNode);
     127            3 :             sessionNode = tmp;
     128              :         } else {
     129           58 :             pre = sessionNode;
     130           58 :             sessionNode = sessionNode->next;
     131              :         }
     132              :     }
     133              :     // push none timeout nodes to the list again
     134           61 :     TraceServerPushDeletedSessionNode(head);
     135           61 :     TraceServerSessionUnlock();
     136           61 : }
     137              : 
     138              : /**
     139              :  * @brief       handle session list node, if handle is invalid, destroy it.
     140              :  * @param [in]  func:         handle function
     141              :  * @return      NA
     142              :  */
     143           74 : void TraceServerHandleSessionNode(TraceSeverSendDataFunc func)
     144              : {
     145           74 :     if (func == NULL) {
     146            0 :         return;
     147              :     }
     148              : 
     149           74 :     SessionNode *tmp = NULL;
     150           74 :     TraceServerSessionLock();
     151           74 :     SessionNode *node = g_sessionPidDevIdList;
     152           74 :     int32_t status = 0; // invalid value
     153           74 :     TraStatus ret = TRACE_SUCCESS;
     154              :     // get the first valid session node
     155           76 :     while (node != NULL) {
     156              :         // if handle is invalid, delete node
     157           15 :         status = 0;
     158           15 :         ret = TraceAdxGetAttrByCommHandle(node->handle, HDC_SESSION_ATTR_STATUS, &status);
     159           15 :         if ((ret != TRACE_SUCCESS) || (status == HDC_SESSION_STATUS_CLOSE)) {
     160            2 :             g_sessionPidDevIdList = node->next;
     161            2 :             TraceAdxDestroyCommHandle(node->handle);
     162            2 :             node->handle = NULL;
     163            2 :             ADIAG_RUN_INF("handle is invalid, release session finished, pid = %d", node->pid);
     164            2 :             tmp = node;
     165            2 :             node = node->next;
     166            2 :             TraceQueueFree(tmp->queue);
     167            2 :             ADIAG_SAFE_FREE(tmp->queue);
     168            2 :             ADIAG_SAFE_FREE(tmp);
     169              :         } else {
     170           13 :             func(node, SESSION_LIST);
     171           13 :             break;
     172              :         }
     173              :     }
     174              : 
     175           75 :     while ((node != NULL) && (node->next != NULL)) {
     176            1 :         status = 0;
     177            1 :         ret = TraceAdxGetAttrByCommHandle(node->next->handle, HDC_SESSION_ATTR_STATUS, &status);
     178            1 :         if ((ret != TRACE_SUCCESS) || (status == HDC_SESSION_STATUS_CLOSE)) {
     179            0 :             TraceAdxDestroyCommHandle(node->next->handle);
     180            0 :             node->next->handle = NULL;
     181            0 :             ADIAG_RUN_INF("handle is invalid, release session finished, pid = %d", node->next->pid);
     182            0 :             tmp = node->next;
     183            0 :             node->next = node->next->next;
     184            0 :             TraceQueueFree(tmp->queue);
     185            0 :             ADIAG_SAFE_FREE(tmp->queue);
     186            0 :             ADIAG_SAFE_FREE(tmp);
     187              :         } else {
     188            1 :             func(node->next, SESSION_LIST);
     189            1 :             node = node->next;
     190              :         }
     191              :     }
     192           74 :     TraceServerSessionUnlock();
     193           74 :     return;
     194              : }
     195              : 
     196        83430 : STATIC SessionNode* TraceServerGetSessionNodeByList(int32_t pid, int32_t devId, SessionNode *list)
     197              : {
     198        83430 :     SessionNode *tmp = list;
     199       104216 :     while (tmp != NULL) {
     200        20829 :         if ((tmp->pid == pid) && (tmp->devId == devId)) {
     201           43 :             return tmp;
     202              :         }
     203        20786 :         tmp = tmp->next;
     204              :     }
     205        83387 :     return NULL;
     206              : }
     207              : 
     208              : /**
     209              :  * @brief       get session node from list by pid and device id.
     210              :  * @param [in]  pid:         pid
     211              :  * @param [in]  devId:       device id
     212              :  * @return      SessionNode
     213              :  */
     214        41716 : SessionNode* TraceServerGetSessionNode(int32_t pid, int32_t devId)
     215              : {
     216        41716 :     if ((devId < 0) || (devId >= MAX_DEV_NUM) || (pid < 0)) {
     217            1 :         ADIAG_ERR("invalid input for session node searching: pid = %d, devId = %d", pid, devId);
     218            1 :         return NULL;
     219              :     }
     220              : 
     221        41715 :     SessionNode *tmp = TraceServerGetSessionNodeByList(pid, devId, g_sessionPidDevIdDeletedList);
     222        41715 :     if (tmp == NULL) {
     223        41715 :         tmp = TraceServerGetSessionNodeByList(pid, devId, g_sessionPidDevIdList);
     224              :     }
     225        41715 :     return tmp;
     226              : }
     227              : 
     228              : /**
     229              :  * @brief       insert session node.
     230              :  * @param [in]  handle:      session handle
     231              :  * @param [in]  pid:         pid
     232              :  * @param [in]  devId:       device id
     233              :  * @param [in]  timeout:     timeout
     234              :  * @return      TraStatus
     235              :  */
     236           25 : TraStatus TraceServerInsertSessionNode(const void *handle, int32_t pid, int32_t devId, int32_t timeout)
     237              : {
     238           25 :     if ((TraceAdxIsCommHandleValid(handle) != TRACE_SUCCESS) || (devId < 0) || (devId >= MAX_DEV_NUM) || (pid < 0)) {
     239            1 :         ADIAG_ERR("invalid input for session node insert: pid = %d, devId = %d", pid, devId);
     240            1 :         return TRACE_INVALID_PARAM;
     241              :     }
     242           24 :     TraceServerSessionLock();
     243           24 :     if (TraceServerGetSessionNode(pid, devId) != NULL) {
     244            1 :         ADIAG_WAR("can not insert session, session has existed.");
     245            1 :         TraceServerSessionUnlock();
     246            1 :         return TRACE_FAILURE;
     247              :     }
     248           23 :     SessionNode *sessionNode = (SessionNode *)AdiagMalloc(sizeof(SessionNode));
     249           23 :     if (sessionNode == NULL) {
     250            1 :         ADIAG_ERR("malloc session node failed, strerr=%s.", strerror(AdiagGetErrorCode()));
     251            1 :         TraceServerSessionUnlock();
     252            1 :         return TRACE_FAILURE;
     253              :     }
     254           22 :     sessionNode->queue = (TraceQueue *)AdiagMalloc(sizeof(TraceQueue));
     255           22 :     if (sessionNode->queue == NULL) {
     256            1 :         ADIAG_ERR("malloc queue failed, strerr=%s.", strerror(AdiagGetErrorCode()));
     257            1 :         TraceServerSessionUnlock();
     258            1 :         ADIAG_SAFE_FREE(sessionNode);
     259            1 :         return TRACE_FAILURE;
     260              :     }
     261           21 :     sessionNode->pid = pid;
     262           21 :     sessionNode->devId = devId;
     263           21 :     sessionNode->handle = handle;
     264           21 :     sessionNode->timeout = timeout;
     265           21 :     TraceQueueInit(sessionNode->queue);
     266           21 :     sessionNode->next = g_sessionPidDevIdList;
     267           21 :     g_sessionPidDevIdList = sessionNode;
     268           21 :     TraceServerSessionUnlock();
     269           21 :     return TRACE_SUCCESS;
     270              : }
     271              : 
     272              : /**
     273              :  * @brief       push session node from session list to deleted session list.
     274              :  * @param [in]  handle:         handle
     275              :  * @param [in]  pid:            pid
     276              :  * @param [in]  devId:          device id
     277              :  * @return      TraStatus
     278              :  */
     279           10 : TraStatus TraceServerDeleteSessionNode(const void *handle, int32_t pid, int32_t devId)
     280              : {
     281           10 :     if ((TraceAdxIsCommHandleValid(handle) != TRACE_SUCCESS) || (devId < 0) || (devId >= MAX_DEV_NUM) || (pid < 0)) {
     282            1 :         ADIAG_ERR("invalid input for session node delete: pid = %d, devId = %d", pid, devId);
     283            1 :         return TRACE_INVALID_PARAM;
     284              :     }
     285            9 :     TraceServerSessionLock();
     286            9 :     if (g_sessionPidDevIdList == NULL) {
     287            1 :         TraceServerSessionUnlock();
     288            1 :         return TRACE_INVALID_DATA;
     289              :     }
     290            8 :     SessionNode *deletedNode = NULL;
     291            8 :     SessionNode *tmp = g_sessionPidDevIdList;
     292            8 :     if ((tmp->pid == pid) && (tmp->devId == devId)) {
     293            5 :         g_sessionPidDevIdList = tmp->next;
     294            5 :         tmp->next = NULL;
     295            5 :         deletedNode = tmp;
     296              :     } else {
     297            3 :         while ((tmp->next != NULL) && ((tmp->next->pid != pid) ||
     298            3 :             (tmp->next->devId != devId))) {
     299            0 :             tmp = tmp->next;
     300              :         }
     301            3 :         if ((tmp->next != NULL) && (tmp->next->pid == pid) &&
     302            3 :             (tmp->next->devId == devId)) {
     303            3 :             deletedNode = tmp->next;
     304            3 :             tmp->next = deletedNode->next;
     305            3 :             deletedNode->next = NULL;
     306              :         }
     307              :     }
     308            8 :     TraceServerPushDeletedSessionNode(deletedNode);
     309            8 :     TraceServerSessionUnlock();
     310            8 :     return TRACE_SUCCESS;
     311              : }
     312              : 
     313           40 : bool TraceIsSessionNodeListNull(void)
     314              : {
     315           40 :     return (g_sessionPidDevIdList == NULL);
     316              : }
     317              : 
     318           40 : bool TraceIsDeletedSessionNodeListNull(void)
     319              : {
     320           40 :     return (g_sessionPidDevIdDeletedList == NULL);
     321              : }
        

Generated by: LCOV version 2.0-1