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

Generated by: LCOV version 2.0-1