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 #if 0 157 void 158 rw_sysinit_flags(void *arg) 159 { 160 rw_sysinit(arg); 161 } 162 #endif 163 164 void 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 187 void _rw_destroy(volatile uintptr_t *c) 188 { 189 190 } 191 192 static void 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 213 rm_init(struct rmlock *rm, const char *name) 214 { 215 rm_init_flags(rm, name, 0); 216 } 217 218 void 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 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 246 rm_destroy(struct rmlock *rm) 247 { 248 249 } 250 251 void 252 _rm_wlock(struct rmlock *rm) 253 { 254 255 } 256 257 void 258 _rm_wunlock(struct rmlock *rm) 259 { 260 261 } 262 263 int 264 _rm_rlock(struct rmlock *rm, struct rm_priotracker *tracker, int trylock) 265 { 266 return (1); 267 } 268 269 void 270 _rm_runlock(struct rmlock *rm, struct rm_priotracker *tracker) 271 { 272 273 } 274 275 int 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 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 320 sx_destroy(struct sx *sx) 321 { 322 323 } 324 325 int 326 _sx_xlock(struct sx *sx, int opts, 327 const char *file, int line) 328 { 329 return (0); 330 } 331 332 int 333 _sx_slock(struct sx *sx, int opts, const char *file, int line) 334 { 335 return (0); 336 } 337 338 void 339 _sx_xunlock(struct sx *sx, const char *file, int line) 340 { 341 342 } 343 344 void 345 _sx_sunlock(struct sx *sx, const char *file, int line) 346 { 347 348 } 349 350 int 351 sx_try_slock_(struct sx *sx, const char *file, int line) 352 { 353 return 1; 354 } 355 356 int 357 sx_try_xlock_(struct sx *sx, const char *file, int line) 358 { 359 return 1; 360 } 361 362 int 363 sx_try_upgrade_(struct sx *sx, const char *file, int line) 364 { 365 return 1; 366 } 367 368 void 369 sx_downgrade_(struct sx *sx, const char *file, int line) 370 { 371 372 } 373 374 void 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 387 lock_spin(struct lock_object *lock, uintptr_t how) 388 { 389 printf("%s: called!\n", __func__); 390 } 391 392 static uintptr_t 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 417 lock_rm(struct lock_object *lock, uintptr_t how) 418 { 419 420 } 421 422 static uintptr_t 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 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