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 
metal_condition_wait(struct metal_condition * cv,metal_mutex_t * m)14 int metal_condition_wait(struct metal_condition *cv,
15 				       metal_mutex_t *m)
16 {
17 	uintptr_t tmpmptr = 0, mptr = (uintptr_t)m;
18 	int v = 0;
19 
20 	/* Check if the mutex has been acquired */
21 	if (!cv || !m || !metal_mutex_is_acquired(m))
22 		return -EINVAL;
23 
24 	if (!atomic_compare_exchange_strong(&cv->mptr, &tmpmptr, mptr)) {
25 		if (tmpmptr != mptr)
26 			return -EINVAL;
27 	}
28 
29 	v = atomic_load(&cv->wakeups);
30 	atomic_fetch_add(&cv->waiters, 1);
31 
32 	/* Release the mutex before sleeping. */
33 	metal_mutex_release(m);
34 	syscall(SYS_futex, &cv->wakeups, FUTEX_WAIT, v, NULL, NULL, 0);
35 	atomic_fetch_sub(&cv->waiters, 1);
36 	/* Acquire the mutex after it's waken up. */
37 	metal_mutex_acquire(m);
38 
39 	return 0;
40 }
41