kernel: add functions for safely (un)locking pairs of objects

when locking a pair of objects, the object with the lesser memory address
is always locked first. the pair is unlocked in the opposite order.
This commit is contained in:
2026-02-26 19:38:49 +00:00
parent 1c7c90ef39
commit 1cdde0d32e
2 changed files with 55 additions and 0 deletions

View File

@@ -31,6 +31,20 @@ extern "C" {
unsigned long flags) \ unsigned long flags) \
{ \ { \
object_unlock_irqrestore(&p->base, flags); \ object_unlock_irqrestore(&p->base, flags); \
} \
static inline void object_name##_lock_pair_irqsave( \
struct object_name *a, \
struct object_name *b, \
unsigned long *flags) \
{ \
object_lock_pair_irqsave(&a->base, &b->base, flags); \
} \
static inline void object_name##_unlock_pair_irqrestore( \
struct object_name *a, \
struct object_name *b, \
unsigned long flags) \
{ \
object_unlock_pair_irqrestore(&a->base, &b->base, flags); \
} }
#define OBJECT_MAGIC 0xBADDCAFE #define OBJECT_MAGIC 0xBADDCAFE
@@ -92,6 +106,15 @@ extern void object_unlock(struct object *obj);
extern void object_lock_irqsave(struct object *obj, unsigned long *flags); extern void object_lock_irqsave(struct object *obj, unsigned long *flags);
extern void object_unlock_irqrestore(struct object *obj, unsigned long flags); extern void object_unlock_irqrestore(struct object *obj, unsigned long flags);
extern void object_lock_pair_irqsave(
struct object *a,
struct object *b,
unsigned long *flags);
extern void object_unlock_pair_irqrestore(
struct object *a,
struct object *b,
unsigned long flags);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -178,6 +178,38 @@ void object_unlock_irqrestore(struct object *obj, unsigned long flags)
spin_unlock_irqrestore(&obj->ob_lock, flags); spin_unlock_irqrestore(&obj->ob_lock, flags);
} }
void object_lock_pair_irqsave(
struct object *a,
struct object *b,
unsigned long *flags)
{
if (a == b) {
object_lock_irqsave(a, flags);
} else if (a < b) {
object_lock_irqsave(a, flags);
object_lock(b);
} else {
object_lock_irqsave(b, flags);
object_lock(a);
}
}
void object_unlock_pair_irqrestore(
struct object *a,
struct object *b,
unsigned long flags)
{
if (a == b) {
object_unlock_irqrestore(a, flags);
} else if (a < b) {
object_unlock(b);
object_unlock_irqrestore(a, flags);
} else {
object_unlock(a);
object_unlock_irqrestore(b, flags);
}
}
void *object_data(struct object *obj) void *object_data(struct object *obj)
{ {
return (char *)obj + sizeof *obj; return (char *)obj + sizeof *obj;