test_pthread.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #include <errno.h>
  2. #include "freertos/FreeRTOS.h"
  3. #include "freertos/task.h"
  4. #include "esp_pthread.h"
  5. #include <pthread.h>
  6. #include "unity.h"
  7. static void *compute_square(void *arg)
  8. {
  9. int *num = (int *) arg;
  10. *num = (*num) * (*num);
  11. pthread_exit((void *) num);
  12. return NULL;
  13. }
  14. TEST_CASE("pthread create join", "[pthread]")
  15. {
  16. int res = 0;
  17. volatile int num = 7;
  18. volatile bool attr_init = false;
  19. void *thread_rval = NULL;
  20. pthread_t new_thread = (pthread_t)NULL;
  21. pthread_attr_t attr;
  22. if (TEST_PROTECT()) {
  23. res = pthread_attr_init(&attr);
  24. TEST_ASSERT_EQUAL_INT(0, res);
  25. attr_init = true;
  26. res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  27. TEST_ASSERT_EQUAL_INT(0, res);
  28. res = pthread_create(&new_thread, &attr, compute_square, (void *) &num);
  29. TEST_ASSERT_EQUAL_INT(0, res);
  30. res = pthread_join(new_thread, &thread_rval);
  31. TEST_ASSERT_EQUAL_INT(EDEADLK, res);
  32. vTaskDelay(100 / portTICK_PERIOD_MS);
  33. TEST_ASSERT_EQUAL_INT(49, num);
  34. res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  35. TEST_ASSERT_EQUAL_INT(0, res);
  36. res = pthread_create(&new_thread, &attr, compute_square, (void *) &num);
  37. TEST_ASSERT_EQUAL_INT(0, res);
  38. res = pthread_join(new_thread, &thread_rval);
  39. TEST_ASSERT_EQUAL_INT(0, res);
  40. TEST_ASSERT_EQUAL_INT(2401, num);
  41. TEST_ASSERT_EQUAL_PTR(&num, thread_rval);
  42. }
  43. if (attr_init) {
  44. pthread_attr_destroy(&attr);
  45. }
  46. }
  47. TEST_CASE("pthread attr init destroy", "[pthread]")
  48. {
  49. int res = 0;
  50. size_t stack_size_1 = 0, stack_size_2 = 0;
  51. volatile bool attr_init = pdFALSE;
  52. pthread_attr_t attr;
  53. if (TEST_PROTECT()) {
  54. res = pthread_attr_init(&attr);
  55. TEST_ASSERT_EQUAL_INT(0, res);
  56. attr_init = true;
  57. res = pthread_attr_getstacksize(&attr, &stack_size_1);
  58. TEST_ASSERT_EQUAL_INT(0, res);
  59. res = pthread_attr_setstacksize(&attr, stack_size_1);
  60. TEST_ASSERT_EQUAL_INT(0, res);
  61. res = pthread_attr_getstacksize(&attr, &stack_size_2);
  62. TEST_ASSERT_EQUAL_INT(0, res);
  63. TEST_ASSERT_EQUAL_INT(stack_size_2, stack_size_1);
  64. stack_size_1 = PTHREAD_STACK_MIN - 1;
  65. res = pthread_attr_setstacksize(&attr, stack_size_1);
  66. TEST_ASSERT_EQUAL_INT(EINVAL, res);
  67. }
  68. if (attr_init) {
  69. TEST_ASSERT_EQUAL_INT(0, pthread_attr_destroy(&attr));
  70. }
  71. }
  72. static void *unlock_mutex(void *arg)
  73. {
  74. pthread_mutex_t *mutex = (pthread_mutex_t *) arg;
  75. intptr_t res = (intptr_t) pthread_mutex_unlock(mutex);
  76. pthread_exit((void *) res);
  77. return NULL;
  78. }
  79. static void test_mutex_lock_unlock(int mutex_type)
  80. {
  81. int res = 0;
  82. int set_type = -1;
  83. volatile bool attr_created = false;
  84. volatile bool mutex_created = false;
  85. volatile intptr_t thread_rval = 0;
  86. pthread_mutex_t mutex;
  87. pthread_mutexattr_t attr;
  88. pthread_t new_thread;
  89. if (TEST_PROTECT()) {
  90. res = pthread_mutexattr_init(&attr);
  91. TEST_ASSERT_EQUAL_INT(0, res);
  92. attr_created = true;
  93. res = pthread_mutexattr_settype(&attr, mutex_type);
  94. TEST_ASSERT_EQUAL_INT(0, res);
  95. res = pthread_mutexattr_gettype(&attr, &set_type);
  96. TEST_ASSERT_EQUAL_INT(0, res);
  97. TEST_ASSERT_EQUAL_INT(mutex_type, set_type);
  98. res = pthread_mutex_init(&mutex, &attr);
  99. TEST_ASSERT_EQUAL_INT(0, res);
  100. mutex_created = true;
  101. res = pthread_mutex_lock(&mutex);
  102. TEST_ASSERT_EQUAL_INT(0, res);
  103. res = pthread_mutex_lock(&mutex);
  104. if(mutex_type == PTHREAD_MUTEX_ERRORCHECK) {
  105. TEST_ASSERT_EQUAL_INT(EDEADLK, res);
  106. } else {
  107. TEST_ASSERT_EQUAL_INT(0, res);
  108. res = pthread_mutex_unlock(&mutex);
  109. TEST_ASSERT_EQUAL_INT(0, res);
  110. }
  111. pthread_create(&new_thread, NULL, unlock_mutex, &mutex);
  112. pthread_join(new_thread, (void **) &thread_rval);
  113. TEST_ASSERT_EQUAL_INT(EPERM, (int) thread_rval);
  114. res = pthread_mutex_unlock(&mutex);
  115. TEST_ASSERT_EQUAL_INT(0, res);
  116. }
  117. if (attr_created) {
  118. pthread_mutexattr_destroy(&attr);
  119. }
  120. if (mutex_created) {
  121. pthread_mutex_destroy(&mutex);
  122. }
  123. }
  124. TEST_CASE("pthread mutex lock unlock", "[pthread]")
  125. {
  126. int res = 0;
  127. /* Present behavior of mutex initializer is unlike what is
  128. * defined in Posix standard, ie. calling pthread_mutex_lock
  129. * on such a mutex would internally cause dynamic allocation.
  130. * Therefore pthread_mutex_destroy needs to be called in
  131. * order to avoid memory leak. */
  132. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  133. res = pthread_mutex_lock(&mutex);
  134. TEST_ASSERT_EQUAL_INT(0, res);
  135. res = pthread_mutex_unlock(&mutex);
  136. TEST_ASSERT_EQUAL_INT(0, res);
  137. /* This deviates from the Posix standard static mutex behavior.
  138. * This needs to be removed in the future when standard mutex
  139. * initializer is supported */
  140. pthread_mutex_destroy(&mutex);
  141. test_mutex_lock_unlock(PTHREAD_MUTEX_ERRORCHECK);
  142. test_mutex_lock_unlock(PTHREAD_MUTEX_RECURSIVE);
  143. }
  144. static void timespec_add_nano(struct timespec * out, struct timespec * in, long val)
  145. {
  146. out->tv_nsec = val + in->tv_nsec;
  147. if (out->tv_nsec < (in->tv_nsec)) {
  148. out->tv_sec += 1;
  149. }
  150. }
  151. TEST_CASE("pthread mutex trylock timedlock", "[pthread]")
  152. {
  153. int res = 0;
  154. volatile bool mutex_created = false;
  155. pthread_mutex_t mutex;
  156. struct timespec abs_timeout;
  157. if (TEST_PROTECT()) {
  158. res = pthread_mutex_init(&mutex, NULL);
  159. TEST_ASSERT_EQUAL_INT(0, res);
  160. mutex_created = true;
  161. res = pthread_mutex_trylock(&mutex);
  162. TEST_ASSERT_EQUAL_INT(0, res);
  163. res = pthread_mutex_trylock(&mutex);
  164. TEST_ASSERT_EQUAL_INT(EBUSY, res);
  165. clock_gettime(CLOCK_REALTIME, &abs_timeout);
  166. timespec_add_nano(&abs_timeout, &abs_timeout, 100000000LL);
  167. res = pthread_mutex_timedlock(&mutex, &abs_timeout);
  168. TEST_ASSERT_EQUAL_INT(ETIMEDOUT, res);
  169. res = pthread_mutex_unlock(&mutex);
  170. TEST_ASSERT_EQUAL_INT(0, res);
  171. }
  172. if (mutex_created) {
  173. pthread_mutex_destroy(&mutex);
  174. }
  175. }