summaryrefslogtreecommitdiff
path: root/nest/route.h
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2021-11-13 22:13:51 +0100
committerMaria Matejka <mq@ucw.cz>2021-11-22 19:05:44 +0100
commit0fd1c1d091ee8e43eb0e15c67a92960ca581ed5f (patch)
treeb95820ae7fab621dfdfcf2a4d2822376827b8353 /nest/route.h
parent2a224a9e1e1fbe1abec96c8585dd754fb716d020 (diff)
Route attribute cache is now lockless on read / clone.
Lots of time was spent locking when accessing route attribute cache. This overhead should be now reduced to a minimum.
Diffstat (limited to 'nest/route.h')
-rw-r--r--nest/route.h25
1 files changed, 11 insertions, 14 deletions
diff --git a/nest/route.h b/nest/route.h
index 3f8bf433..531e004b 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -606,8 +606,8 @@ struct rte_src {
typedef struct rta {
- struct rta *next, **pprev; /* Hash chain */
- u32 uc; /* Use count */
+ struct rta * _Atomic next, * _Atomic *pprev; /* Hash chain */
+ _Atomic u32 uc; /* Use count */
u32 hash_key; /* Hash over important fields */
struct ea_list *eattrs; /* Extended Attribute chain */
struct hostentry *hostentry; /* Hostentry for recursive next-hops */
@@ -758,12 +758,6 @@ struct rte_owner {
event *stop;
};
-DEFINE_DOMAIN(attrs);
-extern DOMAIN(attrs) attrs_domain;
-
-#define RTA_LOCK LOCK_DOMAIN(attrs, attrs_domain)
-#define RTA_UNLOCK UNLOCK_DOMAIN(attrs, attrs_domain)
-
#define RTE_SRC_PU_SHIFT 44
#define RTE_SRC_IN_PROGRESS (1ULL << RTE_SRC_PU_SHIFT)
@@ -879,20 +873,23 @@ static inline size_t rta_size(const rta *a) { return sizeof(rta) + sizeof(u32)*a
#define RTA_MAX_SIZE (sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK)
rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */
static inline int rta_is_cached(rta *r) { return r->cached; }
+
static inline rta *rta_clone(rta *r) {
- RTA_LOCK;
- r->uc++;
- RTA_UNLOCK;
+ u32 uc = atomic_fetch_add_explicit(&r->uc, 1, memory_order_acq_rel);
+ ASSERT_DIE(uc > 0);
return r;
}
void rta__free(rta *r);
static inline void rta_free(rta *r) {
- RTA_LOCK;
- if (r && !--r->uc)
+ if (!r)
+ return;
+
+ u32 uc = atomic_fetch_sub_explicit(&r->uc, 1, memory_order_acq_rel);
+ if (uc == 1)
rta__free(r);
- RTA_UNLOCK;
}
+
rta *rta_do_cow(rta *o, linpool *lp);
static inline rta * rta_cow(rta *r, linpool *lp) { return rta_is_cached(r) ? rta_do_cow(r, lp) : r; }
static inline void rta_uncache(rta *r) { r->cached = 0; r->uc = 0; }