]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/kern_sx.c
Expose sx_xholder() as a public macro. It returns a pointer to the thread
[FreeBSD/FreeBSD.git] / sys / kern / kern_sx.c
1 /*-
2  * Copyright (c) 2007 Attilio Rao <attilio@freebsd.org>
3  * Copyright (c) 2001 Jason Evans <jasone@freebsd.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice(s), this list of conditions and the following disclaimer as
11  *    the first lines of this file unmodified other than the possible
12  *    addition of one or more copyright notices.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice(s), this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
27  * DAMAGE.
28  */
29
30 /*
31  * Shared/exclusive locks.  This implementation attempts to ensure
32  * deterministic lock granting behavior, so that slocks and xlocks are
33  * interleaved.
34  *
35  * Priority propagation will not generally raise the priority of lock holders,
36  * so should not be relied upon in combination with sx locks.
37  */
38
39 #include "opt_adaptive_sx.h"
40 #include "opt_ddb.h"
41
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
44
45 #include <sys/param.h>
46 #include <sys/ktr.h>
47 #include <sys/lock.h>
48 #include <sys/lock_profile.h>
49 #include <sys/mutex.h>
50 #include <sys/proc.h>
51 #include <sys/sleepqueue.h>
52 #include <sys/sx.h>
53 #include <sys/systm.h>
54
55 #ifdef ADAPTIVE_SX
56 #include <machine/cpu.h>
57 #endif
58
59 #ifdef DDB
60 #include <ddb/ddb.h>
61 #endif
62
63 #if !defined(SMP) && defined(ADAPTIVE_SX)
64 #error "You must have SMP to enable the ADAPTIVE_SX option"
65 #endif
66
67 /* Handy macros for sleep queues. */
68 #define SQ_EXCLUSIVE_QUEUE      0
69 #define SQ_SHARED_QUEUE         1
70
71 /*
72  * Variations on DROP_GIANT()/PICKUP_GIANT() for use in this file.  We
73  * drop Giant anytime we have to sleep or if we adaptively spin.
74  */
75 #define GIANT_DECLARE                                                   \
76         int _giantcnt = 0;                                              \
77         WITNESS_SAVE_DECL(Giant)                                        \
78
79 #define GIANT_SAVE() do {                                               \
80         if (mtx_owned(&Giant)) {                                        \
81                 WITNESS_SAVE(&Giant.lock_object, Giant);                \
82                 while (mtx_owned(&Giant)) {                             \
83                         _giantcnt++;                                    \
84                         mtx_unlock(&Giant);                             \
85                 }                                                       \
86         }                                                               \
87 } while (0)
88
89 #define GIANT_RESTORE() do {                                            \
90         if (_giantcnt > 0) {                                            \
91                 mtx_assert(&Giant, MA_NOTOWNED);                        \
92                 while (_giantcnt--)                                     \
93                         mtx_lock(&Giant);                               \
94                 WITNESS_RESTORE(&Giant.lock_object, Giant);             \
95         }                                                               \
96 } while (0)
97
98 /*
99  * Returns true if an exclusive lock is recursed.  It assumes
100  * curthread currently has an exclusive lock.
101  */
102 #define sx_recursed(sx)         ((sx)->sx_recurse != 0)
103
104 #ifdef DDB
105 static void     db_show_sx(struct lock_object *lock);
106 #endif
107 static void     lock_sx(struct lock_object *lock, int how);
108 static int      unlock_sx(struct lock_object *lock);
109
110 struct lock_class lock_class_sx = {
111         .lc_name = "sx",
112         .lc_flags = LC_SLEEPLOCK | LC_SLEEPABLE | LC_RECURSABLE | LC_UPGRADABLE,
113 #ifdef DDB
114         .lc_ddb_show = db_show_sx,
115 #endif
116         .lc_lock = lock_sx,
117         .lc_unlock = unlock_sx,
118 };
119
120 #ifndef INVARIANTS
121 #define _sx_assert(sx, what, file, line)
122 #endif
123
124 void
125 lock_sx(struct lock_object *lock, int how)
126 {
127         struct sx *sx;
128
129         sx = (struct sx *)lock;
130         if (how)
131                 sx_xlock(sx);
132         else
133                 sx_slock(sx);
134 }
135
136 int
137 unlock_sx(struct lock_object *lock)
138 {
139         struct sx *sx;
140
141         sx = (struct sx *)lock;
142         sx_assert(sx, SX_LOCKED | SX_NOTRECURSED);
143         if (sx_xlocked(sx)) {
144                 sx_xunlock(sx);
145                 return (1);
146         } else {
147                 sx_sunlock(sx);
148                 return (0);
149         }
150 }
151
152 void
153 sx_sysinit(void *arg)
154 {
155         struct sx_args *sargs = arg;
156
157         sx_init(sargs->sa_sx, sargs->sa_desc);
158 }
159
160 void
161 sx_init_flags(struct sx *sx, const char *description, int opts)
162 {
163         int flags;
164
165         MPASS((opts & ~(SX_QUIET | SX_RECURSE | SX_NOWITNESS | SX_DUPOK |
166             SX_NOPROFILE | SX_ADAPTIVESPIN)) == 0);
167
168         flags = LO_SLEEPABLE | LO_UPGRADABLE | LO_RECURSABLE;
169         if (opts & SX_DUPOK)
170                 flags |= LO_DUPOK;
171         if (opts & SX_NOPROFILE)
172                 flags |= LO_NOPROFILE;
173         if (!(opts & SX_NOWITNESS))
174                 flags |= LO_WITNESS;
175         if (opts & SX_QUIET)
176                 flags |= LO_QUIET;
177
178         flags |= opts & (SX_ADAPTIVESPIN | SX_RECURSE);
179         sx->sx_lock = SX_LOCK_UNLOCKED;
180         sx->sx_recurse = 0;
181         lock_init(&sx->lock_object, &lock_class_sx, description, NULL, flags);
182 }
183
184 void
185 sx_destroy(struct sx *sx)
186 {
187
188         KASSERT(sx->sx_lock == SX_LOCK_UNLOCKED, ("sx lock still held"));
189         KASSERT(sx->sx_recurse == 0, ("sx lock still recursed"));
190         sx->sx_lock = SX_LOCK_DESTROYED;
191         lock_destroy(&sx->lock_object);
192 }
193
194 void
195 _sx_slock(struct sx *sx, const char *file, int line)
196 {
197
198         MPASS(curthread != NULL);
199         KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
200             ("sx_slock() of destroyed sx @ %s:%d", file, line));
201         WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER, file, line);
202         __sx_slock(sx, file, line);
203         LOCK_LOG_LOCK("SLOCK", &sx->lock_object, 0, 0, file, line);
204         WITNESS_LOCK(&sx->lock_object, 0, file, line);
205         curthread->td_locks++;
206 }
207
208 int
209 _sx_try_slock(struct sx *sx, const char *file, int line)
210 {
211         uintptr_t x;
212
213         x = sx->sx_lock;
214         KASSERT(x != SX_LOCK_DESTROYED,
215             ("sx_try_slock() of destroyed sx @ %s:%d", file, line));
216         if ((x & SX_LOCK_SHARED) && atomic_cmpset_acq_ptr(&sx->sx_lock, x,
217             x + SX_ONE_SHARER)) {
218                 LOCK_LOG_TRY("SLOCK", &sx->lock_object, 0, 1, file, line);
219                 WITNESS_LOCK(&sx->lock_object, LOP_TRYLOCK, file, line);
220                 curthread->td_locks++;
221                 return (1);
222         }
223
224         LOCK_LOG_TRY("SLOCK", &sx->lock_object, 0, 0, file, line);
225         return (0);
226 }
227
228 void
229 _sx_xlock(struct sx *sx, const char *file, int line)
230 {
231
232         MPASS(curthread != NULL);
233         KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
234             ("sx_xlock() of destroyed sx @ %s:%d", file, line));
235         WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER | LOP_EXCLUSIVE, file,
236             line);
237         __sx_xlock(sx, curthread, file, line);
238         LOCK_LOG_LOCK("XLOCK", &sx->lock_object, 0, sx->sx_recurse, file, line);
239         WITNESS_LOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line);
240         curthread->td_locks++;
241 }
242
243 int
244 _sx_try_xlock(struct sx *sx, const char *file, int line)
245 {
246         int rval;
247
248         MPASS(curthread != NULL);
249         KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
250             ("sx_try_xlock() of destroyed sx @ %s:%d", file, line));
251
252         if (sx_xlocked(sx) && (sx->lock_object.lo_flags & SX_RECURSE) != 0) {
253                 sx->sx_recurse++;
254                 atomic_set_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
255                 rval = 1;
256         } else
257                 rval = atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED,
258                     (uintptr_t)curthread);
259         LOCK_LOG_TRY("XLOCK", &sx->lock_object, 0, rval, file, line);
260         if (rval) {
261                 WITNESS_LOCK(&sx->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK,
262                     file, line);
263                 curthread->td_locks++;
264         }
265
266         return (rval);
267 }
268
269 void
270 _sx_sunlock(struct sx *sx, const char *file, int line)
271 {
272
273         MPASS(curthread != NULL);
274         KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
275             ("sx_sunlock() of destroyed sx @ %s:%d", file, line));
276         _sx_assert(sx, SX_SLOCKED, file, line);
277         curthread->td_locks--;
278         WITNESS_UNLOCK(&sx->lock_object, 0, file, line);
279         LOCK_LOG_LOCK("SUNLOCK", &sx->lock_object, 0, 0, file, line);
280         if (SX_SHARERS(sx->sx_lock) == 0)
281                 lock_profile_release_lock(&sx->lock_object);
282         __sx_sunlock(sx, file, line);
283 }
284
285 void
286 _sx_xunlock(struct sx *sx, const char *file, int line)
287 {
288
289         MPASS(curthread != NULL);
290         KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
291             ("sx_xunlock() of destroyed sx @ %s:%d", file, line));
292         _sx_assert(sx, SX_XLOCKED, file, line);
293         curthread->td_locks--;
294         WITNESS_UNLOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line);
295         LOCK_LOG_LOCK("XUNLOCK", &sx->lock_object, 0, sx->sx_recurse, file,
296             line);
297         if (!sx_recursed(sx))
298                 lock_profile_release_lock(&sx->lock_object);
299         __sx_xunlock(sx, curthread, file, line);
300 }
301
302 /*
303  * Try to do a non-blocking upgrade from a shared lock to an exclusive lock.
304  * This will only succeed if this thread holds a single shared lock.
305  * Return 1 if if the upgrade succeed, 0 otherwise.
306  */
307 int
308 _sx_try_upgrade(struct sx *sx, const char *file, int line)
309 {
310         uintptr_t x;
311         int success;
312
313         KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
314             ("sx_try_upgrade() of destroyed sx @ %s:%d", file, line));
315         _sx_assert(sx, SX_SLOCKED, file, line);
316
317         /*
318          * Try to switch from one shared lock to an exclusive lock.  We need
319          * to maintain the SX_LOCK_EXCLUSIVE_WAITERS flag if set so that
320          * we will wake up the exclusive waiters when we drop the lock.
321          */
322         x = sx->sx_lock & SX_LOCK_EXCLUSIVE_WAITERS;
323         success = atomic_cmpset_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1) | x,
324             (uintptr_t)curthread | x);
325         LOCK_LOG_TRY("XUPGRADE", &sx->lock_object, 0, success, file, line);
326         if (success)
327                 WITNESS_UPGRADE(&sx->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK,
328                     file, line);
329         return (success);
330 }
331
332 /*
333  * Downgrade an unrecursed exclusive lock into a single shared lock.
334  */
335 void
336 _sx_downgrade(struct sx *sx, const char *file, int line)
337 {
338         uintptr_t x;
339
340         KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
341             ("sx_downgrade() of destroyed sx @ %s:%d", file, line));
342         _sx_assert(sx, SX_XLOCKED | SX_NOTRECURSED, file, line);
343 #ifndef INVARIANTS
344         if (sx_recursed(sx))
345                 panic("downgrade of a recursed lock");
346 #endif
347
348         WITNESS_DOWNGRADE(&sx->lock_object, 0, file, line);
349
350         /*
351          * Try to switch from an exclusive lock with no shared waiters
352          * to one sharer with no shared waiters.  If there are
353          * exclusive waiters, we don't need to lock the sleep queue so
354          * long as we preserve the flag.  We do one quick try and if
355          * that fails we grab the sleepq lock to keep the flags from
356          * changing and do it the slow way.
357          *
358          * We have to lock the sleep queue if there are shared waiters
359          * so we can wake them up.
360          */
361         x = sx->sx_lock;
362         if (!(x & SX_LOCK_SHARED_WAITERS) &&
363             atomic_cmpset_rel_ptr(&sx->sx_lock, x, SX_SHARERS_LOCK(1) |
364             (x & SX_LOCK_EXCLUSIVE_WAITERS))) {
365                 LOCK_LOG_LOCK("XDOWNGRADE", &sx->lock_object, 0, 0, file, line);
366                 return;
367         }
368
369         /*
370          * Lock the sleep queue so we can read the waiters bits
371          * without any races and wakeup any shared waiters.
372          */
373         sleepq_lock(&sx->lock_object);
374
375         /*
376          * Preserve SX_LOCK_EXCLUSIVE_WAITERS while downgraded to a single
377          * shared lock.  If there are any shared waiters, wake them up.
378          */
379         x = sx->sx_lock;
380         atomic_store_rel_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1) |
381             (x & SX_LOCK_EXCLUSIVE_WAITERS));
382         if (x & SX_LOCK_SHARED_WAITERS)
383                 sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, -1,
384                     SQ_SHARED_QUEUE);
385         else
386                 sleepq_release(&sx->lock_object);
387
388         LOCK_LOG_LOCK("XDOWNGRADE", &sx->lock_object, 0, 0, file, line);
389 }
390
391 /*
392  * This function represents the so-called 'hard case' for sx_xlock
393  * operation.  All 'easy case' failures are redirected to this.  Note
394  * that ideally this would be a static function, but it needs to be
395  * accessible from at least sx.h.
396  */
397 void
398 _sx_xlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line)
399 {
400         GIANT_DECLARE;
401 #ifdef ADAPTIVE_SX
402         volatile struct thread *owner;
403 #endif
404         uintptr_t x;
405         int contested = 0;
406         uint64_t waitstart = 0;
407
408         /* If we already hold an exclusive lock, then recurse. */
409         if (sx_xlocked(sx)) {
410                 KASSERT((sx->lock_object.lo_flags & SX_RECURSE) != 0,
411             ("_sx_xlock_hard: recursed on non-recursive sx %s @ %s:%d\n",
412                     sx->lock_object.lo_name, file, line));              
413                 sx->sx_recurse++;
414                 atomic_set_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
415                 if (LOCK_LOG_TEST(&sx->lock_object, 0))
416                         CTR2(KTR_LOCK, "%s: %p recursing", __func__, sx);
417                 return;
418         }
419         lock_profile_obtain_lock_failed(&(sx)->lock_object,
420             &contested, &waitstart);
421
422         if (LOCK_LOG_TEST(&sx->lock_object, 0))
423                 CTR5(KTR_LOCK, "%s: %s contested (lock=%p) at %s:%d", __func__,
424                     sx->lock_object.lo_name, (void *)sx->sx_lock, file, line);
425
426         while (!atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED, tid)) {
427 #ifdef ADAPTIVE_SX
428                 /*
429                  * If the lock is write locked and the owner is
430                  * running on another CPU, spin until the owner stops
431                  * running or the state of the lock changes.
432                  */
433                 x = sx->sx_lock;
434                 if (!(x & SX_LOCK_SHARED) &&
435                     (sx->lock_object.lo_flags & SX_ADAPTIVESPIN)) {
436                         x = SX_OWNER(x);
437                         owner = (struct thread *)x;
438                         if (TD_IS_RUNNING(owner)) {
439                                 if (LOCK_LOG_TEST(&sx->lock_object, 0))
440                                         CTR3(KTR_LOCK,
441                                             "%s: spinning on %p held by %p",
442                                             __func__, sx, owner);
443                                 GIANT_SAVE();
444                                 while (SX_OWNER(sx->sx_lock) == x &&
445                                     TD_IS_RUNNING(owner))
446                                         cpu_spinwait();
447                                 continue;
448                         }
449                 }
450 #endif
451
452                 sleepq_lock(&sx->lock_object);
453                 x = sx->sx_lock;
454
455                 /*
456                  * If the lock was released while spinning on the
457                  * sleep queue chain lock, try again.
458                  */
459                 if (x == SX_LOCK_UNLOCKED) {
460                         sleepq_release(&sx->lock_object);
461                         continue;
462                 }
463
464 #ifdef ADAPTIVE_SX
465                 /*
466                  * The current lock owner might have started executing
467                  * on another CPU (or the lock could have changed
468                  * owners) while we were waiting on the sleep queue
469                  * chain lock.  If so, drop the sleep queue lock and try
470                  * again.
471                  */
472                 if (!(x & SX_LOCK_SHARED) &&
473                     (sx->lock_object.lo_flags & SX_ADAPTIVESPIN)) {
474                         owner = (struct thread *)SX_OWNER(x);
475                         if (TD_IS_RUNNING(owner)) {
476                                 sleepq_release(&sx->lock_object);
477                                 continue;
478                         }
479                 }
480 #endif
481
482                 /*
483                  * If an exclusive lock was released with both shared
484                  * and exclusive waiters and a shared waiter hasn't
485                  * woken up and acquired the lock yet, sx_lock will be
486                  * set to SX_LOCK_UNLOCKED | SX_LOCK_EXCLUSIVE_WAITERS.
487                  * If we see that value, try to acquire it once.  Note
488                  * that we have to preserve SX_LOCK_EXCLUSIVE_WAITERS
489                  * as there are other exclusive waiters still.  If we
490                  * fail, restart the loop.
491                  */
492                 if (x == (SX_LOCK_UNLOCKED | SX_LOCK_EXCLUSIVE_WAITERS)) {
493                         if (atomic_cmpset_acq_ptr(&sx->sx_lock,
494                             SX_LOCK_UNLOCKED | SX_LOCK_EXCLUSIVE_WAITERS,
495                             tid | SX_LOCK_EXCLUSIVE_WAITERS)) {
496                                 sleepq_release(&sx->lock_object);
497                                 CTR2(KTR_LOCK, "%s: %p claimed by new writer",
498                                     __func__, sx);
499                                 break;
500                         }
501                         sleepq_release(&sx->lock_object);
502                         continue;
503                 }
504
505                 /*
506                  * Try to set the SX_LOCK_EXCLUSIVE_WAITERS.  If we fail,
507                  * than loop back and retry.
508                  */
509                 if (!(x & SX_LOCK_EXCLUSIVE_WAITERS)) {
510                         if (!atomic_cmpset_ptr(&sx->sx_lock, x,
511                             x | SX_LOCK_EXCLUSIVE_WAITERS)) {
512                                 sleepq_release(&sx->lock_object);
513                                 continue;
514                         }
515                         if (LOCK_LOG_TEST(&sx->lock_object, 0))
516                                 CTR2(KTR_LOCK, "%s: %p set excl waiters flag",
517                                     __func__, sx);
518                 }
519
520                 /*
521                  * Since we have been unable to acquire the exclusive
522                  * lock and the exclusive waiters flag is set, we have
523                  * to sleep.
524                  */
525                 if (LOCK_LOG_TEST(&sx->lock_object, 0))
526                         CTR2(KTR_LOCK, "%s: %p blocking on sleep queue",
527                             __func__, sx);
528
529                 GIANT_SAVE();
530                 sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name,
531                     SLEEPQ_SX, SQ_EXCLUSIVE_QUEUE);
532                 sleepq_wait(&sx->lock_object);
533
534                 if (LOCK_LOG_TEST(&sx->lock_object, 0))
535                         CTR2(KTR_LOCK, "%s: %p resuming from sleep queue",
536                             __func__, sx);
537         }
538         
539         GIANT_RESTORE();
540         lock_profile_obtain_lock_success(&(sx)->lock_object, contested,
541             waitstart, file, line);
542 }
543
544 /*
545  * This function represents the so-called 'hard case' for sx_xunlock
546  * operation.  All 'easy case' failures are redirected to this.  Note
547  * that ideally this would be a static function, but it needs to be
548  * accessible from at least sx.h.
549  */
550 void
551 _sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line)
552 {
553         uintptr_t x;
554         int queue;
555
556         MPASS(!(sx->sx_lock & SX_LOCK_SHARED));
557
558         /* If the lock is recursed, then unrecurse one level. */
559         if (sx_xlocked(sx) && sx_recursed(sx)) {
560                 if ((--sx->sx_recurse) == 0)
561                         atomic_clear_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
562                 if (LOCK_LOG_TEST(&sx->lock_object, 0))
563                         CTR2(KTR_LOCK, "%s: %p unrecursing", __func__, sx);
564                 return;
565         }
566         MPASS(sx->sx_lock & (SX_LOCK_SHARED_WAITERS |
567             SX_LOCK_EXCLUSIVE_WAITERS));
568         if (LOCK_LOG_TEST(&sx->lock_object, 0))
569                 CTR2(KTR_LOCK, "%s: %p contested", __func__, sx);
570
571         sleepq_lock(&sx->lock_object);
572         x = SX_LOCK_UNLOCKED;
573
574         /*
575          * The wake up algorithm here is quite simple and probably not
576          * ideal.  It gives precedence to shared waiters if they are
577          * present.  For this condition, we have to preserve the
578          * state of the exclusive waiters flag.
579          */
580         if (sx->sx_lock & SX_LOCK_SHARED_WAITERS) {
581                 queue = SQ_SHARED_QUEUE;
582                 x |= (sx->sx_lock & SX_LOCK_EXCLUSIVE_WAITERS);
583         } else
584                 queue = SQ_EXCLUSIVE_QUEUE;
585
586         /* Wake up all the waiters for the specific queue. */
587         if (LOCK_LOG_TEST(&sx->lock_object, 0))
588                 CTR3(KTR_LOCK, "%s: %p waking up all threads on %s queue",
589                     __func__, sx, queue == SQ_SHARED_QUEUE ? "shared" :
590                     "exclusive");
591         atomic_store_rel_ptr(&sx->sx_lock, x);
592         sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, -1, queue);
593 }
594
595 /*
596  * This function represents the so-called 'hard case' for sx_slock
597  * operation.  All 'easy case' failures are redirected to this.  Note
598  * that ideally this would be a static function, but it needs to be
599  * accessible from at least sx.h.
600  */
601 void
602 _sx_slock_hard(struct sx *sx, const char *file, int line)
603 {
604         GIANT_DECLARE;
605 #ifdef ADAPTIVE_SX
606         volatile struct thread *owner;
607 #endif
608         uintptr_t x;
609         uint64_t waitstart = 0;
610         int contested = 0;
611         /*
612          * As with rwlocks, we don't make any attempt to try to block
613          * shared locks once there is an exclusive waiter.
614          */
615         
616         for (;;) {
617                 x = sx->sx_lock;
618
619                 /*
620                  * If no other thread has an exclusive lock then try to bump up
621                  * the count of sharers.  Since we have to preserve the state
622                  * of SX_LOCK_EXCLUSIVE_WAITERS, if we fail to acquire the
623                  * shared lock loop back and retry.
624                  */
625                 if (x & SX_LOCK_SHARED) {
626                         MPASS(!(x & SX_LOCK_SHARED_WAITERS));
627                         if (atomic_cmpset_acq_ptr(&sx->sx_lock, x,
628                             x + SX_ONE_SHARER)) {
629                                 if (SX_SHARERS(x) == 0)
630                                         lock_profile_obtain_lock_success(
631                                             &sx->lock_object, contested,
632                                             waitstart, file, line);
633                                 if (LOCK_LOG_TEST(&sx->lock_object, 0))
634                                         CTR4(KTR_LOCK,
635                                             "%s: %p succeed %p -> %p", __func__,
636                                             sx, (void *)x,
637                                             (void *)(x + SX_ONE_SHARER));
638                                 break;
639                         }
640                         lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
641                             &waitstart);
642
643                         continue;
644                 }
645
646 #ifdef ADAPTIVE_SX
647                 /*
648                  * If the owner is running on another CPU, spin until
649                  * the owner stops running or the state of the lock
650                  * changes.
651                  */
652                 else if (sx->lock_object.lo_flags & SX_ADAPTIVESPIN) {
653                         x = SX_OWNER(x);
654                         owner = (struct thread *)x;
655                         if (TD_IS_RUNNING(owner)) {
656                                 lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
657                                     &waitstart);
658                                 if (LOCK_LOG_TEST(&sx->lock_object, 0))
659                                         CTR3(KTR_LOCK,
660                                             "%s: spinning on %p held by %p",
661                                             __func__, sx, owner);
662                                 GIANT_SAVE();
663                                 while (SX_OWNER(sx->sx_lock) == x &&
664                                     TD_IS_RUNNING(owner))
665                                         cpu_spinwait();
666                                 continue;
667                         }
668                 } 
669 #endif
670                 else
671                         lock_profile_obtain_lock_failed(&sx->lock_object, &contested,
672                             &waitstart);
673
674                 /*
675                  * Some other thread already has an exclusive lock, so
676                  * start the process of blocking.
677                  */
678                 sleepq_lock(&sx->lock_object);
679                 x = sx->sx_lock;
680
681                 /*
682                  * The lock could have been released while we spun.
683                  * In this case loop back and retry.
684                  */
685                 if (x & SX_LOCK_SHARED) {
686                         sleepq_release(&sx->lock_object);
687                         continue;
688                 }
689
690 #ifdef ADAPTIVE_SX
691                 /*
692                  * If the owner is running on another CPU, spin until
693                  * the owner stops running or the state of the lock
694                  * changes.
695                  */
696                 if (!(x & SX_LOCK_SHARED) &&
697                     (sx->lock_object.lo_flags & SX_ADAPTIVESPIN)) {
698                         owner = (struct thread *)SX_OWNER(x);
699                         if (TD_IS_RUNNING(owner)) {
700                                 sleepq_release(&sx->lock_object);
701                                 continue;
702                         }
703                 }
704 #endif
705
706                 /*
707                  * Try to set the SX_LOCK_SHARED_WAITERS flag.  If we
708                  * fail to set it drop the sleep queue lock and loop
709                  * back.
710                  */
711                 if (!(x & SX_LOCK_SHARED_WAITERS)) {
712                         if (!atomic_cmpset_ptr(&sx->sx_lock, x,
713                             x | SX_LOCK_SHARED_WAITERS)) {
714                                 sleepq_release(&sx->lock_object);
715                                 continue;
716                         }
717                         if (LOCK_LOG_TEST(&sx->lock_object, 0))
718                                 CTR2(KTR_LOCK, "%s: %p set shared waiters flag",
719                                     __func__, sx);
720                 }
721
722                 /*
723                  * Since we have been unable to acquire the shared lock,
724                  * we have to sleep.
725                  */
726                 if (LOCK_LOG_TEST(&sx->lock_object, 0))
727                         CTR2(KTR_LOCK, "%s: %p blocking on sleep queue",
728                             __func__, sx);
729                 
730                 GIANT_SAVE();
731                 sleepq_add(&sx->lock_object, NULL, sx->lock_object.lo_name,
732                     SLEEPQ_SX, SQ_SHARED_QUEUE);
733                 sleepq_wait(&sx->lock_object);
734
735                 if (LOCK_LOG_TEST(&sx->lock_object, 0))
736                         CTR2(KTR_LOCK, "%s: %p resuming from sleep queue",
737                             __func__, sx);
738         }
739
740         GIANT_RESTORE();
741 }
742
743 /*
744  * This function represents the so-called 'hard case' for sx_sunlock
745  * operation.  All 'easy case' failures are redirected to this.  Note
746  * that ideally this would be a static function, but it needs to be
747  * accessible from at least sx.h.
748  */
749 void
750 _sx_sunlock_hard(struct sx *sx, const char *file, int line)
751 {
752         uintptr_t x;
753
754         for (;;) {
755                 x = sx->sx_lock;
756
757                 /*
758                  * We should never have sharers while at least one thread
759                  * holds a shared lock.
760                  */
761                 KASSERT(!(x & SX_LOCK_SHARED_WAITERS),
762                     ("%s: waiting sharers", __func__));
763
764                 /*
765                  * See if there is more than one shared lock held.  If
766                  * so, just drop one and return.
767                  */
768                 if (SX_SHARERS(x) > 1) {
769                         if (atomic_cmpset_ptr(&sx->sx_lock, x,
770                             x - SX_ONE_SHARER)) {
771                                 if (LOCK_LOG_TEST(&sx->lock_object, 0))
772                                         CTR4(KTR_LOCK,
773                                             "%s: %p succeeded %p -> %p",
774                                             __func__, sx, (void *)x,
775                                             (void *)(x - SX_ONE_SHARER));
776                                 break;
777                         }
778                         continue;
779                 }
780
781                 /*
782                  * If there aren't any waiters for an exclusive lock,
783                  * then try to drop it quickly.
784                  */
785                 if (!(x & SX_LOCK_EXCLUSIVE_WAITERS)) {
786                         MPASS(x == SX_SHARERS_LOCK(1));
787                         if (atomic_cmpset_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1),
788                             SX_LOCK_UNLOCKED)) {
789                                 lock_profile_release_lock(&sx->lock_object);
790                                 if (LOCK_LOG_TEST(&sx->lock_object, 0))
791                                         CTR2(KTR_LOCK, "%s: %p last succeeded",
792                                             __func__, sx);
793                                 break;
794                         }
795                         continue;
796                 }
797
798                 /*
799                  * At this point, there should just be one sharer with
800                  * exclusive waiters.
801                  */
802                 MPASS(x == (SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS));
803
804                 lock_profile_release_lock(&sx->lock_object);
805                 sleepq_lock(&sx->lock_object);
806
807                 /*
808                  * Wake up semantic here is quite simple:
809                  * Just wake up all the exclusive waiters.
810                  * Note that the state of the lock could have changed,
811                  * so if it fails loop back and retry.
812                  */
813                 if (!atomic_cmpset_ptr(&sx->sx_lock,
814                     SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS,
815                     SX_LOCK_UNLOCKED)) {
816                         sleepq_release(&sx->lock_object);
817                         continue;
818                 }
819                 if (LOCK_LOG_TEST(&sx->lock_object, 0))
820                         CTR2(KTR_LOCK, "%s: %p waking up all thread on"
821                             "exclusive queue", __func__, sx);
822                 sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, -1,
823                     SQ_EXCLUSIVE_QUEUE);
824                 break;
825         }
826 }
827
828 #ifdef INVARIANT_SUPPORT
829 #ifndef INVARIANTS
830 #undef  _sx_assert
831 #endif
832
833 /*
834  * In the non-WITNESS case, sx_assert() can only detect that at least
835  * *some* thread owns an slock, but it cannot guarantee that *this*
836  * thread owns an slock.
837  */
838 void
839 _sx_assert(struct sx *sx, int what, const char *file, int line)
840 {
841 #ifndef WITNESS
842         int slocked = 0;
843 #endif
844
845         if (panicstr != NULL)
846                 return;
847         switch (what) {
848         case SX_SLOCKED:
849         case SX_SLOCKED | SX_NOTRECURSED:
850         case SX_SLOCKED | SX_RECURSED:
851 #ifndef WITNESS
852                 slocked = 1;
853                 /* FALLTHROUGH */
854 #endif
855         case SX_LOCKED:
856         case SX_LOCKED | SX_NOTRECURSED:
857         case SX_LOCKED | SX_RECURSED:
858 #ifdef WITNESS
859                 witness_assert(&sx->lock_object, what, file, line);
860 #else
861                 /*
862                  * If some other thread has an exclusive lock or we
863                  * have one and are asserting a shared lock, fail.
864                  * Also, if no one has a lock at all, fail.
865                  */
866                 if (sx->sx_lock == SX_LOCK_UNLOCKED ||
867                     (!(sx->sx_lock & SX_LOCK_SHARED) && (slocked ||
868                     sx_xholder(sx) != curthread)))
869                         panic("Lock %s not %slocked @ %s:%d\n",
870                             sx->lock_object.lo_name, slocked ? "share " : "",
871                             file, line);
872
873                 if (!(sx->sx_lock & SX_LOCK_SHARED)) {
874                         if (sx_recursed(sx)) {
875                                 if (what & SX_NOTRECURSED)
876                                         panic("Lock %s recursed @ %s:%d\n",
877                                             sx->lock_object.lo_name, file,
878                                             line);
879                         } else if (what & SX_RECURSED)
880                                 panic("Lock %s not recursed @ %s:%d\n",
881                                     sx->lock_object.lo_name, file, line);
882                 }
883 #endif
884                 break;
885         case SX_XLOCKED:
886         case SX_XLOCKED | SX_NOTRECURSED:
887         case SX_XLOCKED | SX_RECURSED:
888                 if (sx_xholder(sx) != curthread)
889                         panic("Lock %s not exclusively locked @ %s:%d\n",
890                             sx->lock_object.lo_name, file, line);
891                 if (sx_recursed(sx)) {
892                         if (what & SX_NOTRECURSED)
893                                 panic("Lock %s recursed @ %s:%d\n",
894                                     sx->lock_object.lo_name, file, line);
895                 } else if (what & SX_RECURSED)
896                         panic("Lock %s not recursed @ %s:%d\n",
897                             sx->lock_object.lo_name, file, line);
898                 break;
899         case SX_UNLOCKED:
900 #ifdef WITNESS
901                 witness_assert(&sx->lock_object, what, file, line);
902 #else
903                 /*
904                  * If we hold an exclusve lock fail.  We can't
905                  * reliably check to see if we hold a shared lock or
906                  * not.
907                  */
908                 if (sx_xholder(sx) == curthread)
909                         panic("Lock %s exclusively locked @ %s:%d\n",
910                             sx->lock_object.lo_name, file, line);
911 #endif
912                 break;
913         default:
914                 panic("Unknown sx lock assertion: %d @ %s:%d", what, file,
915                     line);
916         }
917 }
918 #endif  /* INVARIANT_SUPPORT */
919
920 #ifdef DDB
921 static void
922 db_show_sx(struct lock_object *lock)
923 {
924         struct thread *td;
925         struct sx *sx;
926
927         sx = (struct sx *)lock;
928
929         db_printf(" state: ");
930         if (sx->sx_lock == SX_LOCK_UNLOCKED)
931                 db_printf("UNLOCKED\n");
932         else if (sx->sx_lock == SX_LOCK_DESTROYED) {
933                 db_printf("DESTROYED\n");
934                 return;
935         } else if (sx->sx_lock & SX_LOCK_SHARED)
936                 db_printf("SLOCK: %ju\n", (uintmax_t)SX_SHARERS(sx->sx_lock));
937         else {
938                 td = sx_xholder(sx);
939                 db_printf("XLOCK: %p (tid %d, pid %d, \"%s\")\n", td,
940                     td->td_tid, td->td_proc->p_pid, td->td_proc->p_comm);
941                 if (sx_recursed(sx))
942                         db_printf(" recursed: %d\n", sx->sx_recurse);
943         }
944
945         db_printf(" waiters: ");
946         switch(sx->sx_lock &
947             (SX_LOCK_SHARED_WAITERS | SX_LOCK_EXCLUSIVE_WAITERS)) {
948         case SX_LOCK_SHARED_WAITERS:
949                 db_printf("shared\n");
950                 break;
951         case SX_LOCK_EXCLUSIVE_WAITERS:
952                 db_printf("exclusive\n");
953                 break;
954         case SX_LOCK_SHARED_WAITERS | SX_LOCK_EXCLUSIVE_WAITERS:
955                 db_printf("exclusive and shared\n");
956                 break;
957         default:
958                 db_printf("none\n");
959         }
960 }
961
962 /*
963  * Check to see if a thread that is blocked on a sleep queue is actually
964  * blocked on an sx lock.  If so, output some details and return true.
965  * If the lock has an exclusive owner, return that in *ownerp.
966  */
967 int
968 sx_chain(struct thread *td, struct thread **ownerp)
969 {
970         struct sx *sx;
971
972         /*
973          * Check to see if this thread is blocked on an sx lock.
974          * First, we check the lock class.  If that is ok, then we
975          * compare the lock name against the wait message.
976          */
977         sx = td->td_wchan;
978         if (LOCK_CLASS(&sx->lock_object) != &lock_class_sx ||
979             sx->lock_object.lo_name != td->td_wmesg)
980                 return (0);
981
982         /* We think we have an sx lock, so output some details. */
983         db_printf("blocked on sx \"%s\" ", td->td_wmesg);
984         *ownerp = sx_xholder(sx);
985         if (sx->sx_lock & SX_LOCK_SHARED)
986                 db_printf("SLOCK (count %ju)\n",
987                     (uintmax_t)SX_SHARERS(sx->sx_lock));
988         else
989                 db_printf("XLOCK\n");
990         return (1);
991 }
992 #endif