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	generic/mutex.h
9  * @brief	Generic mutex primitives for libmetal.
10  */
11 
12 #ifndef __METAL_MUTEX__H__
13 #error "Include metal/mutex.h instead of metal/generic/mutex.h"
14 #endif
15 
16 #ifndef __METAL_GENERIC_MUTEX__H__
17 #define __METAL_GENERIC_MUTEX__H__
18 
19 #include <metal/atomic.h>
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 typedef struct {
26 	atomic_int v;
27 } metal_mutex_t;
28 
29 #define METAL_MUTEX_UNLOCKED 0
30 #define METAL_MUTEX_LOCKED   1
31 
32 /*
33  * METAL_MUTEX_INIT - used for initializing an mutex element in a static struct
34  * or global
35  */
36 #define METAL_MUTEX_INIT(m) { ATOMIC_VAR_INIT(METAL_MUTEX_UNLOCKED) }
37 /*
38  * METAL_MUTEX_DEFINE - used for defining and initializing a global or
39  * static singleton mutex
40  */
41 #define METAL_MUTEX_DEFINE(m) metal_mutex_t m = METAL_MUTEX_INIT(m)
42 
__metal_mutex_init(metal_mutex_t * mutex)43 static inline void __metal_mutex_init(metal_mutex_t *mutex)
44 {
45 	atomic_store(&mutex->v, METAL_MUTEX_UNLOCKED);
46 }
47 
__metal_mutex_deinit(metal_mutex_t * mutex)48 static inline void __metal_mutex_deinit(metal_mutex_t *mutex)
49 {
50 	(void)mutex;
51 }
52 
__metal_mutex_try_acquire(metal_mutex_t * mutex)53 static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex)
54 {
55 	int unlocked = METAL_MUTEX_UNLOCKED;
56 
57 	if (atomic_compare_exchange_strong(&mutex->v, &unlocked,
58 					   METAL_MUTEX_LOCKED)) {
59 		return 1; /* acquired */
60 	} else {
61 		return 0; /* not acquired */
62 	}
63 }
64 
__metal_mutex_acquire(metal_mutex_t * mutex)65 static inline void __metal_mutex_acquire(metal_mutex_t *mutex)
66 {
67 	int unlocked = METAL_MUTEX_UNLOCKED;
68 
69 	while (!atomic_compare_exchange_weak(&mutex->v, &unlocked,
70 					     METAL_MUTEX_LOCKED)) {
71 		;
72 	}
73 }
74 
__metal_mutex_release(metal_mutex_t * mutex)75 static inline void __metal_mutex_release(metal_mutex_t *mutex)
76 {
77 	atomic_store(&mutex->v, METAL_MUTEX_UNLOCKED);
78 }
79 
__metal_mutex_is_acquired(metal_mutex_t * mutex)80 static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex)
81 {
82 	return atomic_load(&mutex->v);
83 }
84 
85 #ifdef __cplusplus
86 }
87 #endif
88 
89 #endif /* __METAL_GENERIC_MUTEX__H__ */
90