test_pthread_cond_var.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #include <pthread.h>
  2. #include "unity.h"
  3. typedef struct {
  4. pthread_cond_t *cond;
  5. pthread_mutex_t *mutex;
  6. unsigned delay_ms;
  7. } thread_args_t;
  8. static void *thread_signals(void *arg)
  9. {
  10. const thread_args_t *targs = (thread_args_t *)arg;
  11. int r;
  12. r = pthread_mutex_lock(targs->mutex);
  13. TEST_ASSERT_EQUAL_INT(0, r);
  14. r = pthread_cond_signal(targs->cond);
  15. TEST_ASSERT_EQUAL_INT(0, r);
  16. r = pthread_mutex_unlock(targs->mutex);
  17. TEST_ASSERT_EQUAL_INT(0, r);
  18. usleep(targs->delay_ms * 1000);
  19. r = pthread_mutex_lock(targs->mutex);
  20. TEST_ASSERT_EQUAL_INT(0, r);
  21. r = pthread_cond_broadcast(targs->cond);
  22. TEST_ASSERT_EQUAL_INT(0, r);
  23. r = pthread_mutex_unlock(targs->mutex);
  24. TEST_ASSERT_EQUAL_INT(0, r);
  25. return NULL;
  26. }
  27. static void *thread_waits(void *arg)
  28. {
  29. const thread_args_t *targs = (thread_args_t *)arg;
  30. int r;
  31. r = pthread_mutex_lock(targs->mutex);
  32. TEST_ASSERT_EQUAL_INT(0, r);
  33. r = pthread_cond_wait(targs->cond, targs->mutex);
  34. TEST_ASSERT_EQUAL_INT(0, r);
  35. r = pthread_mutex_unlock(targs->mutex);
  36. TEST_ASSERT_EQUAL_INT(0, r);
  37. usleep(targs->delay_ms * 1000);
  38. r = pthread_mutex_lock(targs->mutex);
  39. TEST_ASSERT_EQUAL_INT(0, r);
  40. struct timespec two_seconds;
  41. clock_gettime(CLOCK_REALTIME, &two_seconds);
  42. two_seconds.tv_sec += 2;
  43. r = pthread_cond_timedwait(targs->cond, targs->mutex, &two_seconds);
  44. TEST_ASSERT_EQUAL_INT(0, r);
  45. r = pthread_mutex_unlock(targs->mutex);
  46. TEST_ASSERT_EQUAL_INT(0, r);
  47. return NULL;
  48. }
  49. #define NUM_THREADS 3
  50. TEST_CASE("pthread cond wait", "[pthread]")
  51. {
  52. int r;
  53. pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  54. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  55. struct {
  56. thread_args_t args;
  57. pthread_t thread;
  58. } wait[NUM_THREADS];
  59. struct {
  60. thread_args_t args;
  61. pthread_t thread;
  62. } signal[NUM_THREADS];
  63. wait[0].args.delay_ms = 50;
  64. wait[1].args.delay_ms = 100;
  65. wait[2].args.delay_ms = 200;
  66. signal[0].args.delay_ms = 30;
  67. signal[1].args.delay_ms = 150;
  68. signal[2].args.delay_ms = 500; // highest delay, ensure that broadcast will be received by all waiter threads
  69. for (int i = 0; i < NUM_THREADS; i++) {
  70. wait[i].args.cond = &cond;
  71. wait[i].args.mutex = &mutex;
  72. signal[i].args.cond = &cond;
  73. signal[i].args.mutex = &mutex;
  74. r = pthread_create(&signal[i].thread, NULL, thread_signals, &signal[i].args);
  75. TEST_ASSERT_EQUAL_INT(0, r);
  76. r = pthread_create(&wait[i].thread, NULL, thread_waits, &wait[i].args);
  77. TEST_ASSERT_EQUAL_INT(0, r);
  78. }
  79. for (int i = 0; i < NUM_THREADS; i++) {
  80. r = pthread_join(signal[i].thread, NULL);
  81. TEST_ASSERT_EQUAL_INT(0, r);
  82. pthread_join(wait[i].thread, NULL);
  83. TEST_ASSERT_EQUAL_INT(0, r);
  84. }
  85. pthread_mutex_destroy(&cond);
  86. pthread_mutex_destroy(&mutex);
  87. }