lockmgr: shrink struct lock by 8 bytes on LP64

Currently the struct has a 4 byte padding stemming from 3 ints.

1. prio comfortably fits in short, unfortunately there is no dedicated
   type for it and plumbing it throughout the codebase is not worth it
   right now, instead an assert is added which covers also flags for
   safety
2. lk_exslpfail can in principle exceed u_short, but the count is
   already not considered reliable and it only ever gets modified
   straight to 0. In other words it can be incrementing with an upper
   bound of USHRT_MAX

With these in place struct lock shrinks from 48 to 40 bytes.

Reviewed by:	kib (previous version)
Differential Revision:	https://reviews.freebsd.org/D28680
This commit is contained in:
Mateusz Guzik 2021-02-15 05:24:17 +01:00
parent cc743b050a
commit eac22dd480
4 changed files with 20 additions and 10 deletions

View File

@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kdb.h>
#include <sys/ktr.h>
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/lock_profile.h>
#include <sys/lockmgr.h>
@ -61,6 +62,12 @@ __FBSDID("$FreeBSD$");
PMC_SOFT_DECLARE( , , lock, failed);
#endif
/*
* Hack. There should be prio_t or similar so that this is not necessary.
*/
_Static_assert((PRILASTFLAG * 2) - 1 <= USHRT_MAX,
"prio flags wont fit in u_short pri in struct lock");
CTASSERT(LK_UNLOCKED == (LK_UNLOCKED &
~(LK_ALL_WAITERS | LK_EXCLUSIVE_SPINNERS)));
@ -280,8 +287,10 @@ sleeplk(struct lock *lk, u_int flags, struct lock_object *ilk,
if (flags & LK_INTERLOCK)
class->lc_unlock(ilk);
if (queue == SQ_EXCLUSIVE_QUEUE && (flags & LK_SLEEPFAIL) != 0)
lk->lk_exslpfail++;
if (queue == SQ_EXCLUSIVE_QUEUE && (flags & LK_SLEEPFAIL) != 0) {
if (lk->lk_exslpfail < USHRT_MAX)
lk->lk_exslpfail++;
}
GIANT_SAVE();
sleepq_add(&lk->lock_object, NULL, wmesg, SLEEPQ_LK | (catch ?
SLEEPQ_INTERRUPTIBLE : 0), queue);
@ -345,7 +354,7 @@ wakeupshlk(struct lock *lk, const char *file, int line)
realexslp = sleepq_sleepcnt(&lk->lock_object,
SQ_EXCLUSIVE_QUEUE);
if ((x & LK_EXCLUSIVE_WAITERS) != 0 && realexslp != 0) {
if (lk->lk_exslpfail < realexslp) {
if (lk->lk_exslpfail != USHRT_MAX && lk->lk_exslpfail < realexslp) {
lk->lk_exslpfail = 0;
queue = SQ_EXCLUSIVE_QUEUE;
v |= (x & LK_SHARED_WAITERS);
@ -362,7 +371,6 @@ wakeupshlk(struct lock *lk, const char *file, int line)
SLEEPQ_LK, 0, SQ_EXCLUSIVE_QUEUE);
queue = SQ_SHARED_QUEUE;
}
} else {
/*
* Exclusive waiters sleeping with LK_SLEEPFAIL on
@ -1170,7 +1178,7 @@ lockmgr_xunlock_hard(struct lock *lk, uintptr_t x, u_int flags, struct lock_obje
MPASS((x & LK_EXCLUSIVE_SPINNERS) == 0);
realexslp = sleepq_sleepcnt(&lk->lock_object, SQ_EXCLUSIVE_QUEUE);
if ((x & LK_EXCLUSIVE_WAITERS) != 0 && realexslp != 0) {
if (lk->lk_exslpfail < realexslp) {
if (lk->lk_exslpfail != USHRT_MAX && lk->lk_exslpfail < realexslp) {
lk->lk_exslpfail = 0;
queue = SQ_EXCLUSIVE_QUEUE;
v |= (x & LK_SHARED_WAITERS);

View File

@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/lock_profile.h>
#include <sys/malloc.h>

View File

@ -40,9 +40,9 @@
struct lock {
struct lock_object lock_object;
volatile uintptr_t lk_lock;
u_int lk_exslpfail;
u_short lk_exslpfail;
u_short lk_pri;
int lk_timo;
int lk_pri;
#ifdef DEBUG_LOCKS
struct stack lk_stack;
#endif

View File

@ -227,9 +227,10 @@
((off_t)(db) << DEV_BSHIFT)
#endif
#define PRIMASK 0x0ff
#define PCATCH 0x100 /* OR'd with pri for tsleep to check signals */
#define PDROP 0x200 /* OR'd with pri to stop re-entry of interlock mutex */
#define PRIMASK 0x0ff
#define PCATCH 0x100 /* OR'd with pri for tsleep to check signals */
#define PDROP 0x200 /* OR'd with pri to stop re-entry of interlock mutex */
#define PRILASTFLAG 0x200 /* Last flag defined above */
#define NZERO 0 /* default "nice" */