0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

TMP: lockfree usecount and spinhash use callbacks

This commit is contained in:
Maria Matejka 2024-06-15 20:42:09 +02:00
parent 83045e9a1f
commit 6223c4066c
9 changed files with 46 additions and 58 deletions

View File

@ -218,8 +218,7 @@ struct { \
uint cur_order, new_order; \ uint cur_order, new_order; \
struct { type *data; rw_spinlock lock; } *cur, *new; \ struct { type *data; rw_spinlock lock; } *cur, *new; \
pool *pool; \ pool *pool; \
event rehash; \ callback rehash; \
event_list *target; \
} }
#define SPINHASH_INIT(v,id,_pool,_target) \ #define SPINHASH_INIT(v,id,_pool,_target) \
@ -230,19 +229,18 @@ struct { \
(v).cur = mb_allocz(_pool, (1U << id##_ORDER) * sizeof *(v).cur); \ (v).cur = mb_allocz(_pool, (1U << id##_ORDER) * sizeof *(v).cur); \
(v).new = NULL; \ (v).new = NULL; \
(v).pool = _pool; \ (v).pool = _pool; \
(v).rehash = (event) { .hook = id##_REHASH, .data = &(v), }; \ if (_target) callback_init(&(v).rehash, id##_REHASH, _target); \
(v).target = _target; \
}) })
#define SPINHASH_FREE(v) \ #define SPINHASH_FREE(v) \
({ \ ({ \
ev_postpone(&(v).rehash); \ callback_cancel(&(v).rehash); \
mb_free((v).cur); \ mb_free((v).cur); \
ASSERT_DIE((v).new == NULL); \ ASSERT_DIE((v).new == NULL); \
(v).cur = NULL; \ (v).cur = NULL; \
(v).cur_order = 0; \ (v).cur_order = 0; \
(v).pool = NULL; \ (v).pool = NULL; \
(v).target = NULL; \ (v).rehash = (callback) {}; \
}) })
#define SPINHASH_BEGIN_CHAIN(v,id,rw,n,key...) \ #define SPINHASH_BEGIN_CHAIN(v,id,rw,n,key...) \
@ -367,12 +365,12 @@ struct { \
}) })
#define SPINHASH_REQUEST_REHASH(v,id,count) \ #define SPINHASH_REQUEST_REHASH(v,id,count) \
if (SPINHASH_CHECK_REHASH(v,id,count) && (v).target) \ if ((v).rehash.target && SPINHASH_CHECK_REHASH(v,id,count)) \
ev_send((v).target, &(v).rehash); callback_activate(&(v).rehash); \
#define SPINHASH_DEFINE_REHASH_FN(id,type) \ #define SPINHASH_DEFINE_REHASH_FN(id,type) \
static void id##_REHASH(void *_v) { \ static void id##_REHASH(callback *cb) { \
SPINHASH(type) *v = _v; \ SKIP_BACK_DECLARE(SPINHASH(type), v, rehash, cb); \
SPINHASH_REHASH_FN_BODY(v,id,type); \ SPINHASH_REHASH_FN_BODY(v,id,type); \
} }

View File

@ -15,7 +15,7 @@
void lfuc_unlock_deferred(struct deferred_call *dc) void lfuc_unlock_deferred(struct deferred_call *dc)
{ {
SKIP_BACK_DECLARE(struct lfuc_unlock_queue_item, luqi, dc, dc); SKIP_BACK_DECLARE(struct lfuc_unlock_queue_item, luqi, dc, dc);
lfuc_unlock_immediately(luqi->c, luqi->el, luqi->ev); lfuc_unlock_immediately(luqi->c, luqi->cb);
} }
#if 0 #if 0

View File

