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