2 * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
4 * This file is part of Quagga
6 * Quagga is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * Quagga is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 static uint32_t qobj_hash(const struct qobj_node
*node
)
33 return (uint32_t)node
->nid
;
36 static int qobj_cmp(const struct qobj_node
*na
, const struct qobj_node
*nb
)
38 if (na
->nid
< nb
->nid
)
40 if (na
->nid
> nb
->nid
)
45 DECLARE_HASH(qobj_nodes
, struct qobj_node
, nodehash
,
48 static pthread_rwlock_t nodes_lock
;
49 static struct qobj_nodes_head nodes
= { };
52 void qobj_reg(struct qobj_node
*node
, const struct qobj_nodetype
*type
)
55 pthread_rwlock_wrlock(&nodes_lock
);
57 node
->nid
= (uint64_t)frr_weak_random();
58 node
->nid
^= (uint64_t)frr_weak_random() << 32;
59 } while (!node
->nid
|| qobj_nodes_find(&nodes
, node
));
60 qobj_nodes_add(&nodes
, node
);
61 pthread_rwlock_unlock(&nodes_lock
);
64 void qobj_unreg(struct qobj_node
*node
)
66 pthread_rwlock_wrlock(&nodes_lock
);
67 qobj_nodes_del(&nodes
, node
);
68 pthread_rwlock_unlock(&nodes_lock
);
71 struct qobj_node
*qobj_get(uint64_t id
)
73 struct qobj_node dummy
= {.nid
= id
}, *rv
;
74 pthread_rwlock_rdlock(&nodes_lock
);
75 rv
= qobj_nodes_find(&nodes
, &dummy
);
76 pthread_rwlock_unlock(&nodes_lock
);
80 void *qobj_get_typed(uint64_t id
, const struct qobj_nodetype
*type
)
82 struct qobj_node dummy
= {.nid
= id
};
83 struct qobj_node
*node
;
86 pthread_rwlock_rdlock(&nodes_lock
);
87 node
= qobj_nodes_find(&nodes
, &dummy
);
89 /* note: we explicitly hold the lock until after we have checked the
91 * if the caller holds a lock that for example prevents the deletion of
92 * route-maps, we can still race against a delete of something that
95 if (!node
|| node
->type
!= type
)
98 rv
= (char *)node
- node
->type
->node_member_offset
;
100 pthread_rwlock_unlock(&nodes_lock
);
106 pthread_rwlock_init(&nodes_lock
, NULL
);
107 qobj_nodes_init(&nodes
);
110 void qobj_finish(void)
112 struct qobj_node
*node
;
113 while ((node
= qobj_nodes_pop(&nodes
)))
114 qobj_nodes_del(&nodes
, node
);
115 pthread_rwlock_destroy(&nodes_lock
);