OSDN Git Service

Implement interlocked memory access API intrinsic functions.
authorKeith Marshall <keith@users.osdn.me>
Fri, 4 Nov 2022 14:58:41 +0000 (14:58 +0000)
committerKeith Marshall <keith@users.osdn.me>
Fri, 4 Nov 2022 14:58:41 +0000 (14:58 +0000)
w32api/ChangeLog
w32api/include/intrin.h [new file with mode: 0644]
w32api/include/winnt.h

index 12ac32c..726e010 100644 (file)
@@ -1,3 +1,47 @@
+2022-11-04  Keith Marshall  <keith@users.osdn.me>
+
+       Implement interlocked memory access API intrinsic functions.
+
+       * include/intrin.h: New file.
+       [__ATOMIC_ACQ_REL defined]: It declares...
+       (_InterlockedDecrement, _InterlockedDecrement8)
+       (_InterlockedDecrement16, _InterlockedDecrement64)
+       (_InterlockedIncrement, _InterlockedIncrement8)
+       (_InterlockedIncrement16, _InterlockedIncrement64)
+       (_InterlockedExchange, _InterlockedExchange8)
+       (_InterlockedExchange16, _InterlockedExchange64)
+       (_InterlockedCompareExchange, _InterlockedCompareExchange8)
+       (_InterlockedCompareExchange16, _InterlockedCompareExchange64)
+       (_InterlockedExchangeAdd, _InterlockedExchangeAdd8)
+       (_InterlockedExchangeAdd16, _InterlockedExchangeAdd64)
+       (_InterlockedAdd, _InterlockedAdd64, _InterlockedAnd)
+       (_InterlockedAnd8, _InterlockedAnd16, _InterlockedAnd64)
+       (_InterlockedOr, _InterlockedOr8, _InterlockedOr16, _InterlockedOr64)
+       (_InterlockedXor, _InterlockedXor8, _InterlockedXor16)
+       (_InterlockedXor64): ...each of these functions, then defines an
+       intrinsic implementation of each, by mapping each to an equivalent
+       GCC __atomic built-in function.
+
+       * include/winnt.h [__ATOMIC_AC_REL defined]: Include "intrin.h",
+       whence derive and define an appropriate mapping for...
+       (InterlockedDecrement, InterlockedDecrement8)
+       (InterlockedDecrement16, InterlockedDecrement64)
+       (InterlockedIncrement, InterlockedIncrement8)
+       (InterlockedIncrement16, InterlockedIncrement64)
+       (InterlockedExchange, InterlockedExchange8)
+       (InterlockedExchange16, InterlockedExchange64)
+       (InterlockedCompareExchange, InterlockedCompareExchange8)
+       (InterlockedCompareExchange16, InterlockedCompareExchange64)
+       (InterlockedCompareExchangePointer, InterlockedExchangePointer)
+       (InterlockedExchangeAdd, InterlockedExchangeAdd8)
+       (InterlockedExchangeAdd16, InterlockedExchangeAdd64)
+       (InterlockedAdd, InterlockedAdd64, InterlockedAnd)
+       (InterlockedAnd8, InterlockedAnd16, InterlockedAnd64)
+       (InterlockedOr, InterlockedOr8, InterlockedOr16, InterlockedOr64)
+       (InterlockedXor, InterlockedXor8, InterlockedXor16)
+       (InterlockedXor64): ...each of these functions, in terms of its
+       equivalent intrinsic implementation.
+
 2022-11-02  Keith Marshall  <keith@users.osdn.me>
 
        Clean up interlocked memory access API declarations.
