LCOV - code coverage report
Current view: top level - common - adiag_utils.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 97.0 % 99 96
Test Date: 2026-08-31 10:07:06 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        31228 : void* AdiagMalloc(size_t size)
      22              : {
      23        31228 :     ADIAG_CHK_EXPR_ACTION(size == 0, return NULL, "size is 0.");
      24        31228 :     void* ptr = malloc(size);
      25        31228 :     if (ptr == NULL) {
      26            0 :         ADIAG_ERR("malloc failed, size=%zu bytes.", size);
      27            0 :         return NULL;
      28              :     }
      29        31228 :     (void)memset_s(ptr, size, 0, size);
      30        31227 :     return ptr;
      31              : }
      32              : 
      33        38475 : void AdiagFree(void* ptr)
      34              : {
      35        38475 :     if (ptr != NULL) {
      36        31802 :         free(ptr);
      37              :     }
      38        38475 : }
      39              : 
      40         1160 : int32_t AdiagGetErrorCode(void) { return mmGetErrorCode(); }
      41              : 
      42          312 : AdiagStatus AdiagStrToInt(const char* str, int32_t* num)
      43              : {
      44          312 :     if ((str == NULL) || (num == NULL)) {
      45           44 :         return ADIAG_FAILURE;
      46              :     }
      47              : 
      48          268 :     errno = 0;
      49          268 :     char* endPtr = NULL;
      50          268 :     const int32_t numberBase = 10;
      51          268 :     int64_t ret = strtol(str, &endPtr, numberBase);
      52          268 :     AdiagStatus error = ADIAG_SUCCESS;
      53          268 :     if (((const char*)endPtr == str) || (*endPtr != '\0')) {
      54           22 :         error = ADIAG_FAILURE;
      55          246 :     } else if (((ret == LONG_MIN) || (ret == LONG_MAX)) && (errno == ERANGE)) {
      56            0 :         error = ADIAG_FAILURE;
      57          246 :     } else if (ret <= INT32_MAX) {
      58          246 :         *num = (int32_t)ret;
      59              :     } else {
      60              :         ;
      61              :     }
      62          268 :     return error;
      63              : }
      64              : 
      65              : /**
      66              :  * @brief       get cycle counter
      67              :  * @return      cpu cycles
      68              :  */
      69      3167309 : uint64_t GetCpuCycleCounter(void)
      70              : {
      71              :     uint64_t cycles;
      72              : #ifdef CPU_CYCLE_NO_SUPPORT
      73              :     cycles = 0; // just for tiny compile(without mrrc), will not be executed when running
      74              : #else
      75              : #if defined(__aarch64__)
      76              :     asm volatile("mrs %0, cntvct_el0" : "=r"(cycles));
      77              : #elif defined(__x86_64__)
      78      3167309 :     const int uint32Bits = 32; // 32 is uint bit count
      79      3167309 :     uint32_t hi = 0;
      80      3167309 :     uint32_t lo = 0;
      81      3167309 :     __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
      82      3171929 :     cycles = ((uint64_t)lo) | (((uint64_t)hi) << uint32Bits);
      83              : #elif defined(__arm__)
      84              :     const int uint32Bits = 32; // 32 is uint bit count
      85              :     uint32_t hi = 0;
      86              :     uint32_t lo = 0;
      87              :     asm volatile("mrrc p15, 1, %0, %1, c14" : "=r"(lo), "=r"(hi));
      88              :     cycles = ((uint64_t)lo) | (((uint64_t)hi) << uint32Bits);
      89              : #else
      90              :     cycles = 0;
      91              : #endif
      92              : #endif // CPU_CYCLE_NO_SUPPORT
      93      3171929 :     return cycles;
      94              : }
      95              : 
      96              : /**
      97              :  * @brief       get real time
      98              :  * @return      real time, ns
      99              :  */
     100        11935 : uint64_t GetRealTime(void)
     101              : {
     102        11935 :     struct timespec now = {0, 0};
     103        11935 :     (void)clock_gettime(CLOCK_REALTIME, &now);
     104        11935 :     return ((uint64_t)now.tv_sec * SEC_TO_NS) + (uint64_t)now.tv_nsec;
     105              : }
     106              : 
     107              : /**
     108              :  * @brief       get monotonic time, absolute time, which cannot be changed
     109              :  * @return      monotonic time, ns
     110              :  */
     111           50 : uint64_t GetMonotonicTime(void)
     112              : {
     113           50 :     struct timespec now = {0, 0};
     114           50 :     (void)clock_gettime(CLOCK_MONOTONIC_RAW, &now);
     115           50 :     return ((uint64_t)now.tv_sec * SEC_TO_NS) + (uint64_t)now.tv_nsec;
     116              : }
     117              : 
     118              : /**
     119              :  * @brief       get cpu frequency
     120              :  * @return      cpu frequency, kHz
     121              :  */
     122         2060 : uint64_t GetCpuFrequency(void)
     123              : {
     124              :     static uint64_t freq = UINT64_MAX;
     125         2060 :     if (freq == UINT64_MAX) {
     126           25 :         uint64_t startTime = GetMonotonicTime();
     127           25 :         uint64_t startCycle = GetCpuCycleCounter();
     128           25 :         (void)usleep(TIME_MS_TO_US); // sleep 1ms
     129           25 :         uint64_t endCycle = GetCpuCycleCounter();
     130           25 :         uint64_t endTime = GetMonotonicTime();
     131           25 :         freq = (endCycle - startCycle) * FREQ_GHZ_TO_KHZ / (endTime - startTime);
     132              :     }
     133         2060 :     return freq;
     134              : }
     135              : 
     136              : /**
     137              :  * @brief       get nearest power of 2, which is bigger than n
     138              :  * @param [in]  n:            original number
     139              :  * @return      power of 2, bigger than n, eg, return 1024 for 1023
     140              :  */
     141           44 : uint32_t GetNearestPowerOfTwo(uint32_t n)
     142              : {
     143           44 :     uint32_t num = n - 1U;
     144           44 :     uint32_t i = num;
     145          484 :     while (i > 0) {
     146          440 :         num |= i;
     147          440 :         i >>= 1U;
     148              :     }
     149           44 :     return num + 1U;
     150              : }
     151              : 
     152              : /**
     153              :  * @brief           swap the values of two integers
     154              :  * @param [in/out]  a:      pointer to the first integer to swap
     155              :  * @param [in/out]  b:      pointer to the second integer to swap
     156              :  */
     157          264 : static void AdiagSwap(int32_t* a, int32_t* b)
     158              : {
     159          264 :     int32_t temp = *a;
     160          264 :     *a = *b;
     161          264 :     *b = temp;
     162          264 : }
     163              : 
     164              : /**
     165              :  * @brief           partition an array
     166              :  * @param [in/out]  arr:        the array to be partitioned
     167              :  * @param [in]      low:        the starting index of the array
     168              :  * @param [in]      high:       the ending index of the array
     169              :  * @return          the index of the partition point
     170              :  */
     171           88 : static int32_t AdiagPartition(int32_t arr[], int32_t low, int32_t high)
     172              : {
     173           88 :     int32_t pivot = arr[high];
     174           88 :     int32_t i = (low - 1);
     175              : 
     176          440 :     for (int32_t j = low; j <= high - 1; j++) {
     177          352 :         if (arr[j] <= pivot) {
     178          176 :             i++;
     179          176 :             AdiagSwap(&arr[i], &arr[j]);
     180              :         }
     181              :     }
     182           88 :     AdiagSwap(&arr[i + 1], &arr[high]);
     183           88 :     return (i + 1);
     184              : }
     185              : 
     186              : /**
     187              :  * @brief           quicksort an array, the size of the array cannot exceed MAX_QUICK_SORT_LEN
     188              :  * @param [in/out]  arr:        the array to be sorted
     189              :  * @param [in]      low:        the starting index of the array
     190              :  * @param [in]      high:       the ending index of the array
     191              :  */
     192           44 : void AdiagQuickSort(int32_t arr[], int32_t low, int32_t high)
     193              : {
     194           44 :     int32_t len = high - low + 1;
     195           44 :     if (len <= 1 || len > MAX_QUICK_SORT_LEN) {
     196           22 :         return;
     197              :     }
     198           22 :     int32_t tmpHigh = high;
     199           22 :     int32_t tmpLow = low;
     200              :     int32_t stack[MAX_QUICK_SORT_LEN + 2]; // add 2 to avoid stack overflow
     201           22 :     int32_t top = 0;
     202           22 :     stack[top] = low;
     203           22 :     top++;
     204           22 :     stack[top] = high;
     205              : 
     206          132 :     while ((top >= 0) && (top < MAX_QUICK_SORT_LEN)) {
     207           88 :         tmpHigh = stack[top];
     208           88 :         top--;
     209           88 :         tmpLow = stack[top];
     210           88 :         top--;
     211              : 
     212           88 :         int32_t pi = AdiagPartition(arr, tmpLow, tmpHigh);
     213           88 :         if (pi - 1 > tmpLow) {
     214           44 :             top++;
     215           44 :             stack[top] = tmpLow;
     216           44 :             top++;
     217           44 :             stack[top] = pi - 1;
     218              :         }
     219              : 
     220           88 :         if (pi + 1 < tmpHigh) {
     221           22 :             top++;
     222           22 :             stack[top] = pi + 1;
     223           22 :             top++;
     224           22 :             stack[top] = tmpHigh;
     225              :         }
     226              :     }
     227              : }
        

Generated by: LCOV version 2.0-1