0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-10-18 09:58:43 +00:00

Route attributes now use the common lockfree usecount

Also route attributes are not freed immediately anymore.
This commit is contained in:
Maria Matejka 2024-06-04 14:58:45 +02:00 committed by Katerina Kubecova
parent fc1ea9119f
commit 4e60865a4d
2 changed files with 42 additions and 64 deletions

View File

@ -253,8 +253,10 @@ enum ea_stored {
struct ea_storage { struct ea_storage {
struct ea_storage *next_hash; /* Next in hash chain */ struct ea_storage *next_hash; /* Next in hash chain */
_Atomic u32 uc; /* Use count */ struct lfuc uc; /* Use count */
u32 hash_key; /* List hash */ u32 hash_key; /* List hash */
/* 32 bits unused but we don't wanna squeeze the use count
* into 32 bits to pack with the list hash, sorry */
ea_list l[0]; /* The list itself */ ea_list l[0]; /* The list itself */
}; };
@ -543,7 +545,7 @@ static inline struct ea_storage *ea_get_storage(ea_list *r)
static inline ea_list *ea_ref(ea_list *r) static inline ea_list *ea_ref(ea_list *r)
{ {
ASSERT_DIE(0 < atomic_fetch_add_explicit(&ea_get_storage(r)->uc, 1, memory_order_acq_rel)); lfuc_lock(&ea_get_storage(r)->uc);
return r; return r;
} }
@ -556,33 +558,25 @@ static inline ea_list *ea_lookup(ea_list *r, u32 squash_upto, enum ea_stored oid
return ea_lookup_slow(r, squash_upto, oid); return ea_lookup_slow(r, squash_upto, oid);
} }
struct ea_free_deferred { #define ea_free_later ea_free
struct deferred_call dc; extern event ea_cleanup_event;
ea_list *attrs; static inline void ea_free(ea_list *l)
};
void ea_free_deferred(struct deferred_call *dc);
static inline ea_list *ea_free_later(ea_list *r)
{ {
struct ea_free_deferred efd = { if (l)
.dc.hook = ea_free_deferred, lfuc_unlock(&ea_get_storage(l)->uc, &global_work_list, &ea_cleanup_event);
.attrs = r,
};
defer_call(&efd.dc, sizeof efd);
return r;
} }
static inline ea_list *ea_lookup_tmp(ea_list *r, u32 squash_upto, enum ea_stored oid) static inline ea_list *ea_lookup_tmp(ea_list *r, u32 squash_upto, enum ea_stored oid)
{ {
return ea_free_later(ea_lookup(r, squash_upto, oid)); ea_free_later(r = ea_lookup(r, squash_upto, oid));
return r;
} }
static inline ea_list *ea_ref_tmp(ea_list *r) static inline ea_list *ea_ref_tmp(ea_list *r)
{ {
ASSERT_DIE(r->stored); ASSERT_DIE(r->stored);
return ea_free_later(ea_ref(r)); ea_free_later(ea_ref(r));
return r;
} }
static inline ea_list *ea_strip_to(ea_list *r, u32 strip_to) static inline ea_list *ea_strip_to(ea_list *r, u32 strip_to)
@ -594,13 +588,6 @@ static inline ea_list *ea_strip_to(ea_list *r, u32 strip_to)
return r; return r;
} }
void ea__free(struct ea_storage *r);
static inline void ea_free(ea_list *l) {
if (!l) return;
struct ea_storage *r = ea_get_storage(l);
if (1 == atomic_fetch_sub_explicit(&r->uc, 1, memory_order_acq_rel)) ea__free(r);
}
void ea_dump(ea_list *); void ea_dump(ea_list *);
void ea_dump_all(void); void ea_dump_all(void);
void ea_show_list(struct cli *, ea_list *); void ea_show_list(struct cli *, ea_list *);

View File

