Atomics: Add 16 bit fetch + AND and fetch + OR signed integer operations

I could use a 16 bit atomic fetch + AND for D9719. The alternative would be to
turn a `short` into a `int` in DNA, which isn't a nice workaround.

Also adds tests for the new functions.
This commit is contained in:
Julian Eisel 2020-12-04 16:25:49 +01:00
parent 1d2c70d761
commit f5eaf67e34
4 changed files with 69 additions and 0 deletions

View File

@ -87,6 +87,9 @@ ATOMIC_INLINE int32_t atomic_fetch_and_add_int32(int32_t *p, int32_t x);
ATOMIC_INLINE int32_t atomic_fetch_and_or_int32(int32_t *p, int32_t x);
ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x);
ATOMIC_INLINE int16_t atomic_fetch_and_or_int16(int16_t *p, int16_t b);
ATOMIC_INLINE int16_t atomic_fetch_and_and_int16(int16_t *p, int16_t b);
ATOMIC_INLINE uint8_t atomic_fetch_and_or_uint8(uint8_t *p, uint8_t b);
ATOMIC_INLINE uint8_t atomic_fetch_and_and_uint8(uint8_t *p, uint8_t b);

View File

@ -162,6 +162,20 @@ ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x)
return InterlockedAnd((long *)p, x);
}
/******************************************************************************/
/* 16-bit operations. */
/* Signed */
ATOMIC_INLINE int16_t atomic_fetch_and_or_int16(int16_t *p, int16_t x)
{
return InterlockedOr16((short *)p, x);
}
ATOMIC_INLINE int16_t atomic_fetch_and_and_int16(int16_t *p, int16_t x)
{
return InterlockedAnd16((short *)p, x);
}
/******************************************************************************/
/* 8-bit operations. */

View File

@ -55,6 +55,7 @@
* its gcc doesn't have __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n defined.
*/
# define JE_FORCE_SYNC_COMPARE_AND_SWAP_1
# define JE_FORCE_SYNC_COMPARE_AND_SWAP_2
# define JE_FORCE_SYNC_COMPARE_AND_SWAP_4
# define JE_FORCE_SYNC_COMPARE_AND_SWAP_8
#endif
@ -325,6 +326,24 @@ ATOMIC_INLINE int32_t atomic_fetch_and_and_int32(int32_t *p, int32_t x)
# error "Missing implementation for 32-bit atomic operations"
#endif
/******************************************************************************/
/* 16-bit operations. */
#if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_2))
/* Signed */
ATOMIC_INLINE int16_t atomic_fetch_and_and_int16(int16_t *p, int16_t b)
{
return __sync_fetch_and_and(p, b);
}
ATOMIC_INLINE int16_t atomic_fetch_and_or_int16(int16_t *p, int16_t b)
{
return __sync_fetch_and_or(p, b);
}
#else
# error "Missing implementation for 16-bit atomic operations"
#endif
/******************************************************************************/
/* 8-bit operations. */
#if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_1))

View File

@ -559,6 +559,39 @@ TEST(atomic, atomic_fetch_and_and_int32)
/** \} */
/** \name 16 bit signed int atomics
* \{ */
TEST(atomic, atomic_fetch_and_or_int16)
{
{
int16_t value = 12;
EXPECT_EQ(atomic_fetch_and_or_int16(&value, 5), 12);
EXPECT_EQ(value, 13);
}
{
int16_t value = 0x1234;
EXPECT_EQ(atomic_fetch_and_or_int16(&value, -0x5678), 0x1234);
EXPECT_EQ(value, -0x4444);
}
}
TEST(atomic, atomic_fetch_and_and_int16)
{
{
int16_t value = 12;
EXPECT_EQ(atomic_fetch_and_and_int16(&value, 5), 12);
EXPECT_EQ(value, 4);
}
{
int16_t value = 0x1234;
EXPECT_EQ(atomic_fetch_and_and_int16(&value, -0x789A), 0x1234);
EXPECT_EQ(value, 0x224);
}
}
/** \name 8 bit unsigned int atomics
* \{ */