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