condvar_broadcast_tc.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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-11-20 Shell add test suites
  9. */
  10. #include "common.h"
  11. #include "rtconfig.h"
  12. #include "utest_assert.h"
  13. #include <rtdevice.h>
  14. #include <rtdef.h>
  15. static struct rt_mutex _local_mtx;
  16. static struct rt_condvar _local_cv;
  17. #define THREAD_NUM 8
  18. #define STACK_SIZE (0x2000)
  19. static volatile int start_num;
  20. static volatile int waken_num;
  21. static void thr_func(void *arg)
  22. {
  23. int rc;
  24. rt_mutex_t mutex = &_local_mtx;
  25. rt_condvar_t cond = &_local_cv;
  26. rt_mutex_take(mutex, RT_WAITING_FOREVER);
  27. start_num++;
  28. rc = rt_condvar_timedwait(cond, mutex, RT_KILLABLE, RT_WAITING_FOREVER);
  29. if (rc != 0)
  30. {
  31. LOG_E("cond_wait returned %d\n", rc);
  32. uassert_false(1);
  33. return;
  34. }
  35. if (rt_mutex_get_owner(mutex) != rt_thread_self())
  36. {
  37. LOG_E("Should not be able to lock the mutex again");
  38. uassert_false(1);
  39. return;
  40. }
  41. else
  42. {
  43. uassert_true(1);
  44. }
  45. LOG_I("Thread was wakened and acquired the mutex again");
  46. waken_num++;
  47. if (rt_mutex_release(mutex) != 0)
  48. {
  49. LOG_E("Failed to release the mutex");
  50. uassert_false(1);
  51. return;
  52. }
  53. else
  54. {
  55. uassert_true(1);
  56. }
  57. return ;
  58. }
  59. static void *stack_addr[THREAD_NUM];
  60. static void condvar_broadcast_tc(void)
  61. {
  62. rt_mutex_t mutex = &_local_mtx;
  63. rt_condvar_t cond = &_local_cv;
  64. struct rt_thread thread[THREAD_NUM];
  65. for (size_t i = 0; i < THREAD_NUM; i++)
  66. {
  67. if (rt_thread_init(&thread[i], "utest", thr_func, RT_NULL,
  68. stack_addr[i], STACK_SIZE, 25, 100) != 0)
  69. {
  70. LOG_E("Fail to create thread[%d]\n", i);
  71. return;
  72. }
  73. rt_thread_startup(&thread[i]);
  74. }
  75. while (start_num < THREAD_NUM)
  76. rt_thread_mdelay(1);
  77. rt_mutex_take(mutex, RT_WAITING_FOREVER);
  78. if (rt_condvar_broadcast(cond))
  79. {
  80. uassert_false(1);
  81. return ;
  82. }
  83. rt_mutex_release(mutex);
  84. rt_thread_mdelay(1);
  85. if (waken_num < THREAD_NUM)
  86. {
  87. LOG_E("[Main thread] Not all waiters were wakened\n");
  88. uassert_false(1);
  89. return ;
  90. }
  91. else
  92. {
  93. utest_int_equal(waken_num, THREAD_NUM);
  94. }
  95. LOG_I("[Main thread] all waiters were wakened\n");
  96. return;
  97. }
  98. static rt_err_t utest_tc_init(void)
  99. {
  100. start_num = 0;
  101. waken_num = 0;
  102. if (rt_mutex_init(&_local_mtx, "utest", RT_IPC_FLAG_PRIO) != 0)
  103. {
  104. perror("pthread_mutex_init() error");
  105. uassert_false(1);
  106. return -1;
  107. }
  108. rt_condvar_init(&_local_cv, NULL);
  109. for (size_t i = 0; i < THREAD_NUM; i++)
  110. {
  111. stack_addr[i] =
  112. rt_pages_alloc_ext(rt_page_bits(STACK_SIZE), PAGE_ANY_AVAILABLE);
  113. utest_int_not_equal(stack_addr[i], RT_NULL);
  114. }
  115. return RT_EOK;
  116. }
  117. static rt_err_t utest_tc_cleanup(void)
  118. {
  119. rt_mutex_detach(&_local_mtx);
  120. rt_condvar_detach(&_local_cv);
  121. for (size_t i = 0; i < THREAD_NUM; i++)
  122. {
  123. rt_pages_free(stack_addr[i], rt_page_bits(STACK_SIZE));
  124. stack_addr[i] = 0;
  125. }
  126. return RT_EOK;
  127. }
  128. static void testcase(void)
  129. {
  130. UTEST_UNIT_RUN(condvar_broadcast_tc);
  131. }
  132. UTEST_TC_EXPORT(testcase, "testcases.ipc.condvar.broadcast", utest_tc_init,
  133. utest_tc_cleanup, 10);