diff --git a/w32api/include/intrin.h b/w32api/include/intrin.h
new file mode 100644 (file)
index 0000000..384393a
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * intrin.h
+ *
+ * Map Microsoft intrinsics to equivalent GCC built-in functions;
+ * (these mappings are supported ONLY for GCC-4.7, and later).
+ *
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keith@users.osdn.me>
+ * Copyright (C) 2022, MinGW.OSDN Project
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef _INTRIN_H
+#pragma GCC system_header
+#define _INTRIN_H
+
+#ifndef __ATOMIC_ACQ_REL
+#error "Interlocked memory access intrinsics require GCC-4.7 (or later)."
+#endif
+
+/* Already defined, if <winnt.h> has been included beforehand,
+ * we reproduce the definition of _WIN32_INTRINSIC here, in case
+ * the user includes <intrin.h> first; (this is deliberately NOT
+ * guarded, to ensure that consistency is preserved).
+ */
+#define _WIN32_INTRINSIC  extern __inline__ __attribute__((gnu_inline))
+
+/* The following helper macro is local to <intrin.h>; it makes it
+ * more convenient to implement the intrinsic functions.
+ */
+#define __w32api_intrinsic__(NAME, TYPE)  _WIN32_INTRINSIC     \
+  __implement__(NAME, TYPE) {__action__}
+
+/* Declare and implement the InterlockedExchange() function family...
+ */
+long _InterlockedExchange (volatile long *, long);
+short _InterlockedExchange16 (volatile short *, short);
+long long _InterlockedExchange64 (volatile long long *, long long);
+char _InterlockedExchange8 (volatile char *, char);
+
+#define __implement__(NAME, TYPE)  TYPE NAME (volatile TYPE *dest, TYPE val)
+#define __action__  return __atomic_exchange_n (dest, val, __ATOMIC_ACQ_REL);
+
+__w32api_intrinsic__( _InterlockedExchange, long )
+__w32api_intrinsic__( _InterlockedExchange16, short )
+__w32api_intrinsic__( _InterlockedExchange64, long long )
+__w32api_intrinsic__( _InterlockedExchange8, char )
+
+#undef  __action__
+/* The preceding implementation may be readily adapted to deliver
+ * the InterlockedExchangeAdd() family of functions, by the simple
+ * expedient of a redefined action macro...
+ */
+#define __action__  return __atomic_fetch_add (dest, val, __ATOMIC_ACQ_REL);
+
+long _InterlockedExchangeAdd (volatile long *, long);
+short _InterlockedExchangeAdd16 (volatile short *, short);
+long long _InterlockedExchangeAdd64 (volatile long long *, long long);
+char _InterlockedExchangeAdd8 (volatile char *, char);
+
+__w32api_intrinsic__( _InterlockedExchangeAdd, long )
+__w32api_intrinsic__( _InterlockedExchangeAdd16, short )
+__w32api_intrinsic__( _InterlockedExchangeAdd64, long long )
+__w32api_intrinsic__( _InterlockedExchangeAdd8, char )
+
+#undef  __action__
+/* A further redefinition of the action macro delivers a further
+ * adaptation, to the alternative semantics of the InterlockedAdd()
+ * family of functions, (which Microsoft document as supported only
+ * on the Itanium Processor Family, but GCC provides intrinsics to
+ * support the semantics, regardless of architecture)...
+ */
+#define __action__  return __atomic_add_fetch (dest, val, __ATOMIC_ACQ_REL);
+
+/* Microsoft document only 32-bit and 64-bit variants of these;
+ * (there appear to be no 8-bit, or 16-bit variants)...
+ */
+long _InterlockedAdd (volatile long *, long);
+long long _InterlockedAdd64 (volatile long long *, long long);
+
+__w32api_intrinsic__( _InterlockedAdd, long )
+__w32api_intrinsic__( _InterlockedAdd64, long long )
+
+#undef __implement__
+#undef __action__
+
+/* Declare and implement the InterlockedCompareExchange() function family...
+ */
+long _InterlockedCompareExchange (volatile long *, long, long);
+short _InterlockedCompareExchange16 (volatile short *, short, short);
+long long _InterlockedCompareExchange64 (volatile long long *, long long, long long);
+char _InterlockedCompareExchange8 (volatile char *, char, char);
+
+#define __action__  return __atomic_compare_exchange __arglist__ ? exp : *dest;
+#define __implement__(NAME, TYPE)  TYPE NAME (volatile TYPE *dest, TYPE val, TYPE exp)
+#define __arglist__  (dest, &exp, &val, 0, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)
+
+__w32api_intrinsic__( _InterlockedCompareExchange, long )
+__w32api_intrinsic__( _InterlockedCompareExchange16, short )
+__w32api_intrinsic__( _InterlockedCompareExchange64, long long )
+__w32api_intrinsic__( _InterlockedCompareExchange8, char )
+
+#undef __implement__
+#undef __arglist__
+#undef __action__
+
+/* InterlockedIncrement() and InterlockedDecrement() operations;
+ * a common implementation macro may be appled in both cases, but
+ * with a distinct action macro for each...
+ */
+#define __implement__(NAME, TYPE)  TYPE NAME (volatile TYPE *dest)
+
+long _InterlockedDecrement (volatile long *);
+short _InterlockedDecrement16 (volatile short *);
+long long _InterlockedDecrement64 (volatile long long *);
+char _InterlockedDecrement8 (volatile char *);
+
+long _InterlockedIncrement (volatile long *);
+short _InterlockedIncrement16 (volatile short *);
+long long _InterlockedIncrement64 (volatile long long *);
+char _InterlockedIncrement8 (volatile char *);
+
+/* For InterlockedIncrement(), the action is to add one to *dest...
+ */
+#define __action__  return __atomic_add_fetch (dest, 1, __ATOMIC_ACQ_REL);
+
+__w32api_intrinsic__( _InterlockedIncrement, long )
+__w32api_intrinsic__( _InterlockedIncrement16, short )
+__w32api_intrinsic__( _InterlockedIncrement64, long long )
+__w32api_intrinsic__( _InterlockedIncrement8, char )
+
+#undef __action__
+
+/* For InterlockedDecrement(), the action is to subtract one from *dest...
+ */
+#define __action__  return __atomic_sub_fetch (dest, 1, __ATOMIC_ACQ_REL);
+
+__w32api_intrinsic__( _InterlockedDecrement, long )
+__w32api_intrinsic__( _InterlockedDecrement16, short )
+__w32api_intrinsic__( _InterlockedDecrement64, long long )
+__w32api_intrinsic__( _InterlockedDecrement8, char )
+
+#undef __implement__
+#undef __action__
+
+/* Interlocked bit-mask operations; all exhibit the same prototype,
+ * which may be carried through a common implementation macro for each
+ * of InterlockedAnd(), InterlockedOR(), and InterlockedXor() variants,
+ * with just the action macro being redefined for each case...
+ */
+#define __implement__(NAME, TYPE)  TYPE NAME (volatile TYPE *dest, TYPE mask)
+
+/* Declare and implement the InterlockedAnd() function family...
+ */
+long _InterlockedAnd (volatile long *, long);
+short _InterlockedAnd16 (volatile short *, short);
+long long _InterlockedAnd64 (volatile long long *, long long);
+char _InterlockedAnd8 (volatile char *, char);
+
+#define __action__  return __atomic_fetch_and (dest, mask, __ATOMIC_ACQ_REL);
+
+__w32api_intrinsic__( _InterlockedAnd, long )
+__w32api_intrinsic__( _InterlockedAnd16, short )
+__w32api_intrinsic__( _InterlockedAnd64, long long )
+__w32api_intrinsic__( _InterlockedAnd8, char )
+
+#undef __action__
+
+/* Declare and implement the InterlockedOr() function family...
+ */
+long _InterlockedOr (volatile long *, long);
+short _InterlockedOr16 (volatile short *, short);
+long long _InterlockedOr64 (volatile long long *, long long);
+char _InterlockedOr8 (volatile char *, char);
+
+#define __action__  return __atomic_fetch_or (dest, mask, __ATOMIC_ACQ_REL);
+
+__w32api_intrinsic__( _InterlockedOr, long )
+__w32api_intrinsic__( _InterlockedOr16, short )
+__w32api_intrinsic__( _InterlockedOr64, long long )
+__w32api_intrinsic__( _InterlockedOr8, char )
+
+#undef __action__
+
+/* Declare and implement the InterlockedXor() function family...
+ */
+long _InterlockedXor (volatile long *, long);
+short _InterlockedXor16 (volatile short *, short);
+long long _InterlockedXor64 (volatile long long *, long long);
+char _InterlockedXor8 (volatile char *, char);
+
+#define __action__  return __atomic_fetch_xor (dest, mask, __ATOMIC_ACQ_REL);
+
+__w32api_intrinsic__( _InterlockedXor, long )
+__w32api_intrinsic__( _InterlockedXor16, short )
+__w32api_intrinsic__( _InterlockedXor64, long long )
+__w32api_intrinsic__( _InterlockedXor8, char )
+
+#undef __w32api_intrinsic__
+#undef __implement__
+#undef __action__
+
+#endif /* !_INTRIN_H: $RCSfile$: end of file */
index b2a64de..0032991 100644 (file)
@@ -4385,6 +4385,86 @@ PVOID InterlockedExchangePointer (PVOID volatile *D, PVOID X)
   );
 }
 
