1 /*
2 * Copyright (c) 2010 Kip Macy. All rights reserved.
3 * Copyright (C) 2017-2021 THL A29 Limited, a Tencent company.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * Derived in part from libplebnet's pn_lock.c.
27 */
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/bus.h>
32 #include <sys/conf.h>
33 #include <sys/kdb.h>
34 #include <sys/kernel.h>
35 #include <sys/ktr.h>
36 #include <sys/lock.h>
37 #include <sys/malloc.h>
38 #include <sys/mutex.h>
39 #include <sys/rmlock.h>
40 #include <sys/rwlock.h>
41 #include <sys/sx.h>
42 #include <sys/proc.h>
43 #include <sys/resourcevar.h>
44 #include <sys/sched.h>
45 #include <sys/sbuf.h>
46 #include <sys/sysctl.h>
47 #include <sys/turnstile.h>
48 #include <sys/vmmeter.h>
49 #include <sys/lock_profile.h>
50
51 #include "ff_host_interface.h"
52
53 struct mtx Giant;
54
55 static void
assert_mtx(const struct lock_object * lock,int what)56 assert_mtx(const struct lock_object *lock, int what)
57 {
58
59 }
60
61 static void
lock_mtx(struct lock_object * lock,uintptr_t how)62 lock_mtx(struct lock_object *lock, uintptr_t how)
63 {
64
65 }
66
67 static uintptr_t
unlock_mtx(struct lock_object * lock)68 unlock_mtx(struct lock_object *lock)
69 {
70 return (0);
71 }
72
73 /*
74 * Lock classes for sleep and spin mutexes.
75 */
76 struct lock_class lock_class_mtx_sleep = {
77 .lc_name = "sleep mutex",
78 .lc_flags = LC_SLEEPLOCK | LC_RECURSABLE,
79 .lc_assert = assert_mtx,
80 .lc_lock = lock_mtx,
81 .lc_unlock = unlock_mtx,
82 #ifdef DDB
83 .lc_ddb_show = db_show_mtx,
84 #endif
85 #ifdef KDTRACE_HOOKS
86 .lc_owner = owner_mtx,
87 #endif
88 };
89
90 void
ff_mtx_init(struct lock_object * lo,const char * name,const char * type,int opts)91 ff_mtx_init(struct lock_object *lo, const char *name, const char *type, int opts)
92 {
93 lock_init(lo, &lock_class_mtx_sleep, name, type, opts);
94 }
95
96 void
mtx_sysinit(void * arg)97 mtx_sysinit(void *arg)
98 {
99 struct mtx_args *margs = arg;
100 mtx_init((struct mtx *)margs->ma_mtx, margs->ma_desc, NULL, margs->ma_opts);
101 }
102
_mtx_destroy(volatile uintptr_t * c)103 void _mtx_destroy(volatile uintptr_t *c)
104 {
105
106 }
107
108 static void
lock_rw(struct lock_object * lock,uintptr_t how)109 lock_rw(struct lock_object *lock, uintptr_t how)
110 {
111
112 }
113
114 static uintptr_t
unlock_rw(struct lock_object * lock)115 unlock_rw(struct lock_object *lock)
116 {
117 return (0);
118 }
119
120 #ifdef KDTRACE_HOOKS
121 static int
owner_rw(struct lock_object * lock,struct thread ** owner)122 owner_rw(struct lock_object *lock, struct thread **owner)
123 {
124 return 1;//??
125 }
126 #endif
127
128
129 static void
assert_rw(const struct lock_object * lock,int what)130 assert_rw(const struct lock_object *lock, int what)
131 {
132
133 }
134
135 struct lock_class lock_class_rw = {
136 .lc_name = "rw",
137 .lc_flags = LC_SLEEPLOCK | LC_RECURSABLE | LC_UPGRADABLE,
138 .lc_assert = assert_rw,
139 #ifdef DDB
140 .lc_ddb_show = db_show_rwlock,
141 #endif
142 .lc_lock = lock_rw,
143 .lc_unlock = unlock_rw,
144 #ifdef KDTRACE_HOOKS
145 .lc_owner = owner_rw,
146 #endif
147 };
148
149 void
rw_sysinit(void * arg)150 rw_sysinit(void *arg)
151 {
152 struct rw_args *args = arg;
153 rw_init((struct rwlock *)args->ra_rw, args->ra_desc);
154 }
155
156 #if 0
157 void
158 rw_sysinit_flags(void *arg)
159 {
160 rw_sysinit(arg);
161 }
162 #endif
163
164 void
ff_rw_init_flags(struct lock_object * lo,const char * name,int opts)165 ff_rw_init_flags(struct lock_object *lo, const char *name, int opts)
166 {
167 int flags;
168
169 MPASS((opts & ~(RW_DUPOK | RW_NOPROFILE | RW_NOWITNESS | RW_QUIET |
170 RW_RECURSE)) == 0);
171
172 flags = LO_UPGRADABLE;
173 if (opts & RW_DUPOK)
174 flags |= LO_DUPOK;
175 if (opts & RW_NOPROFILE)
176 flags |= LO_NOPROFILE;
177 if (!(opts & RW_NOWITNESS))
178 flags |= LO_WITNESS;
179 if (opts & RW_RECURSE)
180 flags |= LO_RECURSABLE;
181 if (opts & RW_QUIET)
182 flags |= LO_QUIET;
183
184 lock_init(lo, &lock_class_rw, name, NULL, flags);
185 }
186
_rw_destroy(volatile uintptr_t * c)187 void _rw_destroy(volatile uintptr_t *c)
188 {
189
190 }
191
192 static void
assert_rm(const struct lock_object * lock,int what)193 assert_rm(const struct lock_object *lock, int what)
194 {
195
196 }
197
198 struct lock_class lock_class_rm = {
199 .lc_name = "rm",
200 .lc_flags = LC_SLEEPLOCK | LC_RECURSABLE,
201 .lc_assert = assert_rm,
202 #if 0
203 #ifdef DDB
204 .lc_ddb_show = db_show_rwlock,
205 #endif
206 #endif
207 #ifdef KDTRACE_HOOKS
208 .lc_owner = owner_rm,
209 #endif
210 };
211
212 void
rm_init(struct rmlock * rm,const char * name)213 rm_init(struct rmlock *rm, const char *name)
214 {
215 rm_init_flags(rm, name, 0);
216 }
217
218 void
rm_init_flags(struct rmlock * rm,const char * name,int opts)219 rm_init_flags(struct rmlock *rm, const char *name, int opts)
220 {
221 int liflags = 0;
222 if (!(opts & RM_NOWITNESS))
223 liflags |= LO_WITNESS;
224 if (opts & RM_RECURSE)
225 liflags |= LO_RECURSABLE;
226
227 lock_init(&rm->lock_object, &lock_class_rm, name, NULL, liflags);
228 }
229
230 void
rm_sysinit(void * arg)231 rm_sysinit(void *arg)
232 {
233 struct rm_args *args = arg;
234 rm_init((struct rmlock *)args->ra_rm, args->ra_desc);
235 }
236
237 #if 0
238 void
239 rm_sysinit_flags(void *arg)
240 {
241 rm_sysinit(arg);
242 }
243 #endif
244
245 void
rm_destroy(struct rmlock * rm)246 rm_destroy(struct rmlock *rm)
247 {
248
249 }
250
251 void
_rm_wlock(struct rmlock * rm)252 _rm_wlock(struct rmlock *rm)
253 {
254
255 }
256
257 void
_rm_wunlock(struct rmlock * rm)258 _rm_wunlock(struct rmlock *rm)
259 {
260
261 }
262
263 int
_rm_rlock(struct rmlock * rm,struct rm_priotracker * tracker,int trylock)264 _rm_rlock(struct rmlock *rm, struct rm_priotracker *tracker, int trylock)
265 {
266 return (1);
267 }
268
269 void
_rm_runlock(struct rmlock * rm,struct rm_priotracker * tracker)270 _rm_runlock(struct rmlock *rm, struct rm_priotracker *tracker)
271 {
272
273 }
274
275 int
rm_wowned(const struct rmlock * rm)276 rm_wowned(const struct rmlock *rm)
277 {
278 return (1);
279 }
280
281 struct lock_class lock_class_sx = {
282 .lc_name = "sx",
283 .lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE,
284 #ifdef DDB
285 .lc_ddb_show = db_show_sx,
286 #endif
287 #ifdef KDTRACE_HOOKS
288 .lc_owner = owner_sx,
289 #endif
290 };
291
292 void
sx_init_flags(struct sx * sx,const char * description,int opts)293 sx_init_flags(struct sx *sx, const char *description, int opts)
294 {
295 int flags;
296
297 MPASS((opts & ~(SX_QUIET | SX_RECURSE | SX_NOWITNESS | SX_DUPOK |
298 SX_NOPROFILE | SX_NEW)) == 0);
299
300 flags = LO_SLEEPABLE | LO_UPGRADABLE;
301 if (opts & SX_DUPOK)
302 flags |= LO_DUPOK;
303 if (opts & SX_NOPROFILE)
304 flags |= LO_NOPROFILE;
305 if (!(opts & SX_NOWITNESS))
306 flags |= LO_WITNESS;
307 if (opts & SX_RECURSE)
308 flags |= LO_RECURSABLE;
309 if (opts & SX_QUIET)
310 flags |= LO_QUIET;
311 if (opts & SX_NEW)
312 flags |= LO_NEW;
313
314 lock_init(&sx->lock_object, &lock_class_sx, description, NULL, flags);
315 //sx->sx_lock = SX_LOCK_UNLOCKED;
316 //sx->sx_recurse = 0;
317 }
318
319 void
sx_destroy(struct sx * sx)320 sx_destroy(struct sx *sx)
321 {
322
323 }
324
325 int
_sx_xlock(struct sx * sx,int opts,const char * file,int line)326 _sx_xlock(struct sx *sx, int opts,
327 const char *file, int line)
328 {
329 return (0);
330 }
331
332 int
_sx_slock(struct sx * sx,int opts,const char * file,int line)333 _sx_slock(struct sx *sx, int opts, const char *file, int line)
334 {
335 return (0);
336 }
337
338 void
_sx_xunlock(struct sx * sx,const char * file,int line)339 _sx_xunlock(struct sx *sx, const char *file, int line)
340 {
341
342 }
343
344 void
_sx_sunlock(struct sx * sx,const char * file,int line)345 _sx_sunlock(struct sx *sx, const char *file, int line)
346 {
347
348 }
349
350 int
sx_try_slock_(struct sx * sx,const char * file,int line)351 sx_try_slock_(struct sx *sx, const char *file, int line)
352 {
353 return 1;
354 }
355
356 int
sx_try_xlock_(struct sx * sx,const char * file,int line)357 sx_try_xlock_(struct sx *sx, const char *file, int line)
358 {
359 return 1;
360 }
361
362 int
sx_try_upgrade_(struct sx * sx,const char * file,int line)363 sx_try_upgrade_(struct sx *sx, const char *file, int line)
364 {
365 return 1;
366 }
367
368 void
sx_downgrade_(struct sx * sx,const char * file,int line)369 sx_downgrade_(struct sx *sx, const char *file, int line)
370 {
371
372 }
373
374 void
sx_sysinit(void * arg)375 sx_sysinit(void *arg)
376 {
377 struct sx_args *args = arg;
378 sx_init(args->sa_sx, args->sa_desc);
379 }
380
381 /*
382 * XXX should never be used;
383 */
384 struct lock_class lock_class_lockmgr;
385
386 static void
lock_spin(struct lock_object * lock,uintptr_t how)387 lock_spin(struct lock_object *lock, uintptr_t how)
388 {
389 printf("%s: called!\n", __func__);
390 }
391
392 static uintptr_t
unlock_spin(struct lock_object * lock)393 unlock_spin(struct lock_object *lock)
394 {
395 printf("%s: called!\n", __func__);
396 return (0);
397 }
398
399 /*
400 * XXX should never be used;
401 */
402 struct lock_class lock_class_mtx_spin = {
403 .lc_name = "spin mutex",
404 .lc_flags = LC_SPINLOCK | LC_RECURSABLE,
405 .lc_assert = assert_mtx,
406 .lc_lock = lock_spin,
407 .lc_unlock = unlock_spin,
408 };
409
410 /*
411 * These do not support read locks because it would be hard to make
412 * the tracker work correctly with the current lock_class API as you
413 * would need to have the tracker pointer available when calling
414 * rm_rlock() in lock_rm().
415 */
416 static void
lock_rm(struct lock_object * lock,uintptr_t how)417 lock_rm(struct lock_object *lock, uintptr_t how)
418 {
419
420 }
421
422 static uintptr_t
unlock_rm(struct lock_object * lock)423 unlock_rm(struct lock_object *lock)
424 {
425 return (1);
426 }
427
428 struct lock_class lock_class_rm_sleepable = {
429 .lc_name = "sleepable rm",
430 .lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE,
431 .lc_assert = assert_rm,
432 #ifdef DDB
433 .lc_ddb_show = db_show_rm,
434 #endif
435 .lc_lock = lock_rm,
436 .lc_unlock = unlock_rm,
437 #ifdef KDTRACE_HOOKS
438 .lc_owner = owner_rm,
439 #endif
440 };
441
442 void
mutex_init(void)443 mutex_init(void)
444 {
445 mtx_init(&Giant, "Giant", NULL, MTX_DEF | MTX_RECURSE);
446 mtx_init(&proc0.p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK);
447 }
448
449