1 | /** |
2 | * Copyright 2021 Alibaba, Inc. and its affiliates. All Rights Reserved. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | |
16 | * \author Hechong.xyf |
17 | * \date Dec 2017 |
18 | * \brief Interface of Platform Definition |
19 | */ |
20 | |
21 | #ifndef __AILEGO_INTERNAL_PLATFORM_H__ |
22 | #define __AILEGO_INTERNAL_PLATFORM_H__ |
23 | |
24 | #if defined(_WIN32) || defined(_WIN64) |
25 | #include <sdkddkver.h> |
26 | #endif |
27 | |
28 | #include <sys/types.h> |
29 | #include <limits.h> |
30 | #include <stdbool.h> |
31 | #include <stddef.h> |
32 | #include <stdint.h> |
33 | #include <stdio.h> |
34 | #include <stdlib.h> |
35 | #include <string.h> |
36 | #include <time.h> |
37 | |
38 | #if defined(_MSC_VER) |
39 | #include <intrin.h> |
40 | #else |
41 | #include <strings.h> |
42 | #include <unistd.h> |
43 | #if defined(__x86_64__) || defined(__i386) |
44 | #include <x86intrin.h> |
45 | #endif |
46 | #if defined(__ARM_NEON) |
47 | #include <arm_neon.h> |
48 | #endif |
49 | #if defined(__ARM_FEATURE_CRC32) |
50 | #include <arm_acle.h> |
51 | #endif |
52 | #endif |
53 | |
54 | #if defined(__cplusplus) |
55 | extern "C" { |
56 | #endif |
57 | |
58 | #ifndef NDEBUG |
59 | #define AILEGO_DEBUG |
60 | #endif |
61 | |
62 | //! Fixed Intel intrinsics macro in MSVC |
63 | #if defined(_MSC_VER) |
64 | #if (_M_IX86_FP == 2 || defined(_M_AMD64) || defined(_M_X64)) |
65 | #define __SSE__ 1 |
66 | #define __SSE2__ 1 |
67 | #if _MSC_VER >= 1500 |
68 | #define __SSE3__ 1 |
69 | #define __SSSE3__ 1 |
70 | #define __SSE4_1__ 1 |
71 | #define __SSE4_2__ 1 |
72 | #endif |
73 | #elif _M_IX86_FP == 1 |
74 | #define __SSE__ 1 |
75 | #endif |
76 | #endif // _MSC_VER |
77 | |
78 | #if defined(_WIN32) || defined(_WIN64) |
79 | #if defined(_WIN64) |
80 | #define AILEGO_M64 |
81 | #else |
82 | #define AILEGO_M32 |
83 | #endif |
84 | #endif |
85 | |
86 | #if defined(__GNUC__) |
87 | #if defined(__x86_64__) || defined(__aarch64__) || defined(__ppc64__) |
88 | #define AILEGO_M64 |
89 | #else |
90 | #define AILEGO_M32 |
91 | #endif |
92 | #endif |
93 | |
94 | #ifndef AILEGO_ALIGNED |
95 | #if defined(_MSC_VER) |
96 | #define AILEGO_ALIGNED(x) __declspec(align(x)) |
97 | #define AILEGO_DEPRECATED __declspec(deprecated) |
98 | #elif defined(__GNUC__) |
99 | #define AILEGO_ALIGNED(x) __attribute__((aligned(x))) |
100 | #define AILEGO_DEPRECATED __attribute__((deprecated)) |
101 | #else |
102 | #define AILEGO_ALIGNED(x) |
103 | #define AILEGO_DEPRECATED |
104 | #endif |
105 | #endif |
106 | |
107 | //! Add 'inline' for MSVC |
108 | #if defined(_MSC_VER) && !defined(__cplusplus) |
109 | #if !defined(inline) |
110 | #define inline __inline |
111 | #endif |
112 | #endif |
113 | |
114 | //! Add 'ssize_t' for MSVC |
115 | #if defined(_MSC_VER) |
116 | typedef intptr_t ssize_t; |
117 | #endif |
118 | |
119 | #if defined(_MSC_VER) |
120 | //! Returns the number of trailing 0-bits in x |
121 | static inline int ailego_ctz32(uint32_t x) { |
122 | unsigned long r = 0; |
123 | _BitScanForward(&r, x); |
124 | return (int)r; |
125 | } |
126 | |
127 | //! Returns the number of leading 0-bits in x |
128 | static inline int ailego_clz32(uint32_t x) { |
129 | unsigned long r = 0; |
130 | _BitScanReverse(&r, x); |
131 | return (31 - (int)r); |
132 | } |
133 | |
134 | #if defined(AILEGO_M64) |
135 | //! Returns the number of trailing 0-bits in x |
136 | static inline int ailego_ctz64(uint64_t x) { |
137 | unsigned long r = 0; |
138 | _BitScanForward64(&r, x); |
139 | return (int)r; |
140 | } |
141 | |
142 | //! Returns the number of leading 0-bits in x |
143 | static inline int ailego_clz64(uint64_t x) { |
144 | unsigned long r = 0; |
145 | _BitScanReverse64(&r, x); |
146 | return (63 - (int)r); |
147 | } |
148 | #else |
149 | //! Returns the number of trailing 0-bits in x |
150 | static inline int ailego_ctz64(uint64_t x) { |
151 | unsigned long r = 0; |
152 | unsigned long m = (unsigned long)x; |
153 | _BitScanForward(&r, m); |
154 | if (r == 0) { |
155 | m = (unsigned long)(x >> 32); |
156 | _BitScanForward(&r, m); |
157 | if (r != 0) { |
158 | r += 32; |
159 | } |
160 | } |
161 | return (int)r; |
162 | } |
163 | |
164 | //! Returns the number of leading 0-bits in x |
165 | static inline int ailego_clz64(uint64_t x) { |
166 | unsigned long r = 0; |
167 | unsigned long m = (unsigned long)(x >> 32); |
168 | _BitScanReverse(&r, m); |
169 | if (r != 0) { |
170 | return (31 - (int)r); |
171 | } |
172 | m = (unsigned long)x; |
173 | _BitScanReverse(&r, m); |
174 | return (63 - (int)r); |
175 | } |
176 | #endif // AILEGO_M64 |
177 | |
178 | //! Counts the number of one bits |
179 | #define ailego_popcount32(x) (__popcnt(x)) |
180 | #define ailego_popcount64(x) (__popcnt64(x)) |
181 | #define ailego_likely(x) (x) |
182 | #define ailego_unlikely(x) (x) |
183 | #ifdef __SSE__ |
184 | #define ailego_prefetch(p) _mm_prefetch((p), 0) |
185 | #else |
186 | #define ailego_prefetch(p) ((void)(p)) |
187 | #endif |
188 | #else // !_MSC_VER |
189 | #define ailego_ctz32(x) (__builtin_ctz(x)) |
190 | #define ailego_ctz64(x) (__builtin_ctzll(x)) |
191 | #define ailego_clz32(x) (__builtin_clz(x)) |
192 | #define ailego_clz64(x) (__builtin_clzll(x)) |
193 | #define ailego_popcount32(x) (__builtin_popcount(x)) |
194 | #define ailego_popcount64(x) (__builtin_popcountl(x)) |
195 | #define ailego_likely(x) (__builtin_expect(!!(x), 1)) |
196 | #define ailego_unlikely(x) (__builtin_expect(!!(x), 0)) |
197 | #define ailego_prefetch(p) (__builtin_prefetch((p))) |
198 | #endif // _MSC_VER |
199 | |
200 | #if defined(AILEGO_M64) |
201 | #define ailego_ctz ailego_ctz64 |
202 | #define ailego_clz ailego_clz64 |
203 | #define ailego_popcount ailego_popcount64 |
204 | #else |
205 | #define ailego_ctz ailego_ctz32 |
206 | #define ailego_clz ailego_clz32 |
207 | #define ailego_popcount ailego_popcount32 |
208 | #endif // AILEGO_M64 |
209 | |
210 | #if defined(__arm__) || defined(__aarch64__) |
211 | // ARMv7 Architecture Reference Manual (for YIELD) |
212 | // ARM Compiler toolchain Compiler Reference (for __yield() instrinsic) |
213 | #if defined(__CC_ARM) |
214 | #define ailego_yield() __yield() |
215 | #else |
216 | #define ailego_yield() __asm__ __volatile__("yield") |
217 | #endif // __CC_ARM |
218 | #elif defined(__SSE2__) |
219 | #define ailego_yield() _mm_pause() |
220 | #else |
221 | #define ailego_yield() ((void)0) |
222 | #endif // __arm__ || __aarch64__ |
223 | |
224 | #if defined(_MSC_VER) |
225 | #define ailego_aligned_malloc(SIZE, ALIGN) \ |
226 | _aligned_malloc((size_t)(SIZE), (ALIGN)) |
227 | #define ailego_aligned_free _aligned_free |
228 | #else // !_MSC_VER |
229 | #if defined(_ISOC11_SOURCE) |
230 | #define ailego_aligned_malloc(SIZE, ALIGN) \ |
231 | aligned_alloc((ALIGN), (size_t)(SIZE)) |
232 | #else // !_ISOC11_SOURCE |
233 | #define ailego_aligned_malloc(SIZE, ALIGN) \ |
234 | ailego_posix_malloc((size_t)(SIZE), (ALIGN)) |
235 | #endif // _ISOC11_SOURCE |
236 | #define ailego_aligned_free free |
237 | #endif // _MSC_VER |
238 | |
239 | #if !defined(__SANITIZE_ADDRESS__) |
240 | #if defined(__has_feature) |
241 | #if __has_feature(address_sanitizer) |
242 | #define __SANITIZE_ADDRESS__ 1 |
243 | #endif // address_sanitizer |
244 | #endif // __has_feature |
245 | #endif // !__SANITIZE_ADDRESS__ |
246 | |
247 | #if !defined(__SANITIZE_ADDRESS__) |
248 | #if !defined(ailego_malloc) |
249 | #if defined(__AVX512F__) |
250 | #define ailego_malloc(SIZE) ailego_aligned_malloc((SIZE), 64) |
251 | #elif defined(__AVX__) |
252 | #define ailego_malloc(SIZE) ailego_aligned_malloc((SIZE), 32) |
253 | #elif defined(__SSE__) |
254 | #define ailego_malloc(SIZE) ailego_aligned_malloc((SIZE), 16) |
255 | #elif defined(__ARM_NEON) |
256 | #define ailego_malloc(SIZE) ailego_aligned_malloc((SIZE), 16) |
257 | #endif |
258 | #endif // !ailego_malloc |
259 | #if (defined(__SSE__) || defined(__ARM_NEON)) && !defined(ailego_free) |
260 | #define ailego_free ailego_aligned_free |
261 | #endif |
262 | #endif // !__SANITIZE_ADDRESS__ |
263 | |
264 | #ifndef ailego_malloc |
265 | #define ailego_malloc(SIZE) malloc((size_t)(SIZE)) |
266 | #endif |
267 | #ifndef ailego_free |
268 | #define ailego_free free |
269 | #endif |
270 | |
271 | #ifndef ailego_offsetof |
272 | #define ailego_offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER) |
273 | #endif |
274 | |
275 | #ifndef ailego_align |
276 | #define ailego_align(SIZE, BOUND) (((SIZE) + ((BOUND)-1)) & ~((BOUND)-1)) |
277 | #endif |
278 | |
279 | #ifndef ailego_align8 |
280 | #define ailego_align8(SIZE) ailego_align(SIZE, 8) |
281 | #endif |
282 | |
283 | #ifndef ailego_min |
284 | #define ailego_min(A, B) (((A) < (B)) ? (A) : (B)) |
285 | #endif |
286 | |
287 | #ifndef ailego_max |
288 | #define ailego_max(A, B) (((A) > (B)) ? (A) : (B)) |
289 | #endif |
290 | |
291 | #ifndef ailego_malloc_object |
292 | #define ailego_malloc_object(TYPE) ((TYPE *)ailego_malloc(sizeof(TYPE))) |
293 | #endif |
294 | #ifndef ailego_malloc_array |
295 | #define ailego_malloc_array(TYPE, SIZE) \ |
296 | ((TYPE *)ailego_malloc(SIZE * sizeof(TYPE))) |
297 | #endif |
298 | |
299 | #ifndef ailego_minus_if_ne_zero |
300 | #define ailego_minus_if_ne_zero(COND) \ |
301 | if (ailego_unlikely((COND) != 0)) return (-1) |
302 | #endif |
303 | |
304 | #ifndef ailego_zero_if_ne_zero |
305 | #define ailego_zero_if_ne_zero(COND) \ |
306 | if (ailego_unlikely((COND) != 0)) return (0) |
307 | #endif |
308 | |
309 | #ifndef ailego_null_if_ne_zero |
310 | #define ailego_null_if_ne_zero(COND) \ |
311 | if (ailego_unlikely((COND) != 0)) return (NULL) |
312 | #endif |
313 | |
314 | #ifndef ailego_false_if_ne_zero |
315 | #define ailego_false_if_ne_zero(COND) \ |
316 | if (ailego_unlikely((COND) != 0)) return (false) |
317 | #endif |
318 | |
319 | #ifndef ailego_return_if_ne_zero |
320 | #define ailego_return_if_ne_zero(COND) \ |
321 | if (ailego_unlikely((COND) != 0)) return |
322 | #endif |
323 | |
324 | #ifndef ailego_break_if_ne_zero |
325 | #define ailego_break_if_ne_zero(COND) \ |
326 | if (ailego_unlikely((COND) != 0)) break |
327 | #endif |
328 | |
329 | #ifndef ailego_continue_if_ne_zero |
330 | #define ailego_continue_if_ne_zero(COND) \ |
331 | if (ailego_unlikely((COND) != 0)) continue |
332 | #endif |
333 | |
334 | #ifndef ailego_do_if_ne_zero |
335 | #define ailego_do_if_ne_zero(COND) if (ailego_unlikely((COND) != 0)) |
336 | #endif |
337 | |
338 | #ifndef ailego_minus_if_lt_zero |
339 | #define ailego_minus_if_lt_zero(COND) \ |
340 | if (ailego_unlikely((COND) < 0)) return (-1) |
341 | #endif |
342 | |
343 | #ifndef ailego_zero_if_lt_zero |
344 | #define ailego_zero_if_lt_zero(COND) \ |
345 | if (ailego_unlikely((COND) < 0)) return (0) |
346 | #endif |
347 | |
348 | #ifndef ailego_null_if_lt_zero |
349 | #define ailego_null_if_lt_zero(COND) \ |
350 | if (ailego_unlikely((COND) < 0)) return (NULL) |
351 | #endif |
352 | |
353 | #ifndef ailego_false_if_lt_zero |
354 | #define ailego_false_if_lt_zero(COND) \ |
355 | if (ailego_unlikely((COND) < 0)) return (false) |
356 | #endif |
357 | |
358 | #ifndef ailego_return_if_lt_zero |
359 | #define ailego_return_if_lt_zero(COND) \ |
360 | if (ailego_unlikely((COND) < 0)) return |
361 | #endif |
362 | |
363 | #ifndef ailego_break_if_lt_zero |
364 | #define ailego_break_if_lt_zero(COND) \ |
365 | if (ailego_unlikely((COND) < 0)) break |
366 | #endif |
367 | |
368 | #ifndef ailego_continue_if_lt_zero |
369 | #define ailego_continue_if_lt_zero(COND) \ |
370 | if (ailego_unlikely((COND) < 0)) continue |
371 | #endif |
372 | |
373 | #ifndef ailego_do_if_lt_zero |
374 | #define ailego_do_if_lt_zero(COND) if (ailego_unlikely((COND) < 0)) |
375 | #endif |
376 | |
377 | #ifndef ailego_minus_if_false |
378 | #define ailego_minus_if_false(COND) \ |
379 | if (ailego_unlikely(!(COND))) return (-1) |
380 | #endif |
381 | |
382 | #ifndef ailego_zero_if_false |
383 | #define ailego_zero_if_false(COND) \ |
384 | if (ailego_unlikely(!(COND))) return (0) |
385 | #endif |
386 | |
387 | #ifndef ailego_null_if_false |
388 | #define ailego_null_if_false(COND) \ |
389 | if (ailego_unlikely(!(COND))) return (NULL) |
390 | #endif |
391 | |
392 | #ifndef ailego_false_if_false |
393 | #define ailego_false_if_false(COND) \ |
394 | if (ailego_unlikely(!(COND))) return (false) |
395 | #endif |
396 | |
397 | #ifndef ailego_return_if_false |
398 | #define ailego_return_if_false(COND) \ |
399 | if (ailego_unlikely(!(COND))) return |
400 | #endif |
401 | |
402 | #ifndef ailego_break_if_false |
403 | #define ailego_break_if_false(COND) \ |
404 | if (ailego_unlikely(!(COND))) break |
405 | #endif |
406 | |
407 | #ifndef ailego_continue_if_false |
408 | #define ailego_continue_if_false(COND) \ |
409 | if (ailego_unlikely(!(COND))) continue |
410 | #endif |
411 | |
412 | #ifndef ailego_do_if_false |
413 | #define ailego_do_if_false(COND) if (ailego_unlikely(!(COND))) |
414 | #endif |
415 | |
416 | #ifndef ailego_compile_assert |
417 | #define ailego_compile_assert(COND, MSG) \ |
418 | typedef char Static_Assertion_##MSG[(!!(COND)) * 2 - 1] |
419 | #endif |
420 | |
421 | #ifndef ailego_static_assert3 |
422 | #define ailego_static_assert3(COND, LINE) \ |
423 | ailego_compile_assert(COND, At_Line_##LINE) |
424 | #endif |
425 | |
426 | #ifndef ailego_static_assert2 |
427 | #define ailego_static_assert2(COND, LINE) ailego_static_assert3(COND, LINE) |
428 | #endif |
429 | |
430 | #ifndef ailego_static_assert |
431 | #define ailego_static_assert(COND) ailego_static_assert2(COND, __LINE__) |
432 | #endif |
433 | |
434 | //! Abort and report if an assertion is failed |
435 | #ifndef ailego_assert_abort |
436 | #define ailego_assert_abort(COND, MSG) \ |
437 | (void)(ailego_likely(COND) || (ailego_assert_report(__FILE__, __FUNCTION__, \ |
438 | __LINE__, #COND, (MSG)), \ |
439 | abort(), 0)) |
440 | #endif |
441 | |
442 | #ifdef AILEGO_DEBUG |
443 | #ifndef ailego_assert |
444 | #define ailego_assert(COND) ailego_assert_abort(COND, "") |
445 | #endif |
446 | #ifndef ailego_assert_with |
447 | #define ailego_assert_with(COND, MSG) ailego_assert_abort(COND, MSG) |
448 | #endif |
449 | #else // !AILEGO_DEBUG |
450 | #ifndef ailego_assert |
451 | #define ailego_assert(COND) ((void)0) |
452 | #endif |
453 | #ifndef ailego_assert_with |
454 | #define ailego_assert_with(COND, MSG) ((void)0) |
455 | #endif |
456 | #endif // AILEGO_DEBUG |
457 | |
458 | #ifndef ailego_check |
459 | #define ailego_check(COND) ailego_assert_abort(COND, "") |
460 | #endif |
461 | #ifndef ailego_check_with |
462 | #define ailego_check_with(COND, MSG) ailego_assert_abort(COND, MSG) |
463 | #endif |
464 | |
465 | #ifndef _MSC_VER |
466 | //! Allocates memory on a specified alignment boundary |
467 | static inline void *ailego_posix_malloc(size_t size, size_t align) { |
468 | void *ptr; |
469 | ailego_null_if_ne_zero(posix_memalign(&ptr, align, size)); |
470 | return ptr; |
471 | } |
472 | #endif |
473 | |
474 | //! Report an assertion is failed |
475 | static inline void ailego_assert_report(const char *file, const char *func, |
476 | int line, const char *cond, |
477 | const char *msg) { |
478 | fprintf(stderr, "Assertion failed: (%s) in %s(), %s line %d. %s\n" , cond, |
479 | func, file, line, msg); |
480 | } |
481 | |
482 | #ifdef __cplusplus |
483 | } /* extern "C" */ |
484 | #endif |
485 | |
486 | #endif // __AILEGO_INTERNAL_PLATFORM_H__ |
487 | |