]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/locks_i386.c
b6f5f3881fc0757f8b0344dbcc76abaa035062f5
[apple/xnu.git] / osfmk / i386 / locks_i386.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30 /*
31 * @OSF_COPYRIGHT@
32 */
33 /*
34 * Mach Operating System
35 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
36 * All Rights Reserved.
37 *
38 * Permission to use, copy, modify and distribute this software and its
39 * documentation is hereby granted, provided that both the copyright
40 * notice and this permission notice appear in all copies of the
41 * software, derivative works or modified versions, and any portions
42 * thereof, and that both notices appear in supporting documentation.
43 *
44 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
45 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
46 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
47 *
48 * Carnegie Mellon requests users of this software to return to
49 *
50 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
51 * School of Computer Science
52 * Carnegie Mellon University
53 * Pittsburgh PA 15213-3890
54 *
55 * any improvements or extensions that they make and grant Carnegie Mellon
56 * the rights to redistribute these changes.
57 */
58 /*
59 * File: kern/lock.c
60 * Author: Avadis Tevanian, Jr., Michael Wayne Young
61 * Date: 1985
62 *
63 * Locking primitives implementation
64 */
65
66 #include <mach_kdb.h>
67 #include <mach_ldebug.h>
68
69 #include <kern/lock.h>
70 #include <kern/locks.h>
71 #include <kern/kalloc.h>
72 #include <kern/misc_protos.h>
73 #include <kern/thread.h>
74 #include <kern/processor.h>
75 #include <kern/cpu_data.h>
76 #include <kern/cpu_number.h>
77 #include <kern/sched_prim.h>
78 #include <kern/xpr.h>
79 #include <kern/debug.h>
80 #include <string.h>
81
82 #if MACH_KDB
83 #include <ddb/db_command.h>
84 #include <ddb/db_output.h>
85 #include <ddb/db_sym.h>
86 #include <ddb/db_print.h>
87 #endif /* MACH_KDB */
88
89 #include <i386/machine_cpu.h>
90
91 #include <sys/kdebug.h>
92
93 #define LCK_RW_LCK_EXCLUSIVE_CODE 0x100
94 #define LCK_RW_LCK_EXCLUSIVE1_CODE 0x101
95 #define LCK_RW_LCK_SHARED_CODE 0x102
96 #define LCK_RW_LCK_SH_TO_EX_CODE 0x103
97 #define LCK_RW_LCK_SH_TO_EX1_CODE 0x104
98 #define LCK_RW_LCK_EX_TO_SH_CODE 0x105
99
100 #define LCK_MTX_LCK_SPIN 0x200
101
102 #define ANY_LOCK_DEBUG (USLOCK_DEBUG || LOCK_DEBUG || MUTEX_DEBUG)
103
104 unsigned int LcksOpts=0;
105 unsigned int lock_wait_time[2] = { (unsigned int)-1, 100 } ;
106
107 /* Forwards */
108
109 #if MACH_KDB
110 void db_print_simple_lock(
111 simple_lock_t addr);
112
113 void db_print_mutex(
114 mutex_t * addr);
115 #endif /* MACH_KDB */
116
117
118 #if USLOCK_DEBUG
119 /*
120 * Perform simple lock checks.
121 */
122 int uslock_check = 1;
123 int max_lock_loops = 100000000;
124 decl_simple_lock_data(extern , printf_lock)
125 decl_simple_lock_data(extern , panic_lock)
126 #if MACH_KDB
127 decl_simple_lock_data(extern , kdb_lock)
128 #endif /* MACH_KDB */
129 #endif /* USLOCK_DEBUG */
130
131
132 /*
133 * We often want to know the addresses of the callers
134 * of the various lock routines. However, this information
135 * is only used for debugging and statistics.
136 */
137 typedef void *pc_t;
138 #define INVALID_PC ((void *) VM_MAX_KERNEL_ADDRESS)
139 #define INVALID_THREAD ((void *) VM_MAX_KERNEL_ADDRESS)
140 #if ANY_LOCK_DEBUG
141 #define OBTAIN_PC(pc,l) ((pc) = (void *) GET_RETURN_PC(&(l)))
142 #define DECL_PC(pc) pc_t pc;
143 #else /* ANY_LOCK_DEBUG */
144 #define DECL_PC(pc)
145 #ifdef lint
146 /*
147 * Eliminate lint complaints about unused local pc variables.
148 */
149 #define OBTAIN_PC(pc,l) ++pc
150 #else /* lint */
151 #define OBTAIN_PC(pc,l)
152 #endif /* lint */
153 #endif /* USLOCK_DEBUG */
154
155
156 /*
157 * Portable lock package implementation of usimple_locks.
158 */
159
160 #if USLOCK_DEBUG
161 #define USLDBG(stmt) stmt
162 void usld_lock_init(usimple_lock_t, unsigned short);
163 void usld_lock_pre(usimple_lock_t, pc_t);
164 void usld_lock_post(usimple_lock_t, pc_t);
165 void usld_unlock(usimple_lock_t, pc_t);
166 void usld_lock_try_pre(usimple_lock_t, pc_t);
167 void usld_lock_try_post(usimple_lock_t, pc_t);
168 int usld_lock_common_checks(usimple_lock_t, char *);
169 #else /* USLOCK_DEBUG */
170 #define USLDBG(stmt)
171 #endif /* USLOCK_DEBUG */
172
173 /*
174 * Routine: lck_spin_alloc_init
175 */
176 lck_spin_t *
177 lck_spin_alloc_init(
178 lck_grp_t *grp,
179 lck_attr_t *attr)
180 {
181 lck_spin_t *lck;
182
183 if ((lck = (lck_spin_t *)kalloc(sizeof(lck_spin_t))) != 0)
184 lck_spin_init(lck, grp, attr);
185
186 return(lck);
187 }
188
189 /*
190 * Routine: lck_spin_free
191 */
192 void
193 lck_spin_free(
194 lck_spin_t *lck,
195 lck_grp_t *grp)
196 {
197 lck_spin_destroy(lck, grp);
198 kfree(lck, sizeof(lck_spin_t));
199 }
200
201 /*
202 * Routine: lck_spin_init
203 */
204 void
205 lck_spin_init(
206 lck_spin_t *lck,
207 lck_grp_t *grp,
208 __unused lck_attr_t *attr)
209 {
210 usimple_lock_init((usimple_lock_t) lck, 0);
211 lck_grp_reference(grp);
212 lck_grp_lckcnt_incr(grp, LCK_TYPE_SPIN);
213 }
214
215 /*
216 * Routine: lck_spin_destroy
217 */
218 void
219 lck_spin_destroy(
220 lck_spin_t *lck,
221 lck_grp_t *grp)
222 {
223 if (lck->lck_spin_data[0] == LCK_SPIN_TAG_DESTROYED)
224 return;
225 lck->lck_spin_data[0] = LCK_SPIN_TAG_DESTROYED;
226 lck_grp_lckcnt_decr(grp, LCK_TYPE_SPIN);
227 lck_grp_deallocate(grp);
228 return;
229 }
230
231 /*
232 * Routine: lck_spin_lock
233 */
234 void
235 lck_spin_lock(
236 lck_spin_t *lck)
237 {
238 usimple_lock((usimple_lock_t) lck);
239 }
240
241 /*
242 * Routine: lck_spin_unlock
243 */
244 void
245 lck_spin_unlock(
246 lck_spin_t *lck)
247 {
248 usimple_unlock((usimple_lock_t) lck);
249 }
250
251
252 /*
253 * Routine: lck_spin_try_lock
254 */
255 boolean_t
256 lck_spin_try_lock(
257 lck_spin_t *lck)
258 {
259 return(usimple_lock_try((usimple_lock_t) lck));
260 }
261
262 /*
263 * Initialize a usimple_lock.
264 *
265 * No change in preemption state.
266 */
267 void
268 usimple_lock_init(
269 usimple_lock_t l,
270 __unused unsigned short tag)
271 {
272 #ifndef MACHINE_SIMPLE_LOCK
273 USLDBG(usld_lock_init(l, tag));
274 hw_lock_init(&l->interlock);
275 #else
276 simple_lock_init((simple_lock_t)l,tag);
277 #endif
278 }
279
280
281 /*
282 * Acquire a usimple_lock.
283 *
284 * Returns with preemption disabled. Note
285 * that the hw_lock routines are responsible for
286 * maintaining preemption state.
287 */
288 void
289 usimple_lock(
290 usimple_lock_t l)
291 {
292 #ifndef MACHINE_SIMPLE_LOCK
293 pc_t pc = NULL;
294
295 OBTAIN_PC(pc, l);
296 USLDBG(usld_lock_pre(l, pc));
297
298 if(!hw_lock_to(&l->interlock, LockTimeOut)) /* Try to get the lock with a timeout */
299 panic("simple lock deadlock detection - l=%08X, cpu=%d, ret=%08X", l, cpu_number(), pc);
300
301 USLDBG(usld_lock_post(l, pc));
302 #else
303 simple_lock((simple_lock_t)l);
304 #endif
305 }
306
307
308 /*
309 * Release a usimple_lock.
310 *
311 * Returns with preemption enabled. Note
312 * that the hw_lock routines are responsible for
313 * maintaining preemption state.
314 */
315 void
316 usimple_unlock(
317 usimple_lock_t l)
318 {
319 #ifndef MACHINE_SIMPLE_LOCK
320 DECL_PC(pc);
321
322 OBTAIN_PC(pc, l);
323 USLDBG(usld_unlock(l, pc));
324 hw_lock_unlock(&l->interlock);
325 #else
326 simple_unlock_rwmb((simple_lock_t)l);
327 #endif
328 }
329
330
331 /*
332 * Conditionally acquire a usimple_lock.
333 *
334 * On success, returns with preemption disabled.
335 * On failure, returns with preemption in the same state
336 * as when first invoked. Note that the hw_lock routines
337 * are responsible for maintaining preemption state.
338 *
339 * XXX No stats are gathered on a miss; I preserved this
340 * behavior from the original assembly-language code, but
341 * doesn't it make sense to log misses? XXX
342 */
343 unsigned int
344 usimple_lock_try(
345 usimple_lock_t l)
346 {
347 #ifndef MACHINE_SIMPLE_LOCK
348 DECL_PC(pc);
349 unsigned int success;
350
351 OBTAIN_PC(pc, l);
352 USLDBG(usld_lock_try_pre(l, pc));
353 if ((success = hw_lock_try(&l->interlock))) {
354 USLDBG(usld_lock_try_post(l, pc));
355 }
356 return success;
357 #else
358 return(simple_lock_try((simple_lock_t)l));
359 #endif
360 }
361
362 #if USLOCK_DEBUG
363 /*
364 * States of a usimple_lock. The default when initializing
365 * a usimple_lock is setting it up for debug checking.
366 */
367 #define USLOCK_CHECKED 0x0001 /* lock is being checked */
368 #define USLOCK_TAKEN 0x0002 /* lock has been taken */
369 #define USLOCK_INIT 0xBAA0 /* lock has been initialized */
370 #define USLOCK_INITIALIZED (USLOCK_INIT|USLOCK_CHECKED)
371 #define USLOCK_CHECKING(l) (uslock_check && \
372 ((l)->debug.state & USLOCK_CHECKED))
373
374 /*
375 * Trace activities of a particularly interesting lock.
376 */
377 void usl_trace(usimple_lock_t, int, pc_t, const char *);
378
379
380 /*
381 * Initialize the debugging information contained
382 * in a usimple_lock.
383 */
384 void
385 usld_lock_init(
386 usimple_lock_t l,
387 __unused unsigned short tag)
388 {
389 if (l == USIMPLE_LOCK_NULL)
390 panic("lock initialization: null lock pointer");
391 l->lock_type = USLOCK_TAG;
392 l->debug.state = uslock_check ? USLOCK_INITIALIZED : 0;
393 l->debug.lock_cpu = l->debug.unlock_cpu = 0;
394 l->debug.lock_pc = l->debug.unlock_pc = INVALID_PC;
395 l->debug.lock_thread = l->debug.unlock_thread = INVALID_THREAD;
396 l->debug.duration[0] = l->debug.duration[1] = 0;
397 l->debug.unlock_cpu = l->debug.unlock_cpu = 0;
398 l->debug.unlock_pc = l->debug.unlock_pc = INVALID_PC;
399 l->debug.unlock_thread = l->debug.unlock_thread = INVALID_THREAD;
400 }
401
402
403 /*
404 * These checks apply to all usimple_locks, not just
405 * those with USLOCK_CHECKED turned on.
406 */
407 int
408 usld_lock_common_checks(
409 usimple_lock_t l,
410 char *caller)
411 {
412 if (l == USIMPLE_LOCK_NULL)
413 panic("%s: null lock pointer", caller);
414 if (l->lock_type != USLOCK_TAG)
415 panic("%s: 0x%x is not a usimple lock", caller, (integer_t) l);
416 if (!(l->debug.state & USLOCK_INIT))
417 panic("%s: 0x%x is not an initialized lock",
418 caller, (integer_t) l);
419 return USLOCK_CHECKING(l);
420 }
421
422
423 /*
424 * Debug checks on a usimple_lock just before attempting
425 * to acquire it.
426 */
427 /* ARGSUSED */
428 void
429 usld_lock_pre(
430 usimple_lock_t l,
431 pc_t pc)
432 {
433 char caller[] = "usimple_lock";
434
435
436 if (!usld_lock_common_checks(l, caller))
437 return;
438
439 /*
440 * Note that we have a weird case where we are getting a lock when we are]
441 * in the process of putting the system to sleep. We are running with no
442 * current threads, therefore we can't tell if we are trying to retake a lock
443 * we have or someone on the other processor has it. Therefore we just
444 * ignore this test if the locking thread is 0.
445 */
446
447 if ((l->debug.state & USLOCK_TAKEN) && l->debug.lock_thread &&
448 l->debug.lock_thread == (void *) current_thread()) {
449 printf("%s: lock 0x%x already locked (at 0x%x) by",
450 caller, (integer_t) l, l->debug.lock_pc);
451 printf(" current thread 0x%x (new attempt at pc 0x%x)\n",
452 l->debug.lock_thread, pc);
453 panic(caller);
454 }
455 mp_disable_preemption();
456 usl_trace(l, cpu_number(), pc, caller);
457 mp_enable_preemption();
458 }
459
460
461 /*
462 * Debug checks on a usimple_lock just after acquiring it.
463 *
464 * Pre-emption has been disabled at this point,
465 * so we are safe in using cpu_number.
466 */
467 void
468 usld_lock_post(
469 usimple_lock_t l,
470 pc_t pc)
471 {
472 register int mycpu;
473 char caller[] = "successful usimple_lock";
474
475
476 if (!usld_lock_common_checks(l, caller))
477 return;
478
479 if (!((l->debug.state & ~USLOCK_TAKEN) == USLOCK_INITIALIZED))
480 panic("%s: lock 0x%x became uninitialized",
481 caller, (integer_t) l);
482 if ((l->debug.state & USLOCK_TAKEN))
483 panic("%s: lock 0x%x became TAKEN by someone else",
484 caller, (integer_t) l);
485
486 mycpu = cpu_number();
487 l->debug.lock_thread = (void *)current_thread();
488 l->debug.state |= USLOCK_TAKEN;
489 l->debug.lock_pc = pc;
490 l->debug.lock_cpu = mycpu;
491
492 usl_trace(l, mycpu, pc, caller);
493 }
494
495
496 /*
497 * Debug checks on a usimple_lock just before
498 * releasing it. Note that the caller has not
499 * yet released the hardware lock.
500 *
501 * Preemption is still disabled, so there's
502 * no problem using cpu_number.
503 */
504 void
505 usld_unlock(
506 usimple_lock_t l,
507 pc_t pc)
508 {
509 register int mycpu;
510 char caller[] = "usimple_unlock";
511
512
513 if (!usld_lock_common_checks(l, caller))
514 return;
515
516 mycpu = cpu_number();
517
518 if (!(l->debug.state & USLOCK_TAKEN))
519 panic("%s: lock 0x%x hasn't been taken",
520 caller, (integer_t) l);
521 if (l->debug.lock_thread != (void *) current_thread())
522 panic("%s: unlocking lock 0x%x, owned by thread 0x%x",
523 caller, (integer_t) l, l->debug.lock_thread);
524 if (l->debug.lock_cpu != mycpu) {
525 printf("%s: unlocking lock 0x%x on cpu 0x%x",
526 caller, (integer_t) l, mycpu);
527 printf(" (acquired on cpu 0x%x)\n", l->debug.lock_cpu);
528 panic(caller);
529 }
530 usl_trace(l, mycpu, pc, caller);
531
532 l->debug.unlock_thread = l->debug.lock_thread;
533 l->debug.lock_thread = INVALID_PC;
534 l->debug.state &= ~USLOCK_TAKEN;
535 l->debug.unlock_pc = pc;
536 l->debug.unlock_cpu = mycpu;
537 }
538
539
540 /*
541 * Debug checks on a usimple_lock just before
542 * attempting to acquire it.
543 *
544 * Preemption isn't guaranteed to be disabled.
545 */
546 void
547 usld_lock_try_pre(
548 usimple_lock_t l,
549 pc_t pc)
550 {
551 char caller[] = "usimple_lock_try";
552
553 if (!usld_lock_common_checks(l, caller))
554 return;
555 mp_disable_preemption();
556 usl_trace(l, cpu_number(), pc, caller);
557 mp_enable_preemption();
558 }
559
560
561 /*
562 * Debug checks on a usimple_lock just after
563 * successfully attempting to acquire it.
564 *
565 * Preemption has been disabled by the
566 * lock acquisition attempt, so it's safe
567 * to use cpu_number.
568 */
569 void
570 usld_lock_try_post(
571 usimple_lock_t l,
572 pc_t pc)
573 {
574 register int mycpu;
575 char caller[] = "successful usimple_lock_try";
576
577 if (!usld_lock_common_checks(l, caller))
578 return;
579
580 if (!((l->debug.state & ~USLOCK_TAKEN) == USLOCK_INITIALIZED))
581 panic("%s: lock 0x%x became uninitialized",
582 caller, (integer_t) l);
583 if ((l->debug.state & USLOCK_TAKEN))
584 panic("%s: lock 0x%x became TAKEN by someone else",
585 caller, (integer_t) l);
586
587 mycpu = cpu_number();
588 l->debug.lock_thread = (void *) current_thread();
589 l->debug.state |= USLOCK_TAKEN;
590 l->debug.lock_pc = pc;
591 l->debug.lock_cpu = mycpu;
592
593 usl_trace(l, mycpu, pc, caller);
594 }
595
596
597 /*
598 * For very special cases, set traced_lock to point to a
599 * specific lock of interest. The result is a series of
600 * XPRs showing lock operations on that lock. The lock_seq
601 * value is used to show the order of those operations.
602 */
603 usimple_lock_t traced_lock;
604 unsigned int lock_seq;
605
606 void
607 usl_trace(
608 usimple_lock_t l,
609 int mycpu,
610 pc_t pc,
611 const char * op_name)
612 {
613 if (traced_lock == l) {
614 XPR(XPR_SLOCK,
615 "seq %d, cpu %d, %s @ %x\n",
616 (integer_t) lock_seq, (integer_t) mycpu,
617 (integer_t) op_name, (integer_t) pc, 0);
618 lock_seq++;
619 }
620 }
621
622
623 #endif /* USLOCK_DEBUG */
624
625 /*
626 * Routine: lock_alloc
627 * Function:
628 * Allocate a lock for external users who cannot
629 * hard-code the structure definition into their
630 * objects.
631 * For now just use kalloc, but a zone is probably
632 * warranted.
633 */
634 lock_t *
635 lock_alloc(
636 boolean_t can_sleep,
637 unsigned short tag,
638 unsigned short tag1)
639 {
640 lock_t *l;
641
642 if ((l = (lock_t *)kalloc(sizeof(lock_t))) != 0)
643 lock_init(l, can_sleep, tag, tag1);
644 return(l);
645 }
646
647 /*
648 * Routine: lock_free
649 * Function:
650 * Free a lock allocated for external users.
651 * For now just use kfree, but a zone is probably
652 * warranted.
653 */
654 void
655 lock_free(
656 lock_t *l)
657 {
658 kfree(l, sizeof(lock_t));
659 }
660
661
662 /*
663 * Routine: lock_init
664 * Function:
665 * Initialize a lock; required before use.
666 * Note that clients declare the "struct lock"
667 * variables and then initialize them, rather
668 * than getting a new one from this module.
669 */
670 void
671 lock_init(
672 lock_t *l,
673 boolean_t can_sleep,
674 __unused unsigned short tag,
675 __unused unsigned short tag1)
676 {
677 hw_lock_init(&l->interlock);
678 l->want_write = FALSE;
679 l->want_upgrade = FALSE;
680 l->read_count = 0;
681 l->can_sleep = can_sleep;
682 l->lck_rw_tag = tag;
683 }
684
685
686 /*
687 * Sleep locks. These use the same data structure and algorithm
688 * as the spin locks, but the process sleeps while it is waiting
689 * for the lock. These work on uniprocessor systems.
690 */
691
692 #define DECREMENTER_TIMEOUT 1000000
693
694 void
695 lock_write(
696 register lock_t * l)
697 {
698 lck_rw_lock_exclusive(l);
699 }
700
701 void
702 lock_done(
703 register lock_t * l)
704 {
705 (void) lck_rw_done(l);
706 }
707
708 void
709 lock_read(
710 register lock_t * l)
711 {
712 lck_rw_lock_shared(l);
713 }
714
715
716 /*
717 * Routine: lock_read_to_write
718 * Function:
719 * Improves a read-only lock to one with
720 * write permission. If another reader has
721 * already requested an upgrade to a write lock,
722 * no lock is held upon return.
723 *
724 * Returns TRUE if the upgrade *failed*.
725 */
726
727 boolean_t
728 lock_read_to_write(
729 register lock_t * l)
730 {
731 return lck_rw_lock_shared_to_exclusive(l);
732 }
733
734 void
735 lock_write_to_read(
736 register lock_t * l)
737 {
738 lck_rw_lock_exclusive_to_shared(l);
739 }
740
741
742
743 /*
744 * Routine: lck_rw_alloc_init
745 */
746 lck_rw_t *
747 lck_rw_alloc_init(
748 lck_grp_t *grp,
749 lck_attr_t *attr) {
750 lck_rw_t *lck;
751
752 if ((lck = (lck_rw_t *)kalloc(sizeof(lck_rw_t))) != 0)
753 lck_rw_init(lck, grp, attr);
754
755 return(lck);
756 }
757
758 /*
759 * Routine: lck_rw_free
760 */
761 void
762 lck_rw_free(
763 lck_rw_t *lck,
764 lck_grp_t *grp) {
765 lck_rw_destroy(lck, grp);
766 kfree(lck, sizeof(lck_rw_t));
767 }
768
769 /*
770 * Routine: lck_rw_init
771 */
772 void
773 lck_rw_init(
774 lck_rw_t *lck,
775 lck_grp_t *grp,
776 lck_attr_t *attr)
777 {
778 lck_attr_t *lck_attr = (attr != LCK_ATTR_NULL) ?
779 attr : &LockDefaultLckAttr;
780
781 hw_lock_init(&lck->interlock);
782 lck->want_write = FALSE;
783 lck->want_upgrade = FALSE;
784 lck->read_count = 0;
785 lck->can_sleep = TRUE;
786 lck->lck_rw_tag = 0;
787 lck->read_priority = (lck_attr->lck_attr_val &
788 LCK_ATTR_RW_SHARED_PRIORITY) != 0;
789
790 lck_grp_reference(grp);
791 lck_grp_lckcnt_incr(grp, LCK_TYPE_RW);
792 }
793
794 /*
795 * Routine: lck_rw_destroy
796 */
797 void
798 lck_rw_destroy(
799 lck_rw_t *lck,
800 lck_grp_t *grp) {
801 if (lck->lck_rw_tag == LCK_RW_TAG_DESTROYED)
802 return;
803 lck->lck_rw_tag = LCK_RW_TAG_DESTROYED;
804 lck_grp_lckcnt_decr(grp, LCK_TYPE_RW);
805 lck_grp_deallocate(grp);
806 return;
807 }
808
809 /*
810 * Sleep locks. These use the same data structure and algorithm
811 * as the spin locks, but the process sleeps while it is waiting
812 * for the lock. These work on uniprocessor systems.
813 */
814
815 #define DECREMENTER_TIMEOUT 1000000
816
817
818 /*
819 * We need to disable interrupts while holding the mutex interlock
820 * to prevent an IPI intervening.
821 * Hence, local helper functions lck_interlock_lock()/lck_interlock_unlock().
822 */
823 static boolean_t
824 lck_interlock_lock(lck_rw_t *lck)
825 {
826 boolean_t istate;
827
828 istate = ml_set_interrupts_enabled(FALSE);
829 hw_lock_lock(&lck->interlock);
830
831 return istate;
832 }
833
834 static void
835 lck_interlock_unlock(lck_rw_t *lck, boolean_t istate)
836 {
837 hw_lock_unlock(&lck->interlock);
838 ml_set_interrupts_enabled(istate);
839 }
840
841
842 /*
843 * This inline is used when busy-waiting for an rw lock.
844 * If interrupts were disabled when the lock primitive was called,
845 * we poll the IPI handler for pending tlb flushes.
846 * XXX This is a hack to avoid deadlocking on the pmap_system_lock.
847 */
848 static inline void
849 lck_rw_lock_pause(boolean_t interrupts_enabled)
850 {
851 if (!interrupts_enabled)
852 handle_pending_TLB_flushes();
853 cpu_pause();
854 }
855
856 /*
857 * Routine: lck_rw_lock_exclusive
858 */
859 void
860 lck_rw_lock_exclusive(
861 lck_rw_t *lck)
862 {
863 int i;
864 boolean_t lock_miss = FALSE;
865 wait_result_t res;
866 #if MACH_LDEBUG
867 int decrementer;
868 #endif /* MACH_LDEBUG */
869 boolean_t istate;
870
871 istate = lck_interlock_lock(lck);
872
873 #if MACH_LDEBUG
874 decrementer = DECREMENTER_TIMEOUT;
875 #endif /* MACH_LDEBUG */
876
877 /*
878 * Try to acquire the want_write bit.
879 */
880 while (lck->want_write) {
881 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_RW_LCK_EXCLUSIVE_CODE) | DBG_FUNC_START, (int)lck, 0, 0, 0, 0);
882
883 if (!lock_miss) {
884 lock_miss = TRUE;
885 }
886
887 i = lock_wait_time[lck->can_sleep ? 1 : 0];
888 if (i != 0) {
889 lck_interlock_unlock(lck, istate);
890 #if MACH_LDEBUG
891 if (!--decrementer)
892 Debugger("timeout - want_write");
893 #endif /* MACH_LDEBUG */
894 while (--i != 0 && lck->want_write)
895 lck_rw_lock_pause(istate);
896 istate = lck_interlock_lock(lck);
897 }
898
899 if (lck->can_sleep && lck->want_write) {
900 lck->waiting = TRUE;
901 res = assert_wait((event_t) lck, THREAD_UNINT);
902 if (res == THREAD_WAITING) {
903 lck_interlock_unlock(lck, istate);
904 res = thread_block(THREAD_CONTINUE_NULL);
905 istate = lck_interlock_lock(lck);
906 }
907 }
908 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_RW_LCK_EXCLUSIVE_CODE) | DBG_FUNC_END, (int)lck, res, 0, 0, 0);
909 }
910 lck->want_write = TRUE;
911
912 /* Wait for readers (and upgrades) to finish */
913
914 #if MACH_LDEBUG
915 decrementer = DECREMENTER_TIMEOUT;
916 #endif /* MACH_LDEBUG */
917 while ((lck->read_count != 0) || lck->want_upgrade) {
918 if (!lock_miss) {
919 lock_miss = TRUE;
920 }
921
922 i = lock_wait_time[lck->can_sleep ? 1 : 0];
923
924 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_RW_LCK_EXCLUSIVE1_CODE) | DBG_FUNC_START,
925 (int)lck, lck->read_count, lck->want_upgrade, i, 0);
926
927 if (i != 0) {
928 lck_interlock_unlock(lck, istate);
929 #if MACH_LDEBUG
930 if (!--decrementer)
931 Debugger("timeout - wait for readers");
932 #endif /* MACH_LDEBUG */
933 while (--i != 0 && (lck->read_count != 0 ||
934 lck->want_upgrade))
935 lck_rw_lock_pause(istate);
936 istate = lck_interlock_lock(lck);
937 }
938
939 if (lck->can_sleep && (lck->read_count != 0 || lck->want_upgrade)) {
940 lck->waiting = TRUE;
941 res = assert_wait((event_t) lck, THREAD_UNINT);
942 if (res == THREAD_WAITING) {
943 lck_interlock_unlock(lck, istate);
944 res = thread_block(THREAD_CONTINUE_NULL);
945 istate = lck_interlock_lock(lck);
946 }
947 }
948 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_RW_LCK_EXCLUSIVE1_CODE) | DBG_FUNC_END,
949 (int)lck, lck->read_count, lck->want_upgrade, res, 0);
950 }
951
952 lck_interlock_unlock(lck, istate);
953 }
954
955
956 /*
957 * Routine: lck_rw_done
958 */
959 lck_rw_type_t
960 lck_rw_done(
961 lck_rw_t *lck)
962 {
963 boolean_t do_wakeup = FALSE;
964 lck_rw_type_t lck_rw_type;
965 boolean_t istate;
966
967
968 istate = lck_interlock_lock(lck);
969
970 if (lck->read_count != 0) {
971 lck_rw_type = LCK_RW_TYPE_SHARED;
972 lck->read_count--;
973 }
974 else {
975 lck_rw_type = LCK_RW_TYPE_EXCLUSIVE;
976 if (lck->want_upgrade)
977 lck->want_upgrade = FALSE;
978 else
979 lck->want_write = FALSE;
980 }
981
982 /*
983 * There is no reason to wakeup a waiting thread
984 * if the read-count is non-zero. Consider:
985 * we must be dropping a read lock
986 * threads are waiting only if one wants a write lock
987 * if there are still readers, they can't proceed
988 */
989
990 if (lck->waiting && (lck->read_count == 0)) {
991 lck->waiting = FALSE;
992 do_wakeup = TRUE;
993 }
994
995 lck_interlock_unlock(lck, istate);
996
997 if (do_wakeup)
998 thread_wakeup((event_t) lck);
999 return(lck_rw_type);
1000 }
1001
1002
1003
1004
1005 /*
1006 * Routine: lck_rw_unlock
1007 */
1008 void
1009 lck_rw_unlock(
1010 lck_rw_t *lck,
1011 lck_rw_type_t lck_rw_type)
1012 {
1013 if (lck_rw_type == LCK_RW_TYPE_SHARED)
1014 lck_rw_unlock_shared(lck);
1015 else if (lck_rw_type == LCK_RW_TYPE_EXCLUSIVE)
1016 lck_rw_unlock_exclusive(lck);
1017 else
1018 panic("lck_rw_unlock(): Invalid RW lock type: %d\n", lck_rw_type);
1019 }
1020
1021
1022 /*
1023 * Routine: lck_rw_unlock_shared
1024 */
1025 void
1026 lck_rw_unlock_shared(
1027 lck_rw_t *lck)
1028 {
1029 lck_rw_type_t ret;
1030
1031 ret = lck_rw_done(lck);
1032
1033 if (ret != LCK_RW_TYPE_SHARED)
1034 panic("lck_rw_unlock(): lock held in mode: %d\n", ret);
1035 }
1036
1037
1038 /*
1039 * Routine: lck_rw_unlock_exclusive
1040 */
1041 void
1042 lck_rw_unlock_exclusive(
1043 lck_rw_t *lck)
1044 {
1045 lck_rw_type_t ret;
1046
1047 ret = lck_rw_done(lck);
1048
1049 if (ret != LCK_RW_TYPE_EXCLUSIVE)
1050 panic("lck_rw_unlock_exclusive(): lock held in mode: %d\n", ret);
1051 }
1052
1053
1054 /*
1055 * Routine: lck_rw_lock
1056 */
1057 void
1058 lck_rw_lock(
1059 lck_rw_t *lck,
1060 lck_rw_type_t lck_rw_type)
1061 {
1062 if (lck_rw_type == LCK_RW_TYPE_SHARED)
1063 lck_rw_lock_shared(lck);
1064 else if (lck_rw_type == LCK_RW_TYPE_EXCLUSIVE)
1065 lck_rw_lock_exclusive(lck);
1066 else
1067 panic("lck_rw_lock(): Invalid RW lock type: %x\n", lck_rw_type);
1068 }
1069
1070
1071 /*
1072 * Routine: lck_rw_lock_shared
1073 */
1074 void
1075 lck_rw_lock_shared(
1076 lck_rw_t *lck)
1077 {
1078 int i;
1079 wait_result_t res;
1080 #if MACH_LDEBUG
1081 int decrementer;
1082 #endif /* MACH_LDEBUG */
1083 boolean_t istate;
1084
1085 istate = lck_interlock_lock(lck);
1086
1087 #if MACH_LDEBUG
1088 decrementer = DECREMENTER_TIMEOUT;
1089 #endif /* MACH_LDEBUG */
1090 while ((lck->want_write && (lck->read_priority ?
1091 lck->read_count == 0 : TRUE)) ||
1092 lck->want_upgrade) {
1093
1094 i = lock_wait_time[lck->can_sleep ? 1 : 0];
1095
1096 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_RW_LCK_SHARED_CODE) | DBG_FUNC_START,
1097 (int)lck, lck->want_write, lck->want_upgrade, i, 0);
1098
1099 if (i != 0) {
1100 lck_interlock_unlock(lck, istate);
1101 #if MACH_LDEBUG
1102 if (!--decrementer)
1103 Debugger("timeout - wait no writers");
1104 #endif /* MACH_LDEBUG */
1105 while (--i != 0 &&
1106 ((lck->want_write && (lck->read_priority ?
1107 lck->read_count == 0 : TRUE)) ||
1108 lck->want_upgrade))
1109 lck_rw_lock_pause(istate);
1110 istate = lck_interlock_lock(lck);
1111 }
1112
1113 if (lck->can_sleep &&
1114 ((lck->want_write && (lck->read_priority ?
1115 lck->read_count == 0 : TRUE)) ||
1116 lck->want_upgrade)) {
1117 lck->waiting = TRUE;
1118 res = assert_wait((event_t) lck, THREAD_UNINT);
1119 if (res == THREAD_WAITING) {
1120 lck_interlock_unlock(lck, istate);
1121 res = thread_block(THREAD_CONTINUE_NULL);
1122 istate = lck_interlock_lock(lck);
1123 }
1124 }
1125 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_RW_LCK_SHARED_CODE) | DBG_FUNC_END,
1126 (int)lck, lck->want_write, lck->want_upgrade, res, 0);
1127 }
1128
1129 lck->read_count++;
1130
1131 lck_interlock_unlock(lck, istate);
1132 }
1133
1134
1135 /*
1136 * Routine: lck_rw_lock_shared_to_exclusive
1137 * Function:
1138 * Improves a read-only lock to one with
1139 * write permission. If another reader has
1140 * already requested an upgrade to a write lock,
1141 * no lock is held upon return.
1142 *
1143 * Returns TRUE if the upgrade *failed*.
1144 */
1145
1146 boolean_t
1147 lck_rw_lock_shared_to_exclusive(
1148 lck_rw_t *lck)
1149 {
1150 int i;
1151 boolean_t do_wakeup = FALSE;
1152 wait_result_t res;
1153 #if MACH_LDEBUG
1154 int decrementer;
1155 #endif /* MACH_LDEBUG */
1156 boolean_t istate;
1157
1158 istate = lck_interlock_lock(lck);
1159
1160 lck->read_count--;
1161
1162 if (lck->want_upgrade) {
1163 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_RW_LCK_SH_TO_EX_CODE) | DBG_FUNC_START,
1164 (int)lck, lck->read_count, lck->want_upgrade, 0, 0);
1165
1166 /*
1167 * Someone else has requested upgrade.
1168 * Since we've released a read lock, wake
1169 * him up.
1170 */
1171 if (lck->waiting && (lck->read_count == 0)) {
1172 lck->waiting = FALSE;
1173 do_wakeup = TRUE;
1174 }
1175
1176 lck_interlock_unlock(lck, istate);
1177
1178 if (do_wakeup)
1179 thread_wakeup((event_t) lck);
1180
1181 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_RW_LCK_SH_TO_EX_CODE) | DBG_FUNC_END,
1182 (int)lck, lck->read_count, lck->want_upgrade, 0, 0);
1183
1184 return (TRUE);
1185 }
1186
1187 lck->want_upgrade = TRUE;
1188
1189 #if MACH_LDEBUG
1190 decrementer = DECREMENTER_TIMEOUT;
1191 #endif /* MACH_LDEBUG */
1192 while (lck->read_count != 0) {
1193 i = lock_wait_time[lck->can_sleep ? 1 : 0];
1194
1195 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_RW_LCK_SH_TO_EX1_CODE) | DBG_FUNC_START,
1196 (int)lck, lck->read_count, i, 0, 0);
1197
1198 if (i != 0) {
1199 lck_interlock_unlock(lck, istate);
1200 #if MACH_LDEBUG
1201 if (!--decrementer)
1202 Debugger("timeout - read_count");
1203 #endif /* MACH_LDEBUG */
1204 while (--i != 0 && lck->read_count != 0)
1205 lck_rw_lock_pause(istate);
1206 istate = lck_interlock_lock(lck);
1207 }
1208
1209 if (lck->can_sleep && lck->read_count != 0) {
1210 lck->waiting = TRUE;
1211 res = assert_wait((event_t) lck, THREAD_UNINT);
1212 if (res == THREAD_WAITING) {
1213 lck_interlock_unlock(lck, istate);
1214 res = thread_block(THREAD_CONTINUE_NULL);
1215 istate = lck_interlock_lock(lck);
1216 }
1217 }
1218 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_RW_LCK_SH_TO_EX1_CODE) | DBG_FUNC_END,
1219 (int)lck, lck->read_count, 0, 0, 0);
1220 }
1221
1222 lck_interlock_unlock(lck, istate);
1223
1224 return (FALSE);
1225 }
1226
1227 /*
1228 * Routine: lck_rw_lock_exclusive_to_shared
1229 */
1230 void
1231 lck_rw_lock_exclusive_to_shared(
1232 lck_rw_t *lck)
1233 {
1234 boolean_t do_wakeup = FALSE;
1235 boolean_t istate;
1236
1237 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_RW_LCK_EX_TO_SH_CODE) | DBG_FUNC_START,
1238 (int)lck, lck->want_write, lck->want_upgrade, 0, 0);
1239
1240 istate = lck_interlock_lock(lck);
1241
1242 lck->read_count++;
1243 if (lck->want_upgrade)
1244 lck->want_upgrade = FALSE;
1245 else
1246 lck->want_write = FALSE;
1247
1248 if (lck->waiting) {
1249 lck->waiting = FALSE;
1250 do_wakeup = TRUE;
1251 }
1252
1253 lck_interlock_unlock(lck, istate);
1254
1255 if (do_wakeup)
1256 thread_wakeup((event_t) lck);
1257
1258 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS, LCK_RW_LCK_EX_TO_SH_CODE) | DBG_FUNC_END,
1259 (int)lck, lck->want_write, lck->want_upgrade, lck->read_count, 0);
1260
1261 }
1262
1263
1264 /*
1265 * Routine: lck_rw_try_lock
1266 */
1267 boolean_t
1268 lck_rw_try_lock(
1269 lck_rw_t *lck,
1270 lck_rw_type_t lck_rw_type)
1271 {
1272 if (lck_rw_type == LCK_RW_TYPE_SHARED)
1273 return(lck_rw_try_lock_shared(lck));
1274 else if (lck_rw_type == LCK_RW_TYPE_EXCLUSIVE)
1275 return(lck_rw_try_lock_exclusive(lck));
1276 else
1277 panic("lck_rw_try_lock(): Invalid rw lock type: %x\n", lck_rw_type);
1278 return(FALSE);
1279 }
1280
1281 /*
1282 * Routine: lck_rw_try_lock_exclusive
1283 * Function:
1284 * Tries to get a write lock.
1285 *
1286 * Returns FALSE if the lock is not held on return.
1287 */
1288
1289 boolean_t
1290 lck_rw_try_lock_exclusive(
1291 lck_rw_t *lck)
1292 {
1293 boolean_t istate;
1294
1295 istate = lck_interlock_lock(lck);
1296
1297 if (lck->want_write || lck->want_upgrade || lck->read_count) {
1298 /*
1299 * Can't get lock.
1300 */
1301 lck_interlock_unlock(lck, istate);
1302 return(FALSE);
1303 }
1304
1305 /*
1306 * Have lock.
1307 */
1308
1309 lck->want_write = TRUE;
1310
1311 lck_interlock_unlock(lck, istate);
1312
1313 return(TRUE);
1314 }
1315
1316 /*
1317 * Routine: lck_rw_try_lock_shared
1318 * Function:
1319 * Tries to get a read lock.
1320 *
1321 * Returns FALSE if the lock is not held on return.
1322 */
1323
1324 boolean_t
1325 lck_rw_try_lock_shared(
1326 lck_rw_t *lck)
1327 {
1328 boolean_t istate;
1329
1330 istate = lck_interlock_lock(lck);
1331
1332 if (lck->want_write || lck->want_upgrade) {
1333 lck_interlock_unlock(lck, istate);
1334 return(FALSE);
1335 }
1336
1337 lck->read_count++;
1338
1339 lck_interlock_unlock(lck, istate);
1340
1341 return(TRUE);
1342 }
1343
1344 /*
1345 * Routine: lck_mtx_alloc_init
1346 */
1347 lck_mtx_t *
1348 lck_mtx_alloc_init(
1349 lck_grp_t *grp,
1350 lck_attr_t *attr)
1351 {
1352 lck_mtx_t *lck;
1353
1354 if ((lck = (lck_mtx_t *)kalloc(sizeof(lck_mtx_t))) != 0)
1355 lck_mtx_init(lck, grp, attr);
1356
1357 return(lck);
1358 }
1359
1360 /*
1361 * Routine: lck_mtx_free
1362 */
1363 void
1364 lck_mtx_free(
1365 lck_mtx_t *lck,
1366 lck_grp_t *grp)
1367 {
1368 lck_mtx_destroy(lck, grp);
1369 kfree(lck, sizeof(lck_mtx_t));
1370 }
1371
1372 /*
1373 * Routine: lck_mtx_ext_init
1374 */
1375 static void
1376 lck_mtx_ext_init(
1377 lck_mtx_ext_t *lck,
1378 lck_grp_t *grp,
1379 lck_attr_t *attr)
1380 {
1381 lck->lck_mtx.lck_mtx_ilk = 0;
1382 lck->lck_mtx.lck_mtx_locked = 0;
1383 lck->lck_mtx.lck_mtx_waiters = 0;
1384 lck->lck_mtx.lck_mtx_pri = 0;
1385 lck->lck_mtx_attr = 0;
1386
1387 if ((attr->lck_attr_val) & LCK_ATTR_DEBUG) {
1388 lck->lck_mtx_deb.pc = 0;
1389 lck->lck_mtx_deb.thread = 0;
1390 lck->lck_mtx_deb.type = MUTEX_TAG;
1391 lck->lck_mtx_attr |= LCK_MTX_ATTR_DEBUG;
1392 }
1393
1394 lck->lck_mtx_grp = grp;
1395 }
1396
1397 /*
1398 * Routine: lck_mtx_init
1399 */
1400 void
1401 lck_mtx_init(
1402 lck_mtx_t *lck,
1403 lck_grp_t *grp,
1404 lck_attr_t *attr)
1405 {
1406 lck_mtx_ext_t *lck_ext;
1407
1408 if ((attr != LCK_ATTR_NULL) && ((attr->lck_attr_val) & LCK_ATTR_DEBUG)) {
1409 if ((lck_ext = (lck_mtx_ext_t *)kalloc(sizeof(lck_mtx_ext_t))) != 0) {
1410 lck_mtx_ext_init(lck_ext, grp, attr);
1411 lck->lck_mtx_tag = LCK_MTX_TAG_INDIRECT;
1412 lck->lck_mtx_ptr = lck_ext;
1413 }
1414 } else {
1415 lck->lck_mtx_ilk = 0;
1416 lck->lck_mtx_locked = 0;
1417 lck->lck_mtx_waiters = 0;
1418 lck->lck_mtx_pri = 0;
1419 }
1420 lck_grp_reference(grp);
1421 lck_grp_lckcnt_incr(grp, LCK_TYPE_MTX);
1422 }
1423
1424 /*
1425 * Routine: lck_mtx_destroy
1426 */
1427 void
1428 lck_mtx_destroy(
1429 lck_mtx_t *lck,
1430 lck_grp_t *grp)
1431 {
1432 boolean_t lck_is_indirect;
1433
1434 if (lck->lck_mtx_tag == LCK_MTX_TAG_DESTROYED)
1435 return;
1436 lck_is_indirect = (lck->lck_mtx_tag == LCK_MTX_TAG_INDIRECT);
1437 lck->lck_mtx_tag = LCK_MTX_TAG_DESTROYED;
1438 if (lck_is_indirect)
1439 kfree(lck->lck_mtx_ptr, sizeof(lck_mtx_ext_t));
1440 lck_grp_lckcnt_decr(grp, LCK_TYPE_MTX);
1441 lck_grp_deallocate(grp);
1442 return;
1443 }
1444
1445 /*
1446 * Routine: lck_mtx_assert
1447 */
1448 void
1449 lck_mtx_assert(
1450 __unused lck_mtx_t *lck,
1451 __unused unsigned int type)
1452 {
1453 }
1454
1455 /*
1456 * Routine: lck_mtx_lock_spin
1457 *
1458 * Invoked trying to acquire a mutex when there is contention but
1459 * the holder is running on another processor. We spin for up to a maximum
1460 * time waiting for the lock to be released.
1461 *
1462 * Called with the interlock unlocked.
1463 */
1464 void
1465 lck_mtx_lock_spin(
1466 lck_mtx_t *lck)
1467 {
1468 thread_t holder;
1469 lck_mtx_t *mutex;
1470 uint64_t deadline;
1471
1472 if (lck->lck_mtx_tag != LCK_MTX_TAG_INDIRECT)
1473 mutex = lck;
1474 else
1475 mutex = &lck->lck_mtx_ptr->lck_mtx;
1476
1477 KERNEL_DEBUG(
1478 MACHDBG_CODE(DBG_MACH_LOCKS, LCK_MTX_LCK_SPIN) | DBG_FUNC_START,
1479 (int)lck, (int)mutex->lck_mtx_locked, 0, 0, 0);
1480
1481 deadline = mach_absolute_time() + MutexSpin;
1482 /*
1483 * Spin while:
1484 * - mutex is locked, and
1485 * - owner is running on another processor, and
1486 * - owner is not is the idle delay, and
1487 * - we haven't spun for long enough.
1488 */
1489 while ((holder = (thread_t) mutex->lck_mtx_locked) != NULL &&
1490 (holder->machine.specFlags & OnProc) != 0 &&
1491 (holder->options & TH_OPT_DELAYIDLE) == 0 &&
1492 mach_absolute_time() < deadline)
1493 cpu_pause();
1494 }
1495
1496 /*
1497 * Called from assembly code when a mutex interlock is held.
1498 * We spin here re-checking the interlock but panic if we timeout.
1499 * Note: here with interrupts disabled.
1500 */
1501 void
1502 lck_mtx_interlock_spin(
1503 lck_mtx_t *lck)
1504 {
1505 lck_mtx_t *mutex;
1506 uint64_t deadline;
1507
1508 if (lck->lck_mtx_tag != LCK_MTX_TAG_INDIRECT)
1509 mutex = lck;
1510 else
1511 mutex = &lck->lck_mtx_ptr->lck_mtx;
1512
1513 deadline = mach_absolute_time() + LockTimeOut;
1514 while (mutex->lck_mtx_ilk != 0) {
1515 cpu_pause();
1516 if (mach_absolute_time() > deadline)
1517 panic("interlock timeout for mutex %p", lck);
1518 }
1519
1520 }
1521
1522 #if MACH_KDB
1523
1524 void db_show_one_lock(lock_t *);
1525
1526 void
1527 db_show_one_lock(
1528 lock_t *lock)
1529 {
1530 db_printf("Read_count = 0x%x, %swant_upgrade, %swant_write, ",
1531 lock->read_count,
1532 lock->want_upgrade ? "" : "!",
1533 lock->want_write ? "" : "!");
1534 db_printf("%swaiting, %scan_sleep\n",
1535 lock->waiting ? "" : "!", lock->can_sleep ? "" : "!");
1536 db_printf("Interlock:\n");
1537 db_show_one_simple_lock((db_expr_t) ((vm_offset_t)simple_lock_addr(lock->interlock)),
1538 TRUE, (db_expr_t)0, (char *)0);
1539 }
1540
1541 #endif /* MACH_KDB */
1542
1543 /*
1544 * The C portion of the mutex package. These routines are only invoked
1545 * if the optimized assembler routines can't do the work.
1546 */
1547
1548 /*
1549 * Routine: lock_alloc
1550 * Function:
1551 * Allocate a mutex for external users who cannot
1552 * hard-code the structure definition into their
1553 * objects.
1554 * For now just use kalloc, but a zone is probably
1555 * warranted.
1556 */
1557 mutex_t *
1558 mutex_alloc(
1559 unsigned short tag)
1560 {
1561 mutex_t *m;
1562
1563 if ((m = (mutex_t *)kalloc(sizeof(mutex_t))) != 0)
1564 mutex_init(m, tag);
1565 return(m);
1566 }
1567
1568 /*
1569 * Routine: mutex_free
1570 * Function:
1571 * Free a mutex allocated for external users.
1572 * For now just use kfree, but a zone is probably
1573 * warranted.
1574 */
1575 void
1576 mutex_free(
1577 mutex_t *m)
1578 {
1579 kfree(m, sizeof(mutex_t));
1580 }
1581
1582 /*
1583 * Routine: _mutex_assert
1584 */
1585 void
1586 _mutex_assert (
1587 mutex_t *mutex,
1588 unsigned int what)
1589 {
1590
1591 thread_t thread = current_thread();
1592 thread_t holder;
1593
1594 if (panicstr != NULL)
1595 return;
1596
1597 holder = (thread_t) mutex->lck_mtx.lck_mtx_locked;
1598
1599 switch (what) {
1600 case MA_OWNED:
1601 if (thread != holder)
1602 panic("mutex %x not owned\n", mutex);
1603 break;
1604
1605 case MA_NOTOWNED:
1606 if (thread == holder)
1607 panic("mutex %x owned\n", mutex);
1608 break;
1609 }
1610
1611 }
1612
1613 #if MACH_KDB
1614 /*
1615 * Routines to print out simple_locks and mutexes in a nicely-formatted
1616 * fashion.
1617 */
1618
1619 const char *simple_lock_labels = "ENTRY ILK THREAD DURATION CALLER";
1620 const char *mutex_labels = "ENTRY LOCKED WAITERS THREAD CALLER";
1621
1622 void
1623 db_show_one_simple_lock (
1624 db_expr_t addr,
1625 boolean_t have_addr,
1626 __unused db_expr_t count,
1627 __unused char * modif)
1628 {
1629 simple_lock_t saddr = (simple_lock_t) ((vm_offset_t) addr);
1630
1631 if (saddr == (simple_lock_t)0 || !have_addr) {
1632 db_error ("No simple_lock\n");
1633 }
1634 #if USLOCK_DEBUG
1635 else if (saddr->lock_type != USLOCK_TAG)
1636 db_error ("Not a simple_lock\n");
1637 #endif /* USLOCK_DEBUG */
1638
1639 db_printf ("%s\n", simple_lock_labels);
1640 db_print_simple_lock (saddr);
1641 }
1642
1643 void
1644 db_print_simple_lock (
1645 simple_lock_t addr)
1646 {
1647
1648 db_printf ("%08x %3d", addr, *hw_lock_addr(addr->interlock));
1649 #if USLOCK_DEBUG
1650 db_printf (" %08x", addr->debug.lock_thread);
1651 db_printf (" %08x ", addr->debug.duration[1]);
1652 db_printsym ((int)addr->debug.lock_pc, DB_STGY_ANY);
1653 #endif /* USLOCK_DEBUG */
1654 db_printf ("\n");
1655 }
1656
1657 void
1658 db_show_one_mutex (
1659 db_expr_t addr,
1660 boolean_t have_addr,
1661 __unused db_expr_t count,
1662 __unused char * modif)
1663 {
1664 mutex_t * maddr = (mutex_t *)((vm_offset_t) addr);
1665
1666 if (maddr == (mutex_t *)0 || !have_addr)
1667 db_error ("No mutex\n");
1668 #if MACH_LDEBUG
1669 else if (maddr->type != MUTEX_TAG)
1670 db_error ("Not a mutex\n");
1671 #endif /* MACH_LDEBUG */
1672
1673 db_printf ("%s\n", mutex_labels);
1674 db_print_mutex (maddr);
1675 }
1676
1677 void
1678 db_print_mutex (
1679 mutex_t * addr)
1680 {
1681 db_printf ("%08x %6d %7d",
1682 addr, *addr, addr->lck_mtx.lck_mtx_waiters);
1683 #if MACH_LDEBUG
1684 db_printf (" %08x ", addr->thread);
1685 db_printsym (addr->pc, DB_STGY_ANY);
1686 #endif /* MACH_LDEBUG */
1687 db_printf ("\n");
1688 }
1689
1690 #endif /* MACH_KDB */