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