]> git.proxmox.com Git - mirror_spl-debian.git/blob - include/sys/mutex.h
New an improved taskq implementation for the SPL. It allows a
[mirror_spl-debian.git] / include / sys / mutex.h
1 #ifndef _SPL_MUTEX_H
2 #define _SPL_MUTEX_H
3
4 #ifdef __cplusplus
5 extern "C" {
6 #endif
7
8 #include <linux/module.h>
9 #include <linux/hardirq.h>
10 #include <sys/types.h>
11
12 /* See the "Big Theory Statement" in solaris mutex.c.
13 *
14 * Spin mutexes apparently aren't needed by zfs so we assert
15 * if ibc is non-zero.
16 *
17 * Our impementation of adaptive mutexes aren't really adaptive.
18 * They go to sleep every time.
19 */
20
21 #define MUTEX_DEFAULT 0
22 #define MUTEX_HELD(x) (mutex_owned(x))
23
24 #define KM_MAGIC 0x42424242
25 #define KM_POISON 0x84
26
27 typedef struct {
28 int km_magic;
29 char *km_name;
30 struct task_struct *km_owner;
31 struct semaphore km_sem;
32 spinlock_t km_lock;
33 } kmutex_t;
34
35 #undef mutex_init
36 static __inline__ void
37 mutex_init(kmutex_t *mp, char *name, int type, void *ibc)
38 {
39 ENTRY;
40 ASSERT(mp);
41 ASSERT(ibc == NULL); /* XXX - Spin mutexes not needed */
42 ASSERT(type == MUTEX_DEFAULT); /* XXX - Only default type supported */
43
44 mp->km_magic = KM_MAGIC;
45 spin_lock_init(&mp->km_lock);
46 sema_init(&mp->km_sem, 1);
47 mp->km_owner = NULL;
48 mp->km_name = NULL;
49
50 if (name) {
51 mp->km_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
52 if (mp->km_name)
53 strcpy(mp->km_name, name);
54 }
55 EXIT;
56 }
57
58 #undef mutex_destroy
59 static __inline__ void
60 mutex_destroy(kmutex_t *mp)
61 {
62 ENTRY;
63 ASSERT(mp);
64 ASSERT(mp->km_magic == KM_MAGIC);
65 spin_lock(&mp->km_lock);
66
67 if (mp->km_name)
68 kfree(mp->km_name);
69
70 memset(mp, KM_POISON, sizeof(*mp));
71 spin_unlock(&mp->km_lock);
72 EXIT;
73 }
74
75 static __inline__ void
76 mutex_enter(kmutex_t *mp)
77 {
78 ENTRY;
79 ASSERT(mp);
80 ASSERT(mp->km_magic == KM_MAGIC);
81 spin_lock(&mp->km_lock);
82
83 if (unlikely(in_atomic() && !current->exit_state)) {
84 spin_unlock(&mp->km_lock);
85 __CDEBUG_LIMIT(S_MUTEX, D_ERROR,
86 "May schedule while atomic: %s/0x%08x/%d\n",
87 current->comm, preempt_count(), current->pid);
88 SBUG();
89 }
90
91 spin_unlock(&mp->km_lock);
92
93 down(&mp->km_sem);
94
95 spin_lock(&mp->km_lock);
96 ASSERT(mp->km_owner == NULL);
97 mp->km_owner = current;
98 spin_unlock(&mp->km_lock);
99 EXIT;
100 }
101
102 /* Return 1 if we acquired the mutex, else zero. */
103 static __inline__ int
104 mutex_tryenter(kmutex_t *mp)
105 {
106 int rc;
107 ENTRY;
108
109 ASSERT(mp);
110 ASSERT(mp->km_magic == KM_MAGIC);
111 spin_lock(&mp->km_lock);
112
113 if (unlikely(in_atomic() && !current->exit_state)) {
114 spin_unlock(&mp->km_lock);
115 __CDEBUG_LIMIT(S_MUTEX, D_ERROR,
116 "May schedule while atomic: %s/0x%08x/%d\n",
117 current->comm, preempt_count(), current->pid);
118 SBUG();
119 }
120
121 spin_unlock(&mp->km_lock);
122 rc = down_trylock(&mp->km_sem); /* returns 0 if acquired */
123 if (rc == 0) {
124 spin_lock(&mp->km_lock);
125 ASSERT(mp->km_owner == NULL);
126 mp->km_owner = current;
127 spin_unlock(&mp->km_lock);
128 RETURN(1);
129 }
130
131 RETURN(0);
132 }
133
134 static __inline__ void
135 mutex_exit(kmutex_t *mp)
136 {
137 ENTRY;
138 ASSERT(mp);
139 ASSERT(mp->km_magic == KM_MAGIC);
140 spin_lock(&mp->km_lock);
141
142 ASSERT(mp->km_owner == current);
143 mp->km_owner = NULL;
144 spin_unlock(&mp->km_lock);
145 up(&mp->km_sem);
146 EXIT;
147 }
148
149 /* Return 1 if mutex is held by current process, else zero. */
150 static __inline__ int
151 mutex_owned(kmutex_t *mp)
152 {
153 int rc;
154 ENTRY;
155
156 ASSERT(mp);
157 ASSERT(mp->km_magic == KM_MAGIC);
158 spin_lock(&mp->km_lock);
159 rc = (mp->km_owner == current);
160 spin_unlock(&mp->km_lock);
161
162 RETURN(rc);
163 }
164
165 /* Return owner if mutex is owned, else NULL. */
166 static __inline__ kthread_t *
167 mutex_owner(kmutex_t *mp)
168 {
169 kthread_t *thr;
170 ENTRY;
171
172 ASSERT(mp);
173 ASSERT(mp->km_magic == KM_MAGIC);
174 spin_lock(&mp->km_lock);
175 thr = mp->km_owner;
176 spin_unlock(&mp->km_lock);
177
178 RETURN(thr);
179 }
180
181 #ifdef __cplusplus
182 }
183 #endif
184
185 #endif /* _SPL_MUTEX_H */