1 /*
2  * Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /*
8  * @file	zephyr/condition.c
9  * @brief	Zephyr libmetal condition variable handling.
10  */
11 
12 #include <metal/condition.h>
13 #include <metal/irq.h>
14 
15 extern void metal_generic_default_poll(void);
16 
metal_condition_wait(struct metal_condition * cv,metal_mutex_t * m)17 int metal_condition_wait(struct metal_condition *cv,
18 			 metal_mutex_t *m)
19 {
20 	uintptr_t tmpmptr = 0, mptr = (uintptr_t)m;
21 	int v;
22 	unsigned int flags;
23 
24 	/* Check if the mutex has been acquired */
25 	if (!cv || !m || !metal_mutex_is_acquired(m)) {
26 		return -EINVAL;
27 	}
28 
29 	if (!atomic_compare_exchange_strong(&cv->mptr, &tmpmptr, mptr)) {
30 		if (tmpmptr != mptr) {
31 			return -EINVAL;
32 		}
33 	}
34 
35 	v = atomic_load(&cv->v);
36 
37 	/* Release the mutex first. */
38 	metal_mutex_release(m);
39 	do {
40 		flags = metal_irq_save_disable();
41 		if (atomic_load(&cv->v) != v) {
42 			metal_irq_restore_enable(flags);
43 			break;
44 		}
45 		metal_generic_default_poll();
46 		metal_irq_restore_enable(flags);
47 	} while (1);
48 	/* Acquire the mutex again. */
49 	metal_mutex_acquire(m);
50 	return 0;
51 }
52