Deleted Added
full compact
kern_sx.c (179025) kern_sx.c (181334)
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:

--- 26 unchanged lines hidden (view full) ---

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>
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:

--- 26 unchanged lines hidden (view full) ---

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: head/sys/kern/kern_sx.c 179025 2008-05-15 20:10:06Z attilio $");
43__FBSDID("$FreeBSD: head/sys/kern/kern_sx.c 181334 2008-08-05 20:02:31Z jhb $");
44
45#include <sys/param.h>
46#include <sys/ktr.h>
47#include <sys/lock.h>
48#include <sys/mutex.h>
49#include <sys/proc.h>
50#include <sys/sleepqueue.h>
51#include <sys/sx.h>

--- 304 unchanged lines hidden (view full) ---

356
357/*
358 * Downgrade an unrecursed exclusive lock into a single shared lock.
359 */
360void
361_sx_downgrade(struct sx *sx, const char *file, int line)
362{
363 uintptr_t x;
44
45#include <sys/param.h>
46#include <sys/ktr.h>
47#include <sys/lock.h>
48#include <sys/mutex.h>
49#include <sys/proc.h>
50#include <sys/sleepqueue.h>
51#include <sys/sx.h>

--- 304 unchanged lines hidden (view full) ---

356
357/*
358 * Downgrade an unrecursed exclusive lock into a single shared lock.
359 */
360void
361_sx_downgrade(struct sx *sx, const char *file, int line)
362{
363 uintptr_t x;
364 int wakeup_swapper;
364
365 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
366 ("sx_downgrade() of destroyed sx @ %s:%d", file, line));
367 _sx_assert(sx, SA_XLOCKED | SA_NOTRECURSED, file, line);
368#ifndef INVARIANTS
369 if (sx_recursed(sx))
370 panic("downgrade of a recursed lock");
371#endif

--- 24 unchanged lines hidden (view full) ---

396 * without any races and wakeup any shared waiters.
397 */
398 sleepq_lock(&sx->lock_object);
399
400 /*
401 * Preserve SX_LOCK_EXCLUSIVE_WAITERS while downgraded to a single
402 * shared lock. If there are any shared waiters, wake them up.
403 */
365
366 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
367 ("sx_downgrade() of destroyed sx @ %s:%d", file, line));
368 _sx_assert(sx, SA_XLOCKED | SA_NOTRECURSED, file, line);
369#ifndef INVARIANTS
370 if (sx_recursed(sx))
371 panic("downgrade of a recursed lock");
372#endif

--- 24 unchanged lines hidden (view full) ---

397 * without any races and wakeup any shared waiters.
398 */
399 sleepq_lock(&sx->lock_object);
400
401 /*
402 * Preserve SX_LOCK_EXCLUSIVE_WAITERS while downgraded to a single
403 * shared lock. If there are any shared waiters, wake them up.
404 */
405 wakeup_swapper = 0;
404 x = sx->sx_lock;
405 atomic_store_rel_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1) |
406 (x & SX_LOCK_EXCLUSIVE_WAITERS));
407 if (x & SX_LOCK_SHARED_WAITERS)
406 x = sx->sx_lock;
407 atomic_store_rel_ptr(&sx->sx_lock, SX_SHARERS_LOCK(1) |
408 (x & SX_LOCK_EXCLUSIVE_WAITERS));
409 if (x & SX_LOCK_SHARED_WAITERS)
408 sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, 0,
409 SQ_SHARED_QUEUE);
410 wakeup_swapper = sleepq_broadcast(&sx->lock_object, SLEEPQ_SX,
411 0, SQ_SHARED_QUEUE);
410 sleepq_release(&sx->lock_object);
411
412 LOCK_LOG_LOCK("XDOWNGRADE", &sx->lock_object, 0, 0, file, line);
412 sleepq_release(&sx->lock_object);
413
414 LOCK_LOG_LOCK("XDOWNGRADE", &sx->lock_object, 0, 0, file, line);
415
416 if (wakeup_swapper)
417 kick_proc0();
413}
414
415/*
416 * This function represents the so-called 'hard case' for sx_xlock
417 * operation. All 'easy case' failures are redirected to this. Note
418 * that ideally this would be a static function, but it needs to be
419 * accessible from at least sx.h.
420 */

--- 163 unchanged lines hidden (view full) ---

584 * operation. All 'easy case' failures are redirected to this. Note
585 * that ideally this would be a static function, but it needs to be
586 * accessible from at least sx.h.
587 */
588void
589_sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line)
590{
591 uintptr_t x;
418}
419
420/*
421 * This function represents the so-called 'hard case' for sx_xlock
422 * operation. All 'easy case' failures are redirected to this. Note
423 * that ideally this would be a static function, but it needs to be
424 * accessible from at least sx.h.
425 */

--- 163 unchanged lines hidden (view full) ---

