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

View File

@ -15,7 +15,7 @@
void lfuc_unlock_deferred(struct deferred_call *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

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.
* 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
* 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 we're the last unlocker (every owner is already unlocking), schedule
* the owner's prune event */
ev_send(el, ev);
callback_activate(cb);
else
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 deferred_call dc;
struct lfuc *c;
event_list *el;
event *ev;
struct callback *cb;
};
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 = {
.dc.hook = lfuc_unlock_deferred,
.c = c,
.el = el,
.ev = ev,
.cb = cb,
};
defer_call(&luqi.dc, sizeof luqi);

View File

@ -20,9 +20,9 @@
#define NETINDEX_REHASH netindex_rehash
#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");
netindex_spinhash *v = _v;
SKIP_BACK_DECLARE(netindex_spinhash, v, rehash, cb);
int step;
{
NH_LOCK(SKIP_BACK(netindex_hash, hash, v), _);
@ -43,7 +43,7 @@ static void NETINDEX_REHASH(void *_v) {
log(L_TRACE "Netindex rehash: done");
}
static void netindex_hash_cleanup(void *netindex_hash);
static void netindex_hash_cleanup(callback *cb);
static struct netindex *
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;
lfuc_lock_revive(&i->uc);
lfuc_unlock(&i->uc, h->cleanup_list, &h->cleanup_event);
lfuc_unlock(&i->uc, &h->cleanup);
return i;
}
@ -60,7 +60,7 @@ net_lock_revive_unlock(netindex_hash *h, struct netindex *i)
* Index initialization
*/
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);
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);
nh->cleanup_list = cleanup_target;
nh->cleanup_event = (event) { .hook = netindex_hash_cleanup, nh };
callback_init(&nh->cleanup, netindex_hash_cleanup, cleanup_target);
UNLOCK_DOMAIN(attrs, dom);
return SKIP_BACK(netindex_hash, priv, nh);
@ -123,9 +122,9 @@ netindex_hash_cleanup_removed(struct netindex_hash_private *nh, struct netindex
}
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;
LOCK_DOMAIN(attrs, dom);
@ -176,16 +175,16 @@ netindex_hash_cleanup(void *_nh)
kept += netindex_hash_cleanup_removed(nh, block, removed, removed_cnt);
/* Return now unless we're deleted */
if (kept || !nh->deleted_event)
if (kept || !nh->deleted)
{
UNLOCK_DOMAIN(attrs, dom);
return;
}
ev_postpone(&nh->cleanup_event);
callback_cancel(&nh->cleanup);
event *e = nh->deleted_event;
event_list *t = nh->deleted_target;
/* Store the callback */
callback *cd = nh->deleted;
/* Check cleanliness */
SPINHASH_WALK(nh->hash, NETINDEX, i)
@ -203,18 +202,16 @@ netindex_hash_cleanup(void *_nh)
DOMAIN_FREE(attrs, dom);
/* Notify the requestor */
ev_send(t, e);
callback_activate(cd);
}
void
netindex_hash_delete(netindex_hash *h, event *e, event_list *t)
netindex_hash_delete(netindex_hash *h, callback *cb)
{
NH_LOCK(h, hp);
hp->deleted_event = e;
hp->deleted_target = t;
ev_send(hp->cleanup_list, &hp->cleanup_event);
hp->deleted = cb;
callback_activate(&hp->cleanup);
}
/*
@ -243,7 +240,7 @@ net_validate_index(netindex_hash *h, struct netindex *ni)
static struct netindex *
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);
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)
{
// 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 *

View File

@ -28,8 +28,8 @@ struct netindex {
typedef union netindex_hash netindex_hash;
/* Initialization and teardown */
netindex_hash *netindex_hash_new(pool *, event_list *, u8);
void netindex_hash_delete(netindex_hash *, event *, event_list *);
netindex_hash *netindex_hash_new(pool *, struct birdloop *, u8);
void netindex_hash_delete(netindex_hash *, callback *);
/* Find/get/resolve index; pointer valid until end of task */
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 \
DOMAIN(attrs) lock; /* Assigned lock */ \
event_list *cleanup_list; /* Cleanup event list */ \
event cleanup_event; /* Cleanup event */ \
callback cleanup; /* Usecount cleanup */ \
u8 net_type; /* Which NET_* is stored */ \
uint _Atomic block_size; /* How big block is */ \
struct netindex * _Atomic * _Atomic block; /* u32 to netindex */ \
@ -29,8 +28,7 @@ struct netindex_hash_private {
slab *slab;
struct hmap id_map;
u32 block_epoch;
event *deleted_event;
event_list *deleted_target;
callback *deleted;
};
typedef union netindex_hash {

View File

@ -87,8 +87,7 @@ struct rte_owner {
u32 hash_key;
u32 uc;
u32 debug;
event_list *list;
event *prune;
struct callback *prune_callback;
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)
{
lfuc_unlock(&src->uc, src->owner->list, src->owner->prune);
lfuc_unlock(&src->uc, src->owner->prune_callback);
}
#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_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
@ -659,7 +659,7 @@ mpls_channel_shutdown(struct channel *C)
if (!c->rts)
return;
ev_send_loop(c->mpls_map->loop, c->mpls_map->cleanup_event);
callback_activate(&c->mpls_map->cleanup);
}
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);
m->pool = p;
m->loop = loop;
m->cleanup_event = ev_new_init(p, mpls_fec_map_cleanup, m);
callback_init(&m->cleanup, mpls_fec_map_cleanup, loop);
m->channel = C;
channel_add_obstacle(C);
@ -881,9 +880,9 @@ mpls_fec_map_reconfigure(struct mpls_fec_map *m, struct channel *C)
}
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);
HASH_WALK_DELSAFE(m->label_hash, next_l, fec)
if (lfuc_finished(&fec->uc))
@ -896,7 +895,7 @@ mpls_fec_map_cleanup(void *_m)
if (finished)
{
ev_postpone(m->cleanup_event);
callback_cancel(&m->cleanup);
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)
{
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);
}

View File

@ -124,8 +124,7 @@ struct mpls_fec {
struct mpls_fec_map {
pool *pool; /* Pool for FEC map */
struct birdloop *loop; /* Owner's loop for sending events */
event *cleanup_event; /* Event for unlocked FEC cleanup */
callback cleanup; /* Callback for unlocked FEC cleanup */
slab *slabs[4]; /* Slabs for FEC allocation */
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 */