From 1cdde0d32e34c5849aa647d0a3a017406e47ff84 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Thu, 26 Feb 2026 19:38:49 +0000 Subject: [PATCH] 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. --- include/kernel/object.h | 23 +++++++++++++++++++++++ kernel/object.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/include/kernel/object.h b/include/kernel/object.h index 686ab2e..55db392 100644 --- a/include/kernel/object.h +++ b/include/kernel/object.h @@ -31,6 +31,20 @@ extern "C" { unsigned long 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 @@ -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_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 } #endif diff --git a/kernel/object.c b/kernel/object.c index abcd84b..c05339d 100644 --- a/kernel/object.c +++ b/kernel/object.c @@ -178,6 +178,38 @@ void object_unlock_irqrestore(struct object *obj, unsigned long 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) { return (char *)obj + sizeof *obj;