nlib
Platform_win32.h
1 
2 /*---------------------------------------------------------------------------*
3 
4  Project: CrossRoad
5  Copyright (C)2012-2016 Nintendo. All rights reserved.
6 
7  These coded instructions, statements, and computer programs contain
8  proprietary information of Nintendo of America Inc. and/or Nintendo
9  Company Ltd., and are protected by Federal copyright law. They may
10  not be disclosed to third parties or copied or duplicated in any form,
11  in whole or in part, without the prior written consent of Nintendo.
12 
13  *---------------------------------------------------------------------------*/
14 
15 #pragma once
16 #ifndef INCLUDE_NN_NLIB_PLATFORM_WIN32_H_
17 #define INCLUDE_NN_NLIB_PLATFORM_WIN32_H_
18 #ifndef INCLUDE_NN_NLIB_PLATFORM_H_
19 # error do not include directly
20 #endif
21 
22 #if defined(_MSC_VER)
23 
24 #if !defined(_M_IX86) && !defined(_M_X64) && !defined(_M_AMD64)
25 #error Sorry, not supported
26 #endif
27 
28 #if _MSC_VER < 1700
29 # error Use Visual Studio 2012 or later
30 #endif
31 
32 #ifndef WIN32_LEAN_AND_MEAN
33 # pragma message(__FILE__ ": WIN32_LEAN_AND_MEAN not defined, compile may fail")
34 # define WIN32_LEAN_AND_MEAN
35 #endif
36 
37 #ifndef NOMINMAX
38 # pragma message(__FILE__ ": NOMINMAX not defined, compile may fail")
39 # define NOMINMAX
40 #endif
41 
42 #ifndef _USE_MATH_DEFINES
43 # pragma message(__FILE__ ": _USE_MATH_DEFINES not defined, compile may fail")
44 # define _USE_MATH_DEFINES
45 #endif
46 
47 #ifdef _WIN64
48 # define NLIB_64BIT
49 #endif
50 
51 #include <intrin.h>
52 
53 #pragma intrinsic(_BitScanReverse)
54 #pragma intrinsic(_BitScanForward)
55 #ifdef NLIB_64BIT
56 # pragma intrinsic(_BitScanReverse64)
57 # pragma intrinsic(_BitScanForward64)
58 #endif
59 
60 #include <stdlib.h> // for malloc, free, calloc, realloc
61 #include <limits.h> // for RSIZE_MAX
62 #include <WinSock2.h>
63 #include <MSWsock.h>
64 #include <Windows.h> // for HANDLE, CONDITION_VARIABLE, ....
65 #include <fcntl.h> // for O_RDONLY, O_RDWR, O_CREAT, ....
66 
67 #include <in6addr.h>
68 #include <ws2ipdef.h>
69 #include <sal.h>
70 
71 #if _MSC_VER == 1800 && WINVER < 0x0603
72 # pragma message(__FILE__ ": Please update your Windows SDK")
73 #endif
74 
75 #if _MSC_VER == 1700 && WINVER < 0x0602
76 # pragma message(__FILE__ ": Please update your Windows SDK")
77 #endif
78 
79 #if (!defined(_M_IX86_FP) || _M_IX86_FP < 2) && !defined(_M_X64) && !defined(_M_AMD64)
80 # error /arch:SSE2 or higher must be set
81 #endif
82 
83 #ifndef NLIB_SSE41
84 # define NLIB_SSE41
85 #endif
86 
87 #ifndef NLIB_SSE42
88 # define NLIB_SSE42
89 #endif
90 
91 #include <stdint.h>
92 #if (_MSC_VER >= 1800)
93 # define NLIB_HAS_STDHEADER_INTTYPES
94 # include <inttypes.h>
95 #endif
96 #if (_MSC_VER < 1900)
97 # ifndef __func__
98 # define __func__ __FUNCTION__
99 # endif
100 #endif
101 
102 #ifndef NLIB_HAS_STDHEADER_INTTYPES
103 # include "nn/nlib/IntTypes.h"
104 #endif
105 
106 #ifdef __cplusplus
107 extern "C" {
108 #endif
109 
110 #ifndef va_copy
111 # define va_copy(dest, src) (dest = src)
112 #endif
113 #define NLIB_ALWAYS_INLINE __forceinline
114 #define NLIB_NEVER_INLINE __declspec(noinline)
115 #define NLIB_LIKELY(x) (x)
116 #define NLIB_UNLIKELY(x) (x)
117 #define NLIB_EXPECT(var, exp_value) (var)
118 #define NLIB_CHECK_RESULT
119 #define NLIB_NORETURN
120 #define NLIB_NONNULL
121 #define NLIB_NONNULL_1
122 #define NLIB_NONNULL_2
123 #define NLIB_NONNULL_3
124 #define NLIB_NONNULL_4
125 #define NLIB_NONNULL_5
126 #define NLIB_ATTRIBUTE_MALLOC
127 #define NLIB_ATTRIBUTE_PURE
128 #define NLIB_ATTRIBUTE_CONST
129 #define NLIB_ATTRIBUTE_ALLOC_SIZE1(n)
130 #define NLIB_ATTRIBUTE_ALLOC_SIZE2(n0, n1)
131 #define NLIB_ATTRIBUTE_ALLOC_ALIGN(algn)
132 #define NLIB_ATTRIBUTE_ASSUME_ALIGNED(n)
133 #ifndef NLIB_DEPRECATED
134 #define NLIB_DEPRECATED __declspec(deprecated)
135 #endif
136 #ifndef NLIB_DEPRECATED_MSG
137 #define NLIB_DEPRECATED_MSG(msg) __declspec(deprecated(msg))
138 #endif
139 #define NLIB_WEAKSYMBOL
140 #define NLIB_VIS_HIDDEN
141 #ifdef NLIB_WINDLL
142 # define NLIB_EXPIMP_TEMPLATE_(x) template class NLIB_VIS_PUBLIC x
143 # define NLIB_WINEXPORT __declspec(dllexport)
144 # define NLIB_WINIMPORT __declspec(dllimport)
145 # define NLIB_VIS_PUBLIC NLIB_WINIMPORT
146 # define NLIB_EXPIMP_TEMPLATE(x) extern NLIB_EXPIMP_TEMPLATE_(x)
147 #else
148 # define NLIB_VIS_PUBLIC
149 # define NLIB_EXPIMP_TEMPLATE(x)
150 #endif
151 
152 #if defined(n_EXPORTS)
153 # undef NLIB_VIS_PUBLIC
154 # define NLIB_VIS_PUBLIC NLIB_WINEXPORT
155 #elif defined(nx_misc_EXPORTS)
156 # undef NLIB_EXPIMP_TEMPLATE
157 # define NLIB_EXPIMP_TEMPLATE(x) NLIB_EXPIMP_TEMPLATE_(x)
158 #endif
159 
160 #define NLIB_VIS_PUBLIC_ALT
161 
162 #define NLIB_LITTLE_ENDIAN
163 
164 // NOTE:
165 // _WriteBarrier() for the compiler, _mm_sfence() for the processor, ...
166 // NOTE:
167 // You have to comment out error lines in intrin.h if you use VC++2005.
168 // See:
169 // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=262047
170 // http://www.hydrogenaudio.org/forums/index.php?showtopic=50972
171 #define NLIB_MEMORY_ORDER_RELEASE \
172  __pragma(warning(push)) \
173  __pragma(warning(disable:4127)) \
174  do { _WriteBarrier(); _mm_sfence(); } while (0) \
175  __pragma(warning(pop))
176 #define NLIB_MEMORY_ORDER_ACQUIRE \
177  __pragma(warning(push)) \
178  __pragma(warning(disable:4127)) \
179  do { _ReadBarrier(); _mm_lfence(); } while (0) \
180  __pragma(warning(pop))
181 #define NLIB_MEMORY_ORDER_ACQ_REL \
182  __pragma(warning(push)) \
183  __pragma(warning(disable:4127)) \
184  do { _ReadWriteBarrier(); _mm_mfence(); } while (0) \
185  __pragma(warning(pop))
186 #define NLIB_MEMORY_ORDER_SEQ_CST NLIB_MEMORY_ORDER_ACQ_REL
187 
188 // because "%zu" not supported ...
189 #ifdef NLIB_64BIT
190 # define __PRIS_PREFIX "ll"
191 #else
192 # define __PRIS_PREFIX
193 #endif
194 #define NLIB_WARN__(x) #x
195 #define NLIB_WARN_(x) NLIB_WARN__(x)
196 #define NLIB_WARN(exp) (__FILE__ "(" NLIB_WARN_(__LINE__) ") : WARNING: " exp)
197 
198 typedef unsigned int nlib_tls;
199 
200 #if _MSC_VER >= 1900
201 #define NLIB_TIMESPEC_HAS_NATIVE
202 #endif
203 
204 #pragma pack(push, 8)
205 typedef struct nlib_mutex_ {
206  int32_t mark;
207  uint32_t cat;
208  union {
209  HANDLE h;
210  CRITICAL_SECTION cs;
211  } data;
212 } nlib_mutex;
213 #pragma pack(pop)
214 #define NLIB_MUTEX_INITIALIZER { 0x6768696AU, 0 }
215 #define NLIB_RECURSIVE_MUTEX_INITIALIZER { 0x6768696AU, 1 }
216 #define NLIB_RECURSIVE_TIMED_MUTEX_INITIALIZER { 0x6768696AU, 2 }
217 
218 typedef HANDLE nlib_semaphore;
219 
220 typedef struct nlib_cond_ {
221  CONDITION_VARIABLE cond;
222  nlib_mutex mutex;
223 } nlib_cond;
224 #define NLIB_COND_INITIALIZER { 0, NLIB_MUTEX_INITIALIZER }
225 
226 typedef HANDLE nlib_thread;
227 
228 #define NLIB_ATTRIBUTE_PRINTF(x, y)
229 
230 #define NLIB_ASSUME(cond) __assume(cond)
231 
232 #define NLIB_RWLOCK_HAS_NATIVE
233 #ifdef NLIB_RWLOCK_HAS_NATIVE
234 typedef SRWLOCK nlib_rwlock;
235 #define NLIB_RWLOCK_INITIALIZER SRWLOCK_INIT
236 #endif
237 #define NLIB_TIMER_HAS_NATIVE
238 
239 NLIB_VIS_PUBLIC void nlib_free_size_(void* ptr, size_t size);
240 
241 #define NLIB_LIBC_nlib_memcmp
242 #define NLIB_LIBC_nlib_strlen
243 #define NLIB_LIBC_nlib_strnlen
244 #define NLIB_LIBC_nlib_wcslen
245 #define NLIB_LIBC_nlib_wcsnlen
246 #define NLIB_LIBC_nlib_strcpy
247 #define NLIB_LIBC_nlib_strncpy
248 #define NLIB_LIBC_nlib_wcscpy
249 #define NLIB_LIBC_nlib_wcsncpy
250 #define NLIB_LIBC_nlib_strchr
251 #define NLIB_LIBC_nlib_strrchr
252 
253 #if !defined(__INTELLISENSE__)
254 #define NLIB_ATOMIC_RELAXED (0)
255 #define NLIB_ATOMIC_ACQUIRE (1)
256 #define NLIB_ATOMIC_RELEASE (2)
257 #define NLIB_ATOMIC_ACQ_REL (3)
258 #define NLIB_ATOMIC_SEQ_CST (7)
259 
260 //
261 // NOTE:
262 // Windows 8 has xxxNoFence version
263 //
264 
265 static __inline int32_t nlib_atomic_load32(const int32_t* ptr, int memorder) {
266  int32_t result;
267  _ReadWriteBarrier();
268  result = *ptr;
269  (void)memorder;
270  // if (memorder & NLIB_ATOMIC_ACQUIRE)
271  // NLIB_MEMORY_ORDER_ACQUIRE;
272  _ReadWriteBarrier();
273  return result;
274 }
275 
276 static __inline void nlib_atomic_store32(int32_t* ptr, int32_t val, int memorder) {
277  _ReadWriteBarrier();
278  if (memorder != NLIB_ATOMIC_SEQ_CST) {
279  // if (memorder & NLIB_ATOMIC_RELEASE)
280  // NLIB_MEMORY_ORDER_RELEASE;
281  *ptr = val;
282  } else {
283  _InterlockedExchange((volatile long*)ptr, val); // NOLINT
284  }
285  _ReadWriteBarrier();
286 }
287 
288 static __inline int32_t nlib_atomic_exchange32(int32_t* ptr, int32_t val,
289  int memorder) {
290  int32_t result;
291  (void)memorder;
292  _ReadWriteBarrier();
293  result = (int32_t)_InterlockedExchange((volatile long*)ptr, val); // NOLINT
294  _ReadWriteBarrier();
295  return result;
296 }
297 
298 static __inline int nlib_atomic_compare_exchange32(int32_t* ptr, int32_t* expected,
299  int32_t desired, int weak,
300  int success_memorder, int failure_memorder) {
301  int32_t result;
302  _ReadWriteBarrier();
303  result = _InterlockedCompareExchange((volatile long*)ptr, desired, *expected); // NOLINT
304  _ReadWriteBarrier();
305  (void)weak;
306  (void)success_memorder;
307  (void)failure_memorder;
308  if (result == *expected) {
309  return 1;
310  } else {
311  *expected = result;
312  return 0;
313  }
314 }
315 
316 static __inline int32_t nlib_atomic_add_fetch32(int32_t* ptr, int32_t val,
317  int memorder) {
318  int32_t result;
319  (void)memorder;
320  _ReadWriteBarrier();
321  result = _InterlockedExchangeAdd((volatile long*)ptr, val) + val; // NOLINT
322  _ReadWriteBarrier();
323  return result;
324 }
325 
326 static __inline int32_t nlib_atomic_sub_fetch32(int32_t* ptr, int32_t val,
327  int memorder) {
328  int32_t result;
329  (void)memorder;
330  _ReadWriteBarrier();
331  result = _InterlockedExchangeAdd((volatile long*)ptr, -val) - val; // NOLINT
332  _ReadWriteBarrier();
333  return result;
334 }
335 
336 static __inline int32_t nlib_atomic_and_fetch32(int32_t* ptr, int32_t val,
337  int memorder) {
338  int32_t result;
339  (void)memorder;
340  _ReadWriteBarrier();
341  result = _InterlockedAnd((volatile long*)ptr, val) & val; // NOLINT
342  _ReadWriteBarrier();
343  return result;
344 }
345 
346 static __inline int32_t nlib_atomic_xor_fetch32(int32_t* ptr, int32_t val,
347  int memorder) {
348  int32_t result;
349  (void)memorder;
350  _ReadWriteBarrier();
351  result = _InterlockedXor((volatile long*)ptr, val) ^ val; // NOLINT
352  _ReadWriteBarrier();
353  return result;
354 }
355 
356 static __inline int32_t nlib_atomic_or_fetch32(int32_t* ptr, int32_t val,
357  int memorder) {
358  int32_t result;
359  (void)memorder;
360  _ReadWriteBarrier();
361  result = _InterlockedOr((volatile long*)ptr, val) | val; // NOLINT
362  _ReadWriteBarrier();
363  return result;
364 }
365 
366 static __inline int32_t nlib_atomic_fetch_add32(int32_t* ptr, int32_t val,
367  int memorder) {
368  int32_t result;
369  (void)memorder;
370  _ReadWriteBarrier();
371  result = _InterlockedExchangeAdd((volatile long*)ptr, val); // NOLINT
372  _ReadWriteBarrier();
373  return result;
374 }
375 
376 static __inline int32_t nlib_atomic_fetch_sub32(int32_t* ptr, int32_t val,
377  int memorder) {
378  int32_t result;
379  (void)memorder;
380  _ReadWriteBarrier();
381  result = _InterlockedExchangeAdd((volatile long*)ptr, -val); // NOLINT
382  _ReadWriteBarrier();
383  return result;
384 }
385 
386 static __inline int32_t nlib_atomic_fetch_and32(int32_t* ptr, int32_t val,
387  int memorder) {
388  int32_t result;
389  (void)memorder;
390  _ReadWriteBarrier();
391  result = _InterlockedAnd((volatile long*)ptr, val); // NOLINT
392  _ReadWriteBarrier();
393  return result;
394 }
395 
396 static __inline int32_t nlib_atomic_fetch_xor32(int32_t* ptr, int32_t val,
397  int memorder) {
398  int32_t result;
399  (void)memorder;
400  _ReadWriteBarrier();
401  result = _InterlockedXor((volatile long*)ptr, val); // NOLINT
402  _ReadWriteBarrier();
403  return result;
404 }
405 
406 static __inline int32_t nlib_atomic_fetch_or32(int32_t* ptr, int32_t val,
407  int memorder) {
408  int32_t result;
409  (void)memorder;
410  _ReadWriteBarrier();
411  result = _InterlockedOr((volatile long*)ptr, val); // NOLINT
412  _ReadWriteBarrier();
413  return result;
414 }
415 
416 static __inline int64_t nlib_atomic_load64(const int64_t* ptr, int memorder) {
417  int64_t result;
418  _ReadWriteBarrier();
419  result = *ptr;
420  _ReadWriteBarrier();
421  (void)memorder;
422  // if (memorder & NLIB_ATOMIC_ACQUIRE)
423  // NLIB_MEMORY_ORDER_ACQUIRE;
424  return result;
425 }
426 
427 static __inline void nlib_atomic_store64(int64_t* ptr, int64_t val, int memorder) {
428  _ReadWriteBarrier();
429  if (memorder != NLIB_ATOMIC_SEQ_CST) {
430  // if (memorder & NLIB_ATOMIC_RELEASE)
431  // NLIB_MEMORY_ORDER_RELEASE;
432  *ptr = val;
433  } else {
434 #ifndef NLIB_64BIT
435  InterlockedExchange64((volatile long long*)ptr, val); // NOLINT
436 #else
437  _InterlockedExchange64((volatile long long*)ptr, val); // NOLINT
438 #endif
439  }
440  _ReadWriteBarrier();
441 }
442 
443 static __inline int64_t nlib_atomic_exchange64(int64_t* ptr, int64_t val,
444  int memorder) {
445  int64_t result;
446  (void)memorder;
447  _ReadWriteBarrier();
448 #ifndef NLIB_64BIT
449  result = (int64_t)InterlockedExchange64((volatile long long*)ptr, val); // NOLINT
450 #else
451  result = (int64_t)_InterlockedExchange64((volatile long long*)ptr, val); // NOLINT
452 #endif
453  _ReadWriteBarrier();
454  return result;
455 }
456 
457 static __inline void* nlib_atomic_exchangeptr(void** ptr, void* val, int memorder) {
458 #ifndef NLIB_64BIT
459  return (void*)nlib_atomic_exchange32((int32_t*)ptr, (int32_t)val, memorder); // NOLINT
460 #else
461  return (void*)nlib_atomic_exchange64((int64_t*)ptr, (int64_t)val, memorder); // NOLINT
462 #endif
463 }
464 
465 static __inline int nlib_atomic_compare_exchange64(int64_t* ptr, int64_t* expected,
466  int64_t desired, int weak,
467  int success_memorder, int failure_memorder) {
468  int64_t result;
469  _ReadWriteBarrier();
470 #ifndef NLIB_64BIT
471  result = InterlockedCompareExchange64((volatile long long*)ptr, desired, *expected); // NOLINT
472 #else
473  result = _InterlockedCompareExchange64((volatile long long*)ptr, desired, *expected); // NOLINT
474 #endif
475  _ReadWriteBarrier();
476  (void)weak;
477  (void)success_memorder;
478  (void)failure_memorder;
479  if (result == *expected) {
480  return 1;
481  } else {
482  *expected = result;
483  return 0;
484  }
485 }
486 
487 static __inline int64_t nlib_atomic_add_fetch64(int64_t* ptr, int64_t val,
488  int memorder) {
489  int64_t result;
490  (void)memorder;
491  _ReadWriteBarrier();
492 #ifndef NLIB_64BIT
493  result = InterlockedExchangeAdd64((volatile long long*)ptr, val) + val; // NOLINT
494 #else
495  result = _InterlockedExchangeAdd64((volatile long long*)ptr, val) + val; // NOLINT
496 #endif
497  _ReadWriteBarrier();
498  return result;
499 }
500 
501 static __inline int64_t nlib_atomic_sub_fetch64(int64_t* ptr, int64_t val,
502  int memorder) {
503  int64_t result;
504  (void)memorder;
505  _ReadWriteBarrier();
506 #ifndef NLIB_64BIT
507  result = InterlockedExchangeAdd64((volatile long long*)ptr, -val) - val; // NOLINT
508 #else
509  result = _InterlockedExchangeAdd64((volatile long long*)ptr, -val) - val; // NOLINT
510 #endif
511  _ReadWriteBarrier();
512  return result;
513 }
514 
515 static __inline int64_t nlib_atomic_and_fetch64(int64_t* ptr, int64_t val,
516  int memorder) {
517  int64_t result;
518  (void)memorder;
519  _ReadWriteBarrier();
520 #ifndef NLIB_64BIT
521  result = InterlockedAnd64((volatile long long*)ptr, val) & val; // NOLINT
522 #else
523  result = _InterlockedAnd64((volatile long long*)ptr, val) & val; // NOLINT
524 #endif
525  _ReadWriteBarrier();
526  return result;
527 }
528 
529 static __inline int64_t nlib_atomic_xor_fetch64(int64_t* ptr, int64_t val,
530  int memorder) {
531  int64_t result;
532  (void)memorder;
533  _ReadWriteBarrier();
534 #ifndef NLIB_64BIT
535  result = InterlockedXor64((volatile long long*)ptr, val) ^ val; // NOLINT
536 #else
537  result = _InterlockedXor64((volatile long long*)ptr, val) ^ val; // NOLINT
538 #endif
539  _ReadWriteBarrier();
540  return result;
541 }
542 
543 static __inline int64_t nlib_atomic_or_fetch64(int64_t* ptr, int64_t val,
544  int memorder) {
545  int64_t result;
546  (void)memorder;
547  _ReadWriteBarrier();
548 #ifndef NLIB_64BIT
549  result = InterlockedOr64((volatile long long*)ptr, val) | val; // NOLINT
550 #else
551  result = _InterlockedOr64((volatile long long*)ptr, val) | val; // NOLINT
552 #endif
553  _ReadWriteBarrier();
554  return result;
555 }
556 
557 static __inline int64_t nlib_atomic_fetch_add64(int64_t* ptr, int64_t val,
558  int memorder) {
559  int64_t result;
560  (void)memorder;
561  _ReadWriteBarrier();
562 #ifndef NLIB_64BIT
563  result = InterlockedExchangeAdd64((volatile long long*)ptr, val); // NOLINT
564 #else
565  result = _InterlockedExchangeAdd64((volatile long long*)ptr, val); // NOLINT
566 #endif
567  _ReadWriteBarrier();
568  return result;
569 }
570 
571 static __inline int64_t nlib_atomic_fetch_sub64(int64_t* ptr, int64_t val,
572  int memorder) {
573  int64_t result;
574  (void)memorder;
575  _ReadWriteBarrier();
576 #ifndef NLIB_64BIT
577  result = InterlockedExchangeAdd64((volatile long long*)ptr, -val); // NOLINT
578 #else
579  result = _InterlockedExchangeAdd64((volatile long long*)ptr, -val); // NOLINT
580 #endif
581  _ReadWriteBarrier();
582  return result;
583 }
584 
585 static __inline int64_t nlib_atomic_fetch_and64(int64_t* ptr, int64_t val,
586  int memorder) {
587  int64_t result;
588  (void)memorder;
589  _ReadWriteBarrier();
590 #ifndef NLIB_64BIT
591  result = InterlockedAnd64((volatile long long*)ptr, val); // NOLINT
592 #else
593  result = _InterlockedAnd64((volatile long long*)ptr, val); // NOLINT
594 #endif
595  _ReadWriteBarrier();
596  return result;
597 }
598 
599 static __inline int64_t nlib_atomic_fetch_xor64(int64_t* ptr, int64_t val,
600  int memorder) {
601  int64_t result;
602  (void)memorder;
603  _ReadWriteBarrier();
604 #ifndef NLIB_64BIT
605  result = InterlockedXor64((volatile long long*)ptr, val); // NOLINT
606 #else
607  result = _InterlockedXor64((volatile long long*)ptr, val); // NOLINT
608 #endif
609  _ReadWriteBarrier();
610  return result;
611 }
612 
613 static __inline int64_t nlib_atomic_fetch_or64(int64_t* ptr, int64_t val,
614  int memorder) {
615  int64_t result;
616  (void)memorder;
617  _ReadWriteBarrier();
618 #ifndef NLIB_64BIT
619  result = InterlockedOr64((volatile long long*)ptr, val); // NOLINT
620 #else
621  result = _InterlockedOr64((volatile long long*)ptr, val); // NOLINT
622 #endif
623  _ReadWriteBarrier();
624  return result;
625 }
626 
627 static __inline void* nlib_atomic_loadptr(void* const* ptr, int memorder) {
628  void* result;
629  _ReadWriteBarrier();
630  result = *ptr;
631  _ReadWriteBarrier();
632  (void)memorder;
633  // if (memorder & NLIB_ATOMIC_ACQUIRE)
634  // NLIB_MEMORY_ORDER_ACQUIRE;
635  return result;
636 }
637 
638 static __inline void nlib_atomic_storeptr(void** ptr, void* val, int memorder) {
639  _ReadWriteBarrier();
640  if (memorder != NLIB_ATOMIC_SEQ_CST) {
641  // if (memorder & NLIB_ATOMIC_RELEASE)
642  // NLIB_MEMORY_ORDER_RELEASE;
643  *ptr = val;
644  } else {
645 #if _MSC_VER < 1800 || (_MSC_VER == 1800 && !defined(NLIB_64BIT))
646  InterlockedExchangePointer((void* volatile*)ptr, val); // NOLINT
647 #else
648  _InterlockedExchangePointer((void* volatile*)ptr, val); // NOLINT
649 #endif
650  }
651  _ReadWriteBarrier();
652 }
653 
654 static __inline int nlib_atomic_compare_exchangeptr(void** ptr, void** expected,
655  void* desired, int weak,
656  int success_memorder, int failure_memorder) {
657  void* result;
658  _ReadWriteBarrier();
659 #if _MSC_VER < 1800
660  result = InterlockedCompareExchangePointer((void* volatile *)ptr, desired, *expected);
661 #else
662  result = _InterlockedCompareExchangePointer((void* volatile *)ptr, desired, *expected);
663 #endif
664  _ReadWriteBarrier();
665  (void)weak;
666  (void)success_memorder;
667  (void)failure_memorder;
668  if (result == *expected) {
669  return 1;
670  } else {
671  *expected = result;
672  return 0;
673  }
674 }
675 
676 static __inline void nlib_atomic_thread_fence(int memorder) {
677  switch (memorder) {
678  case NLIB_ATOMIC_RELAXED:
679  break;
680  case NLIB_ATOMIC_ACQUIRE:
682  break;
683  case NLIB_ATOMIC_RELEASE:
685  break;
686  default:
688  break;
689  }
690 }
691 #endif
692 
693 #ifdef __cplusplus
694 }
695 #endif
696 
697 #ifndef _WIN64
698 #define NLIB_ALTNAME(func1, func2) \
699  __pragma(comment(linker, "/alternatename:_" NLIB_STRINGIFY(func1) "=_" NLIB_STRINGIFY(func2)))
700 #else
701 #define NLIB_ALTNAME(func1, func2) \
702  __pragma(comment(linker, "/alternatename:" NLIB_STRINGIFY(func1) "=" NLIB_STRINGIFY(func2)))
703 #endif
704 
705 NLIB_ALTNAME(nlib_malloc, malloc)
706 NLIB_ALTNAME(nlib_free, free)
707 NLIB_ALTNAME(nlib_calloc, calloc)
708 NLIB_ALTNAME(nlib_realloc, realloc)
709 NLIB_ALTNAME(nlib_free_size, nlib_free_size_)
710 
711 #if defined(NLIB_SIMD)
712 # ifndef NLIB_LIBC_nlib_strlen
713 NLIB_ALTNAME(nlib_strlen, nlib_strlen_simd)
714 # endif
715 # ifndef NLIB_LIBC_nlib_strlen
716 NLIB_ALTNAME(nlib_strnlen, nlib_strnlen_simd)
717 # endif
718 NLIB_ALTNAME(nlib_utf16len_, nlib_utf16len_simd)
719 NLIB_ALTNAME(nlib_utf16nlen_, nlib_utf16nlen_simd)
720 NLIB_ALTNAME(nlib_utf32len_, nlib_utf32len_generic)
721 NLIB_ALTNAME(nlib_utf32nlen_, nlib_utf32nlen_generic)
722 NLIB_ALTNAME(nlib_utf16cplen_ex_, nlib_utf16cplen_ex_simd)
723 NLIB_ALTNAME(nlib_strchr, nlib_strchr_simd)
724 NLIB_ALTNAME(nlib_strrchr, strrchr)
725 NLIB_ALTNAME(nlib_strchr_mb, nlib_strchr_mb_simd)
726 NLIB_ALTNAME(nlib_memcmp, nlib_memcmp_simd)
727 NLIB_ALTNAME(nlib_memchr, nlib_memchr_simd)
728 NLIB_ALTNAME(nlib_memrchr, nlib_memrchr_simd)
729 NLIB_ALTNAME(nlib_memchr_not, nlib_memchr_not_simd)
730 NLIB_ALTNAME(nlib_memchr_range_not, nlib_memchr_range_not_simd)
731 NLIB_ALTNAME(nlib_memchr_lt, nlib_memchr_lt_simd)
732 NLIB_ALTNAME(nlib_memchr_gt, nlib_memchr_gt_simd)
733 NLIB_ALTNAME(nlib_memchr_mb, nlib_memchr_mb_simd)
734 NLIB_ALTNAME(nlib_skipws, nlib_skipws_simd)
735 NLIB_ALTNAME(nlib_swapendian_16, nlib_swapendian_16_simd)
736 NLIB_ALTNAME(nlib_swapendian_32, nlib_swapendian_32_simd)
737 NLIB_ALTNAME(nlib_swapendian_64, nlib_swapendian_64_simd)
738 #else
739 # ifndef NLIB_LIBC_nlib_strlen
740 NLIB_ALTNAME(nlib_strlen, nlib_strlen_generic)
741 # endif
742 # ifndef NLIB_LIBC_nlib_strlen
743 NLIB_ALTNAME(nlib_strnlen, nlib_strnlen_generic)
744 # endif
745 NLIB_ALTNAME(nlib_utf16len_, nlib_utf16len_generic)
746 NLIB_ALTNAME(nlib_utf16nlen_, nlib_utf16nlen_generic)
747 NLIB_ALTNAME(nlib_utf32len_, nlib_utf32len_generic)
748 NLIB_ALTNAME(nlib_utf32nlen_, nlib_utf32nlen_generic)
749 NLIB_ALTNAME(nlib_utf16cplen_ex_, nlib_utf16cplen_ex_generic)
750 NLIB_ALTNAME(nlib_strchr, nlib_strchr_generic)
751 NLIB_ALTNAME(nlib_strrchr, nlib_strrchr_generic)
752 NLIB_ALTNAME(nlib_strchr_mb, nlib_strchr_mb_generic)
753 NLIB_ALTNAME(nlib_memcmp, nlib_memcmp_generic)
754 NLIB_ALTNAME(nlib_memchr, nlib_memchr_generic)
755 NLIB_ALTNAME(nlib_memrchr, nlib_memrchr_generic)
756 NLIB_ALTNAME(nlib_memchr_not, nlib_memchr_not_generic)
757 NLIB_ALTNAME(nlib_memchr_range_not, nlib_memchr_range_not_generic)
758 NLIB_ALTNAME(nlib_memchr_lt, nlib_memchr_lt_generic)
759 NLIB_ALTNAME(nlib_memchr_gt, nlib_memchr_gt_generic)
760 NLIB_ALTNAME(nlib_memchr_mb, nlib_memchr_mb_generic)
761 NLIB_ALTNAME(nlib_skipws, nlib_skipws_generic)
762 NLIB_ALTNAME(nlib_swapendian_16, nlib_swapendian_16_generic)
763 NLIB_ALTNAME(nlib_swapendian_32, nlib_swapendian_32_generic)
764 NLIB_ALTNAME(nlib_swapendian_64, nlib_swapendian_64_generic)
765 #endif
766 
767 #endif
768 #endif // INCLUDE_NN_NLIB_PLATFORM_WIN32_H_
int32_t nlib_atomic_xor_fetch32(int32_t *ptr, int32_t val, int memorder)
Calculates XOR of atomic values. Its behavior is similar to the one for __atomic_xor_fetch() of gcc...
int64_t nlib_atomic_fetch_and64(int64_t *ptr, int64_t val, int memorder)
Calculates AND of atomic values. Its behavior is similar to the one for __atomic_fetch_and() of gcc...
const char * nlib_strrchr(const char *s, int c)
Searches for a character from the end of a string.
void * nlib_atomic_exchangeptr(void **ptr, void *val, int memorder)
Swaps values in an atomic manner. Its behavior is similar to the one for __atomic_exchange_n() of gcc...
int nlib_atomic_compare_exchangeptr(void **ptr, void **expected, void *desired, int weak, int success_memorder, int failure_memorder)
Compares and swaps atomic values. Its behavior is similar to the one for __atomic_compare_exchange_n(...
int32_t nlib_atomic_load32(const int32_t *ptr, int memorder)
Loads a value in an atomic operation. Its behavior is similar to the one for __atomic_load_n() of gcc...
NLIB_CHECK_RESULT void * nlib_calloc(size_t nmemb, size_t size)
A weak function that calls the C standard function calloc. nlib calls calloc via this function...
int64_t nlib_atomic_fetch_add64(int64_t *ptr, int64_t val, int memorder)
Adds atomic values. Its behavior is similar to the one for __atomic_fetch_add() of gcc...
const void * nlib_memchr_lt(const void *s, int c, size_t n)
Searches the n bytes from the start of memory region (s, s + n) and returns a pointer to data having ...
struct nlib_rwlock_ nlib_rwlock
The type for a read-write lock object.
Definition: Platform.h:1157
sem_t nlib_semaphore
The type for a semaphore object.
#define NLIB_MEMORY_ORDER_ACQUIRE
A memory fence. Corresponds to atomic_thread_fence(memory_order_acquire) in C++11.
size_t nlib_strnlen(const char *s, size_t maxsize)
An implementation corresponding to N1078 strnlen_s.
int nlib_memcmp(const void *buf1, const void *buf2, size_t n)
Compares the n bytes from the starts of buf1 and buf2 as unsigned char data.
#define NLIB_ATOMIC_RELEASE
Similar to __ATOMIC_RELEASE of gcc or std::memory_order_release of C++11.
const void * nlib_memchr_not(const void *s, int c, size_t n)
Searches the n bytes from the start of memory region(s, s + n) and returns a pointer that does not po...
int32_t nlib_atomic_or_fetch32(int32_t *ptr, int32_t val, int memorder)
Calculates OR of atomic values. Its behavior is similar to the one for __atomic_or_fetch() of gcc...
const char * nlib_skipws(size_t *cnt_lf, const char **last_lf, const char *s, size_t n)
Searches a string made up of n characters and returns the pointer to the first character found that i...
int64_t nlib_atomic_fetch_sub64(int64_t *ptr, int64_t val, int memorder)
Subtracts atomic values. Its behavior is similar to the one for __atomic_fetch_sub() of gcc...
void nlib_free_size(void *ptr, size_t size)
Frees memory of a specified size. The default action is to call the nlib_free function.
int64_t nlib_atomic_and_fetch64(int64_t *ptr, int64_t val, int memorder)
Calculates AND of atomic values. Its behavior is similar to the one for __atomic_and_fetch() of gcc...
int nlib_atomic_compare_exchange64(int64_t *ptr, int64_t *expected, int64_t desired, int weak, int success_memorder, int failure_memorder)
Compares and swaps atomic values. Its behavior is similar to the one for __atomic_compare_exchange_n(...
#define NLIB_VIS_PUBLIC
Symbols for functions and classes are made available outside of the library.
Definition: Platform_unix.h:87
const char * nlib_strchr(const char *s, int c)
Searches for a character from the start of a string.
int64_t nlib_atomic_fetch_or64(int64_t *ptr, int64_t val, int memorder)
Calculates OR of atomic values. Its behavior is similar to the one for __atomic_fetch_or() of gcc...
const void * nlib_memchr(const void *s, int c, size_t n)
Searches the n bytes from the start of the memory region (s, s + n) and returns a pointer to byte c...
NLIB_CHECK_RESULT void * nlib_malloc(size_t size)
A weak function that calls the C standard function malloc. nlib calls malloc via this function...
#define NLIB_ATOMIC_ACQUIRE
Similar to __ATOMIC_ACQUIRE of gcc or std::memory_order_acquire of C++11.
pthread_key_t nlib_tls
The type for TLS slot IDs.
void * nlib_atomic_loadptr(void *const *ptr, int memorder)
Loads a value in an atomic operation. Its behavior is similar to the one for __atomic_load_n() of gcc...
int64_t nlib_atomic_exchange64(int64_t *ptr, int64_t val, int memorder)
Swaps values in an atomic operation. Its behavior is similar to the one for __atomic_exchange_n() of ...
#define NLIB_MEMORY_ORDER_SEQ_CST
A memory fence. Corresponds to atomic_thread_fence(memory_order_seq_cst) in C++11.
const void * nlib_memrchr(const void *s, int c, size_t n)
Searches the n bytes from the end of memory region (s, s + n) and returns a pointer to byte c...
int64_t nlib_atomic_sub_fetch64(int64_t *ptr, int64_t val, int memorder)
Subtracts atomic values. Its behavior is similar to the one for __atomic_sub_fetch() of gcc...
int32_t nlib_atomic_fetch_xor32(int32_t *ptr, int32_t val, int memorder)
Calculates XOR of atomic values. Its behavior is similar to the one for __atomic_fetch_xor() of gcc...
int32_t nlib_atomic_sub_fetch32(int32_t *ptr, int32_t val, int memorder)
Subtracts atomic values. Its behavior is similar to the one for __atomic_sub_fetch() of gcc...
int32_t nlib_atomic_fetch_sub32(int32_t *ptr, int32_t val, int memorder)
Subtracts atomic values. Its behavior is similar to the one for __atomic_fetch_sub() of gcc...
int32_t nlib_atomic_add_fetch32(int32_t *ptr, int32_t val, int memorder)
Adds atomic values. Its behavior is similar to the one for __atomic_add_fetch() of gcc...
void nlib_atomic_storeptr(void **ptr, void *val, int memorder)
Stores a value in an atomic operation. Its behavior is similar to the one for __atomic_store_n() of g...
void nlib_atomic_thread_fence(int memorder)
Places the specified memory barrier.
int32_t nlib_atomic_fetch_and32(int32_t *ptr, int32_t val, int memorder)
Calculates AND of atomic values. Its behavior is similar to the one for __atomic_fetch_and() of gcc...
pthread_cond_t nlib_cond
The type for a condition variable object.
NLIB_CHECK_RESULT void * nlib_realloc(void *ptr, size_t size)
A weak function that calls the C standard function realloc. nlib calls realloc via this function...
errno_t nlib_swapendian_32(uint32_t *p, size_t count)
Swaps the endianness.
#define NLIB_ATOMIC_RELAXED
Similar to __ATOMIC_RELAXED of gcc or std::memory_order_relaxed of C++11.
size_t nlib_strlen(const char *s)
Internally calls strlen(). In some cases, it may operate as an independent implementation.
pthread_mutex_t nlib_mutex
The type for mutex variables.
const void * nlib_memchr_range_not(const void *s, const char *range, size_t n)
Searches the n bytes from the start of memory region (s, s + n) and returns a pointer to a character ...
int64_t nlib_atomic_xor_fetch64(int64_t *ptr, int64_t val, int memorder)
Calculates XOR of atomic values. Its behavior is similar to the one for __atomic_xor_fetch() of gcc...
#define NLIB_MEMORY_ORDER_RELEASE
A memory fence. Corresponds to atomic_thread_fence(memory_order_release) in C++11.
int64_t nlib_atomic_add_fetch64(int64_t *ptr, int64_t val, int memorder)
Adds atomic values. Its behavior is similar to the one for __atomic_add_fetch() of gcc...
errno_t nlib_swapendian_16(uint16_t *p, size_t count)
Swaps the endianness.
const void * nlib_memchr_gt(const void *s, int c, size_t n)
Searches the n bytes from the start of memory region (s, s + n) and returns a pointer to data having ...
int32_t nlib_atomic_and_fetch32(int32_t *ptr, int32_t val, int memorder)
Calculates AND of atomic values. Its behavior is similar to the one for __atomic_and_fetch() of gcc...
int nlib_atomic_compare_exchange32(int32_t *ptr, int32_t *expected, int32_t desired, int weak, int success_memorder, int failure_memorder)
Compares and swaps atomic values. Its behavior is similar to the one for __atomic_compare_exchange_n(...
static const char * nlib_strchr_mb(const char *s)
Searches for a character from the start of a string and then returns either the null character or the...
Definition: Platform.h:2959
void nlib_atomic_store64(int64_t *ptr, int64_t val, int memorder)
Stores a value in an atomic operation. Its behavior is similar to the one for __atomic_store_n() of g...
void nlib_free(void *ptr)
A weak function that calls the C standard function free. nlib calls free via this function...
errno_t nlib_swapendian_64(uint64_t *p, size_t count)
Swaps the endianness.
int64_t nlib_atomic_or_fetch64(int64_t *ptr, int64_t val, int memorder)
Calculates OR of atomic values. Its behavior is similar to the one for __atomic_or_fetch() of gcc...
#define NLIB_ATOMIC_SEQ_CST
Similar to __ATOMIC_SEQ_CST of gcc or std::memory_order_seq_cst of C++11.
int32_t nlib_atomic_fetch_or32(int32_t *ptr, int32_t val, int memorder)
Calculates OR of atomic values. Its behavior is similar to the one for __atomic_fetch_or() of gcc...
int64_t nlib_atomic_fetch_xor64(int64_t *ptr, int64_t val, int memorder)
Calculates XOR of atomic values. Its behavior is similar to the one for __atomic_fetch_xor() of gcc...
const void * nlib_memchr_mb(const void *s, size_t n)
Searches the n bytes from the start of memory region (s, s + n) and returns a pointer to the location...
int32_t nlib_atomic_fetch_add32(int32_t *ptr, int32_t val, int memorder)
Adds atomic values. Its behavior is similar to the one for __atomic_fetch_add() of gcc...
void nlib_atomic_store32(int32_t *ptr, int32_t val, int memorder)
Stores a value in an atomic operation. Its behavior is similar to the one for __atomic_store_n() of g...
int32_t nlib_atomic_exchange32(int32_t *ptr, int32_t val, int memorder)
Swaps values in an atomic operation. Its behavior is similar to the one for __atomic_exchange_n() of ...
pthread_t nlib_thread
The identifier for threads.
int64_t nlib_atomic_load64(const int64_t *ptr, int memorder)
Loads a value in an atomic operation. Its behavior is similar to the one for __atomic_load_n() of gcc...