test_stdatomic.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #include <assert.h>
  2. #include <stdint.h>
  3. #include <stddef.h>
  4. #include <stdbool.h>
  5. #include <stdatomic.h>
  6. #include <stdio.h>
  7. #include <pthread.h>
  8. #include "unity.h"
  9. #include "unity_fixture.h"
  10. /* non-static to prevent optimization */
  11. atomic_ullong g_atomic64;
  12. atomic_uint g_atomic32;
  13. atomic_ushort g_atomic16;
  14. atomic_uchar g_atomic8;
  15. TEST_GROUP(stdatomic);
  16. TEST_SETUP(stdatomic)
  17. {
  18. }
  19. TEST_TEAR_DOWN(stdatomic)
  20. {
  21. }
  22. TEST(stdatomic, test_64bit_atomics)
  23. {
  24. unsigned long long x64 = 0;
  25. g_atomic64 = 0; // calls atomic_store
  26. x64 += atomic_fetch_or (&g_atomic64, 0x1111111111111111ULL);
  27. x64 += atomic_fetch_xor(&g_atomic64, 0x3333333333333333ULL);
  28. x64 += atomic_fetch_and(&g_atomic64, 0xf0f0f0f0f0f0f0f0ULL);
  29. x64 += atomic_fetch_sub(&g_atomic64, 0x0f0f0f0f0f0f0f0fULL);
  30. x64 += atomic_fetch_add(&g_atomic64, 0x2222222222222222ULL);
  31. TEST_ASSERT_EQUAL_HEX64(0x6464646464646464ULL, x64);
  32. TEST_ASSERT_EQUAL_HEX64(0x3333333333333333ULL, g_atomic64); // calls atomic_load
  33. }
  34. TEST(stdatomic, test_32bit_atomics)
  35. {
  36. unsigned int x32 = 0;
  37. g_atomic32 = 0;
  38. x32 += atomic_fetch_or (&g_atomic32, 0x11111111U);
  39. x32 += atomic_fetch_xor(&g_atomic32, 0x33333333U);
  40. x32 += atomic_fetch_and(&g_atomic32, 0xf0f0f0f0U);
  41. x32 += atomic_fetch_sub(&g_atomic32, 0x0f0f0f0fU);
  42. x32 += atomic_fetch_add(&g_atomic32, 0x22222222U);
  43. TEST_ASSERT_EQUAL_HEX32(0x64646464, x32);
  44. TEST_ASSERT_EQUAL_HEX32(0x33333333, g_atomic32);
  45. }
  46. TEST(stdatomic, test_16bit_atomics)
  47. {
  48. unsigned int x16 = 0;
  49. g_atomic16 = 0;
  50. x16 += atomic_fetch_or (&g_atomic16, 0x1111);
  51. x16 += atomic_fetch_xor(&g_atomic16, 0x3333);
  52. x16 += atomic_fetch_and(&g_atomic16, 0xf0f0);
  53. x16 += atomic_fetch_sub(&g_atomic16, 0x0f0f);
  54. x16 += atomic_fetch_add(&g_atomic16, 0x2222);
  55. TEST_ASSERT_EQUAL_HEX16(0x6464, x16);
  56. TEST_ASSERT_EQUAL_HEX16(0x3333, g_atomic16);
  57. }
  58. TEST(stdatomic, test_8bit_atomics)
  59. {
  60. unsigned int x8 = 0;
  61. g_atomic8 = 0;
  62. x8 += atomic_fetch_or (&g_atomic8, 0x11);
  63. x8 += atomic_fetch_xor(&g_atomic8, 0x33);
  64. x8 += atomic_fetch_and(&g_atomic8, 0xf0);
  65. x8 += atomic_fetch_sub(&g_atomic8, 0x0f);
  66. x8 += atomic_fetch_add(&g_atomic8, 0x22);
  67. TEST_ASSERT_EQUAL_HEX8(0x64, x8);
  68. TEST_ASSERT_EQUAL_HEX16(0x33, g_atomic8);
  69. }
  70. static void *exclusion_test_task(void *arg);
  71. TEST(stdatomic, test_exclusion)
  72. {
  73. /* Check 64-bit atomics for exclusion.
  74. * Only atomic_fetch_add/sub are checked, since all 64-bit atomics use the
  75. * same locking implementation.
  76. */
  77. g_atomic64 = 0;
  78. pthread_t thread1;
  79. pthread_t thread2;
  80. pthread_create(&thread1, NULL, exclusion_test_task, (void*) 1);
  81. pthread_create(&thread2, NULL, exclusion_test_task, (void*) 0);
  82. pthread_join(thread1, NULL);
  83. pthread_join(thread2, NULL);
  84. TEST_ASSERT_EQUAL(0, g_atomic64);
  85. }
  86. /* Two threads run in parallel, incrementing and decrementing
  87. * a single 64-bit variable. In the end the variable should
  88. * have the same value as at the start.
  89. */
  90. static void* exclusion_test_task(void *varg)
  91. {
  92. int arg = (int) varg;
  93. for (int i = 0; i < 1000000; ++i) {
  94. if (arg == 0) {
  95. atomic_fetch_add(&g_atomic64, 1ULL);
  96. } else {
  97. atomic_fetch_sub(&g_atomic64, 1ULL);
  98. }
  99. }
  100. return NULL;
  101. }
  102. TEST_GROUP_RUNNER(stdatomic)
  103. {
  104. RUN_TEST_CASE(stdatomic, test_64bit_atomics)
  105. RUN_TEST_CASE(stdatomic, test_32bit_atomics)
  106. RUN_TEST_CASE(stdatomic, test_16bit_atomics)
  107. RUN_TEST_CASE(stdatomic, test_8bit_atomics)
  108. RUN_TEST_CASE(stdatomic, test_exclusion)
  109. }