LCOV - code coverage report
Current view: top level - atrace/utrace/ringbuffer - trace_rb_log.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.8 % 292 268
Test Date: 2026-07-28 10:53:44 Functions: 100.0 % 20 20

            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 "trace_rb_log.h"
      12              : #include "trace_system_api.h"
      13              : #include "adiag_print.h"
      14              : #include "adiag_utils.h"
      15              : #include "trace_attr.h"
      16              : #include "securec.h"
      17              : #include "trace_types.h"
      18              : #include "adiag_list.h"
      19              : 
      20              : #define AVERAGE(a, b) (((a) + (b)) >> 1)
      21              : #define MIN(a, b) ((a) > (b) ? (b) : (a))
      22              : #define AO_F_ADD(ptr, value)        ((__typeof__(*(ptr)))__sync_fetch_and_add((ptr), (value)))
      23              : #define AO_SUB_F(ptr, value)        ((__typeof__(*(ptr)))__sync_sub_and_fetch((ptr), (value)))
      24              : #define AO_SET(ptr, value)          ((void)__sync_lock_test_and_set((ptr), (value)))
      25              : #define AO_CASB(ptr, comp, value)   (__sync_bool_compare_and_swap((ptr), (comp), (value)))
      26              : #define MAX_RING_BUFFER_SIZE 1024U
      27              : #define MIN_RING_BUFFER_SIZE 1U
      28              : #define MAX_MSG_SIZE 1024U
      29              : #define MIN_MSG_SIZE 64U
      30              : #define MAX_RING_BUFFER_SPACE 131072U // 128M
      31              : 
      32         1876 : STATIC INLINE void TraceRbLogInitTime(struct RbLogCtrl *head)
      33              : {
      34         1876 :     uint64_t realTime1 = GetRealTime();
      35         1876 :     uint64_t monotonicTime1 = GetCpuCycleCounter();
      36         1876 :     uint64_t monotonicTime2 = GetCpuCycleCounter();
      37         1876 :     uint64_t realTime2 = GetRealTime();
      38         1876 :     head->realTime = AVERAGE(realTime1, realTime2);
      39         1876 :     head->monotonicTime = AVERAGE(monotonicTime1, monotonicTime2);
      40         1876 :     if (TraceGetTimeOffset(&head->minutesWest) != TRACE_SUCCESS) {
      41           20 :         ADIAG_WAR("can not get time offset.");
      42              :     }
      43         1876 :     head->cpuFreq = GetCpuFrequency();
      44         1876 :     ADIAG_INF("init ring buffer time finished, realTime %llu, monotonicTime %llu, freq %llu kHz, minutesWest %d minutes",
      45              :         head->realTime, head->monotonicTime, head->cpuFreq, head->minutesWest);
      46         1876 : }
      47              : 
      48         2120 : STATIC bool TraceRbLogCheckParam(const char *name, const TraceAttr *attr)
      49              : {
      50         2120 :     ADIAG_CHK_NULL_PTR(name, return false);
      51         2120 :     ADIAG_CHK_NULL_PTR(attr, return false);
      52         2120 :     if ((attr->msgNum != 0) && (attr->msgNum > MAX_RING_BUFFER_SIZE || attr->msgNum < MIN_RING_BUFFER_SIZE)) {
      53           40 :         ADIAG_ERR("[%s] msg num %u out of range [%u, %u]",
      54              :             name, attr->msgNum, MIN_RING_BUFFER_SIZE, MAX_RING_BUFFER_SIZE);
      55           40 :         return false;
      56              :     }
      57         2080 :     if ((attr->msgSize != 0) && (attr->msgSize > MAX_MSG_SIZE || attr->msgSize < MIN_MSG_SIZE)) {
      58           40 :         ADIAG_ERR("[%s] msg size %u out of range [%u, %u] bytes", name, attr->msgSize, MIN_MSG_SIZE, MAX_MSG_SIZE);
      59           40 :         return false;
      60              :     }
      61         2040 :     return true;
      62              : }
      63              : 
      64         1876 : STATIC INLINE TraStatus TraceRbLogInitDataStruct(struct RbLog *rb, const TraceAttr *attr)
      65              : {
      66        20636 :     for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
      67        18760 :         if (attr->handle[i] == NULL) {
      68        18568 :             continue;
      69              :         }
      70          192 :         if (attr->handle[i]->list == NULL) {
      71            0 :             ADIAG_ERR("[%s] struct list is invalid.", attr->handle[i]->name);
      72            0 :             return TRACE_FAILURE;
      73              :         }
      74          192 :         errno_t ret = strcpy_s(rb->entry[i].name, TRACE_NAME_LENGTH, attr->handle[i]->name);
      75          192 :         if (ret != EOK) {
      76            0 :             ADIAG_ERR("[%s] strncpy_s data struct name failed.", attr->handle[i]->name);
      77            0 :             return TRACE_FAILURE;
      78              :         }
      79          192 :         rb->entry[i].list = attr->handle[i]->list;
      80          192 :         attr->handle[i]->list = NULL;
      81              :     }
      82         1876 :     return TRACE_SUCCESS;
      83              : }
      84              : 
      85              : /**
      86              :  * @brief       create log ringbuffer
      87              :  * @param [in]  name:       ringbuffer name
      88              :  * @param [in]  bufSize:    ringbuffer size
      89              :  * @return      ring buffer ptr
      90              :  */
      91         2120 : struct RbLog *TraceRbLogCreate(const char *name, const TraceAttr *attr)
      92              : {
      93         2120 :     if (!TraceRbLogCheckParam(name, attr)) {
      94           80 :         return NULL;
      95              :     }
      96         2040 :     uint32_t bufferSize = (attr->msgNum == 0) ? DEFAULT_ATRACE_MSG_NUM : attr->msgNum;
      97         2040 :     uint32_t msgTxtSize = (attr->msgSize == 0) ? DEFAULT_ATRACE_MSG_SIZE : attr->msgSize;
      98              : 
      99         2040 :     if ((bufferSize & (bufferSize - 1U)) != 0) { // bufSize if not power of 2
     100           40 :         bufferSize = GetNearestPowerOfTwo(bufferSize);
     101           40 :         ADIAG_WAR("[%s] buffer size if not power of 2, resize to %u bytes", name, bufferSize);
     102              :     }
     103         2040 :     uint32_t msgSize = msgTxtSize + (uint32_t)sizeof(RbMsgHead);
     104         2040 :     size_t totalSize = (size_t)msgSize * bufferSize;
     105         2040 :     if (msgSize * bufferSize > MAX_RING_BUFFER_SPACE) {
     106           40 :         ADIAG_ERR("[%s] buffer space %zu bytes exceed max buffer space %u bytes", name, totalSize, MAX_RING_BUFFER_SPACE);
     107           40 :         return NULL;
     108              :     }
     109         2000 :     totalSize += sizeof(RbLog);
     110         2000 :     struct RbLog *rb = AdiagMalloc(totalSize);
     111         2000 :     if (rb == NULL) {
     112           42 :         ADIAG_ERR("[%s] malloc ring buffer failed.", name);
     113           42 :         return NULL;
     114              :     }
     115         1958 :     struct RbLogCtrl *head = &rb->head;
     116         1958 :     errno_t ret = strcpy_s(head->name, sizeof(head->name), name);
     117         1958 :     if (ret != EOK) {
     118           82 :         ADIAG_ERR("[%s] strcpy_s ring buffer name failed, ret : %d.", name, ret);
     119           82 :         ADIAG_SAFE_FREE(rb);
     120           82 :         return NULL;
     121              :     }
     122         1876 :     if (TraceRbLogInitDataStruct(rb, attr) != TRACE_SUCCESS) {
     123            0 :         ADIAG_ERR("[%s] init data struct failed.", name);
     124            0 :         ADIAG_SAFE_FREE(rb);
     125            0 :         return NULL;
     126              :     }
     127         1876 :     head->readIdx = 0;
     128         1876 :     head->writeIdx = 0;
     129         1876 :     head->bufSize = bufferSize;
     130         1876 :     head->msgSize = msgSize;
     131         1876 :     head->msgTxtSize = msgTxtSize;
     132         1876 :     head->mask = bufferSize - 1U;
     133         1876 :     head->errCount = 0;
     134         1876 :     TraceRbLogInitTime(head);
     135         1876 :     ADIAG_INF("[%s] create ring buffer successfully, "
     136              :         "msgSize %u bytes, msgTxtSize %u bytes, bufferSize %u bytes, msg space %u bytes, total space %zu bytes",
     137              :         name, msgSize, msgTxtSize, bufferSize, msgSize, totalSize);
     138         1876 :     return rb;
     139              : }
     140              : 
     141              : /**
     142              :  * @brief       destroy log ringbuffer
     143              :  * @param [in]  rb:         ringbuffer ptr
     144              :  * @return      NA
     145              :  */
     146         2113 : void TraceRbLogDestroy(struct RbLog *rb)
     147              : {
     148         2113 :     if (rb != NULL) {
     149        20581 :         for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
     150        18710 :             if (rb->entry[i].list != NULL) {
     151          190 :                 (void)AdiagListDestroy((struct AdiagList *)rb->entry[i].list);
     152          190 :                 ADIAG_SAFE_FREE(rb->entry[i].list);
     153              :             }
     154              :         }
     155         1871 :         ADIAG_SAFE_FREE(rb);
     156              :     }
     157         2113 : }
     158              : 
     159      6414118 : STATIC INLINE RbLogMsg *TraceRbLogGetMsgByIndex(struct RbLog *rb, uint32_t msgIndex)
     160              : {
     161      6414118 :     return (RbLogMsg *)(rb->msg + rb->head.msgSize * msgIndex);
     162              : }
     163              : 
     164              : /**
     165              :  * @brief       write log msg to ringbuffer
     166              :  * @param [in]  rb:         ringbuffer ptr, caller guarantees not be NULL
     167              :  * @param [in]  buffer:     data buffer
     168              :  * @param [in]  bufSize:    data buffer size
     169              :  * @return      TraStatus
     170              :  */
     171      2483308 : TraStatus TraceRbLogWriteRbMsg(struct RbLog *rb, uint8_t bufferType, const char *buffer, uint32_t bufSize)
     172              : {
     173      2483308 :     ADIAG_CHK_NULL_PTR(buffer, return TRACE_INVALID_PARAM);
     174      2483287 :     ADIAG_CHK_EXPR_ACTION(bufSize == 0, return TRACE_INVALID_PARAM, "invalid bufSize 0");
     175      2483267 :     uint32_t txtSize = bufSize;
     176      2483267 :     if (txtSize > rb->head.msgTxtSize) {
     177        81941 :         ADIAG_WAR("[%s] msg size %u bytes exceeded ringbuffer msg size %u bytes, truncated.",
     178              :             rb->head.name, txtSize, rb->head.msgTxtSize);
     179        81941 :         txtSize = rb->head.msgTxtSize;
     180              :     }
     181      2483267 :     uint64_t monotonicTime = GetCpuCycleCounter();
     182      2401067 :     uint64_t originalWriteIdx = AO_F_ADD(&rb->head.writeIdx, 1);
     183      2401067 :     uint32_t writeIdx = (uint32_t)(originalWriteIdx & rb->head.mask);
     184      2401067 :     RbLogMsg *msg = TraceRbLogGetMsgByIndex(rb, writeIdx);
     185      3035507 :     if (!AO_CASB(&msg->head.busy, false, true)) {
     186            0 :         uint32_t errCount = AO_F_ADD(&rb->head.errCount, 1);
     187            0 :         if ((errCount & rb->head.mask) == 0) {
     188            0 :             ADIAG_WAR("[%s] can not write msg [%s] to index %u, buffer is busy", rb->head.name, buffer, writeIdx);
     189              :         }
     190            0 :         return TRACE_FAILURE;
     191              :     }
     192      3035507 :     int32_t ret = memcpy_s(msg->txt, rb->head.msgTxtSize, buffer, txtSize);
     193      2747267 :     if (ret != EOK) {
     194            1 :         ADIAG_ERR("[%s] memcpy_s ringbuffer msg failed.", rb->head.name);
     195           21 :         return TRACE_FAILURE;
     196              :     }
     197      2999646 :     msg->head.cycle = monotonicTime - rb->head.monotonicTime;
     198      2999646 :     msg->head.txtSize = txtSize;
     199      2999646 :     msg->head.bufferType = bufferType;
     200      2999646 :     AO_SET(&msg->head.busy, false);
     201      2999646 :     return TRACE_SUCCESS;
     202              : }
     203              : 
     204           24 : TraStatus TraceRbLogWriteRbMsgNoLock(struct RbLog *rb, uint8_t bufferType, const char *buffer, uint32_t bufSize)
     205              : {
     206           24 :     if ((buffer == NULL) || (bufSize == 0)) {
     207            1 :         return TRACE_INVALID_PARAM;
     208              :     }
     209           23 :     struct RbLogCtrl *head = &rb->head;
     210           23 :     RbLogMsg *msg = (RbLogMsg *)(rb->msg + head->msgSize * (uint32_t)((++head->writeIdx) & head->mask));
     211           23 :     uint32_t txtSize = MIN(bufSize, head->msgTxtSize);
     212              : 
     213           23 :     int32_t ret = memcpy_s(msg->txt, head->msgTxtSize, buffer, txtSize);
     214           23 :     if (ret != EOK) {
     215            1 :         return TRACE_FAILURE;
     216              :     }
     217           22 :     msg->head.cycle = GetCpuCycleCounter() - head->monotonicTime;
     218           22 :     msg->head.txtSize = txtSize;
     219           22 :     msg->head.bufferType = bufferType;
     220           22 :     return TRACE_SUCCESS;
     221              : }
     222              : 
     223      5889406 : STATIC INLINE int RbLogMsgCmp(const void *a, const void *b)
     224              : {
     225      5889406 :     const RbLogMsg *msgA = (const RbLogMsg *)a;
     226      5889406 :     const RbLogMsg *msgB = (const RbLogMsg *)b;
     227      5889406 :     if (msgA->head.busy != msgB->head.busy) {
     228          620 :         return msgA->head.busy ? 1 : 0;     // msgA->head.busy > msgB->head.busy
     229              :     }
     230      5888786 :     return msgA->head.cycle > msgB->head.cycle;
     231              : }
     232              : 
     233      1090600 : STATIC TraStatus TraceRbLogCopyMsg(struct RbLog *newRb, struct RbLog *rb, uint32_t msgIndex)
     234              : {
     235      1090600 :     uint32_t msgTxtSize = rb->head.msgTxtSize;
     236      1090600 :     RbLogMsg *msg = TraceRbLogGetMsgByIndex(rb, msgIndex);
     237      1090600 :     RbLogMsg *newMsg = TraceRbLogGetMsgByIndex(newRb, msgIndex);
     238              : 
     239      1090600 :     uint64_t cycle = msg->head.cycle;
     240      1090600 :     int32_t ret = memcpy_s(&newMsg->txt, msgTxtSize, &msg->txt, msgTxtSize);
     241      1090600 :     if (ret != EOK) {
     242           20 :         ADIAG_ERR("[%s] memcpy_s msg txt failed.", rb->head.name);
     243           20 :         return TRACE_FAILURE;
     244              :     }
     245      1090580 :     ret = memcpy_s(&newMsg->head, sizeof(RbMsgHead), &msg->head, sizeof(RbMsgHead));
     246      1090580 :     if (ret != EOK) {
     247           20 :         ADIAG_ERR("[%s] memcpy_s msg head failed.", rb->head.name);
     248           20 :         return TRACE_FAILURE;
     249              :     }
     250              :     // cycle has changed before memcpy finished, set busy to true to drop data.
     251      1090560 :     if (newMsg->head.cycle != cycle) {
     252           60 :         newMsg->head.busy = true;
     253              :     }
     254      1090560 :     return TRACE_SUCCESS;
     255              : }
     256              : 
     257         1145 : STATIC void TraceRbLogSort(struct RbLog *rb)
     258              : {
     259         1145 :     qsort(rb->msg, rb->head.bufSize, rb->head.msgSize, RbLogMsgCmp);
     260         1145 : }
     261              : 
     262              : /**
     263              :  * @brief           get struct entry list
     264              :  * @param [in/out]  newRb:      new ringbuffer
     265              :  * @param [in]      traList:    trace list of ring buffer
     266              :  * @return          TRACE_SUCCESS  success; TRACE_FAILURE  failure
     267              :  */
     268          128 : STATIC TraStatus TraceRbLogGetStructEntryList(struct AdiagList **newRbList, const struct AdiagList *traList)
     269              : {
     270          128 :     struct AdiagList *newList = (struct AdiagList *)AdiagMalloc(sizeof(struct AdiagList));
     271          128 :     if (newList == NULL) {
     272           20 :         ADIAG_ERR("malloc new ringbuffer list failed.");
     273           20 :         return TRACE_FAILURE;
     274              :     }
     275          108 :     if (AdiagListInit(newList) != TRACE_SUCCESS) {
     276           20 :         ADIAG_ERR("init new ringbuffer list failed.");
     277           20 :         ADIAG_SAFE_FREE(newList);
     278           20 :         return TRACE_FAILURE;
     279              :     }
     280           88 :     struct ListHead *pos = NULL;
     281           88 :     struct AdiagListNode *node = NULL;
     282          400 :     LIST_FOR_EACH(pos, &traList->list) {
     283          352 :         node = LIST_ENTRY(pos, struct AdiagListNode, list);
     284          352 :         if (node == NULL) {
     285            0 :             (void)AdiagListDestroy(newList);
     286            0 :             ADIAG_SAFE_FREE(newList);
     287            0 :             return TRACE_FAILURE;
     288              :         }
     289          352 :         TraceStructField *data = (TraceStructField *)AdiagMalloc(sizeof(TraceStructField));
     290          352 :         if (data == NULL) {
     291           20 :             ADIAG_ERR("malloc struct field failed.");
     292           20 :             (void)AdiagListDestroy(newList);
     293           20 :             ADIAG_SAFE_FREE(newList);
     294           20 :             return TRACE_FAILURE;
     295              :         }
     296          332 :         errno_t ret = memcpy_s(data, sizeof(TraceStructField), node->data, sizeof(TraceStructField));
     297          332 :         if (ret != EOK) {
     298            0 :             ADIAG_ERR("memcpy_s struct field failed.");
     299            0 :             ADIAG_SAFE_FREE(data);
     300            0 :             (void)AdiagListDestroy(newList);
     301            0 :             ADIAG_SAFE_FREE(newList);
     302            0 :             return TRACE_FAILURE;
     303              :         }
     304          332 :         if (AdiagListInsert(newList, data) != ADIAG_SUCCESS) {
     305           20 :             ADIAG_ERR("insert struct list failed.");
     306           20 :             ADIAG_SAFE_FREE(data);
     307           20 :             (void)AdiagListDestroy(newList);
     308           20 :             ADIAG_SAFE_FREE(newList);
     309           20 :             return TRACE_FAILURE;
     310              :         }
     311              :     }
     312           48 :     *newRbList = newList;
     313           48 :     return TRACE_SUCCESS;
     314              : }
     315              : 
     316              : /**
     317              :  * @brief       copy ringbuffer to new buffer and sort valid msg by cycle
     318              :  * @param [out] newRb:      new ringbuffer
     319              :  * @param [in]  rb:         original ringbuffer
     320              :  * @return      TraStatus
     321              :  */
     322         1229 : TraStatus TraceRbLogGetCopyOfRingBuffer(struct RbLog **newRb, struct RbLog *rb)
     323              : {
     324         1229 :     size_t totalSize = sizeof(RbLog) + (size_t)rb->head.bufSize * rb->head.msgSize;
     325         1229 :     *newRb = AdiagMalloc(totalSize);
     326         1229 :     if (*newRb == NULL) {
     327           22 :         ADIAG_ERR("[%s] malloc new ringbuffer failed, size : %zu bytes.", rb->head.name, totalSize);
     328           22 :         return TRACE_FAILURE;
     329              :     }
     330         1207 :     errno_t ret = memcpy_s(*newRb, sizeof(RbLog), rb, sizeof(RbLog));
     331         1207 :     if (ret != EOK) {
     332           22 :         ADIAG_SAFE_FREE(*newRb);
     333           22 :         ADIAG_ERR("[%s] memcpy_s ringbuffer failed.", rb->head.name);
     334           22 :         return TRACE_FAILURE;
     335              :     }
     336      1091745 :     for (uint32_t i = 0; i < rb->head.bufSize; i++) {
     337      1090600 :         if (TraceRbLogCopyMsg(*newRb, rb, i) != TRACE_SUCCESS) {
     338           40 :             ADIAG_SAFE_FREE(*newRb);
     339           40 :             return TRACE_FAILURE;
     340              :         }
     341              :     }
     342         1145 :     TraceRbLogSort(*newRb);
     343              :     // if trace struct not defined, return success
     344         1145 :     struct AdiagList *traList = NULL;
     345        11795 :     for (uint32_t i = 0; i < TRACE_STRUCT_ENTRY_MAX_NUM; i++) {
     346        10730 :         traList = (struct AdiagList *)(rb->entry[i].list);
     347        10730 :         if ((rb->entry[i].list == NULL) || (ListEmpty(&traList->list))) {
     348        10602 :             continue;
     349              :         }
     350          128 :         if (TraceRbLogGetStructEntryList((struct AdiagList **)&(*newRb)->entry[i].list, traList) != TRACE_SUCCESS) {
     351           80 :             ADIAG_SAFE_FREE(*newRb);
     352           80 :             return TRACE_FAILURE;
     353              :         }
     354              :     }
     355         1065 :     return TRACE_SUCCESS;
     356              : }
     357              : 
     358              : /**
     359              :  * @brief       read msg from ringbuffer, must be reentrant, cannot print msg
     360              :  * @param [in]  rb:           ringbuffer
     361              :  * @param [out] timeStr:      timestamp str
     362              :  * @param [out] buffer:       ptr of msg txt in ringbuffer
     363              :  * @return      TraStatus
     364              :  */
     365       364624 : TraStatus TraceRbLogReadRbMsg(struct RbLog *rb, char *timeStr, uint32_t timeStrSize, char **buffer)
     366              : {
     367       364624 :     RbLogMsg *msg = NULL;
     368       960503 :     for (;rb->head.readIdx != rb->head.bufSize; rb->head.readIdx++) {
     369       959508 :         msg = TraceRbLogGetMsgByIndex(rb, rb->head.readIdx);
     370       959508 :         if (msg->head.busy) { // msg has not been written done
     371           60 :             continue;
     372              :         }
     373       959448 :         if (msg->head.txtSize == 0) {
     374       595819 :             continue;
     375              :         }
     376       363629 :         rb->head.readIdx++;
     377       363629 :         double costTime = (double)msg->head.cycle / (double)rb->head.cpuFreq * (double)FREQ_GHZ_TO_KHZ;
     378       363629 :         uint64_t timestamp = (uint64_t)costTime + rb->head.realTime;
     379       363629 :         TraStatus ret = TimestampToStr(timestamp, timeStr, timeStrSize);
     380       363629 :         if (ret != TRACE_SUCCESS) {
     381            0 :             return ret;
     382              :         }
     383       363629 :         uint32_t lastIndex = MIN(msg->head.txtSize, rb->head.msgTxtSize - 1U);
     384       363629 :         msg->txt[lastIndex] = '\0';  // ensure msg must have a string terminator
     385       363629 :         *buffer = msg->txt;
     386       363629 :         return TRACE_SUCCESS;
     387              :     }
     388          995 :     *buffer = NULL;
     389          995 :     return TRACE_RING_BUFFER_EMPTY;
     390              : }
     391              : 
     392              : /**
     393              :  * @brief       read msg from ringbuffer, must be reentrant, cannot print msg
     394              :  * @param [in]  rb:           ringbuffer
     395              :  * @param [out] buffer:       ptr of msg in ringbuffer
     396              :  * @param [out] bufLen:       length of msg in ringbuffer
     397              :  * @return      TraStatus
     398              :  */
     399          149 : TraStatus TraceRbLogReadOriRbMsg(struct RbLog *rb, char **buffer, uint32_t *bufLen)
     400              : {
     401          149 :     RbLogMsg *msg = NULL;
     402        49199 :     for (;rb->head.readIdx != rb->head.bufSize; rb->head.readIdx++) {
     403        49151 :         msg = TraceRbLogGetMsgByIndex(rb, rb->head.readIdx);
     404        49151 :         if (msg->head.txtSize == 0) {
     405        49050 :             continue;
     406              :         }
     407          101 :         rb->head.readIdx++;
     408          101 :         *buffer = (char *)msg;
     409          101 :         *bufLen = rb->head.msgSize;
     410          101 :         return TRACE_SUCCESS;
     411              :     }
     412           48 :     *buffer = NULL;
     413           48 :     *bufLen = 0;
     414           48 :     return TRACE_RING_BUFFER_EMPTY;
     415              : }
     416              : 
     417           82 : void TraceRbLogPrepareForRead(struct RbLog *rb)
     418              : {
     419           82 :     rb->head.readIdx = 0;
     420           82 : }
     421              : 
     422          223 : STATIC RbLogMsg *TraceRbLogGetOldestMsg(struct RbLog *rb, uint64_t *cycle, bool filterBusy)
     423              : {
     424          223 :     RbLogMsg *oldestMsg = NULL;
     425          223 :     RbLogMsg *msg = NULL;
     426       228575 :     for (uint32_t i = 0; i < rb->head.bufSize; i++) {
     427       228352 :         msg = TraceRbLogGetMsgByIndex(rb, i);
     428       228352 :         if (msg->head.txtSize == 0) {
     429       228190 :             continue;
     430              :         }
     431          162 :         if ((filterBusy) && (msg->head.busy)) {
     432            0 :             continue;
     433              :         }
     434          162 :         if (msg->head.cycle <= *cycle) {
     435           21 :             continue;
     436              :         }
     437          141 :         if ((oldestMsg == NULL) || (msg->head.cycle < oldestMsg->head.cycle)) {
     438          141 :             oldestMsg = msg;
     439              :         }
     440              :     }
     441          223 :     if (oldestMsg != NULL) {
     442          141 :         *cycle = oldestMsg->head.cycle;
     443              :     }
     444          223 :     return oldestMsg;
     445              : }
     446              : 
     447              : /**
     448              :  * @brief       read msg from ringbuffer, must be reentrant, cannot print msg
     449              :  * @param [in]  rb:           ringbuffer
     450              :  * @param [out] timeStr:      timestamp str
     451              :  * @param [out] buffer:       ptr of msg txt in ringbuffer
     452              :  * @return      TraStatus
     453              :  */
     454          161 : TraStatus TraceRbLogReadRbMsgSafe(struct RbLog *rb, char *timeStr, uint32_t timeStrSize, char **buffer)
     455              : {
     456          161 :     if (rb->head.readIdx == rb->head.bufSize) {
     457            0 :         return TRACE_RING_BUFFER_EMPTY;
     458              :     }
     459          161 :     uint64_t cycle = 0;
     460          161 :     RbLogMsg *msg = TraceRbLogGetOldestMsg(rb, &cycle, true);
     461          161 :     if (msg == NULL) {
     462           61 :         return TRACE_RING_BUFFER_EMPTY;
     463              :     }
     464          100 :     double costTime = (double)msg->head.cycle / (double)rb->head.cpuFreq * (double)FREQ_GHZ_TO_KHZ;
     465          100 :     uint64_t timestamp = (uint64_t)costTime + rb->head.realTime;
     466          100 :     TraStatus ret = TimestampToStr(timestamp, timeStr, timeStrSize);
     467          100 :     if (ret != TRACE_SUCCESS) {
     468            0 :         return ret;
     469              :     }
     470          100 :     uint32_t lastIndex = MIN(msg->head.txtSize, rb->head.msgTxtSize - 1U);
     471          100 :     msg->txt[lastIndex] = '\0';  // ensure msg must have a string terminator
     472          100 :     *buffer = msg->txt;
     473          100 :     msg->head.txtSize = 0;
     474          100 :     rb->head.readIdx++;
     475          100 :     return TRACE_SUCCESS;
     476              : }
     477              : 
     478              : /**
     479              :  * @brief       read msg from ringbuffer, must be reentrant, cannot print msg
     480              :  * @param [in]  rb:           ringbuffer
     481              :  * @param [out] buffer:       ptr of msg in ringbuffer
     482              :  * @param [out] bufLen:       length of msg in ringbuffer
     483              :  * @return      TraStatus
     484              :  */
     485           62 : TraStatus TraceRbLogReadOriRbMsgSafe(struct RbLog *rb, char **buffer, uint32_t *bufLen, uint64_t *cycle)
     486              : {
     487           62 :     if (rb->head.readIdx == rb->head.bufSize) {
     488            0 :         return TRACE_RING_BUFFER_EMPTY;
     489              :     }
     490           62 :     RbLogMsg *msg = TraceRbLogGetOldestMsg(rb, cycle, false);
     491           62 :     if (msg == NULL) {
     492           21 :         return TRACE_RING_BUFFER_EMPTY;
     493              :     }
     494           41 :     *buffer = (char *)msg;
     495           41 :     *bufLen = rb->head.msgSize;
     496           41 :     rb->head.readIdx++;
     497           41 :     return TRACE_SUCCESS;
     498              : }
     499              : 
     500           98 : uint32_t TracerRbLogGetMsgNum(const RbLog *rb)
     501              : {
     502           98 :     return (rb->head.writeIdx > (uint64_t)rb->head.bufSize) ? rb->head.bufSize : (uint32_t)rb->head.writeIdx;
     503              : }
        

Generated by: LCOV version 2.0-1