Add sx_try_upgrade() and sx_downgrade().
Submitted by: Alexander Kabaev <ak03@gte.com>
This commit is contained in:
parent
9c347fa626
commit
d55229b72e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=81599
@ -169,6 +169,8 @@ MLINKS+=sx.9 sx_try_slock.9
|
|||||||
MLINKS+=sx.9 sx_try_xlock.9
|
MLINKS+=sx.9 sx_try_xlock.9
|
||||||
MLINKS+=sx.9 sx_sunlock.9
|
MLINKS+=sx.9 sx_sunlock.9
|
||||||
MLINKS+=sx.9 sx_xunlock.9
|
MLINKS+=sx.9 sx_xunlock.9
|
||||||
|
MLINKS+=sx.9 sx_try_upgrade.9
|
||||||
|
MLINKS+=sx.9 sx_downgrade.9
|
||||||
MLINKS+=time.9 boottime.9 time.9 mono_time.9 time.9 runtime.9
|
MLINKS+=time.9 boottime.9 time.9 mono_time.9 time.9 runtime.9
|
||||||
MLINKS+=timeout.9 untimeout.9
|
MLINKS+=timeout.9 untimeout.9
|
||||||
MLINKS+=timeout.9 callout_handle_init.9 timeout.9 callout_init.9
|
MLINKS+=timeout.9 callout_handle_init.9 timeout.9 callout_init.9
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
.Nm sx_try_xlock ,
|
.Nm sx_try_xlock ,
|
||||||
.Nm sx_sunlock ,
|
.Nm sx_sunlock ,
|
||||||
.Nm sx_xunlock
|
.Nm sx_xunlock
|
||||||
|
.Nm sx_try_upgrade
|
||||||
|
.Nm sx_downgrade
|
||||||
.Nd kernel shared/exclusive lock
|
.Nd kernel shared/exclusive lock
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Fd #include <sys/types.h>
|
.Fd #include <sys/types.h>
|
||||||
@ -61,6 +63,10 @@
|
|||||||
.Fn sx_sunlock "struct sx *sx"
|
.Fn sx_sunlock "struct sx *sx"
|
||||||
.Ft void
|
.Ft void
|
||||||
.Fn sx_xunlock "struct sx *sx"
|
.Fn sx_xunlock "struct sx *sx"
|
||||||
|
.Ft int
|
||||||
|
.Fn sx_try_upgrade "struct sx *sx"
|
||||||
|
.Ft void
|
||||||
|
.Fn sx_downgrade "struct sx *sx"
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
Shared/exclusive locks are used to protect data that are read far more often
|
Shared/exclusive locks are used to protect data that are read far more often
|
||||||
than they are written.
|
than they are written.
|
||||||
@ -91,6 +97,12 @@ or
|
|||||||
.Fn sx_try_xlock
|
.Fn sx_try_xlock
|
||||||
and
|
and
|
||||||
.Fn sx_xunlock .
|
.Fn sx_xunlock .
|
||||||
|
A thread can attempt to upgrade a currently owned shared lock to an exclusive
|
||||||
|
lock by calling
|
||||||
|
.Fn sx_try_upgrade .
|
||||||
|
A thread that owns an exclusive lock can downgrade it to a shared lock by
|
||||||
|
calling
|
||||||
|
.Fn sx_downgrade .
|
||||||
.Pp
|
.Pp
|
||||||
.Fn sx_try_slock
|
.Fn sx_try_slock
|
||||||
and
|
and
|
||||||
@ -99,6 +111,11 @@ will return 0 if the shared/exclusive lock cannot be acquired immediately;
|
|||||||
otherwise the shared/exclusive lock will be acquired and a non-zero value will
|
otherwise the shared/exclusive lock will be acquired and a non-zero value will
|
||||||
be returned.
|
be returned.
|
||||||
.Pp
|
.Pp
|
||||||
|
.Fn sx_try_upgrade
|
||||||
|
will return 0 if the shared lock cannot be upgraded to an exclusive lock
|
||||||
|
immediately; otherwise the exclusive lock will be acquired and a non-zero value
|
||||||
|
will be returned.
|
||||||
|
.Pp
|
||||||
A thread may not own a shared lock and an exclusive lock simultaneously;
|
A thread may not own a shared lock and an exclusive lock simultaneously;
|
||||||
attempting to do so will result in deadlock.
|
attempting to do so will result in deadlock.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
|
@ -245,3 +245,49 @@ _sx_xunlock(struct sx *sx, const char *file, int line)
|
|||||||
|
|
||||||
mtx_unlock(&sx->sx_lock);
|
mtx_unlock(&sx->sx_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_sx_try_upgrade(struct sx *sx, const char *file, int line)
|
||||||
|
{
|
||||||
|
|
||||||
|
mtx_lock(&sx->sx_lock);
|
||||||
|
_SX_ASSERT_SLOCKED(sx, file, line);
|
||||||
|
|
||||||
|
if (sx->sx_cnt == 1) {
|
||||||
|
WITNESS_UNLOCK(&sx->sx_object, 0, file, line);
|
||||||
|
|
||||||
|
sx->sx_cnt = -1;
|
||||||
|
sx->sx_xholder = curproc;
|
||||||
|
|
||||||
|
LOCK_LOG_TRY("XUPGRADE", &sx->sx_object, 0, 1, file, line);
|
||||||
|
WITNESS_LOCK(&sx->sx_object, LOP_EXCLUSIVE | LOP_TRYLOCK, file,
|
||||||
|
line);
|
||||||
|
|
||||||
|
mtx_unlock(&sx->sx_lock);
|
||||||
|
return (1);
|
||||||
|
} else {
|
||||||
|
LOCK_LOG_TRY("XUPGRADE", &sx->sx_object, 0, 0, file, line);
|
||||||
|
mtx_unlock(&sx->sx_lock);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_sx_downgrade(struct sx *sx, const char *file, int line)
|
||||||
|
{
|
||||||
|
|
||||||
|
mtx_lock(&sx->sx_lock);
|
||||||
|
_SX_ASSERT_XLOCKED(sx, file, line);
|
||||||
|
MPASS(sx->sx_cnt == -1);
|
||||||
|
|
||||||
|
WITNESS_UNLOCK(&sx->sx_object, LOP_EXCLUSIVE, file, line);
|
||||||
|
|
||||||
|
sx->sx_cnt = 1;
|
||||||
|
if (sx->sx_shrd_wcnt > 0)
|
||||||
|
cv_broadcast(&sx->sx_shrd_cv);
|
||||||
|
|
||||||
|
LOCK_LOG_LOCK("XDOWNGRADE", &sx->sx_object, 0, 0, file, line);
|
||||||
|
WITNESS_LOCK(&sx->sx_object, 0, file, line);
|
||||||
|
|
||||||
|
mtx_unlock(&sx->sx_lock);
|
||||||
|
}
|
||||||
|
@ -54,6 +54,8 @@ int _sx_try_slock(struct sx *sx, const char *file, int line);
|
|||||||
int _sx_try_xlock(struct sx *sx, const char *file, int line);
|
int _sx_try_xlock(struct sx *sx, const char *file, int line);
|
||||||
void _sx_sunlock(struct sx *sx, const char *file, int line);
|
void _sx_sunlock(struct sx *sx, const char *file, int line);
|
||||||
void _sx_xunlock(struct sx *sx, const char *file, int line);
|
void _sx_xunlock(struct sx *sx, const char *file, int line);
|
||||||
|
int _sx_try_upgrade(struct sx *sx, const char *file, int line);
|
||||||
|
void _sx_downgrade(struct sx *sx, const char *file, int line);
|
||||||
|
|
||||||
#define sx_slock(sx) _sx_slock((sx), __FILE__, __LINE__)
|
#define sx_slock(sx) _sx_slock((sx), __FILE__, __LINE__)
|
||||||
#define sx_xlock(sx) _sx_xlock((sx), __FILE__, __LINE__)
|
#define sx_xlock(sx) _sx_xlock((sx), __FILE__, __LINE__)
|
||||||
@ -61,6 +63,8 @@ void _sx_xunlock(struct sx *sx, const char *file, int line);
|
|||||||
#define sx_try_xlock(sx) _sx_try_xlock((sx), __FILE__, __LINE__)
|
#define sx_try_xlock(sx) _sx_try_xlock((sx), __FILE__, __LINE__)
|
||||||
#define sx_sunlock(sx) _sx_sunlock((sx), __FILE__, __LINE__)
|
#define sx_sunlock(sx) _sx_sunlock((sx), __FILE__, __LINE__)
|
||||||
#define sx_xunlock(sx) _sx_xunlock((sx), __FILE__, __LINE__)
|
#define sx_xunlock(sx) _sx_xunlock((sx), __FILE__, __LINE__)
|
||||||
|
#define sx_try_upgrade(sx) _sx_try_upgrade((sx), __FILE__, __LINE__)
|
||||||
|
#define sx_downgrade(sx) _sx_downgrade((sx), __FILE__, __LINE__)
|
||||||
|
|
||||||
#ifdef INVARIANTS
|
#ifdef INVARIANTS
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user