1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef HWE_OSDEP_H
17 #define HWE_OSDEP_H
18
19 #include <stdlib.h>
20 #include <limits.h>
21 #include "hwe_type.h"
22 #if defined(_WIN32)
23 #include <process.h>
24 #include <windows.h>
25 #include <time.h>
26 #else
27 #include <sched.h>
28 #include <pthread.h>
29 #include <sys/time.h>
30 #include <sys/prctl.h>
31 #endif
32 #include "hwe_source_record.h"
33
34 #define HWE_FILE __FILE__
35 #define HWE_LINE __LINE__
36
37 // kernel type enumeration
38 #if HWE_ARM_AARCH64
39 typedef enum HWE_Kernel {
40 KERNEL_TYPE_C = 0,
41 KERNEL_TYPE_NEON,
42 KERNEL_TYPE_TOTAL // total type number of kernel
43 } HWE_KernelType;
44 #elif HWE_ARM_AARCH32
45 typedef enum HWE_Kernel {
46 KERNEL_TYPE_C = 0,
47 KERNEL_TYPE_NEON,
48 KERNEL_TYPE_TOTAL // total type number of kernel
49 } HWE_KernelType;
50 #elif HWE_X86_64
51 typedef enum HWE_Kernel {
52 KERNEL_TYPE_C = 0,
53 KERNEL_TYPE_ASM,
54 KERNEL_TYPE_TOTAL,
55 KERNEL_TYPE_SSE2,
56 KERNEL_TYPE_SSE4,
57 KERNEL_TYPE_AVX,
58 KERNEL_TYPE_AVX2
59 } HWE_KernelType;
60 #elif HWE_X86_32
61 typedef enum HWE_Kernel {
62 KERNEL_TYPE_C = 0,
63 KERNEL_TYPE_INTRINSICS,
64 KERNEL_TYPE_TOTAL // total type number of kernel
65 } HWE_KernelType;
66 #else
67 typedef enum HWE_Kernel {
68 KERNEL_TYPE_C = 0,
69 KERNEL_TYPE_ASM,
70 KERNEL_TYPE_TOTAL // total type number of kernel
71 } HWE_KernelType;
72 #endif
73
74 HWE_KernelType HWE_DetectSimdCapibility(void);
75
76 #ifdef __ICL
77 #define inline __inline
78 #endif
79
80 #if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
81 #define HWE_INLINE __attribute__((always_inline)) inline
82 #else
83 #ifdef __ICL
84 #define HWE_INLINE __forceinline
85 #else
86 #define HWE_INLINE __inline
87 #endif
88 #endif
89
90
91 #if defined(_WIN32)
92 #define HWE_SPIN_COUNT 0
93 #define HWE_PTHREAD_MUTEX_INITIALIZER \
94 { \
95 0 \
96 }
97
98 typedef CRITICAL_SECTION HWE_PthreadMutex;
99 typedef struct HWE_PthreadCond {
100 void *ptr;
101 } HWE_PthreadCond;
102 typedef struct HWE_Pthread {
103 void *handle;
104 void *(*func)(void *arg);
105 void *arg;
106 void *ret;
107 signed char isInit;
108 } HWE_Pthread;
109 typedef struct HWE_Win32ThreadControl {
110 HWE_PthreadMutex staticMutex;
111 void(WINAPI *condBroadcast)(HWE_PthreadCond *cond);
112 void(WINAPI *condInit)(HWE_PthreadCond *cond);
113 void(WINAPI *condSignal)(HWE_PthreadCond *cond);
114 BOOL(WINAPI *condWait)(HWE_PthreadCond *cond, HWE_PthreadMutex *mutex, DWORD milliseconds);
115 } HWE_Win32ThreadControl;
116 typedef struct HWE_Win32Cond {
117 HWE_PthreadMutex mtxBroadcast;
118 HWE_PthreadMutex mtxWaiterCount;
119 volatile int32_t waiterCount;
120 HANDLE semaphore;
121 HANDLE waitersDone;
122 volatile int32_t isBroadcast;
123 } HWE_Win32Cond;
124
125 int32_t HWE_PthreadMutexInit(HWE_PthreadMutex *mutex);
126 int32_t HWE_PthreadMutexLock(HWE_PthreadMutex *mutex);
127 int32_t HWE_PthreadMutexUnLock(HWE_PthreadMutex *mutex);
128 int32_t HWE_PthreadMutexDestroy(HWE_PthreadMutex *mutex);
129 int32_t HWE_PthreadCondInit(HWE_PthreadCond *cond);
130 int32_t HWE_PthreadCondDestroy(HWE_PthreadCond *cond);
131 int32_t HWE_PthreadCondWait(HWE_PthreadCond *cond, HWE_PthreadMutex *mutex);
132 int32_t HWE_PthreadCondSignal(HWE_PthreadCond *cond);
133 int32_t HWE_PthreadCondBroadcast(HWE_PthreadCond *cond);
134 int32_t HWE_PthreadJoin(HWE_Pthread thread);
135 #else
136 typedef struct HWE_PthreadMutexType {
137 signed char isInit;
138 pthread_mutex_t mutex;
139 } HWE_PthreadMutex;
140
141 typedef struct HWE_PthreadCondType {
142 signed char isInit;
143 pthread_cond_t cond;
144 } HWE_PthreadCond;
145
146 typedef struct HWE_PthreadType {
147 signed char isInit;
148 pthread_t thread;
149 } HWE_Pthread;
150
151 // detect cpu simd capibility
152
HWE_PthreadMutexInit(HWE_PthreadMutex * mutex)153 static HWE_INLINE int32_t HWE_PthreadMutexInit(HWE_PthreadMutex *mutex)
154 {
155 int32_t ret = pthread_mutex_init(&mutex->mutex, nullptr);
156 mutex->isInit = (ret == 0) ? TRUE : FALSE;
157 if (mutex->isInit) {
158 RecordInitMutexCount();
159 }
160 return ret;
161 }
162
HWE_PthreadMutexLock(HWE_PthreadMutex * mutex)163 static HWE_INLINE int32_t HWE_PthreadMutexLock(HWE_PthreadMutex *mutex)
164 {
165 return mutex->isInit ? pthread_mutex_lock(&mutex->mutex) : -1;
166 }
167
HWE_PthreadMutexUnLock(HWE_PthreadMutex * mutex)168 static HWE_INLINE int32_t HWE_PthreadMutexUnLock(HWE_PthreadMutex *mutex)
169 {
170 return mutex->isInit ? pthread_mutex_unlock(&mutex->mutex) : -1;
171 }
172
HWE_PthreadMutexDestroy(HWE_PthreadMutex * mutex)173 static HWE_INLINE int32_t HWE_PthreadMutexDestroy(HWE_PthreadMutex *mutex)
174 {
175 if (mutex->isInit) {
176 mutex->isInit = 0;
177 RecordDestoryMutexCount();
178 return pthread_mutex_destroy(&mutex->mutex);
179 } else {
180 return -1;
181 }
182 }
183
HWE_PthreadCondInit(HWE_PthreadCond * cond)184 static HWE_INLINE int32_t HWE_PthreadCondInit(HWE_PthreadCond *cond)
185 {
186 int32_t ret = pthread_cond_init(&cond->cond, nullptr);
187 cond->isInit = (ret == 0) ? TRUE : FALSE;
188 if (cond->isInit) {
189 RecordInitCondCount();
190 }
191 return ret;
192 }
193
HWE_PthreadCondDestroy(HWE_PthreadCond * cond)194 static HWE_INLINE int32_t HWE_PthreadCondDestroy(HWE_PthreadCond *cond)
195 {
196 if (cond->isInit) {
197 cond->isInit = 0;
198 RecordDestoryCondCount();
199 return pthread_cond_destroy(&cond->cond);
200 } else {
201 return -1;
202 }
203 }
204
HWE_PthreadCondWait(HWE_PthreadCond * cond,HWE_PthreadMutex * mutex)205 static HWE_INLINE int32_t HWE_PthreadCondWait(HWE_PthreadCond *cond, HWE_PthreadMutex *mutex)
206 {
207 return (cond->isInit && mutex->isInit) ? pthread_cond_wait(&cond->cond, &mutex->mutex) : -1;
208 }
209
HWE_PthreadCondSignal(HWE_PthreadCond * cond)210 static HWE_INLINE int32_t HWE_PthreadCondSignal(HWE_PthreadCond *cond)
211 {
212 return cond->isInit ? pthread_cond_signal(&cond->cond) : -1;
213 }
214
HWE_PthreadCondBroadcast(HWE_PthreadCond * cond)215 static HWE_INLINE int32_t HWE_PthreadCondBroadcast(HWE_PthreadCond *cond)
216 {
217 return cond->isInit ? pthread_cond_broadcast(&cond->cond) : -1;
218 }
219
HWE_PthreadJoin(HWE_Pthread thread)220 static HWE_INLINE int32_t HWE_PthreadJoin(HWE_Pthread thread)
221 {
222 if (thread.isInit) {
223 thread.isInit = 0;
224 RecordDestoryThreadCount();
225 return pthread_join(thread.thread, nullptr);
226 } else {
227 return -1;
228 }
229 }
230
231 #endif
232
233 int32_t HWE_SetThreadAffinityMask(const HWE_Pthread *thread, uint32_t cpuNum, const uint32_t *cpuIdxArray);
234 int32_t HWE_SetThreadPriority(const HWE_Pthread *thread, int32_t schedPriority);
235
HWE_Malloc(size_t size)236 static HWE_INLINE void *HWE_Malloc(size_t size)
237 {
238 if (size == 0 || size >= INT_MAX) {
239 return nullptr;
240 }
241
242 void *p = malloc(size);
243
244 if (p != nullptr) {
245 RecordMallocMemCount();
246 return p;
247 } else {
248 return nullptr;
249 }
250 }
251
252 #ifdef _WIN32
HWE_GetCurrentTime(void)253 static HWE_INLINE uint64_t HWE_GetCurrentTime(void)
254 {
255 clock_t time = clock();
256 return (uint64_t)time;
257 }
258 #else
259 #define TIME_FACTOR 1000000
HWE_GetCurrentTime(void)260 static HWE_INLINE uint64_t HWE_GetCurrentTime(void)
261 {
262 uint64_t time;
263 struct timeval t;
264 gettimeofday(&t, nullptr);
265
266 time = (uint64_t)t.tv_sec * TIME_FACTOR + (uint64_t)t.tv_usec;
267 return time;
268 }
269 #endif
270 #endif