1 /*
2  * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /*
8  * @file	generic/condition.c
9  * @brief	Generic 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 	if (!atomic_compare_exchange_strong(&cv->mptr, &tmpmptr, mptr)) {
29 		if (tmpmptr != mptr)
30 			return -EINVAL;
31 	}
32 
33 	v = atomic_load(&cv->v);
34 
35 	/* Release the mutex first. */
36 	metal_mutex_release(m);
37 	do {
38 		flags = metal_irq_save_disable();
39 		if (atomic_load(&cv->v) != v) {
40 			metal_irq_restore_enable(flags);
41 			break;
42 		}
43 		metal_generic_default_poll();
44 		metal_irq_restore_enable(flags);
45 	} while (1);
46 	/* Acquire the mutex again. */
47 	metal_mutex_acquire(m);
48 	return 0;
49 }
50