mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-04 00:51:42 +01: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);
 | 
						|
}
 |