sched_mtx_tc.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-01-17 Shell the first version
  9. */
  10. #include <rtthread.h>
  11. #include <stdlib.h>
  12. #include "utest.h"
  13. /**
  14. * Stressful Test for Mutex
  15. */
  16. #define TEST_SECONDS 30
  17. #define TEST_LOOP_TICKS (TEST_SECONDS * RT_TICK_PER_SECOND)
  18. #define TEST_THREAD_COUNTS (RT_CPUS_NR)
  19. #define TEST_PROGRESS_COUNTS (36)
  20. #define TEST_PROGRESS_ON (TEST_LOOP_TICKS/TEST_PROGRESS_COUNTS)
  21. #define TEST_PRIORITY_HIGHEST (UTEST_THR_PRIORITY+1)
  22. #define TEST_RANDOM_LATENCY_MAX (1000 * 1000)
  23. static struct rt_semaphore _thr_exit_sem;
  24. static rt_atomic_t _progress_counter;
  25. static rt_atomic_t _exit_flag;
  26. static struct rt_mutex _racing_lock;
  27. static void test_thread_entry(void *param)
  28. {
  29. while (1)
  30. {
  31. rt_mutex_take(&_racing_lock, RT_WAITING_FOREVER);
  32. rt_mutex_release(&_racing_lock);
  33. if (rt_atomic_load(&_exit_flag))
  34. {
  35. break;
  36. }
  37. }
  38. rt_sem_release(&_thr_exit_sem);
  39. }
  40. static void mutex_stress_tc(void)
  41. {
  42. rt_err_t error;
  43. rt_thread_t tester;
  44. const rt_base_t priority_base = TEST_PRIORITY_HIGHEST;
  45. for (size_t i = 0; i < TEST_THREAD_COUNTS; i++)
  46. {
  47. tester = rt_thread_create(
  48. "tester",
  49. test_thread_entry,
  50. (void *)0,
  51. UTEST_THR_STACK_SIZE,
  52. priority_base + (i % (RT_THREAD_PRIORITY_MAX - TEST_PRIORITY_HIGHEST)),
  53. 1);
  54. rt_thread_startup(tester);
  55. }
  56. for (size_t i = 0; i < TEST_LOOP_TICKS; i++)
  57. {
  58. rt_thread_delay(1);
  59. if (rt_atomic_add(&_progress_counter, 1) % TEST_PROGRESS_ON == 0)
  60. uassert_true(1);
  61. }
  62. /* trigger exit request for all sub-threads */
  63. rt_atomic_store(&_exit_flag, 1);
  64. /* waiting for sub-threads to exit */
  65. for (size_t i = 0; i < TEST_THREAD_COUNTS; i++)
  66. {
  67. error = rt_sem_take(&_thr_exit_sem, RT_WAITING_FOREVER);
  68. uassert_int_equal(error, RT_EOK);
  69. }
  70. }
  71. static rt_err_t utest_tc_init(void)
  72. {
  73. int *pseed = rt_malloc(sizeof(int));
  74. srand(*(int *)pseed);
  75. rt_free(pseed);
  76. rt_sem_init(&_thr_exit_sem, "test", 0, RT_IPC_FLAG_PRIO);
  77. rt_mutex_init(&_racing_lock, "ipc", RT_IPC_FLAG_PRIO);
  78. return RT_EOK;
  79. }
  80. static rt_err_t utest_tc_cleanup(void)
  81. {
  82. rt_sem_detach(&_thr_exit_sem);
  83. rt_mutex_detach(&_racing_lock);
  84. return RT_EOK;
  85. }
  86. static void testcase(void)
  87. {
  88. UTEST_UNIT_RUN(mutex_stress_tc);
  89. }
  90. UTEST_TC_EXPORT(testcase, "testcases.kernel.scheduler.mutex", utest_tc_init, utest_tc_cleanup, TEST_SECONDS);