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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user