589 * operation. All 'easy case' failures are redirected to this. Note
590 * that ideally this would be a static function, but it needs to be
591 * accessible from at least sx.h.
592 */
593void
594_sx_xunlock_hard(struct sx *sx, uintptr_t tid, const char *file, int line)
595{
596 uintptr_t x;
592 int queue;
597 int queue, wakeup_swapper;
593
594 MPASS(!(sx->sx_lock & SX_LOCK_SHARED));
595
596 /* If the lock is recursed, then unrecurse one level. */
597 if (sx_xlocked(sx) && sx_recursed(sx)) {
598 if ((--sx->sx_recurse) == 0)
599 atomic_clear_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
600 if (LOCK_LOG_TEST(&sx->lock_object, 0))

--- 21 unchanged lines hidden (view full) ---

622 queue = SQ_EXCLUSIVE_QUEUE;
623
624 /* Wake up all the waiters for the specific queue. */
625 if (LOCK_LOG_TEST(&sx->lock_object, 0))
626 CTR3(KTR_LOCK, "%s: %p waking up all threads on %s queue",
627 __func__, sx, queue == SQ_SHARED_QUEUE ? "shared" :
628 "exclusive");
629 atomic_store_rel_ptr(&sx->sx_lock, x);
598
599 MPASS(!(sx->sx_lock & SX_LOCK_SHARED));
600
601 /* If the lock is recursed, then unrecurse one level. */
602 if (sx_xlocked(sx) && sx_recursed(sx)) {
603 if ((--sx->sx_recurse) == 0)
604 atomic_clear_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
605 if (LOCK_LOG_TEST(&sx->lock_object, 0))

--- 21 unchanged lines hidden (view full) ---

627 queue = SQ_EXCLUSIVE_QUEUE;
628
629 /* Wake up all the waiters for the specific queue. */
630 if (LOCK_LOG_TEST(&sx->lock_object, 0))
631 CTR3(KTR_LOCK, "%s: %p waking up all threads on %s queue",
632 __func__, sx, queue == SQ_SHARED_QUEUE ? "shared" :
633 "exclusive");
634 atomic_store_rel_ptr(&sx->sx_lock, x);
630 sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, 0, queue);
635 wakeup_swapper = sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, 0,
636 queue);
631 sleepq_release(&sx->lock_object);
637 sleepq_release(&sx->lock_object);
638 if (wakeup_swapper)
639 kick_proc0();
632}
633
634/*
635 * This function represents the so-called 'hard case' for sx_slock
636 * operation. All 'easy case' failures are redirected to this. Note
637 * that ideally this would be a static function, but it needs to be
638 * accessible from at least sx.h.
639 */

--- 150 unchanged lines hidden (view full) ---

790 * operation. All 'easy case' failures are redirected to this. Note
791 * that ideally this would be a static function, but it needs to be
792 * accessible from at least sx.h.
793 */
794void
795_sx_sunlock_hard(struct sx *sx, const char *file, int line)
796{
797 uintptr_t x;
640}
641
642/*
643 * This function represents the so-called 'hard case' for sx_slock
644 * operation. All 'easy case' failures are redirected to this. Note
645 * that ideally this would be a static function, but it needs to be
646 * accessible from at least sx.h.
647 */

--- 150 unchanged lines hidden (view full) ---

798 * operation. All 'easy case' failures are redirected to this. Note
799 * that ideally this would be a static function, but it needs to be
800 * accessible from at least sx.h.
801 */
802void
803_sx_sunlock_hard(struct sx *sx, const char *file, int line)
804{
805 uintptr_t x;
806 int wakeup_swapper;
798
799 for (;;) {
800 x = sx->sx_lock;
801
802 /*
803 * We should never have sharers while at least one thread
804 * holds a shared lock.
805 */

--- 51 unchanged lines hidden (view full) ---

857 SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS,
858 SX_LOCK_UNLOCKED)) {
859 sleepq_release(&sx->lock_object);
860 continue;
861 }
862 if (LOCK_LOG_TEST(&sx->lock_object, 0))
863 CTR2(KTR_LOCK, "%s: %p waking up all thread on"
864 "exclusive queue", __func__, sx);
807
808 for (;;) {
809 x = sx->sx_lock;
810
811 /*
812 * We should never have sharers while at least one thread
813 * holds a shared lock.
814 */

--- 51 unchanged lines hidden (view full) ---

866 SX_SHARERS_LOCK(1) | SX_LOCK_EXCLUSIVE_WAITERS,
867 SX_LOCK_UNLOCKED)) {
868 sleepq_release(&sx->lock_object);
869 continue;
870 }
871 if (LOCK_LOG_TEST(&sx->lock_object, 0))
872 CTR2(KTR_LOCK, "%s: %p waking up all thread on"
873 "exclusive queue", __func__, sx);
865 sleepq_broadcast(&sx->lock_object, SLEEPQ_SX, 0,
866 SQ_EXCLUSIVE_QUEUE);
874 wakeup_swapper = sleepq_broadcast(&sx->lock_object, SLEEPQ_SX,
875 0, SQ_EXCLUSIVE_QUEUE);
867 sleepq_release(&sx->lock_object);
876 sleepq_release(&sx->lock_object);
877 if (wakeup_swapper)
878 kick_proc0();
868 break;
869 }
870}
871
872#ifdef INVARIANT_SUPPORT
873#ifndef INVARIANTS
874#undef _sx_assert
875#endif

--- 161 unchanged lines hidden ---
879 break;
880 }
881}
882
883#ifdef INVARIANT_SUPPORT
884#ifndef INVARIANTS
885#undef _sx_assert
886#endif

--- 161 unchanged lines hidden ---