mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 17:51:53 +00:00
Lock position checking allows for safe lock unions
This commit is contained in:
parent
1289c1c5ee
commit
df3264f51f
@ -16,16 +16,14 @@ struct lock_order {
|
|||||||
struct domain_generic *the_bird;
|
struct domain_generic *the_bird;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LOCK_ORDER_DEPTH (sizeof(struct lock_order) / sizeof(struct domain_generic *))
|
|
||||||
|
|
||||||
extern _Thread_local struct lock_order locking_stack;
|
extern _Thread_local struct lock_order locking_stack;
|
||||||
extern _Thread_local struct domain_generic **last_locked;
|
extern _Thread_local struct domain_generic **last_locked;
|
||||||
|
|
||||||
#define DOMAIN(type) struct domain__##type
|
#define DOMAIN(type) struct domain__##type
|
||||||
#define DEFINE_DOMAIN(type) DOMAIN(type) { struct domain_generic *type; }
|
#define DEFINE_DOMAIN(type) DOMAIN(type) { struct domain_generic *type; }
|
||||||
|
|
||||||
#define DOMAIN_NEW(type, name) (DOMAIN(type)) { .type = domain_new(name) }
|
#define DOMAIN_NEW(type, name) (DOMAIN(type)) { .type = domain_new(name, OFFSETOF(struct lock_order, type)) }
|
||||||
struct domain_generic *domain_new(const char *name);
|
struct domain_generic *domain_new(const char *name, uint order);
|
||||||
|
|
||||||
#define DOMAIN_NULL(type) (DOMAIN(type)) {}
|
#define DOMAIN_NULL(type) (DOMAIN(type)) {}
|
||||||
|
|
||||||
|
@ -44,26 +44,31 @@
|
|||||||
* Locking subsystem
|
* Locking subsystem
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
_Thread_local struct lock_order locking_stack = {};
|
||||||
|
_Thread_local struct domain_generic **last_locked = NULL;
|
||||||
|
|
||||||
#define ASSERT_NO_LOCK ASSERT_DIE(last_locked == NULL)
|
#define ASSERT_NO_LOCK ASSERT_DIE(last_locked == NULL)
|
||||||
|
|
||||||
struct domain_generic {
|
struct domain_generic {
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
uint order;
|
||||||
struct domain_generic **prev;
|
struct domain_generic **prev;
|
||||||
struct lock_order *locked_by;
|
struct lock_order *locked_by;
|
||||||
const char *name;
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DOMAIN_INIT(_name) { .mutex = PTHREAD_MUTEX_INITIALIZER, .name = _name }
|
#define DOMAIN_INIT(_name, _order) { .mutex = PTHREAD_MUTEX_INITIALIZER, .name = _name, .order = _order }
|
||||||
|
|
||||||
static struct domain_generic the_bird_domain_gen = DOMAIN_INIT("The BIRD");
|
static struct domain_generic the_bird_domain_gen = DOMAIN_INIT("The BIRD", OFFSETOF(struct lock_order, the_bird));
|
||||||
|
|
||||||
DOMAIN(the_bird) the_bird_domain = { .the_bird = &the_bird_domain_gen };
|
DOMAIN(the_bird) the_bird_domain = { .the_bird = &the_bird_domain_gen };
|
||||||
|
|
||||||
struct domain_generic *
|
struct domain_generic *
|
||||||
domain_new(const char *name)
|
domain_new(const char *name, uint order)
|
||||||
{
|
{
|
||||||
|
ASSERT_DIE(order < sizeof(struct lock_order));
|
||||||
struct domain_generic *dg = xmalloc(sizeof(struct domain_generic));
|
struct domain_generic *dg = xmalloc(sizeof(struct domain_generic));
|
||||||
*dg = (struct domain_generic) DOMAIN_INIT(name);
|
*dg = (struct domain_generic) DOMAIN_INIT(name, order);
|
||||||
return dg;
|
return dg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,11 +79,11 @@ domain_free(struct domain_generic *dg)
|
|||||||
xfree(dg);
|
xfree(dg);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Thread_local struct lock_order locking_stack = {};
|
|
||||||
_Thread_local struct domain_generic **last_locked = NULL;
|
|
||||||
|
|
||||||
void do_lock(struct domain_generic *dg, struct domain_generic **lsp)
|
void do_lock(struct domain_generic *dg, struct domain_generic **lsp)
|
||||||
{
|
{
|
||||||
|
if ((char *) lsp - (char *) &locking_stack != dg->order)
|
||||||
|
bug("Trying to lock on bad position: order=%u, lsp=%p, base=%p", dg->order, lsp, &locking_stack);
|
||||||
|
|
||||||
if (lsp <= last_locked)
|
if (lsp <= last_locked)
|
||||||
bug("Trying to lock in a bad order");
|
bug("Trying to lock in a bad order");
|
||||||
if (*lsp)
|
if (*lsp)
|
||||||
@ -96,6 +101,9 @@ void do_lock(struct domain_generic *dg, struct domain_generic **lsp)
|
|||||||
|
|
||||||
void do_unlock(struct domain_generic *dg, struct domain_generic **lsp)
|
void do_unlock(struct domain_generic *dg, struct domain_generic **lsp)
|
||||||
{
|
{
|
||||||
|
if ((char *) lsp - (char *) &locking_stack != dg->order)
|
||||||
|
bug("Trying to unlock on bad position: order=%u, lsp=%p, base=%p", dg->order, lsp, &locking_stack);
|
||||||
|
|
||||||
if (dg->locked_by != &locking_stack)
|
if (dg->locked_by != &locking_stack)
|
||||||
bug("Inconsistent domain state on unlock");
|
bug("Inconsistent domain state on unlock");
|
||||||
if ((last_locked != lsp) || (*lsp != dg))
|
if ((last_locked != lsp) || (*lsp != dg))
|
||||||
|
Loading…
Reference in New Issue
Block a user