libmetal
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
26 extern "C" {
27 #endif
28 
29 typedef struct {
30  atomic_int v;
32 
33 /*
34  * METAL_MUTEX_INIT - used for initializing an mutex elmenet 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 
44 static 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 
51 static inline void __metal_mutex_init(metal_mutex_t *mutex)
52 {
53  atomic_store(&mutex->v, 0);
54 }
55 
56 static inline void __metal_mutex_deinit(metal_mutex_t *mutex)
57 {
58  (void)mutex;
59 }
60 
61 static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex)
62 {
63  int val = 0;
64  return atomic_compare_exchange_strong(&mutex->v, &val, 1);
65 }
66 
67 static inline void __metal_mutex_acquire(metal_mutex_t *mutex)
68 {
69  int c = 0;
70 
71  if (atomic_compare_exchange_strong(&mutex->v, &c, 1))
72  return;
73  if (c != 2)
74  c = atomic_exchange(&mutex->v, 2);
75  while (c != 0) {
76  syscall(SYS_futex, &mutex->v, FUTEX_WAIT, 2, NULL, NULL, 0);
77  c = atomic_exchange(&mutex->v, 2);
78  }
79 }
80 
81 static inline void __metal_mutex_release(metal_mutex_t *mutex)
82 {
83  if (atomic_fetch_sub(&mutex->v, 1) != 1) {
84  atomic_store(&mutex->v, 0);
85  syscall(SYS_futex, &mutex->v, FUTEX_WAKE, 1, NULL, NULL, 0);
86  }
87 }
88 
89 static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex)
90 {
91  return atomic_load(&mutex->v);
92 }
93 
94 #ifdef __cplusplus
95 }
96 #endif
97 
98 #endif /* __METAL_LINUX_MUTEX__H__ */
atomic_int v
Definition: mutex.h:26
static int __metal_mutex_cmpxchg(metal_mutex_t *mutex, int exp, int val)
Definition: mutex.h:44
static void __metal_mutex_init(metal_mutex_t *mutex)
Definition: mutex.h:51
#define atomic_fetch_sub(OBJ, VAL)
Definition: atomic.h:98
static void __metal_mutex_release(metal_mutex_t *mutex)
Definition: mutex.h:81
#define atomic_exchange(OBJ, DES)
Definition: atomic.h:63
static int __metal_mutex_try_acquire(metal_mutex_t *mutex)
Definition: mutex.h:61
static void __metal_mutex_deinit(metal_mutex_t *mutex)
Definition: mutex.h:56
#define atomic_store(OBJ, VAL)
Definition: atomic.h:55
#define atomic_load(OBJ)
Definition: atomic.h:59
Definition: mutex.h:28
struct k_sem metal_mutex_t
Definition: mutex.h:26
static void __metal_mutex_acquire(metal_mutex_t *mutex)
Definition: mutex.h:67
static int __metal_mutex_is_acquired(metal_mutex_t *mutex)
Definition: mutex.h:89
int atomic_int
Definition: atomic.h:24
#define atomic_compare_exchange_strong(OBJ, EXP, DES)
Definition: atomic.h:78