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

Generated by: LCOV version 2.0-1