libmetal
Loading...
Searching...
No Matches
mutex.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/*
8 * @file linux/mutex.h
9 * @brief Linux mutex primitives for libmetal.
10 */
11
12#ifndef __METAL_MUTEX__H__
13#error "Include metal/mutex.h instead of metal/linux/mutex.h"
14#endif
15
16#ifndef __METAL_LINUX_MUTEX__H__
17#define __METAL_LINUX_MUTEX__H__
18
19#include <unistd.h>
20#include <sys/syscall.h>
21#include <linux/futex.h>
22
23#include <metal/atomic.h>
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
29typedef struct {
30 atomic_int v;
32
33/*
34 * METAL_MUTEX_INIT - used for initializing an mutex element in a static struct
35 * or global
36 */
37#define METAL_MUTEX_INIT(m) { ATOMIC_VAR_INIT(0) }
38/*
39 * METAL_MUTEX_DEFINE - used for defining and initializing a global or
40 * static singleton mutex
41 */
42#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = METAL_MUTEX_INIT(m)
43
44static inline int __metal_mutex_cmpxchg(metal_mutex_t *mutex,
45 int exp, int val)
46{
47 atomic_compare_exchange_strong(&mutex->v, (int *)&exp, val);
48 return exp;
49}
50
51static inline void __metal_mutex_init(metal_mutex_t *mutex)
52{
53 atomic_store(&mutex->v, 0);
54}
55
56static inline void __metal_mutex_deinit(metal_mutex_t *mutex)
57{
58 (void)mutex;
59}
60
62{
63 int val = 0;
64
65 return atomic_compare_exchange_strong(&mutex->v, &val, 1);
66}
67
68static inline void __metal_mutex_acquire(metal_mutex_t *mutex)
69{
70 int c = 0;
71
72 if (atomic_compare_exchange_strong(&mutex->v, &c, 1))
73 return;
74 if (c != 2)
75 c = atomic_exchange(&mutex->v, 2);
76 while (c != 0) {
77 syscall(SYS_futex, &mutex->v, FUTEX_WAIT, 2, NULL, NULL, 0);
78 c = atomic_exchange(&mutex->v, 2);
79 }
80}
81
82static inline void __metal_mutex_release(metal_mutex_t *mutex)
83{
84 if (atomic_fetch_sub(&mutex->v, 1) != 1) {
85 atomic_store(&mutex->v, 0);
86 syscall(SYS_futex, &mutex->v, FUTEX_WAKE, 1, NULL, NULL, 0);
87 }
88}
89
91{
92 return atomic_load(&mutex->v);
93}
94
95#ifdef __cplusplus
96}
97#endif
98
99#endif /* __METAL_LINUX_MUTEX__H__ */
#define atomic_load(OBJ)
Definition: atomic.h:60
int atomic_int
Definition: atomic.h:24
#define atomic_compare_exchange_strong(OBJ, EXP, DES)
Definition: atomic.h:79
#define atomic_store(OBJ, VAL)
Definition: atomic.h:56
#define atomic_exchange(OBJ, DES)
Definition: atomic.h:64
#define atomic_fetch_sub(OBJ, VAL)
Definition: atomic.h:99
Definition: mutex.h:28
atomic_int v
Definition: mutex.h:26
static void __metal_mutex_release(metal_mutex_t *mutex)
Definition: mutex.h:79
static void __metal_mutex_deinit(metal_mutex_t *mutex)
Definition: mutex.h:60
static int __metal_mutex_try_acquire(metal_mutex_t *mutex)
Definition: mutex.h:67
static int __metal_mutex_is_acquired(metal_mutex_t *mutex)
Definition: mutex.h:85
static void __metal_mutex_acquire(metal_mutex_t *mutex)
Definition: mutex.h:73
static void __metal_mutex_init(metal_mutex_t *mutex)
Definition: mutex.h:53
static int __metal_mutex_cmpxchg(metal_mutex_t *mutex, int exp, int val)
Definition: mutex.h:44