lock.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
  4. * Copyright (c) 1993,1994 The University of Utah and
  5. * the Computer Systems Laboratory (CSL).
  6. * All rights reserved.
  7. *
  8. * Permission to use, copy, modify and distribute this software and its
  9. * documentation is hereby granted, provided that both the copyright
  10. * notice and this permission notice appear in all copies of the
  11. * software, derivative works or modified versions, and any portions
  12. * thereof, and that both notices appear in supporting documentation.
  13. *
  14. * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
  15. * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
  16. * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
  17. * THIS SOFTWARE.
  18. *
  19. * Carnegie Mellon requests users of this software to return to
  20. *
  21. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  22. * School of Computer Science
  23. * Carnegie Mellon University
  24. * Pittsburgh PA 15213-3890
  25. *
  26. * any improvements or extensions that they make and grant Carnegie Mellon
  27. * the rights to redistribute these changes.
  28. */
  29. /*
  30. * File: kern/lock.c
  31. * Author: Avadis Tevanian, Jr., Michael Wayne Young
  32. * Date: 1985
  33. *
  34. * Locking primitives implementation
  35. */
  36. #include <string.h>
  37. #include <kern/debug.h>
  38. #include <kern/lock.h>
  39. #include <kern/thread.h>
  40. #include <kern/sched_prim.h>
  41. #if MACH_KDB
  42. #include <machine/db_machdep.h>
  43. #include <ddb/db_output.h>
  44. #include <ddb/db_sym.h>
  45. #endif
  46. #if NCPUS > 1
  47. /*
  48. * Module: lock
  49. * Function:
  50. * Provide reader/writer sychronization.
  51. * Implementation:
  52. * Simple interlock on a bit. Readers first interlock,
  53. * increment the reader count, then let go. Writers hold
  54. * the interlock (thus preventing further readers), and
  55. * wait for already-accepted readers to go away.
  56. */
  57. /*
  58. * The simple-lock routines are the primitives out of which
  59. * the lock package is built. The implementation is left
  60. * to the machine-dependent code.
  61. */
  62. #ifdef notdef
  63. /*
  64. * A sample implementation of simple locks.
  65. * assumes:
  66. * boolean_t test_and_set(boolean_t *)
  67. * indivisibly sets the boolean to TRUE
  68. * and returns its old value
  69. * and that setting a boolean to FALSE is indivisible.
  70. */
  71. /*
  72. * simple_lock_init initializes a simple lock. A simple lock
  73. * may only be used for exclusive locks.
  74. */
  75. void simple_lock_init(simple_lock_t l)
  76. {
  77. *(boolean_t *)l = FALSE;
  78. }
  79. void simple_lock(simple_lock_t l)
  80. {
  81. while (test_and_set((boolean_t *)l))
  82. continue;
  83. }
  84. void simple_unlock(simple_lock_t l)
  85. {
  86. *(boolean_t *)l = FALSE;
  87. }
  88. boolean_t simple_lock_try(simple_lock_t l)
  89. {
  90. return (!test_and_set((boolean_t *)l));
  91. }
  92. #endif /* notdef */
  93. #endif /* NCPUS > 1 */
  94. #if NCPUS > 1
  95. static int lock_wait_time = 100;
  96. #else /* NCPUS > 1 */
  97. /*
  98. * It is silly to spin on a uni-processor as if we
  99. * thought something magical would happen to the
  100. * want_write bit while we are executing.
  101. */
  102. static int lock_wait_time = 0;
  103. #endif /* NCPUS > 1 */
  104. #if MACH_SLOCKS && NCPUS == 1
  105. /*
  106. * This code does not protect simple_locks_taken and simple_locks_info.
  107. * It works despite the fact that interrupt code does use simple locks.
  108. * This is because interrupts use locks in a stack-like manner.
  109. * Each interrupt releases all the locks it acquires, so the data
  110. * structures end up in the same state after the interrupt as before.
  111. * The only precaution necessary is that simple_locks_taken be
  112. * incremented first and decremented last, so that interrupt handlers
  113. * don't over-write active slots in simple_locks_info.
  114. */
  115. unsigned int simple_locks_taken = 0;
  116. #define NSLINFO 1000 /* maximum number of locks held */
  117. struct simple_locks_info {
  118. simple_lock_t l;
  119. const char *expr;
  120. const char *loc;
  121. } simple_locks_info[NSLINFO];
  122. int do_check_simple_locks = 1;
  123. void check_simple_locks(void)
  124. {
  125. assert(! do_check_simple_locks || simple_locks_taken == 0);
  126. }
  127. void check_simple_locks_enable(void)
  128. {
  129. do_check_simple_locks = 1;
  130. }
  131. void check_simple_locks_disable(void)
  132. {
  133. do_check_simple_locks = 0;
  134. }
  135. /* Need simple lock sanity checking code if simple locks are being
  136. compiled in, and we are compiling for a uniprocessor. */
  137. void simple_lock_init(
  138. simple_lock_t l)
  139. {
  140. l->lock_data = 0;
  141. }
  142. void _simple_lock(
  143. simple_lock_t l,
  144. const char *expression,
  145. const char *location)
  146. {
  147. struct simple_locks_info *info;
  148. assert(l->lock_data == 0);
  149. l->lock_data = 1;
  150. info = &simple_locks_info[simple_locks_taken++];
  151. barrier();
  152. info->l = l;
  153. info->expr = expression;
  154. info->loc = location;
  155. }
  156. boolean_t _simple_lock_try(
  157. simple_lock_t l,
  158. const char *expression,
  159. const char *location)
  160. {
  161. struct simple_locks_info *info;
  162. if (l->lock_data != 0)
  163. return FALSE;
  164. l->lock_data = 1;
  165. info = &simple_locks_info[simple_locks_taken++];
  166. barrier();
  167. info->l = l;
  168. info->expr = expression;
  169. info->loc = location;
  170. return TRUE;
  171. }
  172. void simple_unlock(
  173. simple_lock_t l)
  174. {
  175. assert(l->lock_data != 0);
  176. l->lock_data = 0;
  177. if (simple_locks_info[simple_locks_taken-1].l != l) {
  178. unsigned int i = simple_locks_taken;
  179. /* out-of-order unlocking */
  180. do
  181. if (i == 0)
  182. panic("simple_unlock");
  183. while (simple_locks_info[--i].l != l);
  184. simple_locks_info[i] = simple_locks_info[simple_locks_taken-1];
  185. }
  186. barrier();
  187. simple_locks_taken--;
  188. simple_locks_info[simple_locks_taken] = (struct simple_locks_info) {0};
  189. }
  190. #endif /* MACH_SLOCKS && NCPUS == 1 */
  191. /*
  192. * Routine: lock_init
  193. * Function:
  194. * Initialize a lock; required before use.
  195. * Note that clients declare the "struct lock"
  196. * variables and then initialize them, rather
  197. * than getting a new one from this module.
  198. */
  199. void lock_init(
  200. lock_t l,
  201. boolean_t can_sleep)
  202. {
  203. memset(l, 0, sizeof(lock_data_t));
  204. simple_lock_init(&l->interlock);
  205. l->want_write = FALSE;
  206. l->want_upgrade = FALSE;
  207. l->read_count = 0;
  208. l->can_sleep = can_sleep;
  209. l->thread = (struct thread *)-1; /* XXX */
  210. l->recursion_depth = 0;
  211. }
  212. void lock_sleepable(
  213. lock_t l,
  214. boolean_t can_sleep)
  215. {
  216. simple_lock(&l->interlock);
  217. l->can_sleep = can_sleep;
  218. simple_unlock(&l->interlock);
  219. }
  220. /*
  221. * Sleep locks. These use the same data structure and algorithm
  222. * as the spin locks, but the process sleeps while it is waiting
  223. * for the lock. These work on uniprocessor systems.
  224. */
  225. void lock_write(
  226. lock_t l)
  227. {
  228. int i;
  229. check_simple_locks();
  230. simple_lock(&l->interlock);
  231. if (l->thread == current_thread()) {
  232. /*
  233. * Recursive lock.
  234. */
  235. l->recursion_depth++;
  236. simple_unlock(&l->interlock);
  237. return;
  238. }
  239. /*
  240. * Try to acquire the want_write bit.
  241. */
  242. while (l->want_write) {
  243. if ((i = lock_wait_time) > 0) {
  244. simple_unlock(&l->interlock);
  245. while (--i > 0 && l->want_write)
  246. continue;
  247. simple_lock(&l->interlock);
  248. }
  249. if (l->can_sleep && l->want_write) {
  250. l->waiting = TRUE;
  251. thread_sleep(l,
  252. simple_lock_addr(l->interlock), FALSE);
  253. simple_lock(&l->interlock);
  254. }
  255. }
  256. l->want_write = TRUE;
  257. /* Wait for readers (and upgrades) to finish */
  258. while ((l->read_count != 0) || l->want_upgrade) {
  259. if ((i = lock_wait_time) > 0) {
  260. simple_unlock(&l->interlock);
  261. while (--i > 0 && (l->read_count != 0 ||
  262. l->want_upgrade))
  263. continue;
  264. simple_lock(&l->interlock);
  265. }
  266. if (l->can_sleep && (l->read_count != 0 || l->want_upgrade)) {
  267. l->waiting = TRUE;
  268. thread_sleep(l,
  269. simple_lock_addr(l->interlock), FALSE);
  270. simple_lock(&l->interlock);
  271. }
  272. }
  273. #if MACH_LDEBUG
  274. l->writer = current_thread();
  275. #endif /* MACH_LDEBUG */
  276. simple_unlock(&l->interlock);
  277. }
  278. void lock_done(
  279. lock_t l)
  280. {
  281. simple_lock(&l->interlock);
  282. if (l->read_count != 0)
  283. l->read_count--;
  284. else
  285. if (l->recursion_depth != 0)
  286. l->recursion_depth--;
  287. else
  288. if (l->want_upgrade)
  289. l->want_upgrade = FALSE;
  290. else {
  291. l->want_write = FALSE;
  292. #if MACH_LDEBUG
  293. l->writer = THREAD_NULL;
  294. #endif /* MACH_LDEBUG */
  295. }
  296. /*
  297. * There is no reason to wakeup a waiting thread
  298. * if the read-count is non-zero. Consider:
  299. * we must be dropping a read lock
  300. * threads are waiting only if one wants a write lock
  301. * if there are still readers, they can't proceed
  302. */
  303. if (l->waiting && (l->read_count == 0)) {
  304. l->waiting = FALSE;
  305. thread_wakeup(l);
  306. }
  307. simple_unlock(&l->interlock);
  308. }
  309. void lock_read(
  310. lock_t l)
  311. {
  312. int i;
  313. check_simple_locks();
  314. simple_lock(&l->interlock);
  315. if (l->thread == current_thread()) {
  316. /*
  317. * Recursive lock.
  318. */
  319. l->read_count++;
  320. simple_unlock(&l->interlock);
  321. return;
  322. }
  323. while (l->want_write || l->want_upgrade) {
  324. if ((i = lock_wait_time) > 0) {
  325. simple_unlock(&l->interlock);
  326. while (--i > 0 && (l->want_write || l->want_upgrade))
  327. continue;
  328. simple_lock(&l->interlock);
  329. }
  330. if (l->can_sleep && (l->want_write || l->want_upgrade)) {
  331. l->waiting = TRUE;
  332. thread_sleep(l,
  333. simple_lock_addr(l->interlock), FALSE);
  334. simple_lock(&l->interlock);
  335. }
  336. }
  337. l->read_count++;
  338. simple_unlock(&l->interlock);
  339. }
  340. /*
  341. * Routine: lock_read_to_write
  342. * Function:
  343. * Improves a read-only lock to one with
  344. * write permission. If another reader has
  345. * already requested an upgrade to a write lock,
  346. * no lock is held upon return.
  347. *
  348. * Returns TRUE if the upgrade *failed*.
  349. */
  350. boolean_t lock_read_to_write(
  351. lock_t l)
  352. {
  353. int i;
  354. check_simple_locks();
  355. simple_lock(&l->interlock);
  356. l->read_count--;
  357. if (l->thread == current_thread()) {
  358. /*
  359. * Recursive lock.
  360. */
  361. l->recursion_depth++;
  362. simple_unlock(&l->interlock);
  363. return(FALSE);
  364. }
  365. if (l->want_upgrade) {
  366. /*
  367. * Someone else has requested upgrade.
  368. * Since we've released a read lock, wake
  369. * him up.
  370. */
  371. if (l->waiting && (l->read_count == 0)) {
  372. l->waiting = FALSE;
  373. thread_wakeup(l);
  374. }
  375. simple_unlock(&l->interlock);
  376. return TRUE;
  377. }
  378. l->want_upgrade = TRUE;
  379. while (l->read_count != 0) {
  380. if ((i = lock_wait_time) > 0) {
  381. simple_unlock(&l->interlock);
  382. while (--i > 0 && l->read_count != 0)
  383. continue;
  384. simple_lock(&l->interlock);
  385. }
  386. if (l->can_sleep && l->read_count != 0) {
  387. l->waiting = TRUE;
  388. thread_sleep(l,
  389. simple_lock_addr(l->interlock), FALSE);
  390. simple_lock(&l->interlock);
  391. }
  392. }
  393. #if MACH_LDEBUG
  394. l->writer = current_thread();
  395. #endif /* MACH_LDEBUG */
  396. simple_unlock(&l->interlock);
  397. return FALSE;
  398. }
  399. void lock_write_to_read(
  400. lock_t l)
  401. {
  402. simple_lock(&l->interlock);
  403. #if MACH_LDEBUG
  404. assert(l->writer == current_thread());
  405. #endif /* MACH_LDEBUG */
  406. l->read_count++;
  407. if (l->recursion_depth != 0)
  408. l->recursion_depth--;
  409. else
  410. if (l->want_upgrade)
  411. l->want_upgrade = FALSE;
  412. else
  413. l->want_write = FALSE;
  414. if (l->waiting) {
  415. l->waiting = FALSE;
  416. thread_wakeup(l);
  417. }
  418. #if MACH_LDEBUG
  419. l->writer = THREAD_NULL;
  420. #endif /* MACH_LDEBUG */
  421. simple_unlock(&l->interlock);
  422. }
  423. /*
  424. * Routine: lock_try_write
  425. * Function:
  426. * Tries to get a write lock.
  427. *
  428. * Returns FALSE if the lock is not held on return.
  429. */
  430. boolean_t lock_try_write(
  431. lock_t l)
  432. {
  433. simple_lock(&l->interlock);
  434. if (l->thread == current_thread()) {
  435. /*
  436. * Recursive lock
  437. */
  438. l->recursion_depth++;
  439. simple_unlock(&l->interlock);
  440. return TRUE;
  441. }
  442. if (l->want_write || l->want_upgrade || l->read_count) {
  443. /*
  444. * Can't get lock.
  445. */
  446. simple_unlock(&l->interlock);
  447. return FALSE;
  448. }
  449. /*
  450. * Have lock.
  451. */
  452. l->want_write = TRUE;
  453. #if MACH_LDEBUG
  454. l->writer = current_thread();
  455. #endif /* MACH_LDEBUG */
  456. simple_unlock(&l->interlock);
  457. return TRUE;
  458. }
  459. /*
  460. * Routine: lock_try_read
  461. * Function:
  462. * Tries to get a read lock.
  463. *
  464. * Returns FALSE if the lock is not held on return.
  465. */
  466. boolean_t lock_try_read(
  467. lock_t l)
  468. {
  469. simple_lock(&l->interlock);
  470. if (l->thread == current_thread()) {
  471. /*
  472. * Recursive lock
  473. */
  474. l->read_count++;
  475. simple_unlock(&l->interlock);
  476. return TRUE;
  477. }
  478. if (l->want_write || l->want_upgrade) {
  479. simple_unlock(&l->interlock);
  480. return FALSE;
  481. }
  482. l->read_count++;
  483. simple_unlock(&l->interlock);
  484. return TRUE;
  485. }
  486. /*
  487. * Routine: lock_try_read_to_write
  488. * Function:
  489. * Improves a read-only lock to one with
  490. * write permission. If another reader has
  491. * already requested an upgrade to a write lock,
  492. * the read lock is still held upon return.
  493. *
  494. * Returns FALSE if the upgrade *failed*.
  495. */
  496. boolean_t lock_try_read_to_write(
  497. lock_t l)
  498. {
  499. check_simple_locks();
  500. simple_lock(&l->interlock);
  501. if (l->thread == current_thread()) {
  502. /*
  503. * Recursive lock
  504. */
  505. l->read_count--;
  506. l->recursion_depth++;
  507. simple_unlock(&l->interlock);
  508. return TRUE;
  509. }
  510. if (l->want_upgrade) {
  511. simple_unlock(&l->interlock);
  512. return FALSE;
  513. }
  514. l->want_upgrade = TRUE;
  515. l->read_count--;
  516. while (l->read_count != 0) {
  517. l->waiting = TRUE;
  518. thread_sleep(l,
  519. simple_lock_addr(l->interlock), FALSE);
  520. simple_lock(&l->interlock);
  521. }
  522. #if MACH_LDEBUG
  523. l->writer = current_thread();
  524. #endif /* MACH_LDEBUG */
  525. simple_unlock(&l->interlock);
  526. return TRUE;
  527. }
  528. /*
  529. * Allow a process that has a lock for write to acquire it
  530. * recursively (for read, write, or update).
  531. */
  532. void lock_set_recursive(
  533. lock_t l)
  534. {
  535. simple_lock(&l->interlock);
  536. #if MACH_LDEBUG
  537. assert(l->writer == current_thread());
  538. #endif /* MACH_LDEBUG */
  539. if (!l->want_write) {
  540. panic("lock_set_recursive: don't have write lock");
  541. }
  542. l->thread = current_thread();
  543. simple_unlock(&l->interlock);
  544. }
  545. /*
  546. * Prevent a lock from being re-acquired.
  547. */
  548. void lock_clear_recursive(
  549. lock_t l)
  550. {
  551. simple_lock(&l->interlock);
  552. if (l->thread != current_thread()) {
  553. panic("lock_clear_recursive: wrong thread");
  554. }
  555. if (l->recursion_depth == 0)
  556. l->thread = (struct thread *)-1; /* XXX */
  557. simple_unlock(&l->interlock);
  558. }
  559. #if MACH_KDB
  560. #if MACH_SLOCKS && NCPUS == 1
  561. void db_show_all_slocks(void)
  562. {
  563. int i;
  564. struct simple_locks_info *info;
  565. simple_lock_t l;
  566. for (i = 0; i < simple_locks_taken; i++) {
  567. info = &simple_locks_info[i];
  568. db_printf("%d: %s (", i, info->expr);
  569. db_printsym(info->l, DB_STGY_ANY);
  570. db_printf(") locked by %s\n", info->loc);
  571. }
  572. }
  573. #else /* MACH_SLOCKS && NCPUS == 1 */
  574. void db_show_all_slocks(void)
  575. {
  576. db_printf("simple lock info not available\n");
  577. }
  578. #endif /* MACH_SLOCKS && NCPUS == 1 */
  579. #endif /* MACH_KDB */