1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2014-2017, Linaro Limited
4  */
5 #ifndef KERNEL_MUTEX_H
6 #define KERNEL_MUTEX_H
7 
8 #include <kernel/refcount.h>
9 #include <kernel/wait_queue.h>
10 #include <sys/queue.h>
11 #include <types_ext.h>
12 
13 struct mutex {
14 	unsigned spin_lock;	/* used when operating on this struct */
15 	struct wait_queue wq;
16 	short state;		/* -1: write, 0: unlocked, > 0: readers */
17 };
18 
19 #define MUTEX_INITIALIZER { .wq = WAIT_QUEUE_INITIALIZER }
20 
21 struct recursive_mutex {
22 	struct mutex m;		/* used when lock_depth goes 0 -> 1 or 1 -> 0 */
23 	short int owner;
24 	struct refcount lock_depth;
25 };
26 
27 #define RECURSIVE_MUTEX_INITIALIZER { .m = MUTEX_INITIALIZER, \
28 				      .owner = THREAD_ID_INVALID }
29 
30 TAILQ_HEAD(mutex_head, mutex);
31 
32 void mutex_init(struct mutex *m);
33 void mutex_destroy(struct mutex *m);
34 
35 void mutex_init_recursive(struct recursive_mutex *m);
36 void mutex_destroy_recursive(struct recursive_mutex *m);
37 unsigned int mutex_get_recursive_lock_depth(struct recursive_mutex *m);
38 
39 #ifdef CFG_MUTEX_DEBUG
40 void mutex_unlock_debug(struct mutex *m, const char *fname, int lineno);
41 #define mutex_unlock(m) mutex_unlock_debug((m), __FILE__, __LINE__)
42 
43 void mutex_lock_debug(struct mutex *m, const char *fname, int lineno);
44 #define mutex_lock(m) mutex_lock_debug((m), __FILE__, __LINE__)
45 
46 bool mutex_trylock_debug(struct mutex *m, const char *fname, int lineno);
47 #define mutex_trylock(m) mutex_trylock_debug((m), __FILE__, __LINE__)
48 
49 void mutex_read_unlock_debug(struct mutex *m, const char *fname, int lineno);
50 #define mutex_read_unlock(m) mutex_read_unlock_debug((m), __FILE__, __LINE__)
51 
52 void mutex_read_lock_debug(struct mutex *m, const char *fname, int lineno);
53 #define mutex_read_lock(m) mutex_read_lock_debug((m), __FILE__, __LINE__)
54 
55 bool mutex_read_trylock_debug(struct mutex *m, const char *fname, int lineno);
56 #define mutex_read_trylock(m) mutex_read_trylock_debug((m), __FILE__, __LINE__)
57 
58 void mutex_unlock_recursive_debug(struct recursive_mutex *m, const char *fname,
59 				  int lineno);
60 #define mutex_unlock_recursive(m) mutex_unlock_recursive_debug((m), __FILE__, \
61 							       __LINE__)
62 
63 void mutex_lock_recursive_debug(struct recursive_mutex *m, const char *fname,
64 				int lineno);
65 #define mutex_lock_recursive(m) mutex_lock_recursive_debug((m), __FILE__, \
66 							   __LINE__)
67 #else
68 void mutex_unlock(struct mutex *m);
69 void mutex_lock(struct mutex *m);
70 bool mutex_trylock(struct mutex *m);
71 void mutex_read_unlock(struct mutex *m);
72 void mutex_read_lock(struct mutex *m);
73 bool mutex_read_trylock(struct mutex *m);
74 
75 void mutex_unlock_recursive(struct recursive_mutex *m);
76 void mutex_lock_recursive(struct recursive_mutex *m);
77 #endif
78 
79 struct condvar {
80 	unsigned spin_lock;
81 	struct mutex *m;
82 };
83 #define CONDVAR_INITIALIZER { .m = NULL }
84 
85 void condvar_init(struct condvar *cv);
86 void condvar_destroy(struct condvar *cv);
87 
88 #ifdef CFG_MUTEX_DEBUG
89 void condvar_signal_debug(struct condvar *cv, const char *fname, int lineno);
90 #define condvar_signal(cv) condvar_signal_debug((cv), __FILE__, __LINE__)
91 
92 void condvar_broadcast_debug(struct condvar *cv, const char *fname, int lineno);
93 #define condvar_broadcast(cv) condvar_broadcast_debug((cv), __FILE__, __LINE__)
94 
95 void condvar_wait_debug(struct condvar *cv, struct mutex *m,
96 			const char *fname, int lineno);
97 #define condvar_wait(cv, m) condvar_wait_debug((cv), (m), __FILE__, __LINE__)
98 #else
99 void condvar_signal(struct condvar *cv);
100 void condvar_broadcast(struct condvar *cv);
101 void condvar_wait(struct condvar *cv, struct mutex *m);
102 #endif
103 
104 #endif /*KERNEL_MUTEX_H*/
105 
106