mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
116 lines
2.9 KiB
C
116 lines
2.9 KiB
C
|
#include <pthread.h>
|
||
|
#include "unity.h"
|
||
|
|
||
|
typedef struct {
|
||
|
pthread_cond_t *cond;
|
||
|
pthread_mutex_t *mutex;
|
||
|
unsigned delay_ms;
|
||
|
} thread_args_t;
|
||
|
|
||
|
static void *thread_signals(void *arg)
|
||
|
{
|
||
|
const thread_args_t *targs = (thread_args_t *)arg;
|
||
|
int r;
|
||
|
|
||
|
r = pthread_mutex_lock(targs->mutex);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
|
||
|
r = pthread_cond_signal(targs->cond);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
|
||
|
r = pthread_mutex_unlock(targs->mutex);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
|
||
|
usleep(targs->delay_ms * 1000);
|
||
|
|
||
|
r = pthread_mutex_lock(targs->mutex);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
|
||
|
r = pthread_cond_broadcast(targs->cond);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
|
||
|
r = pthread_mutex_unlock(targs->mutex);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static void *thread_waits(void *arg)
|
||
|
{
|
||
|
const thread_args_t *targs = (thread_args_t *)arg;
|
||
|
int r;
|
||
|
|
||
|
r = pthread_mutex_lock(targs->mutex);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
|
||
|
r = pthread_cond_wait(targs->cond, targs->mutex);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
|
||
|
r = pthread_mutex_unlock(targs->mutex);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
|
||
|
usleep(targs->delay_ms * 1000);
|
||
|
|
||
|
r = pthread_mutex_lock(targs->mutex);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
|
||
|
struct timespec two_seconds;
|
||
|
clock_gettime(CLOCK_REALTIME, &two_seconds);
|
||
|
two_seconds.tv_sec += 2;
|
||
|
r = pthread_cond_timedwait(targs->cond, targs->mutex, &two_seconds);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
|
||
|
r = pthread_mutex_unlock(targs->mutex);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
#define NUM_THREADS 3
|
||
|
|
||
|
TEST_CASE("pthread cond wait", "[pthread]")
|
||
|
{
|
||
|
int r;
|
||
|
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||
|
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||
|
|
||
|
struct {
|
||
|
thread_args_t args;
|
||
|
pthread_t thread;
|
||
|
} wait[NUM_THREADS];
|
||
|
struct {
|
||
|
thread_args_t args;
|
||
|
pthread_t thread;
|
||
|
} signal[NUM_THREADS];
|
||
|
|
||
|
wait[0].args.delay_ms = 50;
|
||
|
wait[1].args.delay_ms = 100;
|
||
|
wait[2].args.delay_ms = 200;
|
||
|
|
||
|
signal[0].args.delay_ms = 30;
|
||
|
signal[1].args.delay_ms = 150;
|
||
|
signal[2].args.delay_ms = 500; // highest delay, ensure that broadcast will be received by all waiter threads
|
||
|
|
||
|
for (int i = 0; i < NUM_THREADS; i++) {
|
||
|
wait[i].args.cond = &cond;
|
||
|
wait[i].args.mutex = &mutex;
|
||
|
signal[i].args.cond = &cond;
|
||
|
signal[i].args.mutex = &mutex;
|
||
|
|
||
|
r = pthread_create(&signal[i].thread, NULL, thread_signals, &signal[i].args);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
r = pthread_create(&wait[i].thread, NULL, thread_waits, &wait[i].args);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < NUM_THREADS; i++) {
|
||
|
r = pthread_join(signal[i].thread, NULL);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
pthread_join(wait[i].thread, NULL);
|
||
|
TEST_ASSERT_EQUAL_INT(0, r);
|
||
|
}
|
||
|
|
||
|
pthread_mutex_destroy(&cond);
|
||
|
pthread_mutex_destroy(&mutex);
|
||
|
}
|