2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
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
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
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.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
34 * Mach Operating System
35 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
36 * All Rights Reserved.
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.
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.
48 * Carnegie Mellon requests users of this software to return to
50 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
51 * School of Computer Science
52 * Carnegie Mellon University
53 * Pittsburgh PA 15213-3890
55 * any improvements or extensions that they make and grant Carnegie Mellon
56 * the rights to redistribute these changes.
60 * Author: Avadis Tevanian, Jr., Michael Wayne Young
63 * Locking primitives implementation
67 #include <mach_ldebug.h>
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>
79 #include <kern/debug.h>
83 #include <ddb/db_command.h>
84 #include <ddb/db_output.h>
85 #include <ddb/db_sym.h>
86 #include <ddb/db_print.h>
89 #include <i386/machine_cpu.h>
91 #include <sys/kdebug.h>
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
100 #define LCK_MTX_LCK_SPIN 0x200
102 #define ANY_LOCK_DEBUG (USLOCK_DEBUG || LOCK_DEBUG || MUTEX_DEBUG)
104 unsigned int LcksOpts
=0;
105 unsigned int lock_wait_time
[2] = { (unsigned int)-1, 100 } ;
110 void db_print_simple_lock(
115 #endif /* MACH_KDB */
120 * Perform simple lock checks.
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
)
127 decl_simple_lock_data(extern , kdb_lock
)
128 #endif /* MACH_KDB */
129 #endif /* USLOCK_DEBUG */
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.
138 #define INVALID_PC ((void *) VM_MAX_KERNEL_ADDRESS)
139 #define INVALID_THREAD ((void *) VM_MAX_KERNEL_ADDRESS)
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 */
147 * Eliminate lint complaints about unused local pc variables.
149 #define OBTAIN_PC(pc,l) ++pc
151 #define OBTAIN_PC(pc,l)
153 #endif /* USLOCK_DEBUG */
157 * Portable lock package implementation of usimple_locks.
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 */
171 #endif /* USLOCK_DEBUG */
174 * Routine: lck_spin_alloc_init
183 if ((lck
= (lck_spin_t
*)kalloc(sizeof(lck_spin_t
))) != 0)
184 lck_spin_init(lck
, grp
, attr
);
190 * Routine: lck_spin_free
197 lck_spin_destroy(lck
, grp
);
198 kfree(lck
, sizeof(lck_spin_t
));
202 * Routine: lck_spin_init
208 __unused lck_attr_t
*attr
)
210 usimple_lock_init((usimple_lock_t
) lck
, 0);
211 lck_grp_reference(grp
);
212 lck_grp_lckcnt_incr(grp
, LCK_TYPE_SPIN
);
216 * Routine: lck_spin_destroy
223 if (lck
->lck_spin_data
[0] == LCK_SPIN_TAG_DESTROYED
)
225 lck
->lck_spin_data
[0] = LCK_SPIN_TAG_DESTROYED
;
226 lck_grp_lckcnt_decr(grp
, LCK_TYPE_SPIN
);
227 lck_grp_deallocate(grp
);
232 * Routine: lck_spin_lock
238 usimple_lock((usimple_lock_t
) lck
);
242 * Routine: lck_spin_unlock
248 usimple_unlock((usimple_lock_t
) lck
);
253 * Routine: lck_spin_try_lock
259 return(usimple_lock_try((usimple_lock_t
) lck
));
263 * Initialize a usimple_lock.
265 * No change in preemption state.
270 __unused
unsigned short tag
)
272 #ifndef MACHINE_SIMPLE_LOCK
273 USLDBG(usld_lock_init(l
, tag
));
274 hw_lock_init(&l
->interlock
);
276 simple_lock_init((simple_lock_t
)l
,tag
);
282 * Acquire a usimple_lock.
284 * Returns with preemption disabled. Note
285 * that the hw_lock routines are responsible for
286 * maintaining preemption state.
292 #ifndef MACHINE_SIMPLE_LOCK
296 USLDBG(usld_lock_pre(l
, pc
));
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
);
301 USLDBG(usld_lock_post(l
, pc
));
303 simple_lock((simple_lock_t
)l
);
309 * Release a usimple_lock.
311 * Returns with preemption enabled. Note
312 * that the hw_lock routines are responsible for
313 * maintaining preemption state.
319 #ifndef MACHINE_SIMPLE_LOCK
323 USLDBG(usld_unlock(l
, pc
));
324 hw_lock_unlock(&l
->interlock
);
326 simple_unlock_rwmb((simple_lock_t
)l
);
332 * Conditionally acquire a usimple_lock.
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.
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
347 #ifndef MACHINE_SIMPLE_LOCK
349 unsigned int success
;
352 USLDBG(usld_lock_try_pre(l
, pc
));
353 if ((success
= hw_lock_try(&l
->interlock
))) {
354 USLDBG(usld_lock_try_post(l
, pc
));
358 return(simple_lock_try((simple_lock_t
)l
));
364 * States of a usimple_lock. The default when initializing
365 * a usimple_lock is setting it up for debug checking.
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))
375 * Trace activities of a particularly interesting lock.
377 void usl_trace(usimple_lock_t
, int, pc_t
, const char *);
381 * Initialize the debugging information contained
387 __unused
unsigned short tag
)
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
;
404 * These checks apply to all usimple_locks, not just
405 * those with USLOCK_CHECKED turned on.
408 usld_lock_common_checks(
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
);
424 * Debug checks on a usimple_lock just before attempting
433 char caller
[] = "usimple_lock";
436 if (!usld_lock_common_checks(l
, caller
))
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.
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
);
455 mp_disable_preemption();
456 usl_trace(l
, cpu_number(), pc
, caller
);
457 mp_enable_preemption();
462 * Debug checks on a usimple_lock just after acquiring it.
464 * Pre-emption has been disabled at this point,
465 * so we are safe in using cpu_number.
473 char caller
[] = "successful usimple_lock";
476 if (!usld_lock_common_checks(l
, caller
))
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
);
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
;
492 usl_trace(l
, mycpu
, pc
, caller
);
497 * Debug checks on a usimple_lock just before
498 * releasing it. Note that the caller has not
499 * yet released the hardware lock.
501 * Preemption is still disabled, so there's
502 * no problem using cpu_number.
510 char caller
[] = "usimple_unlock";
513 if (!usld_lock_common_checks(l
, caller
))
516 mycpu
= cpu_number();
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
);
530 usl_trace(l
, mycpu
, pc
, caller
);
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
;
541 * Debug checks on a usimple_lock just before
542 * attempting to acquire it.
544 * Preemption isn't guaranteed to be disabled.
551 char caller
[] = "usimple_lock_try";
553 if (!usld_lock_common_checks(l
, caller
))
555 mp_disable_preemption();
556 usl_trace(l
, cpu_number(), pc
, caller
);
557 mp_enable_preemption();
562 * Debug checks on a usimple_lock just after
563 * successfully attempting to acquire it.
565 * Preemption has been disabled by the
566 * lock acquisition attempt, so it's safe
575 char caller
[] = "successful usimple_lock_try";
577 if (!usld_lock_common_checks(l
, caller
))
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
);
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
;
593 usl_trace(l
, mycpu
, pc
, caller
);
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.
603 usimple_lock_t traced_lock
;
604 unsigned int lock_seq
;
611 const char * op_name
)
613 if (traced_lock
== l
) {
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);
623 #endif /* USLOCK_DEBUG */
626 * Routine: lock_alloc
628 * Allocate a lock for external users who cannot
629 * hard-code the structure definition into their
631 * For now just use kalloc, but a zone is probably
642 if ((l
= (lock_t
*)kalloc(sizeof(lock_t
))) != 0)
643 lock_init(l
, can_sleep
, tag
, tag1
);
650 * Free a lock allocated for external users.
651 * For now just use kfree, but a zone is probably
658 kfree(l
, sizeof(lock_t
));
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.
674 __unused
unsigned short tag
,
675 __unused
unsigned short tag1
)
677 hw_lock_init(&l
->interlock
);
678 l
->want_write
= FALSE
;
679 l
->want_upgrade
= FALSE
;
681 l
->can_sleep
= can_sleep
;
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.
692 #define DECREMENTER_TIMEOUT 1000000
698 lck_rw_lock_exclusive(l
);
705 (void) lck_rw_done(l
);
712 lck_rw_lock_shared(l
);
717 * Routine: lock_read_to_write
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.
724 * Returns TRUE if the upgrade *failed*.
731 return lck_rw_lock_shared_to_exclusive(l
);
738 lck_rw_lock_exclusive_to_shared(l
);
744 * Routine: lck_rw_alloc_init
752 if ((lck
= (lck_rw_t
*)kalloc(sizeof(lck_rw_t
))) != 0)
753 lck_rw_init(lck
, grp
, attr
);
759 * Routine: lck_rw_free
765 lck_rw_destroy(lck
, grp
);
766 kfree(lck
, sizeof(lck_rw_t
));
770 * Routine: lck_rw_init
778 lck_attr_t
*lck_attr
= (attr
!= LCK_ATTR_NULL
) ?
779 attr
: &LockDefaultLckAttr
;
781 hw_lock_init(&lck
->interlock
);
782 lck
->want_write
= FALSE
;
783 lck
->want_upgrade
= FALSE
;
785 lck
->can_sleep
= TRUE
;
787 lck
->read_priority
= (lck_attr
->lck_attr_val
&
788 LCK_ATTR_RW_SHARED_PRIORITY
) != 0;
790 lck_grp_reference(grp
);
791 lck_grp_lckcnt_incr(grp
, LCK_TYPE_RW
);
795 * Routine: lck_rw_destroy
801 if (lck
->lck_rw_tag
== LCK_RW_TAG_DESTROYED
)
803 lck
->lck_rw_tag
= LCK_RW_TAG_DESTROYED
;
804 lck_grp_lckcnt_decr(grp
, LCK_TYPE_RW
);
805 lck_grp_deallocate(grp
);
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.
815 #define DECREMENTER_TIMEOUT 1000000
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().
824 lck_interlock_lock(lck_rw_t
*lck
)
828 istate
= ml_set_interrupts_enabled(FALSE
);
829 hw_lock_lock(&lck
->interlock
);
835 lck_interlock_unlock(lck_rw_t
*lck
, boolean_t istate
)
837 hw_lock_unlock(&lck
->interlock
);
838 ml_set_interrupts_enabled(istate
);
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.
849 lck_rw_lock_pause(boolean_t interrupts_enabled
)
851 if (!interrupts_enabled
)
852 handle_pending_TLB_flushes();
857 * Routine: lck_rw_lock_exclusive
860 lck_rw_lock_exclusive(
864 boolean_t lock_miss
= FALSE
;
868 #endif /* MACH_LDEBUG */
871 istate
= lck_interlock_lock(lck
);
874 decrementer
= DECREMENTER_TIMEOUT
;
875 #endif /* MACH_LDEBUG */
878 * Try to acquire the want_write bit.
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);
887 i
= lock_wait_time
[lck
->can_sleep
? 1 : 0];
889 lck_interlock_unlock(lck
, istate
);
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
);
899 if (lck
->can_sleep
&& lck
->want_write
) {
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
);
908 KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_RW_LCK_EXCLUSIVE_CODE
) | DBG_FUNC_END
, (int)lck
, res
, 0, 0, 0);
910 lck
->want_write
= TRUE
;
912 /* Wait for readers (and upgrades) to finish */
915 decrementer
= DECREMENTER_TIMEOUT
;
916 #endif /* MACH_LDEBUG */
917 while ((lck
->read_count
!= 0) || lck
->want_upgrade
) {
922 i
= lock_wait_time
[lck
->can_sleep
? 1 : 0];
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);
928 lck_interlock_unlock(lck
, istate
);
931 Debugger("timeout - wait for readers");
932 #endif /* MACH_LDEBUG */
933 while (--i
!= 0 && (lck
->read_count
!= 0 ||
935 lck_rw_lock_pause(istate
);
936 istate
= lck_interlock_lock(lck
);
939 if (lck
->can_sleep
&& (lck
->read_count
!= 0 || lck
->want_upgrade
)) {
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
);
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);
952 lck_interlock_unlock(lck
, istate
);
957 * Routine: lck_rw_done
963 boolean_t do_wakeup
= FALSE
;
964 lck_rw_type_t lck_rw_type
;
968 istate
= lck_interlock_lock(lck
);
970 if (lck
->read_count
!= 0) {
971 lck_rw_type
= LCK_RW_TYPE_SHARED
;
975 lck_rw_type
= LCK_RW_TYPE_EXCLUSIVE
;
976 if (lck
->want_upgrade
)
977 lck
->want_upgrade
= FALSE
;
979 lck
->want_write
= FALSE
;
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
990 if (lck
->waiting
&& (lck
->read_count
== 0)) {
991 lck
->waiting
= FALSE
;
995 lck_interlock_unlock(lck
, istate
);
998 thread_wakeup((event_t
) lck
);
1006 * Routine: lck_rw_unlock
1011 lck_rw_type_t lck_rw_type
)
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
);
1018 panic("lck_rw_unlock(): Invalid RW lock type: %d\n", lck_rw_type
);
1023 * Routine: lck_rw_unlock_shared
1026 lck_rw_unlock_shared(
1031 ret
= lck_rw_done(lck
);
1033 if (ret
!= LCK_RW_TYPE_SHARED
)
1034 panic("lck_rw_unlock(): lock held in mode: %d\n", ret
);
1039 * Routine: lck_rw_unlock_exclusive
1042 lck_rw_unlock_exclusive(
1047 ret
= lck_rw_done(lck
);
1049 if (ret
!= LCK_RW_TYPE_EXCLUSIVE
)
1050 panic("lck_rw_unlock_exclusive(): lock held in mode: %d\n", ret
);
1055 * Routine: lck_rw_lock
1060 lck_rw_type_t lck_rw_type
)
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
);
1067 panic("lck_rw_lock(): Invalid RW lock type: %x\n", lck_rw_type
);
1072 * Routine: lck_rw_lock_shared
1082 #endif /* MACH_LDEBUG */
1085 istate
= lck_interlock_lock(lck
);
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
) {
1094 i
= lock_wait_time
[lck
->can_sleep
? 1 : 0];
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);
1100 lck_interlock_unlock(lck
, istate
);
1103 Debugger("timeout - wait no writers");
1104 #endif /* MACH_LDEBUG */
1106 ((lck
->want_write
&& (lck
->read_priority
?
1107 lck
->read_count
== 0 : TRUE
)) ||
1109 lck_rw_lock_pause(istate
);
1110 istate
= lck_interlock_lock(lck
);
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
);
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);
1131 lck_interlock_unlock(lck
, istate
);
1136 * Routine: lck_rw_lock_shared_to_exclusive
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.
1143 * Returns TRUE if the upgrade *failed*.
1147 lck_rw_lock_shared_to_exclusive(
1151 boolean_t do_wakeup
= FALSE
;
1155 #endif /* MACH_LDEBUG */
1158 istate
= lck_interlock_lock(lck
);
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);
1167 * Someone else has requested upgrade.
1168 * Since we've released a read lock, wake
1171 if (lck
->waiting
&& (lck
->read_count
== 0)) {
1172 lck
->waiting
= FALSE
;
1176 lck_interlock_unlock(lck
, istate
);
1179 thread_wakeup((event_t
) lck
);
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);
1187 lck
->want_upgrade
= TRUE
;
1190 decrementer
= DECREMENTER_TIMEOUT
;
1191 #endif /* MACH_LDEBUG */
1192 while (lck
->read_count
!= 0) {
1193 i
= lock_wait_time
[lck
->can_sleep
? 1 : 0];
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);
1199 lck_interlock_unlock(lck
, istate
);
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
);
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
);
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);
1222 lck_interlock_unlock(lck
, istate
);
1228 * Routine: lck_rw_lock_exclusive_to_shared
1231 lck_rw_lock_exclusive_to_shared(
1234 boolean_t do_wakeup
= FALSE
;
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);
1240 istate
= lck_interlock_lock(lck
);
1243 if (lck
->want_upgrade
)
1244 lck
->want_upgrade
= FALSE
;
1246 lck
->want_write
= FALSE
;
1249 lck
->waiting
= FALSE
;
1253 lck_interlock_unlock(lck
, istate
);
1256 thread_wakeup((event_t
) lck
);
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);
1265 * Routine: lck_rw_try_lock
1270 lck_rw_type_t lck_rw_type
)
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
));
1277 panic("lck_rw_try_lock(): Invalid rw lock type: %x\n", lck_rw_type
);
1282 * Routine: lck_rw_try_lock_exclusive
1284 * Tries to get a write lock.
1286 * Returns FALSE if the lock is not held on return.
1290 lck_rw_try_lock_exclusive(
1295 istate
= lck_interlock_lock(lck
);
1297 if (lck
->want_write
|| lck
->want_upgrade
|| lck
->read_count
) {
1301 lck_interlock_unlock(lck
, istate
);
1309 lck
->want_write
= TRUE
;
1311 lck_interlock_unlock(lck
, istate
);
1317 * Routine: lck_rw_try_lock_shared
1319 * Tries to get a read lock.
1321 * Returns FALSE if the lock is not held on return.
1325 lck_rw_try_lock_shared(
1330 istate
= lck_interlock_lock(lck
);
1332 if (lck
->want_write
|| lck
->want_upgrade
) {
1333 lck_interlock_unlock(lck
, istate
);
1339 lck_interlock_unlock(lck
, istate
);
1345 * Routine: lck_mtx_alloc_init
1354 if ((lck
= (lck_mtx_t
*)kalloc(sizeof(lck_mtx_t
))) != 0)
1355 lck_mtx_init(lck
, grp
, attr
);
1361 * Routine: lck_mtx_free
1368 lck_mtx_destroy(lck
, grp
);
1369 kfree(lck
, sizeof(lck_mtx_t
));
1373 * Routine: lck_mtx_ext_init
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;
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
;
1394 lck
->lck_mtx_grp
= grp
;
1398 * Routine: lck_mtx_init
1406 lck_mtx_ext_t
*lck_ext
;
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
;
1415 lck
->lck_mtx_ilk
= 0;
1416 lck
->lck_mtx_locked
= 0;
1417 lck
->lck_mtx_waiters
= 0;
1418 lck
->lck_mtx_pri
= 0;
1420 lck_grp_reference(grp
);
1421 lck_grp_lckcnt_incr(grp
, LCK_TYPE_MTX
);
1425 * Routine: lck_mtx_destroy
1432 boolean_t lck_is_indirect
;
1434 if (lck
->lck_mtx_tag
== LCK_MTX_TAG_DESTROYED
)
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
);
1446 * Routine: lck_mtx_assert
1450 __unused lck_mtx_t
*lck
,
1451 __unused
unsigned int type
)
1456 * Routine: lck_mtx_lock_spin
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.
1462 * Called with the interlock unlocked.
1472 if (lck
->lck_mtx_tag
!= LCK_MTX_TAG_INDIRECT
)
1475 mutex
= &lck
->lck_mtx_ptr
->lck_mtx
;
1478 MACHDBG_CODE(DBG_MACH_LOCKS
, LCK_MTX_LCK_SPIN
) | DBG_FUNC_START
,
1479 (int)lck
, (int)mutex
->lck_mtx_locked
, 0, 0, 0);
1481 deadline
= mach_absolute_time() + MutexSpin
;
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.
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
)
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.
1502 lck_mtx_interlock_spin(
1508 if (lck
->lck_mtx_tag
!= LCK_MTX_TAG_INDIRECT
)
1511 mutex
= &lck
->lck_mtx_ptr
->lck_mtx
;
1513 deadline
= mach_absolute_time() + LockTimeOut
;
1514 while (mutex
->lck_mtx_ilk
!= 0) {
1516 if (mach_absolute_time() > deadline
)
1517 panic("interlock timeout for mutex %p", lck
);
1524 void db_show_one_lock(lock_t
*);
1530 db_printf("Read_count = 0x%x, %swant_upgrade, %swant_write, ",
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);
1541 #endif /* MACH_KDB */
1544 * The C portion of the mutex package. These routines are only invoked
1545 * if the optimized assembler routines can't do the work.
1549 * Routine: lock_alloc
1551 * Allocate a mutex for external users who cannot
1552 * hard-code the structure definition into their
1554 * For now just use kalloc, but a zone is probably
1563 if ((m
= (mutex_t
*)kalloc(sizeof(mutex_t
))) != 0)
1569 * Routine: mutex_free
1571 * Free a mutex allocated for external users.
1572 * For now just use kfree, but a zone is probably
1579 kfree(m
, sizeof(mutex_t
));
1583 * Routine: _mutex_assert
1591 thread_t thread
= current_thread();
1594 if (panicstr
!= NULL
)
1597 holder
= (thread_t
) mutex
->lck_mtx
.lck_mtx_locked
;
1601 if (thread
!= holder
)
1602 panic("mutex %x not owned\n", mutex
);
1606 if (thread
== holder
)
1607 panic("mutex %x owned\n", mutex
);
1615 * Routines to print out simple_locks and mutexes in a nicely-formatted
1619 const char *simple_lock_labels
= "ENTRY ILK THREAD DURATION CALLER";
1620 const char *mutex_labels
= "ENTRY LOCKED WAITERS THREAD CALLER";
1623 db_show_one_simple_lock (
1625 boolean_t have_addr
,
1626 __unused db_expr_t count
,
1627 __unused
char * modif
)
1629 simple_lock_t saddr
= (simple_lock_t
) ((vm_offset_t
) addr
);
1631 if (saddr
== (simple_lock_t
)0 || !have_addr
) {
1632 db_error ("No simple_lock\n");
1635 else if (saddr
->lock_type
!= USLOCK_TAG
)
1636 db_error ("Not a simple_lock\n");
1637 #endif /* USLOCK_DEBUG */
1639 db_printf ("%s\n", simple_lock_labels
);
1640 db_print_simple_lock (saddr
);
1644 db_print_simple_lock (
1648 db_printf ("%08x %3d", addr
, *hw_lock_addr(addr
->interlock
));
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 */
1660 boolean_t have_addr
,
1661 __unused db_expr_t count
,
1662 __unused
char * modif
)
1664 mutex_t
* maddr
= (mutex_t
*)((vm_offset_t
) addr
);
1666 if (maddr
== (mutex_t
*)0 || !have_addr
)
1667 db_error ("No mutex\n");
1669 else if (maddr
->type
!= MUTEX_TAG
)
1670 db_error ("Not a mutex\n");
1671 #endif /* MACH_LDEBUG */
1673 db_printf ("%s\n", mutex_labels
);
1674 db_print_mutex (maddr
);
1681 db_printf ("%08x %6d %7d",
1682 addr
, *addr
, addr
->lck_mtx
.lck_mtx_waiters
);
1684 db_printf (" %08x ", addr
->thread
);
1685 db_printsym (addr
->pc
, DB_STGY_ANY
);
1686 #endif /* MACH_LDEBUG */
1690 #endif /* MACH_KDB */