LCOV - code coverage report
Current view: top level - common - adiag_utils.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 97.0 % 100 97
Test Date: 2026-07-28 10:53:44 Functions: 100.0 % 12 12

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include "adiag_utils.h"
      12              : #include <stdbool.h>
      13              : #include "adiag_print.h"
      14              : #include "adiag_types.h"
      15              : #include "mmpa_api.h"
      16              : #include "adiag_utils.h"
      17              : 
      18              : #define TIME_MS_TO_US       1000U
      19              : #define MAX_QUICK_SORT_LEN  1024
      20              : 
      21        67333 : void *AdiagMalloc(size_t size)
      22              : {
      23        67333 :     ADIAG_CHK_EXPR_ACTION(size == 0, return NULL, "size is 0.");
      24        67333 :     void *ptr = malloc(size);
      25        67333 :     if (ptr == NULL) {
      26            0 :         ADIAG_ERR("malloc failed, size=%zu bytes.", size);
      27            0 :         return NULL;
      28              :     }
      29        67333 :     (void)memset_s(ptr, size, 0, size);
      30        67333 :     return ptr;
      31              : }
      32              : 
      33        73618 : void AdiagFree(void *ptr)
      34              : {
      35        73618 :     if (ptr != NULL) {
      36        67757 :         free(ptr);
      37              :     }
      38        73618 : }
      39              : 
      40          961 : int32_t AdiagGetErrorCode(void)
      41              : {
      42          961 :     return mmGetErrorCode();
      43              : }
      44              : 
      45          275 : AdiagStatus AdiagStrToInt(const char *str, int32_t *num)
      46              : {
      47          275 :     if ((str == NULL) || (num == NULL)) {
      48           40 :         return ADIAG_FAILURE;
      49              :     }
      50              : 
      51          235 :     errno = 0;
      52          235 :     char *endPtr = NULL;
      53          235 :     const int32_t numberBase = 10;
      54          235 :     int64_t ret = strtol(str, &endPtr, numberBase);
      55          235 :     AdiagStatus error = ADIAG_SUCCESS;
      56          235 :     if (((const char *)endPtr == str) || (*endPtr != '\0')) {
      57           20 :         error = ADIAG_FAILURE;
      58          215 :     } else if (((ret == LONG_MIN) || (ret == LONG_MAX)) && (errno == ERANGE)) {
      59            0 :         error = ADIAG_FAILURE;
      60          215 :     } else if (ret <= INT32_MAX) {
      61          215 :         *num = (int32_t)ret;
      62              :     } else {
      63              :         ;
      64              :     }
      65          235 :     return error;
      66              : }
      67              : 
      68              : /**
      69              :  * @brief       get cycle counter
      70              :  * @return      cpu cycles
      71              :  */
      72      2444507 : uint64_t GetCpuCycleCounter(void)
      73              : {
      74              :     uint64_t cycles;
      75              : #ifdef CPU_CYCLE_NO_SUPPORT
      76              :     cycles = 0; // just for tiny compile(without mrrc), will not be executed when running
      77              : #else
      78              : #if defined(__aarch64__)
      79              :     asm volatile("mrs %0, cntvct_el0" : "=r" (cycles));
      80              : #elif defined(__x86_64__)
      81      2444507 :     const int uint32Bits = 32;  // 32 is uint bit count
      82      2444507 :     uint32_t hi = 0;
      83      2444507 :     uint32_t lo = 0;
      84      2444507 :     __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
      85      2454447 :     cycles = ((uint64_t)lo) | (((uint64_t)hi) << uint32Bits);
      86              : #elif defined(__arm__)
      87              :     const int uint32Bits = 32;  // 32 is uint bit count
      88              :     uint32_t hi = 0;
      89              :     uint32_t lo = 0;
      90              :     asm volatile("mrrc p15, 1, %0, %1, c14" : "=r"(lo), "=r"(hi));
      91              :     cycles = ((uint64_t)lo) | (((uint64_t)hi) << uint32Bits);
      92              : #else
      93              :     cycles = 0;
      94              : #endif
      95              : #endif // CPU_CYCLE_NO_SUPPORT
      96      2454447 :     return cycles;
      97              : }
      98              : 
      99              : /**
     100              :  * @brief       get real time
     101              :  * @return      real time, ns
     102              :  */
     103        10489 : uint64_t GetRealTime(void)
     104              : {
     105        10489 :     struct timespec now = {0, 0};
     106        10489 :     (void)clock_gettime(CLOCK_REALTIME, &now);
     107        10489 :     return ((uint64_t)now.tv_sec * SEC_TO_NS) + (uint64_t)now.tv_nsec;
     108              : }
     109              : 
     110              : /**
     111              :  * @brief       get monotonic time, absolute time, which cannot be changed
     112              :  * @return      monotonic time, ns
     113              :  */
     114           46 : uint64_t GetMonotonicTime(void)
     115              : {
     116           46 :     struct timespec now = {0, 0};
     117           46 :     (void)clock_gettime(CLOCK_MONOTONIC_RAW, &now);
     118           46 :     return ((uint64_t)now.tv_sec * SEC_TO_NS) + (uint64_t)now.tv_nsec;
     119              : }
     120              : 
     121              : /**
     122              :  * @brief       get cpu frequency
     123              :  * @return      cpu frequency, kHz
     124              :  */
     125         1876 : uint64_t GetCpuFrequency(void)
     126              : {
     127              :     static uint64_t freq = UINT64_MAX;
     128         1876 :     if (freq == UINT64_MAX) {
     129           23 :         uint64_t startTime = GetMonotonicTime();
     130           23 :         uint64_t startCycle = GetCpuCycleCounter();
     131           23 :         (void)usleep(TIME_MS_TO_US); // sleep 1ms
     132           23 :         uint64_t endCycle = GetCpuCycleCounter();
     133           23 :         uint64_t endTime = GetMonotonicTime();
     134           23 :         freq = (endCycle - startCycle) * FREQ_GHZ_TO_KHZ / (endTime - startTime);
     135              :     }
     136         1876 :     return freq;
     137              : }
     138              : 
     139              : /**
     140              :  * @brief       get nearest power of 2, which is bigger than n
     141              :  * @param [in]  n:            original number
     142              :  * @return      power of 2, bigger than n, eg, return 1024 for 1023
     143              :  */
     144           40 : uint32_t GetNearestPowerOfTwo(uint32_t n)
     145              : {
     146           40 :    uint32_t num = n - 1U;
     147           40 :    uint32_t i = num;
     148          440 :    while (i > 0) {
     149          400 :        num |= i;
     150          400 :        i >>= 1U;
     151              :    }
     152           40 :    return num + 1U;
     153              : }
     154              : 
     155              : /**
     156              :  * @brief           swap the values of two integers
     157              :  * @param [in/out]  a:      pointer to the first integer to swap
     158              :  * @param [in/out]  b:      pointer to the second integer to swap
     159              :  */
     160          240 : static void AdiagSwap(int32_t *a, int32_t *b)
     161              : {
     162          240 :     int32_t temp = *a;
     163          240 :     *a = *b;
     164          240 :     *b = temp;
     165          240 : }
     166              : 
     167              : /**
     168              :  * @brief           partition an array
     169              :  * @param [in/out]  arr:        the array to be partitioned
     170              :  * @param [in]      low:        the starting index of the array
     171              :  * @param [in]      high:       the ending index of the array
     172              :  * @return          the index of the partition point
     173              :  */
     174           80 : static int32_t AdiagPartition(int32_t arr[], int32_t low, int32_t high)
     175              : {
     176           80 :     int32_t pivot = arr[high];
     177           80 :     int32_t i = (low - 1);
     178              : 
     179          400 :     for (int32_t j = low; j <= high - 1; j++) {
     180          320 :         if (arr[j] <= pivot) {
     181          160 :             i++;
     182          160 :             AdiagSwap(&arr[i], &arr[j]);
     183              :         }
     184              :     }
     185           80 :     AdiagSwap(&arr[i + 1], &arr[high]);
     186           80 :     return (i + 1);
     187              : }
     188              : 
     189              : /**
     190              :  * @brief           quicksort an array, the size of the array cannot exceed MAX_QUICK_SORT_LEN
     191              :  * @param [in/out]  arr:        the array to be sorted
     192              :  * @param [in]      low:        the starting index of the array
     193              :  * @param [in]      high:       the ending index of the array
     194              :  */
     195           40 : void AdiagQuickSort(int32_t arr[], int32_t low, int32_t high)
     196              : {
     197           40 :     int32_t len = high - low + 1;
     198           40 :     if (len <= 1 || len > MAX_QUICK_SORT_LEN) {
     199           20 :         return;
     200              :     }
     201           20 :     int32_t tmpHigh = high;
     202           20 :     int32_t tmpLow = low;
     203              :     int32_t stack[MAX_QUICK_SORT_LEN + 2]; // add 2 to avoid stack overflow
     204           20 :     int32_t top = 0;
     205           20 :     stack[top] = low;
     206           20 :     top++;
     207           20 :     stack[top] = high;
     208              : 
     209          120 :     while ((top >= 0) && (top < MAX_QUICK_SORT_LEN)) {
     210           80 :         tmpHigh = stack[top];
     211           80 :         top--;
     212           80 :         tmpLow = stack[top];
     213           80 :         top--;
     214              : 
     215           80 :         int32_t pi = AdiagPartition(arr, tmpLow, tmpHigh);
     216           80 :         if (pi - 1 > tmpLow) {
     217           40 :             top++;
     218           40 :             stack[top] = tmpLow;
     219           40 :             top++;
     220           40 :             stack[top] = pi - 1;
     221              :         }
     222              : 
     223           80 :         if (pi + 1 < tmpHigh) {
     224           20 :             top++;
     225           20 :             stack[top] = pi + 1;
     226           20 :             top++;
     227           20 :             stack[top] = tmpHigh;
     228              :         }
     229              :     }
     230              : }
        

Generated by: LCOV version 2.0-1