Virtio_Balloon implementation for DragonFly
[dragonfly.git] / sys / kern / kern_lock.c
1 /* 
2  * Copyright (c) 1995
3  *      The Regents of the University of California.  All rights reserved.
4  * Copyright (C) 1997
5  *      John S. Dyson.  All rights reserved.
6  * Copyright (C) 2013-2017
7  *      Matthew Dillon, All rights reserved.
8  *
9  * This code contains ideas from software contributed to Berkeley by
10  * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating
11  * System project at Carnegie-Mellon University.
12  *
13  * This code is derived from software contributed to The DragonFly Project
14  * by Matthew Dillon <dillon@backplane.com>.  Extensively rewritten.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  * 3. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  */
40
41 #include "opt_lint.h"
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/proc.h>
47 #include <sys/lock.h>
48 #include <sys/sysctl.h>
49 #include <sys/spinlock.h>
50 #include <sys/thread2.h>
51 #include <sys/spinlock2.h>
52 #include <sys/indefinite2.h>
53
54 static void undo_shreq(struct lock *lkp);
55 static int undo_upreq(struct lock *lkp);
56 static int undo_exreq(struct lock *lkp);
57
58 #ifdef DEBUG_CANCEL_LOCKS
59
60 static int sysctl_cancel_lock(SYSCTL_HANDLER_ARGS);
61 static int sysctl_cancel_test(SYSCTL_HANDLER_ARGS);
62
63 static struct lock cancel_lk;
64 LOCK_SYSINIT(cancellk, &cancel_lk, "cancel", 0);
65 SYSCTL_PROC(_kern, OID_AUTO, cancel_lock, CTLTYPE_INT|CTLFLAG_RW, 0, 0,
66             sysctl_cancel_lock, "I", "test cancelable locks");
67 SYSCTL_PROC(_kern, OID_AUTO, cancel_test, CTLTYPE_INT|CTLFLAG_RW, 0, 0,
68             sysctl_cancel_test, "I", "test cancelable locks");
69
70 #endif
71
72 int lock_test_mode;
73 SYSCTL_INT(_debug, OID_AUTO, lock_test_mode, CTLFLAG_RW,
74            &lock_test_mode, 0, "");
75
76 /*
77  * Locking primitives implementation.
78  * Locks provide shared/exclusive sychronization.
79  */
80
81 #ifdef DEBUG_LOCKS
82 #define COUNT(td, x) (td)->td_locks += (x)
83 #else
84 #define COUNT(td, x) do { } while (0)
85 #endif
86
87 /*
88  * Helper, assert basic conditions
89  */
90 static __inline void
91 _lockmgr_assert(struct lock *lkp, u_int flags)
92 {
93         if (mycpu->gd_intr_nesting_level &&
94             (flags & LK_NOWAIT) == 0 &&
95             (flags & LK_TYPE_MASK) != LK_RELEASE &&
96             panic_cpu_gd != mycpu
97         ) {
98                 panic("lockmgr %s from %p: called from interrupt, ipi, "
99                       "or hard code section",
100                       lkp->lk_wmesg, ((int **)&lkp)[-1]);
101         }
102 }
103
104 /*
105  * Acquire a shared lock
106  */
107 int
108 lockmgr_shared(struct lock *lkp, u_int flags)
109 {
110         uint32_t extflags;
111         thread_t td;
112         uint64_t count;
113         int error;
114         int pflags;
115         int timo;
116         int didloop;
117
118         _lockmgr_assert(lkp, flags);
119         extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
120         td = curthread;
121
122         count = lkp->lk_count;
123         cpu_ccfence();
124
125         /*
126          * If the caller already holds the lock exclusively then
127          * we silently obtain another count on the exclusive lock.
128          * Avoid accessing lk_lockholder until testing exclusivity.
129          *
130          * WARNING!  The old FreeBSD behavior was to downgrade,
131          *           but this creates a problem when recursions
132          *           return to the caller and the caller expects
133          *           its original exclusive lock to remain exclusively
134          *           locked.
135          */
136         if ((count & LKC_XMASK) && lkp->lk_lockholder == td) {
137                 KKASSERT(lkp->lk_count & LKC_XMASK);
138                 if ((extflags & LK_CANRECURSE) == 0) {
139                         if (extflags & LK_NOWAIT)
140                                 return EBUSY;
141                         panic("lockmgr: locking against myself");
142                 }
143                 atomic_add_64(&lkp->lk_count, 1);
144                 COUNT(td, 1);
145                 return 0;
146         }
147
148         /*
149          * Unless TDF_DEADLKTREAT is set, we cannot add LKC_SCOUNT while
150          * SHARED is set and either EXREQ or UPREQ are set.
151          *
152          * NOTE: In the race-to-0 case (see undo_shreq()), we could
153          *       theoretically work the SMASK == 0 case here.
154          */
155         if ((td->td_flags & TDF_DEADLKTREAT) == 0) {
156                 while ((count & LKC_SHARED) &&
157                        (count & (LKC_EXREQ | LKC_UPREQ))) {
158                         /*
159                          * Immediate failure conditions
160                          */
161                         if (extflags & LK_CANCELABLE) {
162                                 if (count & LKC_CANCEL)
163                                         return ENOLCK;
164                         }
165                         if (extflags & LK_NOWAIT)
166                                 return EBUSY;
167
168                         /*
169                          * Interlocked tsleep
170                          */
171                         pflags = (extflags & LK_PCATCH) ? PCATCH : 0;
172                         timo = (extflags & LK_TIMELOCK) ? lkp->lk_timo : 0;
173
174                         tsleep_interlock(lkp, pflags);
175                         count = atomic_fetchadd_long(&lkp->lk_count, 0);
176
177                         if ((count & LKC_SHARED) &&
178                             (count & (LKC_EXREQ | LKC_UPREQ))) {
179                                 error = tsleep(lkp, pflags | PINTERLOCKED,
180                                                lkp->lk_wmesg, timo);
181                                 if (error)
182                                         return error;
183                                 count = lkp->lk_count;
184                                 cpu_ccfence();
185                                 continue;
186                         }
187                         break;
188                 }
189         }
190
191         /*
192          * Bump the SCOUNT field.  The shared lock is granted only once
193          * the SHARED flag gets set.  If it is already set, we are done.
194          *
195          * (Racing an EXREQ or UPREQ operation is ok here, we already did
196          * our duty above).
197          */
198         count = atomic_fetchadd_64(&lkp->lk_count, LKC_SCOUNT) + LKC_SCOUNT;
199         error = 0;
200         didloop = 0;
201
202         for (;;) {
203                 /*
204                  * We may be able to grant ourselves the bit trivially.
205                  * We're done once the SHARED bit is granted.
206                  */
207                 if ((count & (LKC_XMASK | LKC_EXREQ |
208                               LKC_UPREQ | LKC_SHARED)) == 0) {
209                         if (atomic_fcmpset_64(&lkp->lk_count,
210                                               &count, count | LKC_SHARED)) {
211                                 /* count |= LKC_SHARED; NOT USED */
212                                 break;
213                         }
214                         continue;
215                 }
216                 if ((td->td_flags & TDF_DEADLKTREAT) &&
217                     (count & (LKC_XMASK | LKC_SHARED)) == 0) {
218                         if (atomic_fcmpset_64(&lkp->lk_count,
219                                               &count, count | LKC_SHARED)) {
220                                 /* count |= LKC_SHARED; NOT USED */
221                                 break;
222                         }
223                         continue;
224                 }
225                 if (count & LKC_SHARED)
226                         break;
227
228                 /*
229                  * Slow path
230                  */
231                 pflags = (extflags & LK_PCATCH) ? PCATCH : 0;
232                 timo = (extflags & LK_TIMELOCK) ? lkp->lk_timo : 0;
233
234                 if (extflags & LK_CANCELABLE) {
235                         if (count & LKC_CANCEL) {
236                                 undo_shreq(lkp);
237                                 error = ENOLCK;
238                                 break;
239                         }
240                 }
241                 if (extflags & LK_NOWAIT) {
242                         undo_shreq(lkp);
243                         error = EBUSY;
244                         break;
245                 }
246
247                 /*
248                  * Interlocked after the first loop.
249                  */
250                 if (didloop) {
251                         error = tsleep(lkp, pflags | PINTERLOCKED,
252                                        lkp->lk_wmesg, timo);
253                         if (extflags & LK_SLEEPFAIL) {
254                                 undo_shreq(lkp);
255                                 error = ENOLCK;
256                                 break;
257                         }
258                         if (error) {
259                                 undo_shreq(lkp);
260                                 break;
261                         }
262                 }
263                 didloop = 1;
264
265                 /*
266                  * Reload, shortcut grant case, then loop interlock
267                  * and loop.
268                  */
269                 count = lkp->lk_count;
270                 if (count & LKC_SHARED)
271                         break;
272                 tsleep_interlock(lkp, pflags);
273                 count = atomic_fetchadd_64(&lkp->lk_count, 0);
274         }
275         if (error == 0)
276                 COUNT(td, 1);
277
278         return error;
279 }
280
281 /*
282  * Acquire an exclusive lock
283  */
284 int
285 lockmgr_exclusive(struct lock *lkp, u_int flags)
286 {
287         uint64_t count;
288         uint64_t ncount;
289         uint32_t extflags;
290         thread_t td;
291         int error;
292         int pflags;
293         int timo;
294
295         _lockmgr_assert(lkp, flags);
296         extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
297         td = curthread;
298
299         error = 0;
300         count = lkp->lk_count;
301         cpu_ccfence();
302
303         /*
304          * Recursive lock if we already hold it exclusively.  Avoid testing
305          * lk_lockholder until after testing lk_count.
306          */
307         if ((count & LKC_XMASK) && lkp->lk_lockholder == td) {
308                 if ((extflags & LK_CANRECURSE) == 0) {
309                         if (extflags & LK_NOWAIT)
310                                 return EBUSY;
311                         panic("lockmgr: locking against myself");
312                 }
313                 count = atomic_fetchadd_64(&lkp->lk_count, 1) + 1;
314                 KKASSERT((count & LKC_XMASK) > 1);
315                 COUNT(td, 1);
316                 return 0;
317         }
318
319         /*
320          * Trivially acquire the lock, or block until we can set EXREQ.
321          * Set EXREQ2 if EXREQ is already set or the lock is already
322          * held exclusively.  EXREQ2 is an aggregation bit to request
323          * a wakeup.
324          *
325          * WARNING! We cannot set EXREQ if the lock is already held
326          *          exclusively because it may race another EXREQ
327          *          being cleared and granted.  We use the exclusivity
328          *          to prevent both EXREQ and UPREQ from being set.
329          *
330          *          This means that both shared and exclusive requests
331          *          have equal priority against a current exclusive holder's
332          *          release.  Exclusive requests still have priority over
333          *          new shared requests when the lock is already held shared.
334          */
335         for (;;) {
336                 /*
337                  * Normal trivial case
338                  */
339                 if ((count & (LKC_UPREQ | LKC_EXREQ |
340                               LKC_XMASK)) == 0 &&
341                     ((count & LKC_SHARED) == 0 ||
342                      (count & LKC_SMASK) == 0)) {
343                         ncount = (count + 1) & ~LKC_SHARED;
344                         if (atomic_fcmpset_64(&lkp->lk_count,
345                                               &count, ncount)) {
346                                 lkp->lk_lockholder = td;
347                                 COUNT(td, 1);
348                                 return 0;
349                         }
350                         continue;
351                 }
352
353                 if (extflags & LK_CANCELABLE) {
354                         if (count & LKC_CANCEL)
355                                 return ENOLCK;
356                 }
357                 if (extflags & LK_NOWAIT)
358                         return EBUSY;
359
360                 /*
361                  * Interlock to set EXREQ or EXREQ2
362                  */
363                 pflags = (extflags & LK_PCATCH) ? PCATCH : 0;
364                 timo = (extflags & LK_TIMELOCK) ? lkp->lk_timo : 0;
365
366                 if (count & (LKC_EXREQ | LKC_XMASK))
367                         ncount = count | LKC_EXREQ2;
368                 else
369                         ncount = count | LKC_EXREQ;
370                 tsleep_interlock(lkp, pflags);
371                 if (atomic_fcmpset_64(&lkp->lk_count, &count, ncount)) {
372                         /*
373                          * If we successfully transitioned to EXREQ we
374                          * can break out, otherwise we had set EXREQ2 and
375                          * we block.
376                          */
377                         if ((count & (LKC_EXREQ | LKC_XMASK)) == 0) {
378                                 count = ncount;
379                                 break;
380                         }
381
382                         error = tsleep(lkp, pflags | PINTERLOCKED,
383                                        lkp->lk_wmesg, timo);
384                         count = lkp->lk_count;  /* relod */
385                         cpu_ccfence();
386                 }
387 #ifdef INVARIANTS
388                 if (lock_test_mode > 0) {
389                         --lock_test_mode;
390                         print_backtrace(8);
391                 }
392 #endif
393                 if (error)
394                         return error;
395                 if (extflags & LK_SLEEPFAIL)
396                         return ENOLCK;
397         }
398
399         /*
400          * Once EXREQ has been set, wait for it to be granted
401          * We enter the loop with tsleep_interlock() already called.
402          */
403         for (;;) {
404                 /*
405                  * Waiting for EXREQ to be granted to us.
406                  *
407                  * NOTE! If we try to trivially get the exclusive lock
408                  *       (basically by racing undo_shreq()) and succeed,
409                  *       we must still wakeup(lkp) for another exclusive
410                  *       lock trying to acquire EXREQ.  Easier to simply
411                  *       wait for our own wakeup.
412                  */
413                 if ((count & LKC_EXREQ) == 0) {
414                         KKASSERT(count & LKC_XMASK);
415                         lkp->lk_lockholder = td;
416                         COUNT(td, 1);
417                         break;
418                 }
419
420                 /*
421                  * Block waiting for our exreq to be granted.
422                  * Check cancelation.  NOWAIT was already dealt with.
423                  */
424                 if (extflags & LK_CANCELABLE) {
425                         if (count & LKC_CANCEL) {
426                                 if (undo_exreq(lkp) == 0) {
427                                         lkp->lk_lockholder = LK_KERNTHREAD;
428                                         lockmgr_release(lkp, 0);
429                                 }
430                                 error = ENOLCK;
431                                 break;
432                         }
433                 }
434
435                 pflags = (extflags & LK_PCATCH) ? PCATCH : 0;
436                 timo = (extflags & LK_TIMELOCK) ? lkp->lk_timo : 0;
437
438                 error = tsleep(lkp, pflags | PINTERLOCKED, lkp->lk_wmesg, timo);
439 #ifdef INVARIANTS
440                 if (lock_test_mode > 0) {
441                         --lock_test_mode;
442                         print_backtrace(8);
443                 }
444 #endif
445                 /*
446                  * A tsleep error is uncommon.  If it occurs we have to
447                  * undo our EXREQ.  If we are granted the exclusive lock
448                  * as we try to undo we have to deal with it.
449                  */
450                 if (extflags & LK_SLEEPFAIL) {
451                         if (undo_exreq(lkp) == 0) {
452                                 lkp->lk_lockholder = LK_KERNTHREAD;
453                                 lockmgr_release(lkp, 0);
454                         }
455                         if (error == 0)
456                                 error = ENOLCK;
457                         break;
458                 }
459                 if (error) {
460                         if (undo_exreq(lkp))
461                                 break;
462                         lkp->lk_lockholder = td;
463                         COUNT(td, 1);
464                         error = 0;
465                         break;
466                 }
467
468                 /*
469                  * Reload after sleep, shortcut grant case.
470                  * Then set the interlock and loop.
471                  */
472                 count = lkp->lk_count;
473                 cpu_ccfence();
474                 if ((count & LKC_EXREQ) == 0) {
475                         KKASSERT(count & LKC_XMASK);
476                         lkp->lk_lockholder = td;
477                         COUNT(td, 1);
478                         break;
479                 }
480                 tsleep_interlock(lkp, pflags);
481                 count = atomic_fetchadd_64(&lkp->lk_count, 0);
482         }
483         return error;
484 }
485
486 /*
487  * Downgrade an exclusive lock to shared.
488  *
489  * This function always succeeds as long as the caller owns a legal
490  * exclusive lock with one reference.  UPREQ and EXREQ is ignored.
491  */
492 int
493 lockmgr_downgrade(struct lock *lkp, u_int flags)
494 {
495         uint64_t count;
496         uint64_t ncount;
497         uint32_t extflags;
498         thread_t otd;
499         thread_t td;
500
501         extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
502         td = curthread;
503         count = lkp->lk_count;
504
505         for (;;) {
506                 cpu_ccfence();
507
508                 /*
509                  * Downgrade an exclusive lock into a shared lock.  All
510                  * counts on a recursive exclusive lock become shared.
511                  *
512                  * NOTE: Currently to reduce confusion we only allow
513                  *       there to be one exclusive lock count, and panic
514                  *       if there are more.
515                  */
516                 if (lkp->lk_lockholder != td || (count & LKC_XMASK) != 1) {
517                         panic("lockmgr: not holding exclusive lock: "
518                               "%p/%p %016jx", lkp->lk_lockholder, td, count);
519                 }
520
521                 /*
522                  * NOTE! Must NULL-out lockholder before releasing the
523                  *       exclusive lock.
524                  *
525                  * NOTE! There might be pending shared requests, check
526                  *       and wake them up.
527                  */
528                 otd = lkp->lk_lockholder;
529                 lkp->lk_lockholder = NULL;
530                 ncount = (count & ~(LKC_XMASK | LKC_EXREQ2)) +
531                          ((count & LKC_XMASK) << LKC_SSHIFT);
532                 ncount |= LKC_SHARED;
533
534                 if (atomic_fcmpset_64(&lkp->lk_count, &count, ncount)) {
535                         /*
536                          * Wakeup any shared waiters (prior SMASK), or
537                          * any exclusive requests that couldn't set EXREQ
538                          * because the lock had been held exclusively.
539                          */
540                         if (count & (LKC_SMASK | LKC_EXREQ2))
541                                 wakeup(lkp);
542                         /* count = ncount; NOT USED */
543                         break;
544                 }
545                 lkp->lk_lockholder = otd;
546                 /* retry */
547         }
548         return 0;
549 }
550
551 /*
552  * Upgrade a shared lock to exclusive.  If LK_EXCLUPGRADE then guarantee
553  * that no other exclusive requester can get in front of us and fail
554  * immediately if another upgrade is pending.  If we fail, the shared
555  * lock is released.
556  *
557  * If LK_EXCLUPGRADE is not set and we cannot upgrade because someone
558  * else is in front of us, we release the shared lock and acquire the
559  * exclusive lock normally.  If a failure occurs, the shared lock is
560  * released.
561  */
562 int
563 lockmgr_upgrade(struct lock *lkp, u_int flags)
564 {
565         uint64_t count;
566         uint64_t ncount;
567         uint32_t extflags;
568         thread_t td;
569         int error;
570         int pflags;
571         int timo;
572
573         _lockmgr_assert(lkp, flags);
574         extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
575         td = curthread;
576         error = 0;
577         count = lkp->lk_count;
578         cpu_ccfence();
579
580         /*
581          * If we already hold the lock exclusively this operation
582          * succeeds and is a NOP.
583          */
584         if (count & LKC_XMASK) {
585                 if (lkp->lk_lockholder == td)
586                         return 0;
587                 panic("lockmgr: upgrade unowned lock");
588         }
589         if ((count & LKC_SMASK) == 0)
590                 panic("lockmgr: upgrade unowned lock");
591
592         /*
593          * Loop to acquire LKC_UPREQ
594          */
595         for (;;) {
596                 /*
597                  * If UPREQ is already pending, release the shared lock
598                  * and acquire an exclusive lock normally.
599                  *
600                  * If NOWAIT or EXCLUPGRADE the operation must be atomic,
601                  * and this isn't, so we fail.
602                  */
603                 if (count & LKC_UPREQ) {
604                         lockmgr_release(lkp, 0);
605                         if ((flags & LK_TYPE_MASK) == LK_EXCLUPGRADE)
606                                 error = EBUSY;
607                         else if (extflags & LK_NOWAIT)
608                                 error = EBUSY;
609                         else
610                                 error = lockmgr_exclusive(lkp, flags);
611                         return error;
612                 }
613
614                 /*
615                  * Try to immediately grant the upgrade, handle NOWAIT,
616                  * or release the shared lock and simultaneously set UPREQ.
617                  */
618                 if ((count & LKC_SMASK) == LKC_SCOUNT) {
619                         /*
620                          * Immediate grant
621                          */
622                         ncount = (count - LKC_SCOUNT + 1) & ~LKC_SHARED;
623                         if (atomic_fcmpset_64(&lkp->lk_count, &count, ncount)) {
624                                 lkp->lk_lockholder = td;
625                                 return 0;
626                         }
627                 } else if (extflags & LK_NOWAIT) {
628                         /*
629                          * Early EBUSY if an immediate grant is impossible
630                          */
631                         lockmgr_release(lkp, 0);
632                         return EBUSY;
633                 } else {
634                         /*
635                          * Multiple shared locks present, request the
636                          * upgrade and break to the next loop.
637                          */
638                         pflags = (extflags & LK_PCATCH) ? PCATCH : 0;
639                         tsleep_interlock(lkp, pflags);
640                         ncount = (count - LKC_SCOUNT) | LKC_UPREQ;
641                         if (atomic_fcmpset_64(&lkp->lk_count, &count, ncount)) {
642                                 count = ncount;
643                                 break;
644                         }
645                 }
646                 /* retry */
647         }
648
649         /*
650          * We have acquired LKC_UPREQ, wait until the upgrade is granted
651          * or the tsleep fails.
652          *
653          * NOWAIT and EXCLUPGRADE have already been handled.  The first
654          * tsleep_interlock() has already been associated.
655          */
656         for (;;) {
657                 cpu_ccfence();
658
659                 /*
660                  * We were granted our upgrade.  No other UPREQ can be
661                  * made pending because we are now exclusive.
662                  */
663                 if ((count & LKC_UPREQ) == 0) {
664                         KKASSERT((count & LKC_XMASK) == 1);
665                         lkp->lk_lockholder = td;
666                         break;
667                 }
668
669                 if (extflags & LK_CANCELABLE) {
670                         if (count & LKC_CANCEL) {
671                                 if (undo_upreq(lkp) == 0) {
672                                         lkp->lk_lockholder = LK_KERNTHREAD;
673                                         lockmgr_release(lkp, 0);
674                                 }
675                                 error = ENOLCK;
676                                 break;
677                         }
678                 }
679
680                 pflags = (extflags & LK_PCATCH) ? PCATCH : 0;
681                 timo = (extflags & LK_TIMELOCK) ? lkp->lk_timo : 0;
682
683                 error = tsleep(lkp, pflags | PINTERLOCKED, lkp->lk_wmesg, timo);
684                 if (extflags & LK_SLEEPFAIL) {
685                         if (undo_upreq(lkp) == 0) {
686                                 lkp->lk_lockholder = LK_KERNTHREAD;
687                                 lockmgr_release(lkp, 0);
688                         }
689                         if (error == 0)
690                                 error = ENOLCK;
691                         break;
692                 }
693                 if (error) {
694                         if (undo_upreq(lkp))
695                                 break;
696                         error = 0;
697                 }
698
699                 /*
700                  * Reload the lock, short-cut the UPGRANT code before
701                  * taking the time to interlock and loop.
702                  */
703                 count = lkp->lk_count;
704                 if ((count & LKC_UPREQ) == 0) {
705                         KKASSERT((count & LKC_XMASK) == 1);
706                         lkp->lk_lockholder = td;
707                         break;
708                 }
709                 tsleep_interlock(lkp, pflags);
710                 count = atomic_fetchadd_64(&lkp->lk_count, 0);
711                 /* retry */
712         }
713         return error;
714 }
715
716 /*
717  * Release a held lock
718  *
719  * NOTE: When releasing to an unlocked state, we set the SHARED bit
720  *       to optimize shared lock requests.
721  */
722 int
723 lockmgr_release(struct lock *lkp, u_int flags)
724 {
725         uint64_t count;
726         uint64_t ncount;
727         uint32_t extflags;
728         thread_t otd;
729         thread_t td;
730
731         extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK;
732         td = curthread;
733
734         count = lkp->lk_count;
735         cpu_ccfence();
736
737         for (;;) {
738                 /*
739                  * Release the currently held lock, grant all requests
740                  * possible.
741                  *
742                  * WARNING! lksleep() assumes that LK_RELEASE does not
743                  *          block.
744                  *
745                  * Always succeeds.
746                  * Never blocks.
747                  */
748                 if ((count & (LKC_SMASK | LKC_XMASK)) == 0)
749                         panic("lockmgr: LK_RELEASE: no lock held");
750
751                 if (count & LKC_XMASK) {
752                         /*
753                          * Release exclusively held lock
754                          */
755                         if (lkp->lk_lockholder != LK_KERNTHREAD &&
756                             lkp->lk_lockholder != td) {
757                                 panic("lockmgr: pid %d, not exclusive "
758                                       "lock holder thr %p/%p unlocking",
759                                     (td->td_proc ? td->td_proc->p_pid : -1),
760                                     td, lkp->lk_lockholder);
761                         }
762                         if ((count & (LKC_UPREQ | LKC_EXREQ |
763                                       LKC_XMASK)) == 1) {
764                                 /*
765                                  * Last exclusive count is being released
766                                  * with no UPREQ or EXREQ.  The SHARED
767                                  * bit can be set or not without messing
768                                  * anything up, so precondition it to
769                                  * SHARED (which is the most cpu-optimal).
770                                  *
771                                  * Wakeup any EXREQ2.  EXREQ cannot be
772                                  * set while an exclusive count is present
773                                  * so we have to wakeup any EXREQ2 we find.
774                                  *
775                                  * We could hint the EXREQ2 by leaving
776                                  * SHARED unset, but atm I don't see any
777                                  * usefulness.
778                                  */
779                                 otd = lkp->lk_lockholder;
780                                 lkp->lk_lockholder = NULL;
781                                 ncount = (count - 1);
782                                 ncount &= ~(LKC_CANCEL | LKC_EXREQ2);
783                                 ncount |= LKC_SHARED;
784                                 if (atomic_fcmpset_64(&lkp->lk_count,
785                                                       &count, ncount)) {
786                                         if (count & (LKC_SMASK | LKC_EXREQ2))
787                                                 wakeup(lkp);
788                                         if (otd != LK_KERNTHREAD)
789                                                 COUNT(td, -1);
790                                         /* count = ncount; NOT USED */
791                                         break;
792                                 }
793                                 lkp->lk_lockholder = otd;
794                                 /* retry */
795                         } else if ((count & (LKC_UPREQ | LKC_XMASK)) ==
796                                    (LKC_UPREQ | 1)) {
797                                 /*
798                                  * Last exclusive count is being released but
799                                  * an upgrade request is present, automatically
800                                  * grant an exclusive state to the owner of
801                                  * the upgrade request.  Transfer count to
802                                  * grant.
803                                  *
804                                  * EXREQ cannot be set while an exclusive
805                                  * holder exists, so do not clear EXREQ2.
806                                  */
807                                 otd = lkp->lk_lockholder;
808                                 lkp->lk_lockholder = NULL;
809                                 ncount = count & ~LKC_UPREQ;
810                                 if (atomic_fcmpset_64(&lkp->lk_count,
811                                                       &count, ncount)) {
812                                         wakeup(lkp);
813                                         if (otd != LK_KERNTHREAD)
814                                                 COUNT(td, -1);
815                                         /* count = ncount; NOT USED */
816                                         break;
817                                 }
818                                 lkp->lk_lockholder = otd;
819                                 /* retry */
820                         } else if ((count & (LKC_EXREQ | LKC_XMASK)) ==
821                                    (LKC_EXREQ | 1)) {
822                                 /*
823                                  * Last exclusive count is being released but
824                                  * an exclusive request is present.  We
825                                  * automatically grant an exclusive state to
826                                  * the owner of the exclusive request,
827                                  * transfering our count.
828                                  *
829                                  * This case virtually never occurs because
830                                  * EXREQ is not set while exclusive holders
831                                  * exist.  However, it might be set if a
832                                  * an exclusive request is pending and a
833                                  * shared holder upgrades.
834                                  *
835                                  * Don't bother clearing EXREQ2.  A thread
836                                  * waiting to set EXREQ can't do it while
837                                  * an exclusive lock is present.
838                                  */
839                                 otd = lkp->lk_lockholder;
840                                 lkp->lk_lockholder = NULL;
841                                 ncount = count & ~LKC_EXREQ;
842                                 if (atomic_fcmpset_64(&lkp->lk_count,
843                                                       &count, ncount)) {
844                                         wakeup(lkp);
845                                         if (otd != LK_KERNTHREAD)
846                                                 COUNT(td, -1);
847                                         /* count = ncount; NOT USED */
848                                         break;
849                                 }
850                                 lkp->lk_lockholder = otd;
851                                 /* retry */
852                         } else {
853                                 /*
854                                  * Multiple exclusive counts, drop by 1.
855                                  * Since we are the holder and there is more
856                                  * than one count, we can just decrement it.
857                                  */
858                                 count =
859                                     atomic_fetchadd_long(&lkp->lk_count, -1);
860                                 /* count = count - 1  NOT NEEDED */
861                                 if (lkp->lk_lockholder != LK_KERNTHREAD)
862                                         COUNT(td, -1);
863                                 break;
864                         }
865                         /* retry */
866                 } else {
867                         /*
868                          * Release shared lock
869                          */
870                         KKASSERT((count & LKC_SHARED) && (count & LKC_SMASK));
871                         if ((count & (LKC_EXREQ | LKC_UPREQ | LKC_SMASK)) ==
872                             LKC_SCOUNT) {
873                                 /*
874                                  * Last shared count is being released,
875                                  * no exclusive or upgrade request present.
876                                  * Generally leave the shared bit set.
877                                  * Clear the CANCEL bit.
878                                  */
879                                 ncount = (count - LKC_SCOUNT) & ~LKC_CANCEL;
880                                 if (atomic_fcmpset_64(&lkp->lk_count,
881                                                       &count, ncount)) {
882                                         COUNT(td, -1);
883                                         /* count = ncount; NOT USED */
884                                         break;
885                                 }
886                                 /* retry */
887                         } else if ((count & (LKC_UPREQ | LKC_SMASK)) ==
888                                    (LKC_UPREQ | LKC_SCOUNT)) {
889                                 /*
890                                  * Last shared count is being released but
891                                  * an upgrade request is present, automatically
892                                  * grant an exclusive state to the owner of
893                                  * the upgrade request and transfer the count.
894                                  */
895                                 ncount = (count - LKC_SCOUNT + 1) &
896                                          ~(LKC_UPREQ | LKC_CANCEL | LKC_SHARED);
897                                 if (atomic_fcmpset_64(&lkp->lk_count,
898                                                       &count, ncount)) {
899                                         wakeup(lkp);
900                                         COUNT(td, -1);
901                                         /* count = ncount; NOT USED */
902                                         break;
903                                 }
904                                 /* retry */
905                         } else if ((count & (LKC_EXREQ | LKC_SMASK)) ==
906                                    (LKC_EXREQ | LKC_SCOUNT)) {
907                                 /*
908                                  * Last shared count is being released but
909                                  * an exclusive request is present, we
910                                  * automatically grant an exclusive state to
911                                  * the owner of the request and transfer
912                                  * the count.
913                                  */
914                                 ncount = (count - LKC_SCOUNT + 1) &
915                                          ~(LKC_EXREQ | LKC_EXREQ2 |
916                                            LKC_CANCEL | LKC_SHARED);
917                                 if (atomic_fcmpset_64(&lkp->lk_count,
918                                                       &count, ncount)) {
919                                         wakeup(lkp);
920                                         COUNT(td, -1);
921                                         /* count = ncount; NOT USED */
922                                         break;
923                                 }
924                                 /* retry */
925                         } else {
926                                 /*
927                                  * Shared count is greater than 1.  We can
928                                  * just use undo_shreq() to clean things up.
929                                  * undo_shreq() will also handle races to 0
930                                  * after the fact.
931                                  */
932                                 undo_shreq(lkp);
933                                 COUNT(td, -1);
934                                 break;
935                         }
936                         /* retry */
937                 }
938                 /* retry */
939         }
940         return 0;
941 }
942
943 /*
944  * Start canceling blocked requesters or later requestors.
945  * Only blocked requesters using CANCELABLE can be canceled.
946  *
947  * This is intended to then allow other requesters (usually the
948  * caller) to obtain a non-cancelable lock.
949  *
950  * Don't waste time issuing a wakeup if nobody is pending.
951  */
952 int
953 lockmgr_cancel_beg(struct lock *lkp, u_int flags)
954 {
955         uint64_t count;
956
957         count = lkp->lk_count;
958         for (;;) {
959                 cpu_ccfence();
960
961                 KKASSERT((count & LKC_CANCEL) == 0);    /* disallowed case */
962
963                 /* issue w/lock held */
964                 KKASSERT((count & (LKC_XMASK | LKC_SMASK)) != 0);
965
966                 if (!atomic_fcmpset_64(&lkp->lk_count,
967                                        &count, count | LKC_CANCEL)) {
968                         continue;
969                 }
970                 /* count |= LKC_CANCEL; NOT USED */
971
972                 /*
973                  * Wakeup any waiters.
974                  *
975                  * NOTE: EXREQ2 only matters when EXREQ is set, so don't
976                  *       bother checking EXREQ2.
977                  */
978                 if (count & (LKC_EXREQ | LKC_SMASK | LKC_UPREQ)) {
979                         wakeup(lkp);
980                 }
981                 break;
982         }
983         return 0;
984 }
985
986 /*
987  * End our cancel request (typically after we have acquired
988  * the lock ourselves).
989  */
990 int
991 lockmgr_cancel_end(struct lock *lkp, u_int flags)
992 {
993         atomic_clear_long(&lkp->lk_count, LKC_CANCEL);
994
995         return 0;
996 }
997
998 /*
999  * Backout SCOUNT from a failed shared lock attempt and handle any race
1000  * to 0.  This function is also used by the release code for the less
1001  * optimal race to 0 case.
1002  *
1003  * WARNING! Since we are unconditionally decrementing LKC_SCOUNT, it is
1004  *          possible for the lock to get into a LKC_SHARED + ZERO SCOUNT
1005  *          situation.  A shared request can block with a ZERO SCOUNT if
1006  *          EXREQ or UPREQ is pending in this situation.  Be sure to always
1007  *          issue a wakeup() in this situation if we are unable to
1008  *          transition to an exclusive lock, to handle the race.
1009  *
1010  * Always succeeds
1011  * Must not block
1012  */
1013 static void
1014 undo_shreq(struct lock *lkp)
1015 {
1016         uint64_t count;
1017         uint64_t ncount;
1018
1019         count = atomic_fetchadd_64(&lkp->lk_count, -LKC_SCOUNT) - LKC_SCOUNT;
1020         while ((count & (LKC_EXREQ | LKC_UPREQ | LKC_CANCEL)) &&
1021                (count & (LKC_SMASK | LKC_XMASK)) == 0) {
1022                 /*
1023                  * Note that UPREQ must have priority over EXREQ, and EXREQ
1024                  * over CANCEL, so if the atomic op fails we have to loop up.
1025                  */
1026                 if (count & LKC_UPREQ) {
1027                         ncount = (count + 1) & ~(LKC_UPREQ | LKC_CANCEL |
1028                                                  LKC_SHARED);
1029                         if (atomic_fcmpset_64(&lkp->lk_count, &count, ncount)) {
1030                                 wakeup(lkp);
1031                                 /* count = ncount; NOT USED */
1032                                 break;
1033                         }
1034                         wakeup(lkp);
1035                         continue;
1036                 }
1037                 if (count & LKC_EXREQ) {
1038                         ncount = (count + 1) & ~(LKC_EXREQ | LKC_EXREQ2 |
1039                                                  LKC_CANCEL | LKC_SHARED);
1040                         if (atomic_fcmpset_64(&lkp->lk_count, &count, ncount)) {
1041                                 wakeup(lkp);
1042                                 /* count = ncount; NOT USED */
1043                                 break;
1044                         }
1045                         wakeup(lkp);
1046                         continue;
1047                 }
1048                 if (count & LKC_CANCEL) {
1049                         ncount = count & ~LKC_CANCEL;
1050                         if (atomic_fcmpset_64(&lkp->lk_count, &count, ncount)) {
1051                                 wakeup(lkp);
1052                                 /* count = ncount; NOT USED */
1053                                 break;
1054                         }
1055                 }
1056                 /* retry */
1057         }
1058 }
1059
1060 /*
1061  * Undo an exclusive request.  Returns EBUSY if we were able to undo the
1062  * request, and 0 if the request was granted before we could undo it.
1063  * When 0 is returned, the lock state has not been modified.  The caller
1064  * is responsible for setting the lockholder to curthread.
1065  */
1066 static
1067 int
1068 undo_exreq(struct lock *lkp)
1069 {
1070         uint64_t count;
1071         uint64_t ncount;
1072         int error;
1073
1074         count = lkp->lk_count;
1075         error = 0;
1076
1077         for (;;) {
1078                 cpu_ccfence();
1079
1080                 if ((count & LKC_EXREQ) == 0) {
1081                         /*
1082                          * EXREQ was granted.  We own the exclusive lock.
1083                          */
1084                         break;
1085                 }
1086                 if (count & LKC_XMASK) {
1087                         /*
1088                          * Clear the EXREQ we still own.  Only wakeup on
1089                          * EXREQ2 if no UPREQ.  There are still exclusive
1090                          * holders so do not wake up any shared locks or
1091                          * any UPREQ.
1092                          *
1093                          * If there is an UPREQ it will issue a wakeup()
1094                          * for any EXREQ wait looops, so we can clear EXREQ2
1095                          * now.
1096                          */
1097                         ncount = count & ~(LKC_EXREQ | LKC_EXREQ2);
1098                         if (atomic_fcmpset_64(&lkp->lk_count, &count, ncount)) {
1099                                 if ((count & (LKC_EXREQ2 | LKC_UPREQ)) ==
1100                                     LKC_EXREQ2) {
1101                                         wakeup(lkp);
1102                                 }
1103                                 error = EBUSY;
1104                                 /* count = ncount; NOT USED */
1105                                 break;
1106                         }
1107                         /* retry */
1108                 } else if (count & LKC_UPREQ) {
1109                         /*
1110                          * Clear the EXREQ we still own.  We cannot wakeup any
1111                          * shared or exclusive waiters because there is an
1112                          * uprequest pending (that we do not handle here).
1113                          *
1114                          * If there is an UPREQ it will issue a wakeup()
1115                          * for any EXREQ wait looops, so we can clear EXREQ2
1116                          * now.
1117                          */
1118                         ncount = count & ~(LKC_EXREQ | LKC_EXREQ2);
1119                         if (atomic_fcmpset_64(&lkp->lk_count, &count, ncount)) {
1120                                 error = EBUSY;
1121                                 break;
1122                         }
1123                         /* retry */
1124                 } else if ((count & LKC_SHARED) && (count & LKC_SMASK)) {
1125                         /*
1126                          * No UPREQ, lock not held exclusively, but the lock
1127                          * is held shared.  Clear EXREQ, wakeup anyone trying
1128                          * to get the EXREQ bit (they have to set it
1129                          * themselves, EXREQ2 is an aggregation).
1130                          *
1131                          * We must also wakeup any shared locks blocked
1132                          * by the EXREQ, so just issue the wakeup
1133                          * unconditionally.  See lockmgr_shared() + 76 lines
1134                          * or so.
1135                          */
1136                         ncount = count & ~(LKC_EXREQ | LKC_EXREQ2);
1137                         if (atomic_fcmpset_64(&lkp->lk_count, &count, ncount)) {
1138                                 wakeup(lkp);
1139                                 error = EBUSY;
1140                                 /* count = ncount; NOT USED */
1141                                 break;
1142                         }
1143                         /* retry */
1144                 } else {
1145                         /*
1146                          * No UPREQ, lock not held exclusively or shared.
1147                          * Grant the EXREQ and wakeup anyone waiting on
1148                          * EXREQ2.
1149                          *
1150                          * We must also issue a wakeup if SHARED is set,
1151                          * even without an SCOUNT, due to pre-shared blocking
1152                          * that can occur on EXREQ in lockmgr_shared().
1153                          */
1154                         ncount = (count + 1) & ~(LKC_EXREQ | LKC_EXREQ2);
1155                         if (atomic_fcmpset_64(&lkp->lk_count, &count, ncount)) {
1156                                 if (count & (LKC_EXREQ2 | LKC_SHARED))
1157                                         wakeup(lkp);
1158                                 /* count = ncount; NOT USED */
1159                                 /* we are granting, error == 0 */
1160                                 break;
1161                         }
1162                         /* retry */
1163                 }
1164                 /* retry */
1165         }
1166         return error;
1167 }
1168
1169 /*
1170  * Undo an upgrade request.  Returns EBUSY if we were able to undo the
1171  * request, and 0 if the request was granted before we could undo it.
1172  * When 0 is returned, the lock state has not been modified.  The caller
1173  * is responsible for setting the lockholder to curthread.
1174  */
1175 static
1176 int
1177 undo_upreq(struct lock *lkp)
1178 {
1179         uint64_t count;
1180         uint64_t ncount;
1181         int error;
1182
1183         count = lkp->lk_count;
1184         error = 0;
1185
1186         for (;;) {
1187                 cpu_ccfence();
1188
1189                 if ((count & LKC_UPREQ) == 0) {
1190                         /*
1191                          * UPREQ was granted
1192                          */
1193                         break;
1194                 }
1195                 if (count & LKC_XMASK) {
1196                         /*
1197                          * Clear the UPREQ we still own.  Nobody to wakeup
1198                          * here because there is an existing exclusive
1199                          * holder.
1200                          */
1201                         if (atomic_fcmpset_64(&lkp->lk_count, &count,
1202                                               count & ~LKC_UPREQ)) {
1203                                 error = EBUSY;
1204                                 /* count &= ~LKC_UPREQ; NOT USED */
1205                                 break;
1206                         }
1207                 } else if (count & LKC_EXREQ) {
1208                         /*
1209                          * Clear the UPREQ we still own.  Grant the exclusive
1210                          * request and wake it up.
1211                          */
1212                         ncount = (count + 1);
1213                         ncount &= ~(LKC_EXREQ | LKC_EXREQ2 | LKC_UPREQ);
1214
1215                         if (atomic_fcmpset_64(&lkp->lk_count, &count, ncount)) {
1216                                 wakeup(lkp);
1217                                 error = EBUSY;
1218                                 /* count = ncount; NOT USED */
1219                                 break;
1220                         }
1221                 } else {
1222                         /*
1223                          * Clear the UPREQ we still own.  Wakeup any shared
1224                          * waiters.
1225                          *
1226                          * We must also issue a wakeup if SHARED was set
1227                          * even if no shared waiters due to pre-shared blocking
1228                          * that can occur on UPREQ.
1229                          */
1230                         ncount = count & ~LKC_UPREQ;
1231                         if (count & LKC_SMASK)
1232                                 ncount |= LKC_SHARED;
1233
1234                         if (atomic_fcmpset_64(&lkp->lk_count, &count, ncount)) {
1235                                 if ((count & LKC_SHARED) ||
1236                                     (ncount & LKC_SHARED)) {
1237                                         wakeup(lkp);
1238                                 }
1239                                 error = EBUSY;
1240                                 /* count = ncount; NOT USED */
1241                                 break;
1242                         }
1243                 }
1244                 /* retry */
1245         }
1246         return error;
1247 }
1248
1249 void
1250 lockmgr_kernproc(struct lock *lp)
1251 {
1252         struct thread *td __debugvar = curthread;
1253
1254         if (lp->lk_lockholder != LK_KERNTHREAD) {
1255                 KASSERT(lp->lk_lockholder == td,
1256                     ("lockmgr_kernproc: lock not owned by curthread %p: %p",
1257                     td, lp->lk_lockholder));
1258                 lp->lk_lockholder = LK_KERNTHREAD;
1259                 COUNT(td, -1);
1260         }
1261 }
1262
1263 /*
1264  * Initialize a lock; required before use.
1265  */
1266 void
1267 lockinit(struct lock *lkp, const char *wmesg, int timo, int flags)
1268 {
1269         lkp->lk_flags = (flags & LK_EXTFLG_MASK);
1270         lkp->lk_count = 0;
1271         lkp->lk_wmesg = wmesg;
1272         lkp->lk_timo = timo;
1273         lkp->lk_lockholder = NULL;
1274 }
1275
1276 /*
1277  * Reinitialize a lock that is being reused for a different purpose, but
1278  * which may have pending (blocked) threads sitting on it.  The caller
1279  * must already hold the interlock.
1280  */
1281 void
1282 lockreinit(struct lock *lkp, const char *wmesg, int timo, int flags)
1283 {
1284         lkp->lk_wmesg = wmesg;
1285         lkp->lk_timo = timo;
1286 }
1287
1288 /*
1289  * De-initialize a lock.  The structure must no longer be used by anyone.
1290  */
1291 void
1292 lockuninit(struct lock *lkp)
1293 {
1294         uint64_t count __unused;
1295
1296         count = lkp->lk_count;
1297         cpu_ccfence();
1298         KKASSERT((count & (LKC_EXREQ | LKC_UPREQ)) == 0 &&
1299                  ((count & LKC_SHARED) || (count & LKC_SMASK) == 0));
1300 }
1301
1302 /*
1303  * Determine the status of a lock.
1304  */
1305 int
1306 lockstatus(struct lock *lkp, struct thread *td)
1307 {
1308         int lock_type = 0;
1309         uint64_t count;
1310
1311         count = lkp->lk_count;
1312         cpu_ccfence();
1313
1314         if (count & (LKC_XMASK | LKC_SMASK | LKC_EXREQ | LKC_UPREQ)) {
1315                 if (count & LKC_XMASK) {
1316                         if (td == NULL || lkp->lk_lockholder == td)
1317                                 lock_type = LK_EXCLUSIVE;
1318                         else
1319                                 lock_type = LK_EXCLOTHER;
1320                 } else if ((count & LKC_SMASK) && (count & LKC_SHARED)) {
1321                         lock_type = LK_SHARED;
1322                 }
1323         }
1324         return (lock_type);
1325 }
1326
1327 /*
1328  * Return non-zero if the caller owns the lock shared or exclusive.
1329  * We can only guess re: shared locks.
1330  */
1331 int
1332 lockowned(struct lock *lkp)
1333 {
1334         thread_t td = curthread;
1335         uint64_t count;
1336
1337         count = lkp->lk_count;
1338         cpu_ccfence();
1339
1340         if (count & LKC_XMASK)
1341                 return(lkp->lk_lockholder == td);
1342         else
1343                 return((count & LKC_SMASK) != 0);
1344 }
1345
1346 #if 0
1347 /*
1348  * Determine the number of holders of a lock.
1349  *
1350  * REMOVED - Cannot be used due to our use of atomic_fetchadd_64()
1351  *           for shared locks.  Caller can only test if the lock has
1352  *           a count or not using lockinuse(lk) (sys/lock.h)
1353  */
1354 int
1355 lockcount(struct lock *lkp)
1356 {
1357         panic("lockcount cannot be used");
1358 }
1359
1360 int
1361 lockcountnb(struct lock *lkp)
1362 {
1363         panic("lockcount cannot be used");
1364 }
1365 #endif
1366
1367 /*
1368  * Print out information about state of a lock. Used by VOP_PRINT
1369  * routines to display status about contained locks.
1370  */
1371 void
1372 lockmgr_printinfo(struct lock *lkp)
1373 {
1374         struct thread *td = lkp->lk_lockholder;
1375         struct proc *p;
1376         uint64_t count;
1377
1378         count = lkp->lk_count;
1379         cpu_ccfence();
1380
1381         if (td && td != LK_KERNTHREAD)
1382                 p = td->td_proc;
1383         else
1384                 p = NULL;
1385
1386         if (count & LKC_XMASK) {
1387                 kprintf(" lock type %s: EXCLUS (count %016jx) by td %p pid %d",
1388                     lkp->lk_wmesg, (intmax_t)count, td,
1389                     p ? p->p_pid : -99);
1390         } else if ((count & LKC_SMASK) && (count & LKC_SHARED)) {
1391                 kprintf(" lock type %s: SHARED (count %016jx)",
1392                     lkp->lk_wmesg, (intmax_t)count);
1393         } else {
1394                 kprintf(" lock type %s: NOTHELD", lkp->lk_wmesg);
1395         }
1396         if ((count & (LKC_EXREQ | LKC_UPREQ)) ||
1397             ((count & LKC_XMASK) && (count & LKC_SMASK)))
1398                 kprintf(" with waiters\n");
1399         else
1400                 kprintf("\n");
1401 }
1402
1403 void
1404 lock_sysinit(struct lock_args *arg)
1405 {
1406         lockinit(arg->la_lock, arg->la_desc, 0, arg->la_flags);
1407 }
1408
1409 #ifdef DEBUG_CANCEL_LOCKS
1410
1411 static
1412 int
1413 sysctl_cancel_lock(SYSCTL_HANDLER_ARGS)
1414 {
1415         int error;
1416
1417         if (req->newptr) {
1418                 SYSCTL_XUNLOCK();
1419                 lockmgr(&cancel_lk, LK_EXCLUSIVE);
1420                 error = tsleep(&error, PCATCH, "canmas", hz * 5);
1421                 lockmgr(&cancel_lk, LK_CANCEL_BEG);
1422                 error = tsleep(&error, PCATCH, "canmas", hz * 5);
1423                 lockmgr(&cancel_lk, LK_RELEASE);
1424                 SYSCTL_XLOCK();
1425                 SYSCTL_OUT(req, &error, sizeof(error));
1426         }
1427         error = 0;
1428
1429         return error;
1430 }
1431
1432 static
1433 int
1434 sysctl_cancel_test(SYSCTL_HANDLER_ARGS)
1435 {
1436         int error;
1437
1438         if (req->newptr) {
1439                 error = lockmgr(&cancel_lk, LK_EXCLUSIVE|LK_CANCELABLE);
1440                 if (error == 0)
1441                         lockmgr(&cancel_lk, LK_RELEASE);
1442                 SYSCTL_OUT(req, &error, sizeof(error));
1443                 kprintf("test %d\n", error);
1444         }
1445
1446         return 0;
1447 }
1448
1449 #endif