2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
28 * All Rights Reserved.
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.
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.
40 * Carnegie Mellon requests users of this software to return to
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
52 * Author: Avadis Tevanian, Jr., Michael Wayne Young
55 * Locking primitives implementation
60 #include <mach_ldebug.h>
62 #include <kern/lock.h>
63 #include <kern/etap_macros.h>
64 #include <kern/misc_protos.h>
65 #include <kern/thread.h>
66 #include <kern/processor.h>
67 #include <kern/sched_prim.h>
69 #include <kern/debug.h>
73 #include <ddb/db_command.h>
74 #include <ddb/db_output.h>
75 #include <ddb/db_sym.h>
76 #include <ddb/db_print.h>
80 #include <ppc/Firmware.h>
83 #include <sys/kdebug.h>
85 #define ANY_LOCK_DEBUG (USLOCK_DEBUG || LOCK_DEBUG || MUTEX_DEBUG)
88 * Some portions of the lock debugging code must run with
89 * interrupts disabled. This can be machine-dependent,
90 * but we don't have any good hooks for that at the moment.
91 * If your architecture is different, add a machine-dependent
92 * ifdef here for these macros. XXX
95 #define DISABLE_INTERRUPTS(s) s = ml_set_interrupts_enabled(FALSE)
96 #define ENABLE_INTERRUPTS(s) (void)ml_set_interrupts_enabled(s)
99 /* Time we loop without holding the interlock.
100 * The former is for when we cannot sleep, the latter
101 * for when our thread can go to sleep (loop less)
102 * we shouldn't retake the interlock at all frequently
103 * if we cannot go to sleep, since it interferes with
104 * any other processors. In particular, 100 is too small
105 * a number for powerpc MP systems because of cache
106 * coherency issues and differing lock fetch times between
109 unsigned int lock_wait_time
[2] = { (unsigned int)-1, 100 } ;
110 #else /* NCPUS > 1 */
113 * It is silly to spin on a uni-processor as if we
114 * thought something magical would happen to the
115 * want_write bit while we are executing.
118 unsigned int lock_wait_time
[2] = { 0, 0 };
119 #endif /* NCPUS > 1 */
124 void db_print_simple_lock(
129 #endif /* MACH_KDB */
134 * Perform simple lock checks.
136 int uslock_check
= 1;
137 int max_lock_loops
= 100000000;
138 decl_simple_lock_data(extern , printf_lock
)
139 decl_simple_lock_data(extern , panic_lock
)
140 #if MACH_KDB && NCPUS > 1
141 decl_simple_lock_data(extern , kdb_lock
)
142 #endif /* MACH_KDB && NCPUS >1 */
143 #endif /* USLOCK_DEBUG */
147 * We often want to know the addresses of the callers
148 * of the various lock routines. However, this information
149 * is only used for debugging and statistics.
152 #define INVALID_PC ((void *) VM_MAX_KERNEL_ADDRESS)
153 #define INVALID_THREAD ((void *) VM_MAX_KERNEL_ADDRESS)
154 #if ANY_LOCK_DEBUG || ETAP_LOCK_TRACE
155 #define OBTAIN_PC(pc,l) ((pc) = (void *) GET_RETURN_PC(&(l)))
156 #else /* ANY_LOCK_DEBUG || ETAP_LOCK_TRACE */
159 * Eliminate lint complaints about unused local pc variables.
161 #define OBTAIN_PC(pc,l) ++pc
163 #define OBTAIN_PC(pc,l)
165 #endif /* USLOCK_DEBUG || ETAP_LOCK_TRACE */
168 /* #ifndef USIMPLE_LOCK_CALLS
169 * The i386 production version of usimple_locks isn't ready yet.
172 * Portable lock package implementation of usimple_locks.
176 #define ETAPCALL(stmt) stmt
177 void etap_simplelock_init(simple_lock_t
, etap_event_t
);
178 void etap_simplelock_unlock(simple_lock_t
);
179 void etap_simplelock_hold(simple_lock_t
, pc_t
, etap_time_t
);
180 etap_time_t
etap_simplelock_miss(simple_lock_t
);
182 void etap_mutex_init(mutex_t
*, etap_event_t
);
183 void etap_mutex_unlock(mutex_t
*);
184 void etap_mutex_hold(mutex_t
*, pc_t
, etap_time_t
);
185 etap_time_t
etap_mutex_miss(mutex_t
*);
186 #else /* ETAP_LOCK_TRACE */
187 #define ETAPCALL(stmt)
188 #endif /* ETAP_LOCK_TRACE */
191 #define USLDBG(stmt) stmt
192 void usld_lock_init(usimple_lock_t
, etap_event_t
);
193 void usld_lock_pre(usimple_lock_t
, pc_t
);
194 void usld_lock_post(usimple_lock_t
, pc_t
);
195 void usld_unlock(usimple_lock_t
, pc_t
);
196 void usld_lock_try_pre(usimple_lock_t
, pc_t
);
197 void usld_lock_try_post(usimple_lock_t
, pc_t
);
198 void usld_lock_held(usimple_lock_t
);
199 void usld_lock_none_held(void);
200 int usld_lock_common_checks(usimple_lock_t
, char *);
201 #else /* USLOCK_DEBUG */
203 #endif /* USLOCK_DEBUG */
206 * Initialize a usimple_lock.
208 * No change in preemption state.
215 #ifndef MACHINE_SIMPLE_LOCK
216 USLDBG(usld_lock_init(l
, event
));
217 ETAPCALL(etap_simplelock_init((l
),(event
)));
218 hw_lock_init(&l
->interlock
);
220 simple_lock_init((simple_lock_t
)l
,event
);
226 * Acquire a usimple_lock.
228 * Returns with preemption disabled. Note
229 * that the hw_lock routines are responsible for
230 * maintaining preemption state.
236 #ifndef MACHINE_SIMPLE_LOCK
240 etap_time_t start_wait_time
;
241 int no_miss_info
= 0;
242 #endif /* ETAP_LOCK_TRACE */
245 #endif /* USLOCK_DEBUG */
248 USLDBG(usld_lock_pre(l
, pc
));
250 ETAP_TIME_CLEAR(start_wait_time
);
251 #endif /* ETAP_LOCK_TRACE */
253 if(!hw_lock_to(&l
->interlock
, LockTimeOut
)) /* Try to get the lock with a timeout */
254 panic("simple lock deadlock detection - l=%08X, cpu=%d, ret=%08X", l
, cpu_number(), pc
);
256 ETAPCALL(etap_simplelock_hold(l
, pc
, start_wait_time
));
257 USLDBG(usld_lock_post(l
, pc
));
259 simple_lock((simple_lock_t
)l
);
265 * Release a usimple_lock.
267 * Returns with preemption enabled. Note
268 * that the hw_lock routines are responsible for
269 * maintaining preemption state.
275 #ifndef MACHINE_SIMPLE_LOCK
278 // checkNMI(); /* (TEST/DEBUG) */
281 USLDBG(usld_unlock(l
, pc
));
282 ETAPCALL(etap_simplelock_unlock(l
));
286 hw_lock_unlock(&l
->interlock
);
288 simple_unlock_rwmb((simple_lock_t
)l
);
294 * Conditionally acquire a usimple_lock.
296 * On success, returns with preemption disabled.
297 * On failure, returns with preemption in the same state
298 * as when first invoked. Note that the hw_lock routines
299 * are responsible for maintaining preemption state.
301 * XXX No stats are gathered on a miss; I preserved this
302 * behavior from the original assembly-language code, but
303 * doesn't it make sense to log misses? XXX
309 #ifndef MACHINE_SIMPLE_LOCK
311 unsigned int success
;
312 etap_time_t zero_time
;
315 USLDBG(usld_lock_try_pre(l
, pc
));
316 if (success
= hw_lock_try(&l
->interlock
)) {
317 USLDBG(usld_lock_try_post(l
, pc
));
318 ETAP_TIME_CLEAR(zero_time
);
319 ETAPCALL(etap_simplelock_hold(l
, pc
, zero_time
));
323 return(simple_lock_try((simple_lock_t
)l
));
329 simple_lock_no_trace(
335 USLDBG(usld_lock_pre(l
, pc
));
336 while (!hw_lock_try(&l
->interlock
)) {
337 while (hw_lock_held(&l
->interlock
)) {
339 * Spin watching the lock value in cache,
340 * without consuming external bus cycles.
341 * On most SMP architectures, the atomic
342 * instruction(s) used by hw_lock_try
343 * cost much, much more than an ordinary
348 USLDBG(usld_lock_post(l
, pc
));
352 simple_unlock_no_trace(
358 USLDBG(usld_unlock(l
, pc
));
359 hw_lock_unlock(&l
->interlock
);
363 simple_lock_try_no_trace(
367 unsigned int success
;
370 USLDBG(usld_lock_try_pre(l
, pc
));
371 if (success
= hw_lock_try(&l
->interlock
)) {
372 USLDBG(usld_lock_try_post(l
, pc
));
376 #endif /* ETAP_LOCK_TRACE */
381 * Verify that the lock is locked and owned by
382 * the current thread.
393 * Verify that no usimple_locks are held by
394 * this processor. Typically used in a
395 * trap handler when returning to user mode
396 * or in a path known to relinquish the processor.
399 usimple_lock_none_held(void)
401 usld_lock_none_held();
403 #endif /* USLOCK_DEBUG */
408 * States of a usimple_lock. The default when initializing
409 * a usimple_lock is setting it up for debug checking.
411 #define USLOCK_CHECKED 0x0001 /* lock is being checked */
412 #define USLOCK_TAKEN 0x0002 /* lock has been taken */
413 #define USLOCK_INIT 0xBAA0 /* lock has been initialized */
414 #define USLOCK_INITIALIZED (USLOCK_INIT|USLOCK_CHECKED)
415 #define USLOCK_CHECKING(l) (uslock_check && \
416 ((l)->debug.state & USLOCK_CHECKED))
419 * Maintain a per-cpu stack of acquired usimple_locks.
421 void usl_stack_push(usimple_lock_t
, int);
422 void usl_stack_pop(usimple_lock_t
, int);
425 * Trace activities of a particularly interesting lock.
427 void usl_trace(usimple_lock_t
, int, pc_t
, const char *);
431 * Initialize the debugging information contained
439 if (l
== USIMPLE_LOCK_NULL
)
440 panic("lock initialization: null lock pointer");
441 l
->lock_type
= USLOCK_TAG
;
442 l
->debug
.state
= uslock_check
? USLOCK_INITIALIZED
: 0;
443 l
->debug
.lock_cpu
= l
->debug
.unlock_cpu
= 0;
444 l
->debug
.lock_pc
= l
->debug
.unlock_pc
= INVALID_PC
;
445 l
->debug
.lock_thread
= l
->debug
.unlock_thread
= INVALID_THREAD
;
446 l
->debug
.duration
[0] = l
->debug
.duration
[1] = 0;
447 l
->debug
.unlock_cpu
= l
->debug
.unlock_cpu
= 0;
448 l
->debug
.unlock_pc
= l
->debug
.unlock_pc
= INVALID_PC
;
449 l
->debug
.unlock_thread
= l
->debug
.unlock_thread
= INVALID_THREAD
;
454 * These checks apply to all usimple_locks, not just
455 * those with USLOCK_CHECKED turned on.
458 usld_lock_common_checks(
462 if (l
== USIMPLE_LOCK_NULL
)
463 panic("%s: null lock pointer", caller
);
464 if (l
->lock_type
!= USLOCK_TAG
)
465 panic("%s: 0x%x is not a usimple lock", caller
, (integer_t
) l
);
466 if (!(l
->debug
.state
& USLOCK_INIT
))
467 panic("%s: 0x%x is not an initialized lock",
468 caller
, (integer_t
) l
);
469 return USLOCK_CHECKING(l
);
474 * Debug checks on a usimple_lock just before attempting
483 char *caller
= "usimple_lock";
487 printf("*** %08X %08X %04X %02X %08X %02X %08X - %s\n", /* (TEST/DEBUG) */
489 l
->debug
.lock_thread
,
492 l
->debug
.unlock_thread
,
498 if (!usld_lock_common_checks(l
, caller
))
502 * Note that we have a weird case where we are getting a lock when we are]
503 * in the process of putting the system to sleep. We are running with no
504 * current threads, therefore we can't tell if we are trying to retake a lock
505 * we have or someone on the other processor has it. Therefore we just
506 * ignore this test if the locking thread is 0.
509 if ((l
->debug
.state
& USLOCK_TAKEN
) && l
->debug
.lock_thread
&&
510 l
->debug
.lock_thread
== (void *) current_thread()) {
511 printf("%s: lock 0x%x already locked (at 0x%x) by",
512 caller
, (integer_t
) l
, l
->debug
.lock_pc
);
513 printf(" current thread 0x%x (new attempt at pc 0x%x)\n",
514 l
->debug
.lock_thread
, pc
);
517 mp_disable_preemption();
518 usl_trace(l
, cpu_number(), pc
, caller
);
519 mp_enable_preemption();
524 * Debug checks on a usimple_lock just after acquiring it.
526 * Pre-emption has been disabled at this point,
527 * so we are safe in using cpu_number.
535 char *caller
= "successful usimple_lock";
539 printf("*** %08X %08X %04X %02X %08X %02X %08X - %s\n", /* (TEST/DEBUG) */
541 l
->debug
.lock_thread
,
544 l
->debug
.unlock_thread
,
550 if (!usld_lock_common_checks(l
, caller
))
553 if (!((l
->debug
.state
& ~USLOCK_TAKEN
) == USLOCK_INITIALIZED
))
554 panic("%s: lock 0x%x became uninitialized",
555 caller
, (integer_t
) l
);
556 if ((l
->debug
.state
& USLOCK_TAKEN
))
557 panic("%s: lock 0x%x became TAKEN by someone else",
558 caller
, (integer_t
) l
);
560 mycpu
= cpu_number();
561 l
->debug
.lock_thread
= (void *)current_thread();
562 l
->debug
.state
|= USLOCK_TAKEN
;
563 l
->debug
.lock_pc
= pc
;
564 l
->debug
.lock_cpu
= mycpu
;
566 usl_stack_push(l
, mycpu
);
567 usl_trace(l
, mycpu
, pc
, caller
);
572 * Debug checks on a usimple_lock just before
573 * releasing it. Note that the caller has not
574 * yet released the hardware lock.
576 * Preemption is still disabled, so there's
577 * no problem using cpu_number.
585 char *caller
= "usimple_unlock";
589 printf("*** %08X %08X %04X %02X %08X %02X %08X - %s\n", /* (TEST/DEBUG) */
591 l
->debug
.lock_thread
,
594 l
->debug
.unlock_thread
,
600 if (!usld_lock_common_checks(l
, caller
))
603 mycpu
= cpu_number();
605 if (!(l
->debug
.state
& USLOCK_TAKEN
))
606 panic("%s: lock 0x%x hasn't been taken",
607 caller
, (integer_t
) l
);
608 if (l
->debug
.lock_thread
!= (void *) current_thread())
609 panic("%s: unlocking lock 0x%x, owned by thread 0x%x",
610 caller
, (integer_t
) l
, l
->debug
.lock_thread
);
611 if (l
->debug
.lock_cpu
!= mycpu
) {
612 printf("%s: unlocking lock 0x%x on cpu 0x%x",
613 caller
, (integer_t
) l
, mycpu
);
614 printf(" (acquired on cpu 0x%x)\n", l
->debug
.lock_cpu
);
617 usl_trace(l
, mycpu
, pc
, caller
);
618 usl_stack_pop(l
, mycpu
);
620 l
->debug
.unlock_thread
= l
->debug
.lock_thread
;
621 l
->debug
.lock_thread
= INVALID_PC
;
622 l
->debug
.state
&= ~USLOCK_TAKEN
;
623 l
->debug
.unlock_pc
= pc
;
624 l
->debug
.unlock_cpu
= mycpu
;
629 * Debug checks on a usimple_lock just before
630 * attempting to acquire it.
632 * Preemption isn't guaranteed to be disabled.
639 char *caller
= "usimple_lock_try";
641 if (!usld_lock_common_checks(l
, caller
))
643 mp_disable_preemption();
644 usl_trace(l
, cpu_number(), pc
, caller
);
645 mp_enable_preemption();
650 * Debug checks on a usimple_lock just after
651 * successfully attempting to acquire it.
653 * Preemption has been disabled by the
654 * lock acquisition attempt, so it's safe
663 char *caller
= "successful usimple_lock_try";
665 if (!usld_lock_common_checks(l
, caller
))
668 if (!((l
->debug
.state
& ~USLOCK_TAKEN
) == USLOCK_INITIALIZED
))
669 panic("%s: lock 0x%x became uninitialized",
670 caller
, (integer_t
) l
);
671 if ((l
->debug
.state
& USLOCK_TAKEN
))
672 panic("%s: lock 0x%x became TAKEN by someone else",
673 caller
, (integer_t
) l
);
675 mycpu
= cpu_number();
676 l
->debug
.lock_thread
= (void *) current_thread();
677 l
->debug
.state
|= USLOCK_TAKEN
;
678 l
->debug
.lock_pc
= pc
;
679 l
->debug
.lock_cpu
= mycpu
;
682 printf("*** %08X %08X %04X %02X %08X %02X %08X - %s\n", /* (TEST/DEBUG) */
684 l
->debug
.lock_thread
,
687 l
->debug
.unlock_thread
,
693 usl_stack_push(l
, mycpu
);
694 usl_trace(l
, mycpu
, pc
, caller
);
699 * Determine whether the lock in question is owned
700 * by the current thread.
706 char *caller
= "usimple_lock_held";
710 printf("*** %08X %08X %04X %02X %08X %02X %08X - %s\n", /* (TEST/DEBUG) */
712 l
->debug
.lock_thread
,
715 l
->debug
.unlock_thread
,
721 if (!usld_lock_common_checks(l
, caller
))
724 if (!(l
->debug
.state
& USLOCK_TAKEN
))
725 panic("%s: lock 0x%x hasn't been taken",
726 caller
, (integer_t
) l
);
727 if (l
->debug
.lock_thread
!= (void *) current_thread())
728 panic("%s: lock 0x%x is owned by thread 0x%x", caller
,
729 (integer_t
) l
, (integer_t
) l
->debug
.lock_thread
);
732 * The usimple_lock is active, so preemption
733 * is disabled and the current cpu should
734 * match the one recorded at lock acquisition time.
736 if (l
->debug
.lock_cpu
!= cpu_number())
737 panic("%s: current cpu 0x%x isn't acquiring cpu 0x%x",
738 caller
, cpu_number(), (integer_t
) l
->debug
.lock_cpu
);
743 * Per-cpu stack of currently active usimple_locks.
744 * Requires spl protection so that interrupt-level
745 * locks plug-n-play with their thread-context friends.
747 #define USLOCK_STACK_DEPTH 20
748 usimple_lock_t uslock_stack
[NCPUS
][USLOCK_STACK_DEPTH
];
749 unsigned int uslock_stack_index
[NCPUS
];
750 boolean_t uslock_stack_enabled
= FALSE
;
754 * Record a usimple_lock just acquired on
755 * the current processor.
757 * Preemption has been disabled by lock
758 * acquisition, so it's safe to use the cpu number
759 * specified by the caller.
768 if (uslock_stack_enabled
== FALSE
)
771 DISABLE_INTERRUPTS(s
);
772 assert(uslock_stack_index
[mycpu
] >= 0);
773 assert(uslock_stack_index
[mycpu
] < USLOCK_STACK_DEPTH
);
774 if (uslock_stack_index
[mycpu
] >= USLOCK_STACK_DEPTH
) {
775 printf("usl_stack_push (cpu 0x%x): too many locks (%d)",
776 mycpu
, uslock_stack_index
[mycpu
]);
777 printf(" disabling stacks\n");
778 uslock_stack_enabled
= FALSE
;
779 ENABLE_INTERRUPTS(s
);
782 uslock_stack
[mycpu
][uslock_stack_index
[mycpu
]] = l
;
783 uslock_stack_index
[mycpu
]++;
784 ENABLE_INTERRUPTS(s
);
789 * Eliminate the entry for a usimple_lock
790 * that had been active on the current processor.
792 * Preemption has been disabled by lock
793 * acquisition, and we haven't yet actually
794 * released the hardware lock associated with
795 * this usimple_lock, so it's safe to use the
796 * cpu number supplied by the caller.
803 unsigned int i
, index
;
806 if (uslock_stack_enabled
== FALSE
)
809 DISABLE_INTERRUPTS(s
);
810 assert(uslock_stack_index
[mycpu
] > 0);
811 assert(uslock_stack_index
[mycpu
] <= USLOCK_STACK_DEPTH
);
812 if (uslock_stack_index
[mycpu
] == 0) {
813 printf("usl_stack_pop (cpu 0x%x): not enough locks (%d)",
814 mycpu
, uslock_stack_index
[mycpu
]);
815 printf(" disabling stacks\n");
816 uslock_stack_enabled
= FALSE
;
817 ENABLE_INTERRUPTS(s
);
820 index
= --uslock_stack_index
[mycpu
];
821 for (i
= 0; i
<= index
; ++i
) {
822 if (uslock_stack
[mycpu
][i
] == l
) {
824 uslock_stack
[mycpu
][i
] =
825 uslock_stack
[mycpu
][index
];
826 ENABLE_INTERRUPTS(s
);
830 ENABLE_INTERRUPTS(s
);
831 panic("usl_stack_pop: can't find usimple_lock 0x%x", l
);
836 * Determine whether any usimple_locks are currently held.
838 * Caller's preemption state is uncertain. If
839 * preemption has been disabled, this check is accurate.
840 * Otherwise, this check is just a guess. We do the best
841 * we can by disabling scheduler interrupts, so at least
842 * the check is accurate w.r.t. whatever cpu we're running
843 * on while in this routine.
846 usld_lock_none_held()
850 unsigned int locks_held
;
851 char *caller
= "usimple_lock_none_held";
853 DISABLE_INTERRUPTS(s
);
854 mp_disable_preemption();
855 mycpu
= cpu_number();
856 locks_held
= uslock_stack_index
[mycpu
];
857 mp_enable_preemption();
858 ENABLE_INTERRUPTS(s
);
860 panic("%s: no locks should be held (0x%x locks held)",
861 caller
, (integer_t
) locks_held
);
866 * For very special cases, set traced_lock to point to a
867 * specific lock of interest. The result is a series of
868 * XPRs showing lock operations on that lock. The lock_seq
869 * value is used to show the order of those operations.
871 usimple_lock_t traced_lock
;
872 unsigned int lock_seq
;
879 const char * op_name
)
881 if (traced_lock
== l
) {
883 "seq %d, cpu %d, %s @ %x\n",
884 (integer_t
) lock_seq
, (integer_t
) mycpu
,
885 (integer_t
) op_name
, (integer_t
) pc
, 0);
893 #define printf kdbprintf
894 void db_show_all_slocks(void);
896 db_show_all_slocks(void)
898 unsigned int i
, index
;
899 int mycpu
= cpu_number();
902 if (uslock_stack_enabled
== FALSE
) {
903 printf("Lock stack not enabled\n");
908 if (!mach_slocks_init
)
909 iprintf("WARNING: simple locks stack may not be accurate\n");
911 assert(uslock_stack_index
[mycpu
] >= 0);
912 assert(uslock_stack_index
[mycpu
] <= USLOCK_STACK_DEPTH
);
913 index
= uslock_stack_index
[mycpu
];
914 for (i
= 0; i
< index
; ++i
) {
915 l
= uslock_stack
[mycpu
][i
];
917 db_printsym((vm_offset_t
)l
, DB_STGY_ANY
);
918 if (l
->debug
.lock_pc
!= INVALID_PC
) {
919 printf(" locked by ");
920 db_printsym((int)l
->debug
.lock_pc
, DB_STGY_PROC
);
925 #endif /* MACH_KDB */
927 #endif /* USLOCK_DEBUG */
929 /* #endif USIMPLE_LOCK_CALLS */
932 * Routine: lock_alloc
934 * Allocate a lock for external users who cannot
935 * hard-code the structure definition into their
937 * For now just use kalloc, but a zone is probably
944 etap_event_t i_event
)
948 if ((l
= (lock_t
*)kalloc(sizeof(lock_t
))) != 0)
949 lock_init(l
, can_sleep
, event
, i_event
);
956 * Free a lock allocated for external users.
957 * For now just use kfree, but a zone is probably
964 kfree((vm_offset_t
)l
, sizeof(lock_t
));
971 * Initialize a lock; required before use.
972 * Note that clients declare the "struct lock"
973 * variables and then initialize them, rather
974 * than getting a new one from this module.
981 etap_event_t i_event
)
983 (void) memset((void *) l
, 0, sizeof(lock_t
));
986 etap_event_table_assign(&l
->u
.event_table_chain
, event
);
987 l
->u
.s
.start_list
= SD_ENTRY_NULL
;
988 #endif /* ETAP_LOCK_TRACE */
990 simple_lock_init(&l
->interlock
, i_event
);
991 l
->want_write
= FALSE
;
992 l
->want_upgrade
= FALSE
;
994 l
->can_sleep
= can_sleep
;
996 #if ETAP_LOCK_ACCUMULATE
997 l
->cbuff_write
= etap_cbuff_reserve(lock_event_table(l
));
998 if (l
->cbuff_write
!= CBUFF_ENTRY_NULL
) {
999 l
->cbuff_write
->event
= event
;
1000 l
->cbuff_write
->instance
= (unsigned long) l
;
1001 l
->cbuff_write
->kind
= WRITE_LOCK
;
1003 l
->cbuff_read
= CBUFF_ENTRY_NULL
;
1004 #endif /* ETAP_LOCK_ACCUMULATE */
1009 * Sleep locks. These use the same data structure and algorithm
1010 * as the spin locks, but the process sleeps while it is waiting
1011 * for the lock. These work on uniprocessor systems.
1014 #define DECREMENTER_TIMEOUT 1000000
1018 register lock_t
* l
)
1021 start_data_node_t entry
= {0};
1022 boolean_t lock_miss
= FALSE
;
1023 unsigned short dynamic
= 0;
1024 unsigned short trace
= 0;
1025 etap_time_t total_time
;
1026 etap_time_t stop_wait_time
;
1030 #endif /* MACH_LDEBUG */
1033 ETAP_STAMP(lock_event_table(l
), trace
, dynamic
);
1034 ETAP_CREATE_ENTRY(entry
, trace
);
1035 MON_ASSIGN_PC(entry
->start_pc
, pc
, trace
);
1037 simple_lock(&l
->interlock
);
1040 * Link the new start_list entry
1042 ETAP_LINK_ENTRY(l
, entry
, trace
);
1045 decrementer
= DECREMENTER_TIMEOUT
;
1046 #endif /* MACH_LDEBUG */
1049 * Try to acquire the want_write bit.
1051 while (l
->want_write
) {
1053 ETAP_CONTENTION_TIMESTAMP(entry
, trace
);
1057 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
1059 simple_unlock(&l
->interlock
);
1062 Debugger("timeout - want_write");
1063 #endif /* MACH_LDEBUG */
1064 while (--i
!= 0 && l
->want_write
)
1066 simple_lock(&l
->interlock
);
1069 if (l
->can_sleep
&& l
->want_write
) {
1071 ETAP_SET_REASON(current_thread(),
1072 BLOCKED_ON_COMPLEX_LOCK
);
1073 thread_sleep_simple_lock((event_t
) l
,
1074 simple_lock_addr(l
->interlock
),
1076 /* interlock relocked */
1079 l
->want_write
= TRUE
;
1081 /* Wait for readers (and upgrades) to finish */
1084 decrementer
= DECREMENTER_TIMEOUT
;
1085 #endif /* MACH_LDEBUG */
1086 while ((l
->read_count
!= 0) || l
->want_upgrade
) {
1088 ETAP_CONTENTION_TIMESTAMP(entry
,trace
);
1092 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
1094 simple_unlock(&l
->interlock
);
1097 Debugger("timeout - wait for readers");
1098 #endif /* MACH_LDEBUG */
1099 while (--i
!= 0 && (l
->read_count
!= 0 ||
1102 simple_lock(&l
->interlock
);
1105 if (l
->can_sleep
&& (l
->read_count
!= 0 || l
->want_upgrade
)) {
1107 ETAP_SET_REASON(current_thread(),
1108 BLOCKED_ON_COMPLEX_LOCK
);
1109 thread_sleep_simple_lock((event_t
) l
,
1110 simple_lock_addr(l
->interlock
),
1112 /* interlock relocked */
1117 * do not collect wait data if either the lock
1118 * was free or no wait traces are enabled.
1121 if (lock_miss
&& ETAP_CONTENTION_ENABLED(trace
)) {
1122 ETAP_TIMESTAMP(stop_wait_time
);
1123 ETAP_TOTAL_TIME(total_time
,
1125 entry
->start_wait_time
);
1126 CUM_WAIT_ACCUMULATE(l
->cbuff_write
, total_time
, dynamic
, trace
);
1135 simple_unlock(&l
->interlock
);
1138 * Set start hold time if some type of hold tracing is enabled.
1140 * Note: if the stop_wait_time was already stamped, use
1141 * it as the start_hold_time instead of doing an
1142 * expensive bus access.
1146 if (lock_miss
&& ETAP_CONTENTION_ENABLED(trace
))
1147 ETAP_COPY_START_HOLD_TIME(entry
, stop_wait_time
, trace
);
1149 ETAP_DURATION_TIMESTAMP(entry
, trace
);
1155 register lock_t
* l
)
1157 boolean_t do_wakeup
= FALSE
;
1158 start_data_node_t entry
;
1159 unsigned short dynamic
= 0;
1160 unsigned short trace
= 0;
1161 etap_time_t stop_hold_time
;
1162 etap_time_t total_time
;
1163 unsigned long lock_kind
;
1167 ETAP_STAMP(lock_event_table(l
), trace
, dynamic
);
1169 simple_lock(&l
->interlock
);
1171 if (l
->read_count
!= 0) {
1173 lock_kind
= READ_LOCK
;
1176 if (l
->want_upgrade
) {
1177 l
->want_upgrade
= FALSE
;
1178 lock_kind
= WRITE_LOCK
;
1181 l
->want_write
= FALSE
;
1182 lock_kind
= WRITE_LOCK
;
1186 * There is no reason to wakeup a waiting thread
1187 * if the read-count is non-zero. Consider:
1188 * we must be dropping a read lock
1189 * threads are waiting only if one wants a write lock
1190 * if there are still readers, they can't proceed
1193 if (l
->waiting
&& (l
->read_count
== 0)) {
1198 * Collect hold data if hold tracing is
1203 * NOTE: All complex locks whose tracing was on when the
1204 * lock was acquired will have an entry in the start_data
1208 ETAP_UNLINK_ENTRY(l
,entry
);
1209 if (ETAP_DURATION_ENABLED(trace
) && entry
!= SD_ENTRY_NULL
) {
1210 ETAP_TIMESTAMP (stop_hold_time
);
1211 ETAP_TOTAL_TIME (total_time
,
1213 entry
->start_hold_time
);
1215 if (lock_kind
& WRITE_LOCK
)
1216 CUM_HOLD_ACCUMULATE (l
->cbuff_write
,
1221 CUM_READ_ENTRY_RESERVE(l
,l
->cbuff_read
,trace
);
1222 CUM_HOLD_ACCUMULATE (l
->cbuff_read
,
1227 MON_ASSIGN_PC(entry
->end_pc
,pc
,trace
);
1228 MON_DATA_COLLECT(l
,entry
,
1235 simple_unlock(&l
->interlock
);
1237 ETAP_DESTROY_ENTRY(entry
);
1240 thread_wakeup((event_t
) l
);
1245 register lock_t
* l
)
1248 start_data_node_t entry
= {0};
1249 boolean_t lock_miss
= FALSE
;
1250 unsigned short dynamic
= 0;
1251 unsigned short trace
= 0;
1252 etap_time_t total_time
;
1253 etap_time_t stop_wait_time
;
1257 #endif /* MACH_LDEBUG */
1259 ETAP_STAMP(lock_event_table(l
), trace
, dynamic
);
1260 ETAP_CREATE_ENTRY(entry
, trace
);
1261 MON_ASSIGN_PC(entry
->start_pc
, pc
, trace
);
1263 simple_lock(&l
->interlock
);
1266 * Link the new start_list entry
1268 ETAP_LINK_ENTRY(l
,entry
,trace
);
1271 decrementer
= DECREMENTER_TIMEOUT
;
1272 #endif /* MACH_LDEBUG */
1273 while (l
->want_write
|| l
->want_upgrade
) {
1275 ETAP_CONTENTION_TIMESTAMP(entry
, trace
);
1279 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
1282 simple_unlock(&l
->interlock
);
1285 Debugger("timeout - wait no writers");
1286 #endif /* MACH_LDEBUG */
1287 while (--i
!= 0 && (l
->want_write
|| l
->want_upgrade
))
1289 simple_lock(&l
->interlock
);
1292 if (l
->can_sleep
&& (l
->want_write
|| l
->want_upgrade
)) {
1294 thread_sleep_simple_lock((event_t
) l
,
1295 simple_lock_addr(l
->interlock
),
1297 /* interlock relocked */
1304 * Do not collect wait data if the lock was free
1305 * or if no wait traces are enabled.
1308 if (lock_miss
&& ETAP_CONTENTION_ENABLED(trace
)) {
1309 ETAP_TIMESTAMP(stop_wait_time
);
1310 ETAP_TOTAL_TIME(total_time
,
1312 entry
->start_wait_time
);
1313 CUM_READ_ENTRY_RESERVE(l
, l
->cbuff_read
, trace
);
1314 CUM_WAIT_ACCUMULATE(l
->cbuff_read
, total_time
, dynamic
, trace
);
1322 simple_unlock(&l
->interlock
);
1325 * Set start hold time if some type of hold tracing is enabled.
1327 * Note: if the stop_wait_time was already stamped, use
1328 * it instead of doing an expensive bus access.
1332 if (lock_miss
&& ETAP_CONTENTION_ENABLED(trace
))
1333 ETAP_COPY_START_HOLD_TIME(entry
, stop_wait_time
, trace
);
1335 ETAP_DURATION_TIMESTAMP(entry
,trace
);
1340 * Routine: lock_read_to_write
1342 * Improves a read-only lock to one with
1343 * write permission. If another reader has
1344 * already requested an upgrade to a write lock,
1345 * no lock is held upon return.
1347 * Returns TRUE if the upgrade *failed*.
1352 register lock_t
* l
)
1355 boolean_t do_wakeup
= FALSE
;
1356 start_data_node_t entry
= {0};
1357 boolean_t lock_miss
= FALSE
;
1358 unsigned short dynamic
= 0;
1359 unsigned short trace
= 0;
1360 etap_time_t total_time
;
1361 etap_time_t stop_time
;
1365 #endif /* MACH_LDEBUG */
1368 ETAP_STAMP(lock_event_table(l
), trace
, dynamic
);
1370 simple_lock(&l
->interlock
);
1375 * Since the read lock is lost whether the write lock
1376 * is acquired or not, read hold data is collected here.
1377 * This, of course, is assuming some type of hold
1378 * tracing is enabled.
1380 * Note: trace is set to zero if the entry does not exist.
1383 ETAP_FIND_ENTRY(l
, entry
, trace
);
1385 if (ETAP_DURATION_ENABLED(trace
)) {
1386 ETAP_TIMESTAMP(stop_time
);
1387 ETAP_TOTAL_TIME(total_time
, stop_time
, entry
->start_hold_time
);
1388 CUM_HOLD_ACCUMULATE(l
->cbuff_read
, total_time
, dynamic
, trace
);
1389 MON_ASSIGN_PC(entry
->end_pc
, pc
, trace
);
1398 if (l
->want_upgrade
) {
1400 * Someone else has requested upgrade.
1401 * Since we've released a read lock, wake
1404 if (l
->waiting
&& (l
->read_count
== 0)) {
1409 ETAP_UNLINK_ENTRY(l
, entry
);
1410 simple_unlock(&l
->interlock
);
1411 ETAP_DESTROY_ENTRY(entry
);
1414 thread_wakeup((event_t
) l
);
1418 l
->want_upgrade
= TRUE
;
1420 MON_ASSIGN_PC(entry
->start_pc
, pc
, trace
);
1423 decrementer
= DECREMENTER_TIMEOUT
;
1424 #endif /* MACH_LDEBUG */
1425 while (l
->read_count
!= 0) {
1427 ETAP_CONTENTION_TIMESTAMP(entry
, trace
);
1431 i
= lock_wait_time
[l
->can_sleep
? 1 : 0];
1434 simple_unlock(&l
->interlock
);
1437 Debugger("timeout - read_count");
1438 #endif /* MACH_LDEBUG */
1439 while (--i
!= 0 && l
->read_count
!= 0)
1441 simple_lock(&l
->interlock
);
1444 if (l
->can_sleep
&& l
->read_count
!= 0) {
1446 thread_sleep_simple_lock((event_t
) l
,
1447 simple_lock_addr(l
->interlock
),
1449 /* interlock relocked */
1454 * do not collect wait data if the lock was free
1455 * or if no wait traces are enabled.
1458 if (lock_miss
&& ETAP_CONTENTION_ENABLED(trace
)) {
1459 ETAP_TIMESTAMP (stop_time
);
1460 ETAP_TOTAL_TIME(total_time
, stop_time
, entry
->start_wait_time
);
1461 CUM_WAIT_ACCUMULATE(l
->cbuff_write
, total_time
, dynamic
, trace
);
1470 simple_unlock(&l
->interlock
);
1473 * Set start hold time if some type of hold tracing is enabled
1475 * Note: if the stop_time was already stamped, use
1476 * it as the new start_hold_time instead of doing
1477 * an expensive VME access.
1481 if (lock_miss
&& ETAP_CONTENTION_ENABLED(trace
))
1482 ETAP_COPY_START_HOLD_TIME(entry
, stop_time
, trace
);
1484 ETAP_DURATION_TIMESTAMP(entry
, trace
);
1491 register lock_t
* l
)
1493 boolean_t do_wakeup
= FALSE
;
1494 start_data_node_t entry
= {0};
1495 unsigned short dynamic
= 0;
1496 unsigned short trace
= 0;
1497 etap_time_t stop_hold_time
;
1498 etap_time_t total_time
;
1501 ETAP_STAMP(lock_event_table(l
), trace
,dynamic
);
1503 simple_lock(&l
->interlock
);
1506 if (l
->want_upgrade
)
1507 l
->want_upgrade
= FALSE
;
1509 l
->want_write
= FALSE
;
1517 * Since we are switching from a write lock to a read lock,
1518 * the write lock data is stored and the read lock data
1519 * collection begins.
1521 * Note: trace is set to zero if the entry does not exist.
1524 ETAP_FIND_ENTRY(l
, entry
, trace
);
1526 if (ETAP_DURATION_ENABLED(trace
)) {
1527 ETAP_TIMESTAMP (stop_hold_time
);
1528 ETAP_TOTAL_TIME(total_time
, stop_hold_time
, entry
->start_hold_time
);
1529 CUM_HOLD_ACCUMULATE(l
->cbuff_write
, total_time
, dynamic
, trace
);
1530 MON_ASSIGN_PC(entry
->end_pc
, pc
, trace
);
1539 simple_unlock(&l
->interlock
);
1542 * Set start hold time if some type of hold tracing is enabled
1544 * Note: if the stop_hold_time was already stamped, use
1545 * it as the new start_hold_time instead of doing
1546 * an expensive bus access.
1550 if (ETAP_DURATION_ENABLED(trace
))
1551 ETAP_COPY_START_HOLD_TIME(entry
, stop_hold_time
, trace
);
1553 ETAP_DURATION_TIMESTAMP(entry
, trace
);
1555 MON_ASSIGN_PC(entry
->start_pc
, pc
, trace
);
1558 thread_wakeup((event_t
) l
);
1564 * Routine: lock_try_write
1566 * Tries to get a write lock.
1568 * Returns FALSE if the lock is not held on return.
1573 register lock_t
* l
)
1575 start_data_node_t entry
= {0};
1576 unsigned short trace
= 0;
1579 ETAP_STAMP(lock_event_table(l
), trace
, trace
);
1580 ETAP_CREATE_ENTRY(entry
, trace
);
1582 simple_lock(&l
->interlock
);
1584 if (l
->want_write
|| l
->want_upgrade
|| l
->read_count
) {
1588 simple_unlock(&l
->interlock
);
1589 ETAP_DESTROY_ENTRY(entry
);
1597 l
->want_write
= TRUE
;
1599 ETAP_LINK_ENTRY(l
, entry
, trace
);
1601 simple_unlock(&l
->interlock
);
1603 MON_ASSIGN_PC(entry
->start_pc
, pc
, trace
);
1604 ETAP_DURATION_TIMESTAMP(entry
, trace
);
1610 * Routine: lock_try_read
1612 * Tries to get a read lock.
1614 * Returns FALSE if the lock is not held on return.
1619 register lock_t
* l
)
1621 start_data_node_t entry
= {0};
1622 unsigned short trace
= 0;
1625 ETAP_STAMP(lock_event_table(l
), trace
, trace
);
1626 ETAP_CREATE_ENTRY(entry
, trace
);
1628 simple_lock(&l
->interlock
);
1630 if (l
->want_write
|| l
->want_upgrade
) {
1631 simple_unlock(&l
->interlock
);
1632 ETAP_DESTROY_ENTRY(entry
);
1638 ETAP_LINK_ENTRY(l
, entry
, trace
);
1640 simple_unlock(&l
->interlock
);
1642 MON_ASSIGN_PC(entry
->start_pc
, pc
, trace
);
1643 ETAP_DURATION_TIMESTAMP(entry
, trace
);
1651 void db_show_one_lock(lock_t
*);
1658 db_printf("Read_count = 0x%x, %swant_upgrade, %swant_write, ",
1660 lock
->want_upgrade
? "" : "!",
1661 lock
->want_write
? "" : "!");
1662 db_printf("%swaiting, %scan_sleep\n",
1663 lock
->waiting
? "" : "!", lock
->can_sleep
? "" : "!");
1664 db_printf("Interlock:\n");
1665 db_show_one_simple_lock((db_expr_t
)simple_lock_addr(lock
->interlock
),
1666 TRUE
, (db_expr_t
)0, (char *)0);
1668 #endif /* MACH_KDB */
1671 * The C portion of the mutex package. These routines are only invoked
1672 * if the optimized assembler routines can't do the work.
1676 * Routine: lock_alloc
1678 * Allocate a mutex for external users who cannot
1679 * hard-code the structure definition into their
1681 * For now just use kalloc, but a zone is probably
1690 if ((m
= (mutex_t
*)kalloc(sizeof(mutex_t
))) != 0)
1691 mutex_init(m
, event
);
1696 * Routine: mutex_free
1698 * Free a mutex allocated for external users.
1699 * For now just use kfree, but a zone is probably
1706 kfree((vm_offset_t
)m
, sizeof(mutex_t
));
1712 * Invoked in order to wait on contention.
1714 * Called with the interlock locked and
1715 * returns it unlocked.
1722 thread_t self
= current_thread();
1725 spl_t s
= splsched();
1727 priority
= self
->sched_pri
;
1728 if (priority
< self
->priority
)
1729 priority
= self
->priority
;
1730 if (priority
> MINPRI_KERNEL
)
1731 priority
= MINPRI_KERNEL
;
1733 if (priority
< BASEPRI_DEFAULT
)
1734 priority
= BASEPRI_DEFAULT
;
1736 assert(holder
->thread
== holder
); /* XXX */
1737 thread_lock(holder
);
1738 if (mutex
->promoted_pri
== 0)
1739 holder
->promotions
++;
1740 if (holder
->priority
< MINPRI_KERNEL
) {
1741 holder
->sched_mode
|= TH_MODE_PROMOTED
;
1742 if ( mutex
->promoted_pri
< priority
&&
1743 holder
->sched_pri
< priority
) {
1744 KERNEL_DEBUG_CONSTANT(
1745 MACHDBG_CODE(DBG_MACH_SCHED
,MACH_PROMOTE
) | DBG_FUNC_NONE
,
1746 holder
->sched_pri
, priority
, (int)holder
, (int)mutex
, 0);
1748 set_sched_pri(holder
, priority
);
1751 thread_unlock(holder
);
1754 if (mutex
->promoted_pri
< priority
)
1755 mutex
->promoted_pri
= priority
;
1758 if (self
->pending_promoter
[self
->pending_promoter_index
] == NULL
) {
1759 self
->pending_promoter
[self
->pending_promoter_index
] = mutex
;
1763 if (self
->pending_promoter
[self
->pending_promoter_index
] != mutex
) {
1764 self
->pending_promoter
[++self
->pending_promoter_index
] = mutex
;
1768 assert_wait(mutex
, THREAD_UNINT
);
1769 interlock_unlock(&mutex
->interlock
);
1771 thread_block(THREAD_CONTINUE_NULL
);
1775 * mutex_lock_acquire
1777 * Invoked on acquiring the mutex when there is
1780 * Returns the current number of waiters.
1782 * Called with the interlock locked.
1788 thread_t thread
= current_thread();
1790 if (thread
->pending_promoter
[thread
->pending_promoter_index
] == mutex
) {
1791 thread
->pending_promoter
[thread
->pending_promoter_index
] = NULL
;
1792 if (thread
->pending_promoter_index
> 0)
1793 thread
->pending_promoter_index
--;
1798 if (mutex
->waiters
> 0) {
1799 integer_t priority
= mutex
->promoted_pri
;
1800 spl_t s
= splsched();
1802 thread_lock(thread
);
1803 thread
->promotions
++;
1804 if (thread
->priority
< MINPRI_KERNEL
) {
1805 thread
->sched_mode
|= TH_MODE_PROMOTED
;
1806 if (thread
->sched_pri
< priority
) {
1807 KERNEL_DEBUG_CONSTANT(
1808 MACHDBG_CODE(DBG_MACH_SCHED
,MACH_PROMOTE
) | DBG_FUNC_NONE
,
1809 thread
->sched_pri
, priority
, 0, (int)mutex
, 0);
1811 set_sched_pri(thread
, priority
);
1814 thread_unlock(thread
);
1818 mutex
->promoted_pri
= 0;
1821 return (mutex
->waiters
);
1825 * mutex_unlock_wakeup
1827 * Invoked on unlock when there is contention.
1829 * Called with the interlock locked.
1832 mutex_unlock_wakeup (
1837 thread_t thread
= current_thread();
1839 if (thread
->top_act
!= holder
)
1840 panic("mutex_unlock_wakeup: mutex %x holder %x\n", mutex
, holder
);
1842 if (thread
->promotions
> 0) {
1843 spl_t s
= splsched();
1845 thread_lock(thread
);
1846 if ( --thread
->promotions
== 0 &&
1847 (thread
->sched_mode
& TH_MODE_PROMOTED
) ) {
1848 thread
->sched_mode
&= ~TH_MODE_PROMOTED
;
1849 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
) {
1850 KERNEL_DEBUG_CONSTANT(
1851 MACHDBG_CODE(DBG_MACH_SCHED
,MACH_DEMOTE
) | DBG_FUNC_NONE
,
1852 thread
->sched_pri
, DEPRESSPRI
, 0, (int)mutex
, 0);
1854 set_sched_pri(thread
, DEPRESSPRI
);
1857 if (thread
->priority
< thread
->sched_pri
) {
1858 KERNEL_DEBUG_CONSTANT(
1859 MACHDBG_CODE(DBG_MACH_SCHED
,MACH_DEMOTE
) |
1861 thread
->sched_pri
, thread
->priority
,
1865 compute_priority(thread
, FALSE
);
1868 thread_unlock(thread
);
1873 assert(mutex
->waiters
> 0);
1874 thread_wakeup_one(mutex
);
1878 mutex_preblock_wait(
1883 wait_result_t wresult
;
1887 assert(holder
== NULL
|| holder
->thread
== holder
);
1889 wq
= wait_event_wait_queue((event_t
)mutex
);
1890 if (!wait_queue_lock_try(wq
))
1893 if (holder
!= NULL
&& !thread_lock_try(holder
)) {
1894 wait_queue_unlock(wq
);
1898 wresult
= wait_queue_assert_wait64_locked(wq
, (uint32_t)mutex
,
1899 THREAD_UNINT
, thread
);
1900 wait_queue_unlock(wq
);
1901 assert(wresult
== THREAD_WAITING
);
1903 priority
= thread
->sched_pri
;
1904 if (priority
< thread
->priority
)
1905 priority
= thread
->priority
;
1906 if (priority
> MINPRI_KERNEL
)
1907 priority
= MINPRI_KERNEL
;
1909 if (priority
< BASEPRI_DEFAULT
)
1910 priority
= BASEPRI_DEFAULT
;
1912 if (holder
!= NULL
) {
1913 if (mutex
->promoted_pri
== 0)
1914 holder
->promotions
++;
1915 if (holder
->priority
< MINPRI_KERNEL
) {
1916 holder
->sched_mode
|= TH_MODE_PROMOTED
;
1917 if ( mutex
->promoted_pri
< priority
&&
1918 holder
->sched_pri
< priority
) {
1919 KERNEL_DEBUG_CONSTANT(
1920 MACHDBG_CODE(DBG_MACH_SCHED
,MACH_PROMOTE
) | DBG_FUNC_NONE
,
1921 holder
->sched_pri
, priority
,
1922 (int)holder
, (int)mutex
, 0);
1924 set_sched_pri(holder
, priority
);
1927 thread_unlock(holder
);
1930 if (mutex
->promoted_pri
< priority
)
1931 mutex
->promoted_pri
= priority
;
1933 if (thread
->pending_promoter
[thread
->pending_promoter_index
] == NULL
) {
1934 thread
->pending_promoter
[thread
->pending_promoter_index
] = mutex
;
1938 if (thread
->pending_promoter
[thread
->pending_promoter_index
] != mutex
) {
1939 thread
->pending_promoter
[++thread
->pending_promoter_index
] = mutex
;
1943 KERNEL_DEBUG_CONSTANT(
1944 MACHDBG_CODE(DBG_MACH_SCHED
,MACH_PREBLOCK_MUTEX
) | DBG_FUNC_NONE
,
1945 (int)thread
, thread
->sched_pri
, (int)mutex
, 0, 0);
1951 * mutex_pause: Called by former callers of simple_lock_pause().
1957 wait_result_t wait_result
;
1959 wait_result
= assert_wait_timeout( 1, THREAD_UNINT
);
1960 assert(wait_result
== THREAD_WAITING
);
1962 ETAP_SET_REASON(current_thread(), BLOCKED_ON_MUTEX_LOCK
);
1964 wait_result
= thread_block(THREAD_CONTINUE_NULL
);
1965 assert(wait_result
== THREAD_TIMED_OUT
);
1970 * Routines to print out simple_locks and mutexes in a nicely-formatted
1974 char *simple_lock_labels
= "ENTRY ILK THREAD DURATION CALLER";
1975 char *mutex_labels
= "ENTRY LOCKED WAITERS THREAD CALLER";
1978 db_show_one_simple_lock (
1980 boolean_t have_addr
,
1984 simple_lock_t saddr
= (simple_lock_t
)addr
;
1986 if (saddr
== (simple_lock_t
)0 || !have_addr
) {
1987 db_error ("No simple_lock\n");
1990 else if (saddr
->lock_type
!= USLOCK_TAG
)
1991 db_error ("Not a simple_lock\n");
1992 #endif /* USLOCK_DEBUG */
1994 db_printf ("%s\n", simple_lock_labels
);
1995 db_print_simple_lock (saddr
);
1999 db_print_simple_lock (
2003 db_printf ("%08x %3d", addr
, *hw_lock_addr(addr
->interlock
));
2005 db_printf (" %08x", addr
->debug
.lock_thread
);
2006 db_printf (" %08x ", addr
->debug
.duration
[1]);
2007 db_printsym ((int)addr
->debug
.lock_pc
, DB_STGY_ANY
);
2008 #endif /* USLOCK_DEBUG */
2015 boolean_t have_addr
,
2019 mutex_t
* maddr
= (mutex_t
*)addr
;
2021 if (maddr
== (mutex_t
*)0 || !have_addr
)
2022 db_error ("No mutex\n");
2024 else if (maddr
->type
!= MUTEX_TAG
)
2025 db_error ("Not a mutex\n");
2026 #endif /* MACH_LDEBUG */
2028 db_printf ("%s\n", mutex_labels
);
2029 db_print_mutex (maddr
);
2036 db_printf ("%08x %6d %7d",
2037 addr
, *hw_lock_addr(addr
->locked
), addr
->waiters
);
2039 db_printf (" %08x ", addr
->thread
);
2040 db_printsym (addr
->pc
, DB_STGY_ANY
);
2041 #endif /* MACH_LDEBUG */
2044 #endif /* MACH_KDB */
2047 extern void meter_simple_lock (
2049 extern void meter_simple_unlock (
2051 extern void cyctm05_stamp (
2052 unsigned long * start
);
2053 extern void cyctm05_diff (
2054 unsigned long * start
,
2055 unsigned long * end
,
2056 unsigned long * diff
);
2059 simple_lock_data_t loser
;
2067 cyctm05_stamp (lp
->duration
);
2071 int long_simple_lock_crash
;
2072 int long_simple_lock_time
= 0x600;
2074 * This is pretty gawd-awful. XXX
2076 decl_simple_lock_data(extern,kd_tty
)
2079 meter_simple_unlock(
2083 unsigned long stime
[2], etime
[2], delta
[2];
2085 if (lp
== &kd_tty
) /* XXX */
2088 stime
[0] = lp
->duration
[0];
2089 stime
[1] = lp
->duration
[1];
2091 cyctm05_stamp (etime
);
2093 if (etime
[1] < stime
[1]) /* XXX */
2096 cyctm05_diff (stime
, etime
, delta
);
2098 if (delta
[1] >= 0x10000) /* XXX */
2101 lp
->duration
[0] = delta
[0];
2102 lp
->duration
[1] = delta
[1];
2104 if (loser
.duration
[1] < lp
->duration
[1])
2107 assert (!long_simple_lock_crash
|| delta
[1] < long_simple_lock_time
);
2110 #endif /* MACH_LDEBUG */
2116 * ==============================================================
2117 * ETAP hook when initializing a usimple_lock. May be invoked
2118 * from the portable lock package or from an optimized machine-
2119 * dependent implementation.
2120 * ==============================================================
2124 etap_simplelock_init (
2128 ETAP_CLEAR_TRACE_DATA(l
);
2129 etap_event_table_assign(&l
->u
.event_table_chain
, event
);
2131 #if ETAP_LOCK_ACCUMULATE
2132 /* reserve an entry in the cumulative buffer */
2133 l
->cbuff_entry
= etap_cbuff_reserve(lock_event_table(l
));
2134 /* initialize the entry if one was returned */
2135 if (l
->cbuff_entry
!= CBUFF_ENTRY_NULL
) {
2136 l
->cbuff_entry
->event
= event
;
2137 l
->cbuff_entry
->instance
= (unsigned long) l
;
2138 l
->cbuff_entry
->kind
= SPIN_LOCK
;
2140 #endif /* ETAP_LOCK_ACCUMULATE */
2145 etap_simplelock_unlock(
2148 unsigned short dynamic
= 0;
2149 unsigned short trace
= 0;
2150 etap_time_t total_time
;
2151 etap_time_t stop_hold_time
;
2155 ETAP_STAMP(lock_event_table(l
), trace
, dynamic
);
2158 * Calculate & collect hold time data only if
2159 * the hold tracing was enabled throughout the
2160 * whole operation. This prevents collection of
2161 * bogus data caused by mid-operation trace changes.
2165 if (ETAP_DURATION_ENABLED(trace
) && ETAP_WHOLE_OP(l
)) {
2166 ETAP_TIMESTAMP (stop_hold_time
);
2167 ETAP_TOTAL_TIME(total_time
, stop_hold_time
,
2168 l
->u
.s
.start_hold_time
);
2169 CUM_HOLD_ACCUMULATE(l
->cbuff_entry
, total_time
, dynamic
, trace
);
2170 MON_ASSIGN_PC(l
->end_pc
, pc
, trace
);
2178 ETAP_CLEAR_TRACE_DATA(l
);
2181 /* ========================================================================
2182 * Since the the simple_lock() routine is machine dependant, it must always
2183 * be coded in assembly. The two hook routines below are used to collect
2185 * ========================================================================
2189 * ROUTINE: etap_simplelock_miss()
2191 * FUNCTION: This spin lock routine is called upon the first
2192 * spin (miss) of the lock.
2194 * A timestamp is taken at the beginning of the wait period,
2195 * if wait tracing is enabled.
2200 * - timestamp address.
2202 * RETURNS: Wait timestamp value. The timestamp value is later used
2203 * by etap_simplelock_hold().
2205 * NOTES: This routine is NOT ALWAYS called. The lock may be free
2206 * (never spinning). For this reason the pc is collected in
2207 * etap_simplelock_hold().
2211 etap_simplelock_miss (
2215 unsigned short trace
= 0;
2216 unsigned short dynamic
= 0;
2217 etap_time_t start_miss_time
;
2219 ETAP_STAMP(lock_event_table(l
), trace
, dynamic
);
2221 if (trace
& ETAP_CONTENTION
)
2222 ETAP_TIMESTAMP(start_miss_time
);
2224 return(start_miss_time
);
2228 * ROUTINE: etap_simplelock_hold()
2230 * FUNCTION: This spin lock routine is ALWAYS called once the lock
2231 * is acquired. Here, the contention time is calculated and
2232 * the start hold time is stamped.
2236 * - PC of the calling function.
2237 * - start wait timestamp.
2242 etap_simplelock_hold (
2245 etap_time_t start_hold_time
)
2247 unsigned short dynamic
= 0;
2248 unsigned short trace
= 0;
2249 etap_time_t total_time
;
2250 etap_time_t stop_hold_time
;
2252 ETAP_STAMP(lock_event_table(l
), trace
, dynamic
);
2254 MON_ASSIGN_PC(l
->start_pc
, pc
, trace
);
2256 /* do not collect wait data if lock was free */
2257 if (ETAP_TIME_IS_ZERO(start_hold_time
) && (trace
& ETAP_CONTENTION
)) {
2258 ETAP_TIMESTAMP(stop_hold_time
);
2259 ETAP_TOTAL_TIME(total_time
,
2262 CUM_WAIT_ACCUMULATE(l
->cbuff_entry
, total_time
, dynamic
, trace
);
2269 ETAP_COPY_START_HOLD_TIME(&l
->u
.s
, stop_hold_time
, trace
);
2272 ETAP_DURATION_TIMESTAMP(&l
->u
.s
, trace
);
2280 ETAP_CLEAR_TRACE_DATA(l
);
2281 etap_event_table_assign(&l
->u
.event_table_chain
, event
);
2283 #if ETAP_LOCK_ACCUMULATE
2284 /* reserve an entry in the cumulative buffer */
2285 l
->cbuff_entry
= etap_cbuff_reserve(lock_event_table(l
));
2286 /* initialize the entry if one was returned */
2287 if (l
->cbuff_entry
!= CBUFF_ENTRY_NULL
) {
2288 l
->cbuff_entry
->event
= event
;
2289 l
->cbuff_entry
->instance
= (unsigned long) l
;
2290 l
->cbuff_entry
->kind
= MUTEX_LOCK
;
2292 #endif /* ETAP_LOCK_ACCUMULATE */
2299 unsigned short trace
= 0;
2300 unsigned short dynamic
= 0;
2301 etap_time_t start_miss_time
;
2303 ETAP_STAMP(lock_event_table(l
), trace
, dynamic
);
2305 if (trace
& ETAP_CONTENTION
)
2306 ETAP_TIMESTAMP(start_miss_time
);
2308 ETAP_TIME_CLEAR(start_miss_time
);
2310 return(start_miss_time
);
2317 etap_time_t start_hold_time
)
2319 unsigned short dynamic
= 0;
2320 unsigned short trace
= 0;
2321 etap_time_t total_time
;
2322 etap_time_t stop_hold_time
;
2324 ETAP_STAMP(lock_event_table(l
), trace
, dynamic
);
2326 MON_ASSIGN_PC(l
->start_pc
, pc
, trace
);
2328 /* do not collect wait data if lock was free */
2329 if (!ETAP_TIME_IS_ZERO(start_hold_time
) && (trace
& ETAP_CONTENTION
)) {
2330 ETAP_TIMESTAMP(stop_hold_time
);
2331 ETAP_TOTAL_TIME(total_time
,
2334 CUM_WAIT_ACCUMULATE(l
->cbuff_entry
, total_time
, dynamic
, trace
);
2341 ETAP_COPY_START_HOLD_TIME(&l
->u
.s
, stop_hold_time
, trace
);
2344 ETAP_DURATION_TIMESTAMP(&l
->u
.s
, trace
);
2351 unsigned short dynamic
= 0;
2352 unsigned short trace
= 0;
2353 etap_time_t total_time
;
2354 etap_time_t stop_hold_time
;
2358 ETAP_STAMP(lock_event_table(l
), trace
, dynamic
);
2361 * Calculate & collect hold time data only if
2362 * the hold tracing was enabled throughout the
2363 * whole operation. This prevents collection of
2364 * bogus data caused by mid-operation trace changes.
2368 if (ETAP_DURATION_ENABLED(trace
) && ETAP_WHOLE_OP(l
)) {
2369 ETAP_TIMESTAMP(stop_hold_time
);
2370 ETAP_TOTAL_TIME(total_time
, stop_hold_time
,
2371 l
->u
.s
.start_hold_time
);
2372 CUM_HOLD_ACCUMULATE(l
->cbuff_entry
, total_time
, dynamic
, trace
);
2373 MON_ASSIGN_PC(l
->end_pc
, pc
, trace
);
2381 ETAP_CLEAR_TRACE_DATA(l
);
2384 #endif /* ETAP_LOCK_TRACE */