test_stdatomic.c 3.6 KB

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