@ -1227,8 +1227,6 @@ ea_list_ref(ea_list *l)
ea_ref(l->next); ea_ref(l->next);
} }
static void ea_free_nested(ea_list *l);
static void static void
ea_list_unref(ea_list *l) ea_list_unref(ea_list *l)
{ {
@ -1249,7 +1247,7 @@ ea_list_unref(ea_list *l)
} }
if (l->next) if (l->next)
ea_free_nested(l->next); lfuc_unlock(&ea_get_storage(l->next)->uc, &global_work_list, &ea_cleanup_event);
} }
void void
@ -1523,7 +1521,7 @@ ea_dump(ea_list *e)
(e->flags & EALF_SORTED) ? 'S' : 's', (e->flags & EALF_SORTED) ? 'S' : 's',
(e->flags & EALF_BISECT) ? 'B' : 'b', (e->flags & EALF_BISECT) ? 'B' : 'b',
e->stored, e->stored,
s ? atomic_load_explicit(&s->uc, memory_order_relaxed) : 0, s ? atomic_load_explicit(&s->uc.uc, memory_order_relaxed) : 0,
s ? s->hash_key : 0); s ? s->hash_key : 0);
for(i=0; i<e->count; i++) for(i=0; i<e->count; i++)
{ {
@ -1623,6 +1621,8 @@ ea_append(ea_list *to, ea_list *what)
* rta's * rta's
*/ */
event ea_cleanup_event;
static HASH(struct ea_storage) rta_hash_table; static HASH(struct ea_storage) rta_hash_table;
#define RTAH_KEY(a) a->l, a->hash_key #define RTAH_KEY(a) a->l, a->hash_key
@ -1675,7 +1675,7 @@ ea_lookup_slow(ea_list *o, u32 squash_upto, enum ea_stored oid)
if (r) if (r)
{ {
atomic_fetch_add_explicit(&r->uc, 1, memory_order_acq_rel); lfuc_lock_revive(&r->uc);
RTA_UNLOCK; RTA_UNLOCK;
return r->l; return r->l;
} }
@ -1699,7 +1699,9 @@ ea_lookup_slow(ea_list *o, u32 squash_upto, enum ea_stored oid)
r->l->flags |= huge; r->l->flags |= huge;
r->l->stored = oid; r->l->stored = oid;
r->hash_key = h; r->hash_key = h;
atomic_store_explicit(&r->uc, 1, memory_order_release);
memset(&r->uc, 0, sizeof r->uc);
lfuc_lock_revive(&r->uc);
HASH_INSERT2(rta_hash_table, RTAH, rta_pool, r); HASH_INSERT2(rta_hash_table, RTAH, rta_pool, r);
@ -1708,41 +1710,26 @@ ea_lookup_slow(ea_list *o, u32 squash_upto, enum ea_stored oid)
} }
static void static void
ea_free_locked(struct ea_storage *a) ea_cleanup(void *_ UNUSED)
{
/* Somebody has cloned this rta inbetween. This sometimes happens. */
if (atomic_load_explicit(&a->uc, memory_order_acquire))
return;
HASH_REMOVE2(rta_hash_table, RTAH, rta_pool, a);
ea_list_unref(a->l);
if (a->l->flags & EALF_HUGE)
mb_free(a);
else
sl_free(a);
}
static void
ea_free_nested(struct ea_list *l)
{
struct ea_storage *r = ea_get_storage(l);
if (1 == atomic_fetch_sub_explicit(&r->uc, 1, memory_order_acq_rel))
ea_free_locked(r);
}
void
ea__free(struct ea_storage *a)
{ {
RTA_LOCK; RTA_LOCK;
ea_free_locked(a);
RTA_UNLOCK;
}
void HASH_WALK_FILTER(rta_hash_table, next_hash, r, rp)
ea_free_deferred(struct deferred_call *dc) {
{ if (lfuc_finished(&r->uc))
ea_free(SKIP_BACK(struct ea_free_deferred, dc, dc)->attrs); {
HASH_DO_REMOVE(rta_hash_table, RTAH, rp);
ea_list_unref(r->l);
if (r->l->flags & EALF_HUGE)
mb_free(r);
else
sl_free(r);
}
}
HASH_WALK_FILTER_END;
RTA_UNLOCK;
} }
/** /**
@ -1800,6 +1787,10 @@ rta_init(void)
rte_src_init(); rte_src_init();
ea_class_init(); ea_class_init();
ea_cleanup_event = (event) {
.hook = ea_cleanup,
};
RTA_UNLOCK; RTA_UNLOCK;
/* These attributes are required to be first for nice "show route" output */ /* These attributes are required to be first for nice "show route" output */