1 /* 2 * Copyright (c) 2010 Kip Macy. All rights reserved. 3 * Copyright (C) 2017 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 56 assert_mtx(const struct lock_object *lock, int what) 57 { 58 59 } 60 61 static void 62 lock_mtx(struct lock_object *lock, uintptr_t how) 63 { 64 65 } 66 67 static uintptr_t 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 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 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 103 void _mtx_destroy(volatile uintptr_t *c) 104 { 105 106 } 107 108 static void 109 lock_rw(struct lock_object *lock, uintptr_t how) 110 { 111 112 } 113 114 static uintptr_t 115 unlock_rw(struct lock_object *lock) 116 { 117 return (0); 118 } 119 120 #ifdef KDTRACE_HOOKS 121 static int 122 owner_rw(struct lock_object *lock, struct thread **owner) 123 { 124 return 1;//?? 125 } 126 #endif 127 128 129 static void 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 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 void 157 rw_sysinit_flags(void *arg) 158 { 159 rw_sysinit(arg); 160 } 161 162 void 163 ff_rw_init_flags(struct lock_object *lo, const char *name, int opts) 164 { 165 int flags; 166 167 MPASS((opts & ~(RW_DUPOK | RW_NOPROFILE | RW_NOWITNESS | RW_QUIET | 168 RW_RECURSE)) == 0); 169 170 flags = LO_UPGRADABLE; 171 if (opts & RW_DUPOK) 172 flags |= LO_DUPOK; 173 if (opts & RW_NOPROFILE) 174 flags |= LO_NOPROFILE; 175 if (!(opts & RW_NOWITNESS)) 176 flags |= LO_WITNESS; 177 if (opts & RW_RECURSE) 178 flags |= LO_RECURSABLE; 179 if (opts & RW_QUIET) 180 flags |= LO_QUIET; 181 182 lock_init(lo, &lock_class_rw, name, NULL, flags); 183 } 184 185 void _rw_destroy(volatile uintptr_t *c) 186 { 187 188 } 189 190 static void 191 assert_rm(const struct lock_object *lock, int what) 192 { 193 194 } 195 196 struct lock_class lock_class_rm = { 197 .lc_name = "rm", 198 .lc_flags = LC_SLEEPLOCK | LC_RECURSABLE, 199 .lc_assert = assert_rm, 200 #if 0 201 #ifdef DDB 202 .lc_ddb_show = db_show_rwlock, 203 #endif 204 #endif 205 #ifdef KDTRACE_HOOKS 206 .lc_owner = owner_rm, 207 #endif 208 }; 209 210 void 211 rm_init(struct rmlock *rm, const char *name) 212 { 213 rm_init_flags(rm, name, 0); 214 } 215 216 void 217 rm_init_flags(struct rmlock *rm, const char *name, int opts) 218 { 219 int liflags = 0; 220 if (!(opts & RM_NOWITNESS)) 221 liflags |= LO_WITNESS; 222 if (opts & RM_RECURSE) 223 liflags |= LO_RECURSABLE; 224 225 lock_init(&rm->lock_object, &lock_class_rm, name, NULL, liflags); 226 } 227 228 void 229 rm_sysinit(void *arg) 230 { 231 struct rm_args *args = arg; 232 rm_init((struct rmlock *)args->ra_rm, args->ra_desc); 233 } 234 235 void 236 rm_sysinit_flags(void *arg) 237 { 238 rm_sysinit(arg); 239 } 240 241 void 242 rm_destroy(struct rmlock *rm) 243 { 244 245 } 246 247 void 248 _rm_wlock(struct rmlock *rm) 249 { 250 251 } 252 253 void 254 _rm_wunlock(struct rmlock *rm) 255 { 256 257 } 258 259 int 260 _rm_rlock(struct rmlock *rm, struct rm_priotracker *tracker, int trylock) 261 { 262 return (1); 263 } 264 265 void 266 _rm_runlock(struct rmlock *rm, struct rm_priotracker *tracker) 267 { 268 269 } 270 271 int 272 rm_wowned(const struct rmlock *rm) 273 { 274 return (1); 275 } 276 277 struct lock_class lock_class_sx = { 278 .lc_name = "sx", 279 .lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE, 280 #ifdef DDB 281 .lc_ddb_show = db_show_sx, 282 #endif 283 #ifdef KDTRACE_HOOKS 284 .lc_owner = owner_sx, 285 #endif 286 }; 287 288 void 289 sx_init_flags(struct sx *sx, const char *description, int opts) 290 { 291 int flags; 292 293 MPASS((opts & ~(SX_QUIET | SX_RECURSE | SX_NOWITNESS | SX_DUPOK | 294 SX_NOPROFILE | SX_NOADAPTIVE)) == 0); 295 296 flags = LO_SLEEPABLE | LO_UPGRADABLE; 297 if (opts & SX_DUPOK) 298 flags |= LO_DUPOK; 299 if (opts & SX_NOPROFILE) 300 flags |= LO_NOPROFILE; 301 if (!(opts & SX_NOWITNESS)) 302 flags |= LO_WITNESS; 303 if (opts & SX_RECURSE) 304 flags |= LO_RECURSABLE; 305 if (opts & SX_QUIET) 306 flags |= LO_QUIET; 307 308 flags |= opts & SX_NOADAPTIVE; 309 lock_init(&sx->lock_object, &lock_class_sx, description, NULL, flags); 310 } 311 312 void 313 sx_destroy(struct sx *sx) 314 { 315 316 } 317 318 int 319 _sx_xlock(struct sx *sx, int opts, 320 const char *file, int line) 321 { 322 return (0); 323 } 324 325 int 326 _sx_slock(struct sx *sx, int opts, const char *file, int line) 327 { 328 return (0); 329 } 330 331 void 332 _sx_xunlock(struct sx *sx, const char *file, int line) 333 { 334 335 } 336 337 void 338 _sx_sunlock(struct sx *sx, const char *file, int line) 339 { 340 341 } 342 343 int 344 sx_try_slock_(struct sx *sx, const char *file, int line) 345 { 346 return 1; 347 } 348 349 int 350 sx_try_xlock_(struct sx *sx, const char *file, int line) 351 { 352 return 1; 353 } 354 355 int 356 sx_try_upgrade_(struct sx *sx, const char *file, int line) 357 { 358 return 1; 359 } 360 361 void 362 sx_downgrade_(struct sx *sx, const char *file, int line) 363 { 364 365 } 366 367 void 368 sx_sysinit(void *arg) 369 { 370 struct sx_args *args = arg; 371 sx_init(args->sa_sx, args->sa_desc); 372 } 373 374 /* 375 * XXX should never be used; 376 */ 377 struct lock_class lock_class_lockmgr; 378 379 static void 380 lock_spin(struct lock_object *lock, uintptr_t how) 381 { 382 printf("%s: called!\n", __func__); 383 } 384 385 static uintptr_t 386 unlock_spin(struct lock_object *lock) 387 { 388 printf("%s: called!\n", __func__); 389 return (0); 390 } 391 392 /* 393 * XXX should never be used; 394 */ 395 struct lock_class lock_class_mtx_spin = { 396 .lc_name = "spin mutex", 397 .lc_flags = LC_SPINLOCK | LC_RECURSABLE, 398 .lc_assert = assert_mtx, 399 .lc_lock = lock_spin, 400 .lc_unlock = unlock_spin, 401 }; 402 403 /* 404 * These do not support read locks because it would be hard to make 405 * the tracker work correctly with the current lock_class API as you 406 * would need to have the tracker pointer available when calling 407 * rm_rlock() in lock_rm(). 408 */ 409 static void 410 lock_rm(struct lock_object *lock, uintptr_t how) 411 { 412 413 } 414 415 static uintptr_t 416 unlock_rm(struct lock_object *lock) 417 { 418 return (1); 419 } 420 421 struct lock_class lock_class_rm_sleepable = { 422 .lc_name = "sleepable rm", 423 .lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE, 424 .lc_assert = assert_rm, 425 #ifdef DDB 426 .lc_ddb_show = db_show_rm, 427 #endif 428 .lc_lock = lock_rm, 429 .lc_unlock = unlock_rm, 430 #ifdef KDTRACE_HOOKS 431 .lc_owner = owner_rm, 432 #endif 433 }; 434 435 void 436 mutex_init(void) 437 { 438 mtx_init(&Giant, "Giant", NULL, MTX_DEF | MTX_RECURSE); 439 mtx_init(&proc0.p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK); 440 } 441 442