Skip to content

Commit

Permalink
Merge release/1.1.0 into main (#50)
Browse files Browse the repository at this point in the history
## [1.1.0] - 2024-04-01

- Add implementation to support implicit and explicit atomic operations
using
  the `_Interlocked` API
- Implementation has id `patomic_id_MSVC`, kind `patomic_kind_ASM`, and
  supports up to `128` bit operations

---------

Signed-off-by: doodspav <[email protected]>
  • Loading branch information
doodspav authored Jan 6, 2025
1 parent 0b5d803 commit 4e8b886
Show file tree
Hide file tree
Showing 67 changed files with 10,280 additions and 50 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.0] - 2024-04-01

### Added

- Add implementation to support implicit and explicit atomic operations using
the `_Interlocked` API
- Implementation has id `patomic_id_MSVC`, kind `patomic_kind_ASM`, and
supports up to `128` bit operations

## [1.0.0] - 2024-12-25

### Added
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ set(package_name "patomic")
# create base project
project(
patomic
VERSION 1.0.0
VERSION 1.1.0
DESCRIPTION "Portable C90 Atomics Library"
HOMEPAGE_URL "https://github.com/doodspav/patomic"
LANGUAGES C
Expand Down
25 changes: 15 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ This library provides portable access to lock-free atomic operations at runtime
through a unified C90 interface.

Transactional operations are also provided in a similar manner, except there is
no guarantee that a transaction ever succeeds.
no guarantee that a transaction ever succeeds. It should also be noted that
platform support for transactional operations is very rare.

The goal of this library is to provide the foundation for an atomics library in
Python, however there is no reason it could not be used in any other language.
Expand Down Expand Up @@ -255,6 +256,9 @@ them on larger objects.
They come with the drawback that the operation might never succeed; this always
needs to be checked after calling the operation.
Transactions also require hardware support, making it very unlikely that they
are supported on most platforms.
```c
/* setup */
patomic_transaction_t pa = patomic_create_transaction(...);
Expand All @@ -263,13 +267,13 @@ int expected = 0;
const int desired = 5;
/* configure */
patomic_transaction_config_wfb_t config {};
patomic_transaction_config_wfb_t config = {0};
config.width = sizeof(obj);
config.attempts = 1000;
config.fallback_attempts = 1000;
/* perform operation (checks omitted) */
patomic_transaction_result_wfb_t result {};
patomic_transaction_result_wfb_t result = {0};
int ok = pa.ops.xchg_ops.fp_cmpxchg_weak(
&obj, &expected, &desired, config, &result
);
Expand Down Expand Up @@ -326,7 +330,7 @@ int obj;
unsigned int kinds = patomic_opkind_ADD;
kinds = patomic_feature_check_leaf(
&pa.ops,
patomic_opcat_ARI_F
patomic_opcat_ARI_F,
kinds
);
assert(kinds == 0);
Expand Down Expand Up @@ -365,7 +369,7 @@ int obj;
unsigned int kinds = patomic_opkind_ADD;
kinds = patomic_feature_check_leaf_explicit(
&pa.ops,
patomic_opcat_ARI_F
patomic_opcat_ARI_F,
kinds
);
assert(kinds == 0);
Expand Down Expand Up @@ -403,7 +407,7 @@ int obj;
unsigned int kinds = patomic_opkind_ADD;
kinds = patomic_feature_check_leaf_transaction(
&pa.ops,
patomic_opcat_ARI_F
patomic_opcat_ARI_F,
kinds
);
assert(kinds == 0);
Expand All @@ -412,10 +416,10 @@ assert(kinds == 0);
obj = 1;
const int arg = 5;
int ret;
patomic_transaction_config_t config {};
patomic_transaction_config_t config = {0};
config.width = sizeof(obj);
config.attempts = 1000;
patomic_transaction_config_t result {};
patomic_transaction_result_t result = {0};
pa.ops.arithmetic_ops.fp_fetch_add(&obj, &arg, &ret, config, &result);
/* check transaction */
Expand All @@ -429,7 +433,7 @@ assert(ret == 1);

# Traps and Pitfalls

The biggest pitfall is not reading the documentation. These are some others:
The biggest pitfall is not reading the documentation. Here are some others:

##### 1.

Expand All @@ -441,7 +445,8 @@ where both signed and unsigned objects have the same representation.
##### 2.

Where multiple integer types have the same width, non-transaction atomic
operations for that width will use the highest ranking unsigned integer type.
operations for that width will use the highest ranking unsigned integer type
which can be used for atomic operations.

This could cause issues on platforms where multiple integer types have the same
width but different representations (e.g. one has trap bits).
Expand Down
23 changes: 23 additions & 0 deletions cmake/check/HasType.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
# | COMPILER_HAS_LONG_LONG_EXTN | '__extension__ long long' is available as a type |
# | COMPILER_HAS_MS_INT128 | '__int128' is available as a type |
# | COMPILER_HAS_MS_INT128_EXTN | '__extension__ __int128' is available as a type |
# | COMPILER_HAS_MS_INT64 | '__int64' is available as a type |
# | COMPILER_HAS_MS_INT64_EXTN | '__extension__ __int64' is available as a type |
# | COMPILER_HAS_STDINT_INTPTR | <stdint.h> header is available and makes 'intptr_t' available as a type |
# | COMPILER_HAS_STDINT_INTPTR_EXTN | <stdint.h> header is available and makes '__extension__ intptr_t' available as a type |
# | COMPILER_HAS_STDDEF_INTPTR | <stddef.h> header is available and makes 'intptr_t' available as a type |
Expand Down Expand Up @@ -59,6 +61,27 @@ check_c_source_compiles_or_zero(
${COMPILER_HAS_EXTN}
)

# '__int64' is available as a type
check_c_source_compiles_or_zero(
SOURCE
"int main(void) { __int64 x = 0; return (int) x; }"
OUTPUT_VARIABLE
COMPILER_HAS_MS_INT64
)

# '__extension__ __int64' is available as a type
check_c_source_compiles_or_zero(
SOURCE
"int main(void) { __extension__ __int64 x = 0; return (int) x; }"
OUTPUT_VARIABLE
COMPILER_HAS_MS_INT64_EXTN
WILL_SUCCEED_IF_ALL
${COMPILER_HAS_MS_INT64}
${COMPILER_HAS_EXTN}
WILL_FAIL_IF_ANY_NOT
${COMPILER_HAS_EXTN}
)

# <stdint.h> header is available and makes 'intptr_t' available as a type
check_c_source_compiles_or_zero(
SOURCE
Expand Down
28 changes: 28 additions & 0 deletions cmake/in/_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,34 @@
#endif


#ifndef PATOMIC_HAS_MS_INT64
/**
* @addtogroup config.safe
*
* @brief
* '__int64' is available as a type.
*
* @note
* Usually requires: MS compatible(-ish) compiler.
*/
#define PATOMIC_HAS_MS_INT64 @COMPILER_HAS_MS_INT64@
#endif


#ifndef PATOMIC_HAS_MS_INT64_EXTN
/**
* @addtogroup config.safe
*
* @brief
* '__extension__ __int64' is available as a type.
*
* @note
* Usually requires: MS compatible(-ish) compiler.
*/
#define PATOMIC_HAS_MS_INT64_EXTN @COMPILER_HAS_MS_INT64_EXTN@
#endif


#ifndef PATOMIC_HAS_STDINT_INTPTR
/**
* @addtogroup config.safe
Expand Down
7 changes: 6 additions & 1 deletion include/patomic/api/ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ typedef unsigned long patomic_id_t;
/** @brief The id corresponding to the C standard implementation. */
#define patomic_id_STDC (1ul << 0ul)

/** @brief The id corresponding to the _Interlocked intrinsics implementation. */
#define patomic_id_MSVC (1ul << 1ul)


/**
* @addtogroup impl
Expand Down Expand Up @@ -73,7 +76,9 @@ typedef unsigned long patomic_id_t;
* @note
* The BLTN (builtin) kind should only be used where the implementation makes
* a best-faith effort to provide an ASM implementation (e.g. with __atomic),
* otherwise LIB, OS, or DYN should be used.
* otherwise LIB, OS, or DYN should be used. If a builtin or intrinsic is
* guaranteed to compile to specific instructions equivalent to using inline
* assembly, ASM kind may be used.
*/
typedef enum {

Expand Down
1 change: 1 addition & 0 deletions src/impl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# SPDX-License-Identifier: LGPL-3.0-or-later WITH LGPL-3.0-linking-exception

# add all subdirectories
add_subdirectory(msvc)
add_subdirectory(null)
add_subdirectory(std)

Expand Down
12 changes: 12 additions & 0 deletions src/impl/msvc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright (c) doodspav.
# SPDX-License-Identifier: LGPL-3.0-or-later WITH LGPL-3.0-linking-exception

# add all subdirectories
add_subdirectory(ops)

# add directory files to target
target_sources(${target_name} PRIVATE
msvc.h
msvc.c
ops.h
)
100 changes: 100 additions & 0 deletions src/impl/msvc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Visual C++ 4.1 (_MSC_VER == 1010)

Atomic:

- `CompareExchange`
- `Decrement`
- `Exchange`
- `ExchangeAdd`
- `Increment`

# Visual C++ 4.2 (_MSC_VER == 1020)

Nothing.

# Visual Studio 97 (_MSC_VER == 1100)

Nothing.

# Visual Studio 6.0 (_MSC_VER == 1200)

Nothing.

# Visual Studio .NET 2002 (_MSC_VER == 1300)

Atomic:

- `And`
- `Or`
- `Xor`

Other:

- `_ReadWriteBarrier`
- `_WriteBarrier`

# Visual Studio .NET 2003 (_MSC_VER == 1310)

Nothing.

# Visual Studio 2005

TODO: (GHI #49)

# Visual Studio 2008

TODO: (GHI #49)

# Visual Studio 2010

TODO: (GHI #49)

# Visual Studio 2012

TODO: (GHI #49)



# Later

Atomic:

- `_InterlockedAdd`
- `_InterlockedAdd64`
- `_InterlockedAnd8`
- `_InterlockedAnd16`
- `_InterlockedAnd64`
- `_interlockedbittestandreset`
- `_interlockedbittestandreset64`
- `_interlockedbittestandset`
- `_interlockedbittestandset64`
- `_InterlockedCompareExchange8`
- `_InterlockedCompareExchange16`
- `_InterlockedCompareExchange64`
- `_InterlockedCompareExchange128`
- `_InterlockedCompareExchangePointer`
- `_InterlockedDecrement16`
- `_InterlockedDecrement64`
- `_InterlockedExchange8`
- `_InterlockedExchange16`
- `_InterlockedExchange64`
- `_InterlockedExchangeAdd8`
- `_InterlockedExchangeAdd16`
- `_InterlockedExchangeAdd64`
- `_InterlockedExchangePointer`
- `_InterlockedIncrement16`
- `_InterlockedIncrement64`
- `_InterlockedOr8`
- `_InterlockedOr16`
- `_InterlockedOr64`
- `_InterlockedXor8`
- `_InterlockedXor16`
- `_InterlockedXor64`

Other:

- `__writeeflags`
- `__readeflags`
- `__cpuid`
- `__cpuidex`
- `_ReadBarrier`
Loading

0 comments on commit 4e8b886

Please sign in to comment.