2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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 License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
34 * All Rights Reserved.
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
58 * Author: Avadis Tevanian, Jr., Michael Wayne Young
61 * Locking primitives implementation
65 #include <mach_ldebug.h>
67 #include <kern/lock.h>
68 #include <kern/locks.h>
69 #include <kern/kalloc.h>
70 #include <kern/misc_protos.h>
71 #include <kern/thread.h>
72 #include <kern/processor.h>
73 #include <kern/cpu_data.h>
74 #include <kern/cpu_number.h>
75 #include <kern/sched_prim.h>
77 #include <kern/debug.h>
81 #include <ddb/db_command.h>
82 #include <ddb/db_output.h>
83 #include <ddb/db_sym.h>
84 #include <ddb/db_print.h>
87 #include <i386/machine_cpu.h>
89 #include <sys/kdebug.h>
91 #define LCK_RW_LCK_EXCLUSIVE_CODE 0x100
92 #define LCK_RW_LCK_EXCLUSIVE1_CODE 0x101
93 #define LCK_RW_LCK_SHARED_CODE 0x102
94 #define LCK_RW_LCK_SH_TO_EX_CODE 0x103
95 #define LCK_RW_LCK_SH_TO_EX1_CODE 0x104
96 #define LCK_RW_LCK_EX_TO_SH_CODE 0x105
98 #define LCK_MTX_LCK_SPIN 0x200
100 #define ANY_LOCK_DEBUG (USLOCK_DEBUG || LOCK_DEBUG || MUTEX_DEBUG)
102 unsigned int LcksOpts
=0;
103 unsigned int lock_wait_time
[2] = { (unsigned int)-1, 100 } ;
108 void db_print_simple_lock(
113 #endif /* MACH_KDB */
118 * Perform simple lock checks.
120 int uslock_check
= 1;
121 int max_lock_loops
= 100000000;
122 decl_simple_lock_data(extern , printf_lock
)
123 decl_simple_lock_data(extern , panic_lock
)
125 decl_simple_lock_data(extern , kdb_lock
)
126 #endif /* MACH_KDB */
127 #endif /* USLOCK_DEBUG */
131 * We often want to know the addresses of the callers
132 * of the various lock routines. However, this information
133 * is only used for debugging and statistics.
136 #define INVALID_PC ((void *) VM_MAX_KERNEL_ADDRESS)
137 #define INVALID_THREAD ((void *) VM_MAX_KERNEL_ADDRESS)
139 #define OBTAIN_PC(pc,l) ((pc) = (void *) GET_RETURN_PC(&(l)))
140 #define DECL_PC(pc) pc_t pc;
141 #else /* ANY_LOCK_DEBUG */
145 * Eliminate lint complaints about unused local pc variables.
147 #define OBTAIN_PC(pc,l) ++pc
149 #define OBTAIN_PC(pc,l)
151 #endif /* USLOCK_DEBUG */
155 * Portable lock package implementation of usimple_locks.
159 #define USLDBG(stmt) stmt
160 void usld_lock_init(usimple_lock_t
, unsigned short);
161 void usld_lock_pre(usimple_lock_t
, pc_t
);
162 void usld_lock_post(usimple_lock_t
, pc_t
);
163 void usld_unlock(usimple_lock_t
, pc_t
);
164 void usld_lock_try_pre(usimple_lock_t
, pc_t
);
165 void usld_lock_try_post(usimple_lock_t
, pc_t
);
166 int usld_lock_common_checks(usimple_lock_t
, char *);
167 #else /* USLOCK_DEBUG */
169 #endif /* USLOCK_DEBUG */
172 * Routine: lck_spin_alloc_init
181 if ((lck
= (lck_spin_t
*)kalloc(sizeof(lck_spin_t
))) != 0)
182 lck_spin_init(lck
, grp
, attr
);
188 * Routine: lck_spin_free
195 lck_spin_destroy(lck
, grp
);
196 kfree(lck
, sizeof(lck_spin_t
));
200 * Routine: lck_spin_init
206 __unused lck_attr_t
*attr
)
208 usimple_lock_init((usimple_lock_t
) lck
, 0);
209 lck_grp_reference(grp
);
210 lck_grp_lckcnt_incr(grp
, LCK_TYPE_SPIN
);
214 * Routine: lck_spin_destroy
221 if (lck
->lck_spin_data
[0] == LCK_SPIN_TAG_DESTROYED
)
223 lck
->lck_spin_data
[0] = LCK_SPIN_TAG_DESTROYED
;
224 lck_grp_lckcnt_decr(grp
, LCK_TYPE_SPIN
);
225 lck_grp_deallocate(grp
);
230 * Routine: lck_spin_lock
236 usimple_lock((usimple_lock_t
) lck
);
240 * Routine: lck_spin_unlock
246 usimple_unlock((usimple_lock_t
) lck
);
251 * Routine: lck_spin_try_lock
257 return(usimple_lock_try((usimple_lock_t
) lck
));
261 * Initialize a usimple_lock.
263 * No change in preemption state.
268 __unused
unsigned short tag
)
270 #ifndef MACHINE_SIMPLE_LOCK
271 USLDBG(usld_lock_init(l
, tag
));
272 hw_lock_init(&l
->interlock
);
274 simple_lock_init((simple_lock_t
)l
,tag
);
280 * Acquire a usimple_lock.
282 * Returns with preemption disabled. Note
283 * that the hw_lock routines are responsible for
284 * maintaining preemption state.
290 #ifndef MACHINE_SIMPLE_LOCK
294 USLDBG(usld_lock_pre(l
, pc
));
296 if(!hw_lock_to(&l
->interlock
, LockTimeOut
)) /* Try to get the lock with a timeout */
297 panic("simple lock deadlock detection - l=%08X, cpu=%d, ret=%08X", l
, cpu_number(), pc
);
299 USLDBG(usld_lock_post(l
, pc
));
301 simple_lock((simple_lock_t
)l
);
307 * Release a usimple_lock.
309 * Returns with preemption enabled. Note
310 * that the hw_lock routines are responsible for
311 * maintaining preemption state.
317 #ifndef MACHINE_SIMPLE_LOCK
321 USLDBG(usld_unlock(l
, pc
));
322 hw_lock_unlock(&l
->interlock
);
324 simple_unlock_rwmb((simple_lock_t
)l
);
330 * Conditionally acquire a usimple_lock.
332 * On success, returns with preemption disabled.
333 * On failure, returns with preemption in the same state
334 * as when first invoked. Note that the hw_lock routines
335 * are responsible for maintaining preemption state.
337 * XXX No stats are gathered on a miss; I preserved this
338 * behavior from the original assembly-language code, but
339 * doesn't it make sense to log misses? XXX
345 #ifndef MACHINE_SIMPLE_LOCK
347 unsigned int success
;
350 USLDBG(usld_lock_try_pre(l
, pc
));
351 if ((success
= hw_lock_try(&l
->interlock
))) {
352 USLDBG(usld_lock_try_post(l
, pc
));
356 return(simple_lock_try((simple_lock_t
)l
));
362 * States of a usimple_lock. The default when initializing
363 * a usimple_lock is setting it up for debug checking.
365 #define USLOCK_CHECKED 0x0001 /* lock is being checked */
366 #define USLOCK_TAKEN 0x0002 /* lock has been taken */
367 #define USLOCK_INIT 0xBAA0 /* lock has been initialized */
368 #define USLOCK_INITIALIZED (USLOCK_INIT|USLOCK_CHECKED)
369 #define USLOCK_CHECKING(l) (uslock_check && \
370 ((l)->debug.state & USLOCK_CHECKED))
373 * Trace activities of a particularly interesting lock.
375 void usl_trace(usimple_lock_t
, int, pc_t
, const char *);
379 * Initialize the debugging information contained
385 __unused
unsigned short tag
)
387 if (l
== USIMPLE_LOCK_NULL
)
388 panic("lock initialization: null lock pointer");
389 l
->lock_type
= USLOCK_TAG
;
390 l
->debug
.state
= uslock_check
? USLOCK_INITIALIZED
: 0;
391 l
->debug
.lock_cpu
= l
->debug
.unlock_cpu
= 0;
392 l
->debug
.lock_pc
= l
->debug
.unlock_pc
= INVALID_PC
;
393 l
->debug
.lock_thread
= l
->debug
.unlock_thread
= INVALID_THREAD
;
394 l
->debug
.duration
[0] = l
->debug
.duration
[1] = 0;
395 l
->debug
.unlock_cpu
= l
->debug
.unlock_cpu
= 0;
396 l
->debug
.unlock_pc
= l
->debug
.unlock_pc
= INVALID_PC
;
397 l
->debug
.unlock_thread
= l
->debug
.unlock_thread
= INVALID_THREAD
;
402 * These checks apply to all usimple_locks, not just
403 * those with USLOCK_CHECKED turned on.
406 usld_lock_common_checks(
410 if (l
== USIMPLE_LOCK_NULL
)
411 panic("%s: null lock pointer", caller
);
412 if (l
->lock_type
!= USLOCK_TAG
)
413 panic("%s: 0x%x is not a usimple lock", caller
, (integer_t
) l
);
414 if (!(l
->debug
.state
& USLOCK_INIT
))
415 panic("%s: 0x%x is not an initialized lock",
416 caller
, (integer_t
) l
);
417 return USLOCK_CHECKING(l
);
422 * Debug checks on a usimple_lock just before attempting
431 char caller
[] = "usimple_lock";
434 if (!usld_lock_common_checks(l
, caller
))
438 * Note that we have a weird case where we are getting a lock when we are]
439 * in the process of putting the system to sleep. We are running with no
440 * current threads, therefore we can't tell if we are trying to retake a lock
441 * we have or someone on the other processor has it. Therefore we just
442 * ignore this test if the locking thread is 0.
445 if ((l
->debug
.state
& USLOCK_TAKEN
) && l
->debug
.lock_thread
&&
446 l
->debug
.lock_thread
== (void *) current_thread()) {
447 printf("%s: lock 0x%x already locked (at 0x%x) by",
448 caller
, (integer_t
) l
, l
->debug
.lock_pc
);
449 printf(" current thread 0x%x (new attempt at pc 0x%x)\n",
450 l
->debug
.lock_thread
, pc
);
453 mp_disable_preemption();
454 usl_trace(l
, cpu_number(), pc
, caller
);
455 mp_enable_preemption();
460 * Debug checks on a usimple_lock just after acquiring it.
462 * Pre-emption has been disabled at this point,
463 * so we are safe in using cpu_number.
471 char caller
[] = "successful usimple_lock";
474 if (!usld_lock_common_checks(l
, caller
))
477 if (!((l
->debug
.state
& ~USLOCK_TAKEN
) == USLOCK_INITIALIZED
))
478 panic("%s: lock 0x%x became uninitialized",
479 caller
, (integer_t
) l
);
480 if ((l
->debug
.state
& USLOCK_TAKEN
))
481 panic("%s: lock 0x%x became TAKEN by someone else",
482 caller
, (integer_t
) l
);
484 mycpu
= cpu_number();
485 l
->debug
.lock_thread
= (void *)current_thread();
486 l
->debug
.state
|= USLOCK_TAKEN
;
487 l
->debug
.lock_pc
= pc
;
488 l
->debug
.lock_cpu
= mycpu
;
490 usl_trace(l
, mycpu
, pc
, caller
);
495 * Debug checks on a usimple_lock just before
496 * releasing it. Note that the caller has not
497 * yet released the hardware lock.
499 * Preemption is still disabled, so there's
500 * no problem using cpu_number.
508 char caller
[] = "usimple_unlock";
511 if (!usld_lock_common_checks(l
, caller
))
514 mycpu
= cpu_number();
516 if (!(l
->debug
.state
& USLOCK_TAKEN
))
517 panic("%s: lock 0x%x hasn't been taken",
518 caller
, (integer_t
) l
);
519 if (l
->debug
.lock_thread
!= (void *) current_thread())
520 panic("%s: unlocking lock 0x%x, owned by thread 0x%x",
521 caller
, (integer_t
) l
, l
->debug
.lock_thread
);
522 if (l
->debug
.lock_cpu
!= mycpu
) {
523 printf("%s: unlocking lock 0x%x on cpu 0x%x",
524 caller
, (integer_t
) l
, mycpu
);
525 printf(" (acquired on cpu 0x%x)\n", l
->debug
.lock_cpu
);
528 usl_trace(l
, mycpu
, pc
, caller
);
530 l
->debug
.unlock_thread
= l
->debug
.lock_thread
;
531 l
->debug
.lock_thread
= INVALID_PC
;
532 l
->debug
.state
&= ~USLOCK_TAKEN
;
533 l
->debug
.unlock_pc
= pc
;
534 l
->debug
.unlock_cpu
= mycpu
;
539 * Debug checks on a usimple_lock just before
540 * attempting to acquire it.
542 * Preemption isn't guaranteed to be disabled.
549 char caller
[] = "usimple_lock_try";
551 if (!usld_lock_common_checks(l
, caller
))
553 mp_disable_preemption();
554 usl_trace(l
, cpu_number(), pc
, caller
);
555 mp_enable_preemption();
560 * Debug checks on a usimple_lock just after
561 * successfully attempting to acquire it.
563 * Preemption has been disabled by the
564 * lock acquisition attempt, so it's safe
573 char caller
[] = "successful usimple_lock_try";
575 if (!usld_lock_common_checks(l
, caller
))
578 if (!((l
->debug
.state
& ~USLOCK_TAKEN
) == USLOCK_INITIALIZED
))
579 panic("%s: lock 0x%x became uninitialized",
580 caller
, (integer_t
) l
);
581 if ((l
->debug
.state
& USLOCK_TAKEN
))
582 panic("%s: lock 0x%x became TAKEN by someone else",
583 caller
, (integer_t
) l
);
585 mycpu
= cpu_number();
586 l
->debug
.lock_thread
= (void *) current_thread();
587 l
->debug
.state
|= USLOCK_TAKEN
;
588 l
->debug
.lock_pc
= pc
;
589 l
->debug
.lock_cpu
= mycpu
;
591 usl_trace(l
, mycpu
, pc
, caller
);
596 * For very special cases, set traced_lock to point to a
597 * specific lock of interest. The result is a series of
598 * XPRs showing lock operations on that lock. The lock_seq
599 * value is used to show the order of those operations.
601 usimple_lock_t traced_lock
;
602 unsigned int lock_seq
;
609 const char * op_name
)
611 if (traced_lock
== l
) {
613 "seq %d, cpu %d, %s @ %x\n",
614 (integer_t
) lock_seq
, (integer_t
) mycpu
,
615 (integer_t
) op_name
, (integer_t
) pc
, 0);
621 #endif /* USLOCK_DEBUG */
624 * Routine: lock_alloc
626 * Allocate a lock for external users who cannot
627 * hard-code the structure definition into their
629 * For now just use kalloc, but a zone is probably
640 if ((l
= (lock_t
*)kalloc(sizeof(lock_t
))) != 0)
641 lock_init(l
, can_sleep
, tag
, tag1
);
648 * Free a lock allocated for external users.
649 * For now just use kfree, but a zone is probably
656 kfree(l
, sizeof(lock_t
));
663 * Initialize a lock; required before use.
664 * Note that clients declare the "struct lock"
665 * variables and then initialize them, rather
666 * than getting a new one from this module.
672 __unused
unsigned short tag
,
673 __unused
unsigned short tag1
)
675 hw_lock_init(&l
->interlock
);
676 l
->want_write
= FALSE
;
677 l
->want_upgrade
= FALSE
;
679 l
->can_sleep
= can_sleep
;
685 * Sleep locks. These use the same data structure and algorithm
686 * as the spin locks, but the process sleeps while it is waiting
687 * for the lock. These work on uniprocessor systems.
690 #define DECREMENTER_TIMEOUT 1000000
696 lck_rw_lock_exclusive(l
);
703 (void) lck_rw_done(l
);
710 lck_rw_lock_shared(l
);
715 * Routine: lock_read_to_write
717 * Improves a read-only lock to one with
718 * write permission. If another reader has
719 * already requested an upgrade to a write lock,
720 * no lock is held upon return.
722 * Returns TRUE if the upgrade *failed*.
729 return lck_rw_lock_shared_to_exclusive(l
);
736 lck_rw_lock_exclusive_to_shared(l
);
742 * Routine: lck_rw_alloc_init
750 if ((lck
= (lck_rw_t
*)kalloc(sizeof(lck_rw_t
))) != 0)
751 lck_rw_init(lck
, grp
, attr
);
757 * Routine: lck_rw_free
763 lck_rw_destroy(lck
, grp
);
764 kfree(lck
, sizeof(lck_rw_t
));
768 * Routine: lck_rw_init
776 lck_attr_t
*lck_attr
= (attr
!= LCK_ATTR_NULL
) ?
777 attr
: &LockDefaultLckAttr
;
779 hw_lock_init(&lck
->interlock
);
780 lck
->want_write
= FALSE
;
781 lck
->want_upgrade
= FALSE
;
783 lck
->can_sleep
= TRUE
;
785 lck
->read_priority
= (lck_attr
->lck_attr_val
&
786 LCK_ATTR_RW_SHARED_PRIORITY
) != 0;
788 lck_grp_reference(grp
);
789 lck_grp_lckcnt_incr(grp
, LCK_TYPE_RW
);
793 * Routine: lck_rw_destroy
799 if (lck
->lck_rw_tag
== LCK_RW_TAG_DESTROYED
)
801 lck
->lck_rw_tag
= LCK_RW_TAG_DESTROYED
;
802 lck_grp_lckcnt_decr(grp
, LCK_TYPE_RW
);
803 lck_grp_deallocate(grp
);
808 * Sleep locks. These use the same data structure and algorithm
809 * as the spin locks, but the process sleeps while it is waiting
810 * for the lock. These work on uniprocessor systems.
813 #define DECREMENTER_TIMEOUT 1000000
817 * We need to disable interrupts while holding the mutex interlock
818 * to prevent an IPI intervening.
819 * Hence, local helper functions lck_interlock_lock()/lck_interlock_unlock().
822 lck_interlock_lock(lck_rw_t
*lck
)
826 istate
= ml_set_interrupts_enabled(FALSE
);
827 hw_lock_lock(&lck
->interlock
);
833 lck_interlock_unlock(lck_rw_t
*lck
, boolean_t istate
)
835 hw_lock_unlock(&lck
->interlock
);
836 ml_set_interrupts_enabled(istate
);
841 * This inline is used when busy-waiting for an rw lock.
842 * If interrupts were disabled when the lock primitive was called,
843 * we poll the IPI handler for pending tlb flushes.
844 * XXX This is a hack to avoid deadlocking on the pmap_system_lock.
847 lck_rw_lock_pause(boolean_t interrupts_enabled
)
849 if (!interrupts_enabled
)
850 handle_pending_TLB_flushes();
855 * Routine: lck_rw_lock_exclusive
858 lck_rw_lock_exclusive(
862 boolean_t lock_miss
= FALSE
;
866 #endif /* MACH_LDEBUG */
869 istate
= lck_interlock_lock(lck
);
872 decrementer
= DECREMENTER_TIMEOUT
;
873 #endif /* MACH_LDEBUG */
876 * Try to acquire the want_write bit.
878 while (lck
->want_write
) {
879 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_RW_LCK_EXCLUSIVE_CODE
) | DBG_FUNC_START
, (int)lck
, 0, 0, 0, 0);
885 i
= lock_wait_time
[lck
->can_sleep
? 1 : 0];
887 lck_interlock_unlock(lck
, istate
);
890 Debugger("timeout - want_write");
891 #endif /* MACH_LDEBUG */
892 while (--i
!= 0 && lck
->want_write
)
893 lck_rw_lock_pause(istate
);
894 istate
= lck_interlock_lock(lck
);
897 if (lck
->can_sleep
&& lck
->want_write
) {
899 res
= assert_wait((event_t
) lck
, THREAD_UNINT
);
900 if (res
== THREAD_WAITING
) {
901 lck_interlock_unlock(lck
, istate
);
902 res
= thread_block(THREAD_CONTINUE_NULL
);
903 istate
= lck_interlock_lock(lck
);
906 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_RW_LCK_EXCLUSIVE_CODE
) | DBG_FUNC_END
, (int)lck
, res
, 0, 0, 0);
908 lck
->want_write
= TRUE
;
910 /* Wait for readers (and upgrades) to finish */
913 decrementer
= DECREMENTER_TIMEOUT
;
914 #endif /* MACH_LDEBUG */
915 while ((lck
->read_count
!= 0) || lck
->want_upgrade
) {
920 i
= lock_wait_time
[lck
->can_sleep
? 1 : 0];
922 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_RW_LCK_EXCLUSIVE1_CODE
) | DBG_FUNC_START
,
923 (int)lck
, lck
->read_count
, lck
->want_upgrade
, i
, 0);
926 lck_interlock_unlock(lck
, istate
);
929 Debugger("timeout - wait for readers");
930 #endif /* MACH_LDEBUG */
931 while (--i
!= 0 && (lck
->read_count
!= 0 ||
933 lck_rw_lock_pause(istate
);
934 istate
= lck_interlock_lock(lck
);
937 if (lck
->can_sleep
&& (lck
->read_count
!= 0 || lck
->want_upgrade
)) {
939 res
= assert_wait((event_t
) lck
, THREAD_UNINT
);
940 if (res
== THREAD_WAITING
) {
941 lck_interlock_unlock(lck
, istate
);
942 res
= thread_block(THREAD_CONTINUE_NULL
);
943 istate
= lck_interlock_lock(lck
);
946 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_RW_LCK_EXCLUSIVE1_CODE
) | DBG_FUNC_END
,
947 (int)lck
, lck
->read_count
, lck
->want_upgrade
, res
, 0);
950 lck_interlock_unlock(lck
, istate
);
955 * Routine: lck_rw_done
961 boolean_t do_wakeup
= FALSE
;
962 lck_rw_type_t lck_rw_type
;
966 istate
= lck_interlock_lock(lck
);
968 if (lck
->read_count
!= 0) {
969 lck_rw_type
= LCK_RW_TYPE_SHARED
;
973 lck_rw_type
= LCK_RW_TYPE_EXCLUSIVE
;
974 if (lck
->want_upgrade
)
975 lck
->want_upgrade
= FALSE
;
977 lck
->want_write
= FALSE
;
981 * There is no reason to wakeup a waiting thread
982 * if the read-count is non-zero. Consider:
983 * we must be dropping a read lock
984 * threads are waiting only if one wants a write lock
985 * if there are still readers, they can't proceed
988 if (lck
->waiting
&& (lck
->read_count
== 0)) {
989 lck
->waiting
= FALSE
;
993 lck_interlock_unlock(lck
, istate
);
996 thread_wakeup((event_t
) lck
);
1004 * Routine: lck_rw_unlock
1009 lck_rw_type_t lck_rw_type
)
1011 if (lck_rw_type
== LCK_RW_TYPE_SHARED
)
1012 lck_rw_unlock_shared(lck
);
1013 else if (lck_rw_type
== LCK_RW_TYPE_EXCLUSIVE
)
1014 lck_rw_unlock_exclusive(lck
);
1016 panic("lck_rw_unlock(): Invalid RW lock type: %d\n", lck_rw_type
);
1021 * Routine: lck_rw_unlock_shared
1024 lck_rw_unlock_shared(
1029 ret
= lck_rw_done(lck
);
1031 if (ret
!= LCK_RW_TYPE_SHARED
)
1032 panic("lck_rw_unlock(): lock held in mode: %d\n", ret
);
1037 * Routine: lck_rw_unlock_exclusive
1040 lck_rw_unlock_exclusive(
1045 ret
= lck_rw_done(lck
);
1047 if (ret
!= LCK_RW_TYPE_EXCLUSIVE
)
1048 panic("lck_rw_unlock_exclusive(): lock held in mode: %d\n", ret
);
1053 * Routine: lck_rw_lock
1058 lck_rw_type_t lck_rw_type
)
1060 if (lck_rw_type
== LCK_RW_TYPE_SHARED
)
1061 lck_rw_lock_shared(lck
);
1062 else if (lck_rw_type
== LCK_RW_TYPE_EXCLUSIVE
)
1063 lck_rw_lock_exclusive(lck
);
1065 panic("lck_rw_lock(): Invalid RW lock type: %x\n", lck_rw_type
);
1070 * Routine: lck_rw_lock_shared
1080 #endif /* MACH_LDEBUG */
1083 istate
= lck_interlock_lock(lck
);
1086 decrementer
= DECREMENTER_TIMEOUT
;
1087 #endif /* MACH_LDEBUG */
1088 while ((lck
->want_write
&& (lck
->read_priority
?
1089 lck
->read_count
== 0 : TRUE
)) ||
1090 lck
->want_upgrade
) {
1092 i
= lock_wait_time
[lck
->can_sleep
? 1 : 0];
1094 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_RW_LCK_SHARED_CODE
) | DBG_FUNC_START
,
1095 (int)lck
, lck
->want_write
, lck
->want_upgrade
, i
, 0);
1098 lck_interlock_unlock(lck
, istate
);
1101 Debugger("timeout - wait no writers");
1102 #endif /* MACH_LDEBUG */
1104 ((lck
->want_write
&& (lck
->read_priority
?
1105 lck
->read_count
== 0 : TRUE
)) ||
1107 lck_rw_lock_pause(istate
);
1108 istate
= lck_interlock_lock(lck
);
1111 if (lck
->can_sleep
&&
1112 ((lck
->want_write
&& (lck
->read_priority
?
1113 lck
->read_count
== 0 : TRUE
)) ||
1114 lck
->want_upgrade
)) {
1115 lck
->waiting
= TRUE
;
1116 res
= assert_wait((event_t
) lck
, THREAD_UNINT
);
1117 if (res
== THREAD_WAITING
) {
1118 lck_interlock_unlock(lck
, istate
);
1119 res
= thread_block(THREAD_CONTINUE_NULL
);
1120 istate
= lck_interlock_lock(lck
);
1123 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_RW_LCK_SHARED_CODE
) | DBG_FUNC_END
,
1124 (int)lck
, lck
->want_write
, lck
->want_upgrade
, res
, 0);
1129 lck_interlock_unlock(lck
, istate
);
1134 * Routine: lck_rw_lock_shared_to_exclusive
1136 * Improves a read-only lock to one with
1137 * write permission. If another reader has
1138 * already requested an upgrade to a write lock,
1139 * no lock is held upon return.
1141 * Returns TRUE if the upgrade *failed*.
1145 lck_rw_lock_shared_to_exclusive(
1149 boolean_t do_wakeup
= FALSE
;
1153 #endif /* MACH_LDEBUG */
1156 istate
= lck_interlock_lock(lck
);
1160 if (lck
->want_upgrade
) {
1161 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_RW_LCK_SH_TO_EX_CODE
) | DBG_FUNC_START
,
1162 (int)lck
, lck
->read_count
, lck
->want_upgrade
, 0, 0);
1165 * Someone else has requested upgrade.
1166 * Since we've released a read lock, wake
1169 if (lck
->waiting
&& (lck
->read_count
== 0)) {
1170 lck
->waiting
= FALSE
;
1174 lck_interlock_unlock(lck
, istate
);
1177 thread_wakeup((event_t
) lck
);
1179 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_RW_LCK_SH_TO_EX_CODE
) | DBG_FUNC_END
,
1180 (int)lck
, lck
->read_count
, lck
->want_upgrade
, 0, 0);
1185 lck
->want_upgrade
= TRUE
;
1188 decrementer
= DECREMENTER_TIMEOUT
;
1189 #endif /* MACH_LDEBUG */
1190 while (lck
->read_count
!= 0) {
1191 i
= lock_wait_time
[lck
->can_sleep
? 1 : 0];
1193 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_RW_LCK_SH_TO_EX1_CODE
) | DBG_FUNC_START
,
1194 (int)lck
, lck
->read_count
, i
, 0, 0);
1197 lck_interlock_unlock(lck
, istate
);
1200 Debugger("timeout - read_count");
1201 #endif /* MACH_LDEBUG */
1202 while (--i
!= 0 && lck
->read_count
!= 0)
1203 lck_rw_lock_pause(istate
);
1204 istate
= lck_interlock_lock(lck
);
1207 if (lck
->can_sleep
&& lck
->read_count
!= 0) {
1208 lck
->waiting
= TRUE
;
1209 res
= assert_wait((event_t
) lck
, THREAD_UNINT
);
1210 if (res
== THREAD_WAITING
) {
1211 lck_interlock_unlock(lck
, istate
);
1212 res
= thread_block(THREAD_CONTINUE_NULL
);
1213 istate
= lck_interlock_lock(lck
);
1216 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_RW_LCK_SH_TO_EX1_CODE
) | DBG_FUNC_END
,
1217 (int)lck
, lck
->read_count
, 0, 0, 0);
1220 lck_interlock_unlock(lck
, istate
);
1226 * Routine: lck_rw_lock_exclusive_to_shared
1229 lck_rw_lock_exclusive_to_shared(
1232 boolean_t do_wakeup
= FALSE
;
1235 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_RW_LCK_EX_TO_SH_CODE
) | DBG_FUNC_START
,
1236 (int)lck
, lck
->want_write
, lck
->want_upgrade
, 0, 0);
1238 istate
= lck_interlock_lock(lck
);
1241 if (lck
->want_upgrade
)
1242 lck
->want_upgrade
= FALSE
;
1244 lck
->want_write
= FALSE
;
1247 lck
->waiting
= FALSE
;
1251 lck_interlock_unlock(lck
, istate
);
1254 thread_wakeup((event_t
) lck
);
1256 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_RW_LCK_EX_TO_SH_CODE
) | DBG_FUNC_END
,
1257 (int)lck
, lck
->want_write
, lck
->want_upgrade
, lck
->read_count
, 0);
1263 * Routine: lck_rw_try_lock
1268 lck_rw_type_t lck_rw_type
)
1270 if (lck_rw_type
== LCK_RW_TYPE_SHARED
)
1271 return(lck_rw_try_lock_shared(lck
));
1272 else if (lck_rw_type
== LCK_RW_TYPE_EXCLUSIVE
)
1273 return(lck_rw_try_lock_exclusive(lck
));
1275 panic("lck_rw_try_lock(): Invalid rw lock type: %x\n", lck_rw_type
);
1280 * Routine: lck_rw_try_lock_exclusive
1282 * Tries to get a write lock.
1284 * Returns FALSE if the lock is not held on return.
1288 lck_rw_try_lock_exclusive(
1293 istate
= lck_interlock_lock(lck
);
1295 if (lck
->want_write
|| lck
->want_upgrade
|| lck
->read_count
) {
1299 lck_interlock_unlock(lck
, istate
);
1307 lck
->want_write
= TRUE
;
1309 lck_interlock_unlock(lck
, istate
);
1315 * Routine: lck_rw_try_lock_shared
1317 * Tries to get a read lock.
1319 * Returns FALSE if the lock is not held on return.
1323 lck_rw_try_lock_shared(
1328 istate
= lck_interlock_lock(lck
);
1330 if (lck
->want_write
|| lck
->want_upgrade
) {
1331 lck_interlock_unlock(lck
, istate
);
1337 lck_interlock_unlock(lck
, istate
);
1343 * Routine: lck_mtx_alloc_init
1352 if ((lck
= (lck_mtx_t
*)kalloc(sizeof(lck_mtx_t
))) != 0)
1353 lck_mtx_init(lck
, grp
, attr
);
1359 * Routine: lck_mtx_free
1366 lck_mtx_destroy(lck
, grp
);
1367 kfree(lck
, sizeof(lck_mtx_t
));
1371 * Routine: lck_mtx_ext_init
1379 lck
->lck_mtx
.lck_mtx_ilk
= 0;
1380 lck
->lck_mtx
.lck_mtx_locked
= 0;
1381 lck
->lck_mtx
.lck_mtx_waiters
= 0;
1382 lck
->lck_mtx
.lck_mtx_pri
= 0;
1383 lck
->lck_mtx_attr
= 0;
1385 if ((attr
->lck_attr_val
) & LCK_ATTR_DEBUG
) {
1386 lck
->lck_mtx_deb
.pc
= 0;
1387 lck
->lck_mtx_deb
.thread
= 0;
1388 lck
->lck_mtx_deb
.type
= MUTEX_TAG
;
1389 lck
->lck_mtx_attr
|= LCK_MTX_ATTR_DEBUG
;
1392 lck
->lck_mtx_grp
= grp
;
1396 * Routine: lck_mtx_init
1404 lck_mtx_ext_t
*lck_ext
;
1406 if ((attr
!= LCK_ATTR_NULL
) && ((attr
->lck_attr_val
) & LCK_ATTR_DEBUG
)) {
1407 if ((lck_ext
= (lck_mtx_ext_t
*)kalloc(sizeof(lck_mtx_ext_t
))) != 0) {
1408 lck_mtx_ext_init(lck_ext
, grp
, attr
);
1409 lck
->lck_mtx_tag
= LCK_MTX_TAG_INDIRECT
;
1410 lck
->lck_mtx_ptr
= lck_ext
;
1413 lck
->lck_mtx_ilk
= 0;
1414 lck
->lck_mtx_locked
= 0;
1415 lck
->lck_mtx_waiters
= 0;
1416 lck
->lck_mtx_pri
= 0;
1418 lck_grp_reference(grp
);
1419 lck_grp_lckcnt_incr(grp
, LCK_TYPE_MTX
);
1423 * Routine: lck_mtx_destroy
1430 boolean_t lck_is_indirect
;
1432 if (lck
->lck_mtx_tag
== LCK_MTX_TAG_DESTROYED
)
1434 lck_is_indirect
= (lck
->lck_mtx_tag
== LCK_MTX_TAG_INDIRECT
);
1435 lck
->lck_mtx_tag
= LCK_MTX_TAG_DESTROYED
;
1436 if (lck_is_indirect
)
1437 kfree(lck
->lck_mtx_ptr
, sizeof(lck_mtx_ext_t
));
1438 lck_grp_lckcnt_decr(grp
, LCK_TYPE_MTX
);
1439 lck_grp_deallocate(grp
);
1444 * Routine: lck_mtx_assert
1448 __unused lck_mtx_t
*lck
,
1449 __unused
unsigned int type
)
1454 * Routine: lck_mtx_lock_spin
1456 * Invoked trying to acquire a mutex when there is contention but
1457 * the holder is running on another processor. We spin for up to a maximum
1458 * time waiting for the lock to be released.
1460 * Called with the interlock unlocked.
1470 if (lck
->lck_mtx_tag
!= LCK_MTX_TAG_INDIRECT
)
1473 mutex
= &lck
->lck_mtx_ptr
->lck_mtx
;
1476 MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_MTX_LCK_SPIN
) | DBG_FUNC_START
,
1477 (int)lck
, (int)mutex
->lck_mtx_locked
, 0, 0, 0);
1479 deadline
= mach_absolute_time() + MutexSpin
;
1482 * - mutex is locked, and
1483 * - owner is running on another processor, and
1484 * - owner is not is the idle delay, and
1485 * - we haven't spun for long enough.
1487 while ((holder
= (thread_t
) mutex
->lck_mtx_locked
) != NULL
&&
1488 (holder
->machine
.specFlags
& OnProc
) != 0 &&
1489 (holder
->options
& TH_OPT_DELAYIDLE
) == 0 &&
1490 mach_absolute_time() < deadline
)
1495 * Called from assembly code when a mutex interlock is held.
1496 * We spin here re-checking the interlock but panic if we timeout.
1497 * Note: here with interrupts disabled.
1500 lck_mtx_interlock_spin(
1506 if (lck
->lck_mtx_tag
!= LCK_MTX_TAG_INDIRECT
)
1509 mutex
= &lck
->lck_mtx_ptr
->lck_mtx
;
1511 deadline
= mach_absolute_time() + LockTimeOut
;
1512 while (mutex
->lck_mtx_ilk
!= 0) {
1514 if (mach_absolute_time() > deadline
)
1515 panic("interlock timeout for mutex %p", lck
);
1522 void db_show_one_lock(lock_t
*);
1528 db_printf("Read_count = 0x%x, %swant_upgrade, %swant_write, ",
1530 lock
->want_upgrade
? "" : "!",
1531 lock
->want_write
? "" : "!");
1532 db_printf("%swaiting, %scan_sleep\n",
1533 lock
->waiting
? "" : "!", lock
->can_sleep
? "" : "!");
1534 db_printf("Interlock:\n");
1535 db_show_one_simple_lock((db_expr_t
) ((vm_offset_t
)simple_lock_addr(lock
->interlock
)),
1536 TRUE
, (db_expr_t
)0, (char *)0);
1539 #endif /* MACH_KDB */
1542 * The C portion of the mutex package. These routines are only invoked
1543 * if the optimized assembler routines can't do the work.
1547 * Routine: lock_alloc
1549 * Allocate a mutex for external users who cannot
1550 * hard-code the structure definition into their
1552 * For now just use kalloc, but a zone is probably
1561 if ((m
= (mutex_t
*)kalloc(sizeof(mutex_t
))) != 0)
1567 * Routine: mutex_free
1569 * Free a mutex allocated for external users.
1570 * For now just use kfree, but a zone is probably
1577 kfree(m
, sizeof(mutex_t
));
1581 * Routine: _mutex_assert
1589 thread_t thread
= current_thread();
1592 if (panicstr
!= NULL
)
1595 holder
= (thread_t
) mutex
->lck_mtx
.lck_mtx_locked
;
1599 if (thread
!= holder
)
1600 panic("mutex %x not owned\n", mutex
);
1604 if (thread
== holder
)
1605 panic("mutex %x owned\n", mutex
);
1613 * Routines to print out simple_locks and mutexes in a nicely-formatted
1617 const char *simple_lock_labels
= "ENTRY ILK THREAD DURATION CALLER";
1618 const char *mutex_labels
= "ENTRY LOCKED WAITERS THREAD CALLER";
1621 db_show_one_simple_lock (
1623 boolean_t have_addr
,
1624 __unused db_expr_t count
,
1625 __unused
char * modif
)
1627 simple_lock_t saddr
= (simple_lock_t
) ((vm_offset_t
) addr
);
1629 if (saddr
== (simple_lock_t
)0 || !have_addr
) {
1630 db_error ("No simple_lock\n");
1633 else if (saddr
->lock_type
!= USLOCK_TAG
)
1634 db_error ("Not a simple_lock\n");
1635 #endif /* USLOCK_DEBUG */
1637 db_printf ("%s\n", simple_lock_labels
);
1638 db_print_simple_lock (saddr
);
1642 db_print_simple_lock (
1646 db_printf ("%08x %3d", addr
, *hw_lock_addr(addr
->interlock
));
1648 db_printf (" %08x", addr
->debug
.lock_thread
);
1649 db_printf (" %08x ", addr
->debug
.duration
[1]);
1650 db_printsym ((int)addr
->debug
.lock_pc
, DB_STGY_ANY
);
1651 #endif /* USLOCK_DEBUG */
1658 boolean_t have_addr
,
1659 __unused db_expr_t count
,
1660 __unused
char * modif
)
1662 mutex_t
* maddr
= (mutex_t
*)((vm_offset_t
) addr
);
1664 if (maddr
== (mutex_t
*)0 || !have_addr
)
1665 db_error ("No mutex\n");
1667 else if (maddr
->type
!= MUTEX_TAG
)
1668 db_error ("Not a mutex\n");
1669 #endif /* MACH_LDEBUG */
1671 db_printf ("%s\n", mutex_labels
);
1672 db_print_mutex (maddr
);
1679 db_printf ("%08x %6d %7d",
1680 addr
, *addr
, addr
->lck_mtx
.lck_mtx_waiters
);
1682 db_printf (" %08x ", addr
->thread
);
1683 db_printsym (addr
->pc
, DB_STGY_ANY
);
1684 #endif /* MACH_LDEBUG */
1688 #endif /* MACH_KDB */