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 : }
|