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