1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
5 * This file is part of Quagga
18 static uint32_t qobj_hash(const struct qobj_node
*node
)
20 return (uint32_t)node
->nid
;
23 static int qobj_cmp(const struct qobj_node
*na
, const struct qobj_node
*nb
)
25 if (na
->nid
< nb
->nid
)
27 if (na
->nid
> nb
->nid
)
32 DECLARE_HASH(qobj_nodes
, struct qobj_node
, nodehash
,
35 static pthread_rwlock_t nodes_lock
;
36 static struct qobj_nodes_head nodes
= { };
39 void qobj_reg(struct qobj_node
*node
, const struct qobj_nodetype
*type
)
42 pthread_rwlock_wrlock(&nodes_lock
);
44 node
->nid
= (uint64_t)frr_weak_random();
45 node
->nid
^= (uint64_t)frr_weak_random() << 32;
46 } while (!node
->nid
|| qobj_nodes_find(&nodes
, node
));
47 qobj_nodes_add(&nodes
, node
);
48 pthread_rwlock_unlock(&nodes_lock
);
51 void qobj_unreg(struct qobj_node
*node
)
53 pthread_rwlock_wrlock(&nodes_lock
);
54 qobj_nodes_del(&nodes
, node
);
55 pthread_rwlock_unlock(&nodes_lock
);
58 struct qobj_node
*qobj_get(uint64_t id
)
60 struct qobj_node dummy
= {.nid
= id
}, *rv
;
61 pthread_rwlock_rdlock(&nodes_lock
);
62 rv
= qobj_nodes_find(&nodes
, &dummy
);
63 pthread_rwlock_unlock(&nodes_lock
);
67 void *qobj_get_typed(uint64_t id
, const struct qobj_nodetype
*type
)
69 struct qobj_node dummy
= {.nid
= id
};
70 struct qobj_node
*node
;
73 pthread_rwlock_rdlock(&nodes_lock
);
74 node
= qobj_nodes_find(&nodes
, &dummy
);
76 /* note: we explicitly hold the lock until after we have checked the
78 * if the caller holds a lock that for example prevents the deletion of
79 * route-maps, we can still race against a delete of something that
82 if (!node
|| node
->type
!= type
)
85 rv
= (char *)node
- node
->type
->node_member_offset
;
87 pthread_rwlock_unlock(&nodes_lock
);
93 pthread_rwlock_init(&nodes_lock
, NULL
);
94 qobj_nodes_init(&nodes
);
97 void qobj_finish(void)
99 struct qobj_node
*node
;
100 while ((node
= qobj_nodes_pop(&nodes
)))
101 qobj_nodes_del(&nodes
, node
);
102 pthread_rwlock_destroy(&nodes_lock
);