+#ifdef __ATOMIC_ACQ_REL /* supported by GCC */
+/* This implies a sufficiently recent version of GCC to allow us to
+ * support implementations of Microsoft's interlocked memory access
+ * intrinsic functions, in terms of GCC's atomic operations built-in
+ * functions; the appropriate Microsoft-to-GCC mapping of function
+ * names, together with associated implementations, is specified by
+ * inclusion of...
+ */
+#include "intrin.h"
+
+/* Irrespective of Microsoft's documentation, of earliest supporting
+ * Windows versions, the intrinsic function implementations provided
+ * within "intrin.h" depend, not on the host's version of MS-Windows,
+ * but on the built-in support of the particular version of GCC which
+ * is used to compile the code; thus, we may safely define each of
+ * the following, without regard to Windows version...
+ */
+#define InterlockedAnd                 _InterlockedAnd
+#define InterlockedAnd16               _InterlockedAnd16
+#define InterlockedAnd64               _InterlockedAnd64
+#define InterlockedAnd8                _InterlockedAnd8
+
+#define InterlockedOr                  _InterlockedOr
+#define InterlockedOr16                _InterlockedOr16
+#define InterlockedOr64                _InterlockedOr64
+#define InterlockedOr8                 _InterlockedOr8
+
+#define InterlockedXor                 _InterlockedXor
+#define InterlockedXor16               _InterlockedXor16
+#define InterlockedXor64               _InterlockedXor64
+#define InterlockedXor8                _InterlockedXor8
+
+#define InterlockedDecrement           _InterlockedDecrement
+#define InterlockedDecrement16         _InterlockedDecrement16
+#define InterlockedDecrement64         _InterlockedDecrement64
+#define InterlockedDecrement8          _InterlockedDecrement8
+
+#define InterlockedIncrement           _InterlockedIncrement
+#define InterlockedIncrement16         _InterlockedIncrement16
+#define InterlockedIncrement64         _InterlockedIncrement64
+#define InterlockedIncrement8          _InterlockedIncrement8
+
+#define InterlockedExchange            _InterlockedExchange
+#define InterlockedExchange16          _InterlockedExchange16
+#define InterlockedExchange64          _InterlockedExchange64
+#define InterlockedExchange8           _InterlockedExchange8
+
+#define InterlockedCompareExchange     _InterlockedCompareExchange
+#define InterlockedCompareExchange16   _InterlockedCompareExchange16
+#define InterlockedCompareExchange64   _InterlockedCompareExchange64
+#define InterlockedCompareExchange8    _InterlockedCompareExchange8
+
+#define InterlockedExchangeAdd         _InterlockedExchangeAdd
+#define InterlockedExchangeAdd16       _InterlockedExchangeAdd16
+#define InterlockedExchangeAdd64       _InterlockedExchangeAdd64
+#define InterlockedExchangeAdd8        _InterlockedExchangeAdd8
+
+#define InterlockedAdd                 _InterlockedAdd
+#define InterlockedAdd64               _InterlockedAdd64
+
+/* The following reimplementations of the interlocked pointer exchange
+ * intrinsics allows them to take full advantage of their corresponding
+ * long int exchange intrinsics.
+ */
+_WIN32_INTRINSIC
+#define InterlockedCompareExchangePointer _InterlockedCompareExchangePointer
+PVOID InterlockedCompareExchangePointer (PVOID volatile *D, PVOID X, PVOID C)
+{ return (PVOID)(
+    InterlockedCompareExchange ((LONG volatile *)(D), (LONG)(X), (LONG)(C))
+  );
+}
+_WIN32_INTRINSIC
+#define InterlockedExchangePointer _InterlockedExchangePointer
+PVOID InterlockedExchangePointer (PVOID volatile *D, PVOID X)
+{ return (PVOID)(
+    InterlockedExchange ((LONG volatile *)(D), (LONG)(X))
+  );
+}
+#endif /* __ATOMIC_ACQ_REL supported by GCC */
+
 _END_C_DECLS
 
 #endif /* ! RC_INVOKED */