test_synchronization.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-03-24 WangXiaoyao Complete testcase for synchronization
  9. */
  10. #ifndef __TEST_SYNCHRONIZATION_H__
  11. #define __TEST_SYNCHRONIZATION_H__
  12. #include "common.h"
  13. #include "semaphore.h"
  14. #ifdef RT_USING_SMP
  15. #define THREAD_CNT RT_CPUS_NR
  16. #define TEST_TIMES 2000
  17. #define PRIO (UTEST_THR_PRIORITY + 1)
  18. /* size of mapping buffer */
  19. #define BUF_SIZE (64ul << 10)
  20. /* engage with sibling */
  21. struct rt_semaphore done;
  22. static semaphore_t sem1[THREAD_CNT / 2];
  23. static semaphore_t sem2[THREAD_CNT / 2];
  24. static void *map(void)
  25. {
  26. int err;
  27. int flags = MMF_PREFETCH;
  28. size_t attr = MMU_MAP_K_RWCB;
  29. void *vaddr = 0;
  30. err =
  31. rt_aspace_map(&rt_kernel_space, &vaddr, BUF_SIZE, attr, flags, &rt_mm_dummy_mapper, 0);
  32. if (err)
  33. uassert_true(0);
  34. return vaddr;
  35. }
  36. static void unmap(void *buf)
  37. {
  38. int err;
  39. err =
  40. rt_aspace_unmap(&rt_kernel_space, buf);
  41. if (err)
  42. uassert_true(0);
  43. return ;
  44. }
  45. static void group1_entry(void *param)
  46. {
  47. const size_t id = (size_t)param;
  48. size_t test_times = TEST_TIMES;
  49. size_t alive = test_times / 10;
  50. void *buf;
  51. while (test_times--)
  52. {
  53. if (test_times % alive == 0)
  54. uassert_true(1);
  55. buf = map();
  56. memset(buf, 'A' + id, BUF_SIZE);
  57. /* if other core write to our cache, force the changes to be visible to us */
  58. rt_hw_dmb();
  59. if (memtest(buf, 'A' + id, BUF_SIZE))
  60. uassert_true(0);
  61. semaphore_signal(&sem1[id]);
  62. semaphore_wait(&sem2[id]);
  63. unmap(buf);
  64. }
  65. rt_sem_release(&done);
  66. return;
  67. }
  68. static void group2_entry(void *param)
  69. {
  70. const size_t id = (size_t)param;
  71. size_t test_times = TEST_TIMES;
  72. size_t alive = test_times / 10;
  73. void *buf;
  74. while (test_times--)
  75. {
  76. if (test_times % alive == 0)
  77. uassert_true(1);
  78. semaphore_signal(&sem2[id]);
  79. semaphore_wait(&sem1[id]);
  80. buf = map();
  81. memset(buf, 'a' + id, BUF_SIZE);
  82. /* if other core write to our cache, force the changes to be visible to us */
  83. rt_hw_dmb();
  84. if (memtest(buf, 'a' + id, BUF_SIZE))
  85. uassert_true(0);
  86. unmap(buf);
  87. }
  88. rt_sem_release(&done);
  89. return;
  90. }
  91. /**
  92. * @brief On a smp system, we create at least 4 threads
  93. * 2 doing map, 2 doing unmapping at the same moment
  94. */
  95. static void synchronization_tc(void)
  96. {
  97. rt_thread_t group1[THREAD_CNT / 2];
  98. rt_thread_t group2[THREAD_CNT / 2];
  99. rt_sem_init(&done, __func__, 0, RT_IPC_FLAG_FIFO);
  100. for (size_t i = 0; i < THREAD_CNT / 2; i++)
  101. {
  102. char name[RT_NAME_MAX];
  103. rt_sprintf(name, "grp1_%d", i);
  104. group1[i] =
  105. rt_thread_create(name, group1_entry, (void *)i, ARCH_PAGE_SIZE, PRIO, 10);
  106. uassert_true(!!group1[i]);
  107. semaphore_init(&sem1[i], 0);
  108. uassert_true(!rt_thread_startup(group1[i]));
  109. }
  110. for (size_t i = 0; i < THREAD_CNT / 2; i++)
  111. {
  112. char name[RT_NAME_MAX];
  113. rt_sprintf(name, "grp2_%d", i);
  114. group2[i] =
  115. rt_thread_create(name, group2_entry, (void *)i, ARCH_PAGE_SIZE, PRIO, 10);
  116. uassert_true(!!group2[i]);
  117. semaphore_init(&sem2[i], 0);
  118. uassert_true(!rt_thread_startup(group2[i]));
  119. }
  120. /* wait all thread exit */
  121. for (size_t i = 0; i < (THREAD_CNT / 2 * 2); i++)
  122. {
  123. rt_sem_take(&done, RT_WAITING_FOREVER);
  124. }
  125. LOG_I("all threads exit");
  126. rt_sem_detach(&done);
  127. }
  128. #else /* RT_USING_SMP */
  129. static void synchronization_tc(void)
  130. {
  131. uassert_true(1);
  132. }
  133. #endif /* RT_USING_SMP */
  134. #endif /* __TEST_SYNCHRONIZATION_H__ */