@ -67,7 +67,7 @@ static inline u64 lfuc_lock_revive(struct lfuc *c)
* If the usecount reaches zero, a prune event is run to possibly free the object. * If the usecount reaches zero, a prune event is run to possibly free the object.
* The prune event MUST use lfuc_finished() to check the object state. * The prune event MUST use lfuc_finished() to check the object state.
*/ */
static inline void lfuc_unlock_immediately(struct lfuc *c, event_list *el, event *ev) static inline void lfuc_unlock_immediately(struct lfuc *c, struct callback *cb)
{ {
/* Unlocking is tricky. We do it lockless so at the same time, the prune /* Unlocking is tricky. We do it lockless so at the same time, the prune
* event may be running, therefore if the unlock gets us to zero, it must be * event may be running, therefore if the unlock gets us to zero, it must be
@ -98,7 +98,7 @@ static inline void lfuc_unlock_immediately(struct lfuc *c, event_list *el, event
if (uc == pending) if (uc == pending)
/* If we're the last unlocker (every owner is already unlocking), schedule /* If we're the last unlocker (every owner is already unlocking), schedule
* the owner's prune event */ * the owner's prune event */
ev_send(el, ev); callback_activate(cb);
else else
ASSERT_DIE(uc > pending); ASSERT_DIE(uc > pending);
@ -112,19 +112,17 @@ static inline void lfuc_unlock_immediately(struct lfuc *c, event_list *el, event
struct lfuc_unlock_queue_item { struct lfuc_unlock_queue_item {
struct deferred_call dc; struct deferred_call dc;
struct lfuc *c; struct lfuc *c;
event_list *el; struct callback *cb;
event *ev;
}; };
void lfuc_unlock_deferred(struct deferred_call *dc); void lfuc_unlock_deferred(struct deferred_call *dc);
static inline void lfuc_unlock(struct lfuc *c, event_list *el, event *ev) static inline void lfuc_unlock(struct lfuc *c, struct callback *cb)
{ {
struct lfuc_unlock_queue_item luqi = { struct lfuc_unlock_queue_item luqi = {
.dc.hook = lfuc_unlock_deferred, .dc.hook = lfuc_unlock_deferred,
.c = c, .c = c,
.el = el, .cb = cb,
.ev = ev,
}; };
defer_call(&luqi.dc, sizeof luqi); defer_call(&luqi.dc, sizeof luqi);

View File

@ -20,9 +20,9 @@
#define NETINDEX_REHASH netindex_rehash #define NETINDEX_REHASH netindex_rehash
#define NETINDEX_PARAMS /8, *2, 2, 2, 12, 28 #define NETINDEX_PARAMS /8, *2, 2, 2, 12, 28
static void NETINDEX_REHASH(void *_v) { static void NETINDEX_REHASH(callback *cb) {
log(L_TRACE "Netindex rehash: begin"); log(L_TRACE "Netindex rehash: begin");
netindex_spinhash *v = _v; SKIP_BACK_DECLARE(netindex_spinhash, v, rehash, cb);
int step; int step;
{ {
NH_LOCK(SKIP_BACK(netindex_hash, hash, v), _); NH_LOCK(SKIP_BACK(netindex_hash, hash, v), _);
@ -43,7 +43,7 @@ static void NETINDEX_REHASH(void *_v) {
log(L_TRACE "Netindex rehash: done"); log(L_TRACE "Netindex rehash: done");
} }
static void netindex_hash_cleanup(void *netindex_hash); static void netindex_hash_cleanup(callback *cb);
static struct netindex * static struct netindex *
net_lock_revive_unlock(netindex_hash *h, struct netindex *i) net_lock_revive_unlock(netindex_hash *h, struct netindex *i)
@ -52,7 +52,7 @@ net_lock_revive_unlock(netindex_hash *h, struct netindex *i)
return NULL; return NULL;
lfuc_lock_revive(&i->uc); lfuc_lock_revive(&i->uc);
lfuc_unlock(&i->uc, h->cleanup_list, &h->cleanup_event); lfuc_unlock(&i->uc, &h->cleanup);
return i; return i;
} }
@ -60,7 +60,7 @@ net_lock_revive_unlock(netindex_hash *h, struct netindex *i)
* Index initialization * Index initialization
*/ */
netindex_hash * netindex_hash *
netindex_hash_new(pool *sp, event_list *cleanup_target, u8 type) netindex_hash_new(pool *sp, struct birdloop *cleanup_target, u8 type)
{ {
DOMAIN(attrs) dom = DOMAIN_NEW_RCU_SYNC(attrs); DOMAIN(attrs) dom = DOMAIN_NEW_RCU_SYNC(attrs);
LOCK_DOMAIN(attrs, dom); LOCK_DOMAIN(attrs, dom);
@ -82,8 +82,7 @@ netindex_hash_new(pool *sp, event_list *cleanup_target, u8 type)
hmap_init(&nh->id_map, nh->pool, 128); hmap_init(&nh->id_map, nh->pool, 128);
nh->cleanup_list = cleanup_target; callback_init(&nh->cleanup, netindex_hash_cleanup, cleanup_target);
nh->cleanup_event = (event) { .hook = netindex_hash_cleanup, nh };
UNLOCK_DOMAIN(attrs, dom); UNLOCK_DOMAIN(attrs, dom);
return SKIP_BACK(netindex_hash, priv, nh); return SKIP_BACK(netindex_hash, priv, nh);
@ -123,9 +122,9 @@ netindex_hash_cleanup_removed(struct netindex_hash_private *nh, struct netindex
} }
static void static void
netindex_hash_cleanup(void *_nh) netindex_hash_cleanup(callback *cb)
{ {
struct netindex_hash_private *nh = _nh; SKIP_BACK_DECLARE(struct netindex_hash_private, nh, cleanup, cb);
DOMAIN(attrs) dom = nh->lock; DOMAIN(attrs) dom = nh->lock;
LOCK_DOMAIN(attrs, dom); LOCK_DOMAIN(attrs, dom);
@ -176,16 +175,16 @@ netindex_hash_cleanup(void *_nh)
kept += netindex_hash_cleanup_removed(nh, block, removed, removed_cnt); kept += netindex_hash_cleanup_removed(nh, block, removed, removed_cnt);
/* Return now unless we're deleted */ /* Return now unless we're deleted */
if (kept || !nh->deleted_event) if (kept || !nh->deleted)
{ {
UNLOCK_DOMAIN(attrs, dom); UNLOCK_DOMAIN(attrs, dom);
return; return;
} }
ev_postpone(&nh->cleanup_event); callback_cancel(&nh->cleanup);
event *e = nh->deleted_event; /* Store the callback */
event_list *t = nh->deleted_target; callback *cd = nh->deleted;
/* Check cleanliness */ /* Check cleanliness */
SPINHASH_WALK(nh->hash, NETINDEX, i) SPINHASH_WALK(nh->hash, NETINDEX, i)
@ -203,18 +202,16 @@ netindex_hash_cleanup(void *_nh)
DOMAIN_FREE(attrs, dom); DOMAIN_FREE(attrs, dom);
/* Notify the requestor */ /* Notify the requestor */
ev_send(t, e); callback_activate(cd);
} }
void void
netindex_hash_delete(netindex_hash *h, event *e, event_list *t) netindex_hash_delete(netindex_hash *h, callback *cb)
{ {
NH_LOCK(h, hp); NH_LOCK(h, hp);
hp->deleted_event = e; hp->deleted = cb;
hp->deleted_target = t; callback_activate(&hp->cleanup);
ev_send(hp->cleanup_list, &hp->cleanup_event);
} }
/* /*
@ -243,7 +240,7 @@ net_validate_index(netindex_hash *h, struct netindex *ni)
static struct netindex * static struct netindex *
net_new_index_locked(struct netindex_hash_private *hp, const net_addr *n) net_new_index_locked(struct netindex_hash_private *hp, const net_addr *n)
{ {
ASSERT_DIE(!hp->deleted_event); ASSERT_DIE(!hp->deleted);
u32 i = hmap_first_zero(&hp->id_map); u32 i = hmap_first_zero(&hp->id_map);
hmap_set(&hp->id_map, i); hmap_set(&hp->id_map, i);
@ -302,7 +299,7 @@ void net_lock_index(netindex_hash *h UNUSED, struct netindex *i)
void net_unlock_index(netindex_hash *h, struct netindex *i) void net_unlock_index(netindex_hash *h, struct netindex *i)
{ {
// log(L_TRACE "Unlock index %p", i); // log(L_TRACE "Unlock index %p", i);
lfuc_unlock(&i->uc, h->cleanup_list, &h->cleanup_event); lfuc_unlock(&i->uc, &h->cleanup);
} }
struct netindex * struct netindex *

View File

@ -28,8 +28,8 @@ struct netindex {
typedef union netindex_hash netindex_hash; typedef union netindex_hash netindex_hash;
/* Initialization and teardown */ /* Initialization and teardown */
netindex_hash *netindex_hash_new(pool *, event_list *, u8); netindex_hash *netindex_hash_new(pool *, struct birdloop *, u8);
void netindex_hash_delete(netindex_hash *, event *, event_list *); void netindex_hash_delete(netindex_hash *, callback *);
/* Find/get/resolve index; pointer valid until end of task */ /* Find/get/resolve index; pointer valid until end of task */
struct netindex *net_find_index(netindex_hash *, const net_addr *); struct netindex *net_find_index(netindex_hash *, const net_addr *);

View File

@ -15,8 +15,7 @@ typedef SPINHASH(struct netindex) netindex_spinhash;
#define NETINDEX_HASH_PUBLIC \ #define NETINDEX_HASH_PUBLIC \
DOMAIN(attrs) lock; /* Assigned lock */ \ DOMAIN(attrs) lock; /* Assigned lock */ \
event_list *cleanup_list; /* Cleanup event list */ \ callback cleanup; /* Usecount cleanup */ \
event cleanup_event; /* Cleanup event */ \
u8 net_type; /* Which NET_* is stored */ \ u8 net_type; /* Which NET_* is stored */ \
uint _Atomic block_size; /* How big block is */ \ uint _Atomic block_size; /* How big block is */ \
struct netindex * _Atomic * _Atomic block; /* u32 to netindex */ \ struct netindex * _Atomic * _Atomic block; /* u32 to netindex */ \
@ -29,8 +28,7 @@ struct netindex_hash_private {
slab *slab; slab *slab;
struct hmap id_map; struct hmap id_map;
u32 block_epoch; u32 block_epoch;
event *deleted_event; callback *deleted;
event_list *deleted_target;
}; };
typedef union netindex_hash { typedef union netindex_hash {

View File

@ -87,8 +87,7 @@ struct rte_owner {
u32 hash_key; u32 hash_key;
u32 uc; u32 uc;
u32 debug; u32 debug;
event_list *list; struct callback *prune_callback;
event *prune;
event *stop; event *stop;
}; };
@ -119,7 +118,7 @@ static inline void rt_lock_source(struct rte_src *src)
static inline void rt_unlock_source(struct rte_src *src) static inline void rt_unlock_source(struct rte_src *src)
{ {
lfuc_unlock(&src->uc, src->owner->list, src->owner->prune); lfuc_unlock(&src->uc, src->owner->prune_callback);
} }
#ifdef RT_SOURCE_DEBUG #ifdef RT_SOURCE_DEBUG

View File

@ -93,7 +93,7 @@ static void mpls_remove_range(struct mpls_range *r);
static void mpls_cleanup_ranges(void *_domain); static void mpls_cleanup_ranges(void *_domain);
static void mpls_free_fec(struct mpls_fec_map *m, struct mpls_fec *fec); static void mpls_free_fec(struct mpls_fec_map *m, struct mpls_fec *fec);
static void mpls_fec_map_cleanup(void *_m); static void mpls_fec_map_cleanup(callback *cb);
/* /*
* MPLS domain * MPLS domain
@ -659,7 +659,7 @@ mpls_channel_shutdown(struct channel *C)
if (!c->rts) if (!c->rts)
return; return;
ev_send_loop(c->mpls_map->loop, c->mpls_map->cleanup_event); callback_activate(&c->mpls_map->cleanup);
} }
static void static void
@ -792,8 +792,7 @@ mpls_fec_map_new(pool *pp, struct birdloop *loop, struct channel *C, uint rts)
DBGL("New FEC Map %p", m); DBGL("New FEC Map %p", m);
m->pool = p; m->pool = p;
m->loop = loop; callback_init(&m->cleanup, mpls_fec_map_cleanup, loop);
m->cleanup_event = ev_new_init(p, mpls_fec_map_cleanup, m);
m->channel = C; m->channel = C;
channel_add_obstacle(C); channel_add_obstacle(C);
@ -881,9 +880,9 @@ mpls_fec_map_reconfigure(struct mpls_fec_map *m, struct channel *C)
} }
static void static void
mpls_fec_map_cleanup(void *_m) mpls_fec_map_cleanup(callback *cb)
{ {
struct mpls_fec_map *m = _m; SKIP_BACK_DECLARE(struct mpls_fec_map, m, cleanup, cb);
_Bool finished = (m->channel->channel_state == CS_STOP); _Bool finished = (m->channel->channel_state == CS_STOP);
HASH_WALK_DELSAFE(m->label_hash, next_l, fec) HASH_WALK_DELSAFE(m->label_hash, next_l, fec)
if (lfuc_finished(&fec->uc)) if (lfuc_finished(&fec->uc))
@ -896,7 +895,7 @@ mpls_fec_map_cleanup(void *_m)
if (finished) if (finished)
{ {
ev_postpone(m->cleanup_event); callback_cancel(&m->cleanup);
channel_del_obstacle(m->channel); channel_del_obstacle(m->channel);
} }
} }
@ -1193,7 +1192,7 @@ inline void mpls_lock_fec(struct mpls_fec *fec)
inline void mpls_unlock_fec(struct mpls_fec *fec) inline void mpls_unlock_fec(struct mpls_fec *fec)
{ {
lfuc_unlock(&fec->uc, birdloop_event_list(fec->map->loop), fec->map->cleanup_event); lfuc_unlock(&fec->uc, &fec->map->cleanup);
DBGL("Unlocked FEC %p %u (deferred)", fec, fec->label); DBGL("Unlocked FEC %p %u (deferred)", fec, fec->label);
} }

View File

@ -124,8 +124,7 @@ struct mpls_fec {
struct mpls_fec_map { struct mpls_fec_map {
pool *pool; /* Pool for FEC map */ pool *pool; /* Pool for FEC map */
struct birdloop *loop; /* Owner's loop for sending events */ callback cleanup; /* Callback for unlocked FEC cleanup */
event *cleanup_event; /* Event for unlocked FEC cleanup */
slab *slabs[4]; /* Slabs for FEC allocation */ slab *slabs[4]; /* Slabs for FEC allocation */
HASH(struct mpls_fec) net_hash; /* Hash table for MPLS_POLICY_PREFIX FECs */ HASH(struct mpls_fec) net_hash; /* Hash table for MPLS_POLICY_PREFIX FECs */
HASH(struct mpls_fec) attrs_hash; /* Hash table for MPLS_POLICY_AGGREGATE FECs */ HASH(struct mpls_fec) attrs_hash; /* Hash table for MPLS_POLICY_AGGREGATE FECs */