100 lines
2.2 KiB
C
100 lines
2.2 KiB
C
/*
|
|
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <pthread.h>
|
|
|
|
#include "metal-test.h"
|
|
#include <metal/log.h>
|
|
#include <metal/sys.h>
|
|
#include <metal/mutex.h>
|
|
#include <metal/condition.h>
|
|
|
|
#define COUNTER_MAX 10
|
|
|
|
#define THREADS 10
|
|
|
|
METAL_MUTEX_DEFINE(lock);
|
|
static struct metal_condition nempty_condv = METAL_CONDITION_INIT;
|
|
static struct metal_condition nfull_condv = METAL_CONDITION_INIT;
|
|
static unsigned int counter;
|
|
|
|
static void *consumer_thread(void *arg)
|
|
{
|
|
(void)arg;
|
|
metal_mutex_acquire(&lock);
|
|
while (!counter)
|
|
metal_condition_wait(&nempty_condv, &lock);
|
|
counter--;
|
|
metal_condition_signal(&nfull_condv);
|
|
metal_mutex_release(&lock);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void *producer_thread(void *arg)
|
|
{
|
|
(void)arg;
|
|
metal_mutex_acquire(&lock);
|
|
while (counter == COUNTER_MAX)
|
|
metal_condition_wait(&nfull_condv, &lock);
|
|
counter++;
|
|
metal_condition_signal(&nempty_condv);
|
|
metal_mutex_release(&lock);
|
|
|
|
return NULL;
|
|
}
|
|
static int condition(void)
|
|
{
|
|
int ret;
|
|
int ts_created;
|
|
pthread_t tids[THREADS];
|
|
|
|
/** TC1 consumer threads go first */
|
|
/** create 10 consumer threads first */
|
|
ret = metal_run_noblock(THREADS, consumer_thread, NULL, tids,
|
|
&ts_created);
|
|
if (ret < 0) {
|
|
metal_log(METAL_LOG_ERROR, "Failed to create consumer thread: %d.\n",
|
|
ret);
|
|
goto out;
|
|
}
|
|
|
|
/** create 10 producer threads next */
|
|
ret = metal_run(THREADS, producer_thread, NULL);
|
|
if (ret < 0) {
|
|
metal_log(METAL_LOG_ERROR, "Failed to create producer thread: %d.\n",
|
|
ret);
|
|
goto out;
|
|
}
|
|
|
|
/** wait for consumer threads to finish */
|
|
metal_finish_threads(THREADS, (void *)tids);
|
|
|
|
/** TC2 producer threads go first */
|
|
/** create 10 producer threads first */
|
|
ret = metal_run_noblock(THREADS, producer_thread, NULL, tids,
|
|
&ts_created);
|
|
if (ret < 0) {
|
|
metal_log(METAL_LOG_ERROR, "Failed to create consumer thread: %d.\n",
|
|
ret);
|
|
goto out;
|
|
}
|
|
|
|
/** create 10 consumer threads next */
|
|
ret = metal_run(THREADS, consumer_thread, NULL);
|
|
if (ret < 0) {
|
|
metal_log(METAL_LOG_ERROR, "Failed to create producer thread: %d.\n",
|
|
ret);
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
/** wait for producer threads to finish */
|
|
metal_finish_threads(THREADS, (void *)tids);
|
|
return ret;
|
|
}
|
|
METAL_ADD_TEST(condition);
|