summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/ng_base.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2008-04-16 19:52:29 +0000
committermav <mav@FreeBSD.org>2008-04-16 19:52:29 +0000
commit0e42cfa396df2a7c5e458f0b15e23e31c86a3da7 (patch)
tree0b8c9d18d91811ab1b9ee36b9f5ea9bb619cc2ca /sys/netgraph/ng_base.c
parente0c673b7e2ac1ffa29dad589abbb9cfd44ffdbf4 (diff)
downloadFreeBSD-src-0e42cfa396df2a7c5e458f0b15e23e31c86a3da7.zip
FreeBSD-src-0e42cfa396df2a7c5e458f0b15e23e31c86a3da7.tar.gz
Use separate UMA zone for data items allocation. It is a partial
rev. 1.149 rework. It allows to save several percents of CPU time on SMP by using UMA's internal per-CPU allocation limits instead of own global variable each time updated with atomics. Tested with: Netperf cluster
Diffstat (limited to 'sys/netgraph/ng_base.c')
-rw-r--r--sys/netgraph/ng_base.c110
1 files changed, 70 insertions, 40 deletions
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c
index 29b3a64..9e7acef 100644
--- a/sys/netgraph/ng_base.c
+++ b/sys/netgraph/ng_base.c
@@ -2844,16 +2844,16 @@ out:
************************************************************************/
uma_zone_t ng_qzone;
+uma_zone_t ng_qdzone;
static int maxalloc = 4096;/* limit the damage of a leak */
static int maxdata = 512; /* limit the damage of a DoS */
-static int useddata = 0;
TUNABLE_INT("net.graph.maxalloc", &maxalloc);
SYSCTL_INT(_net_graph, OID_AUTO, maxalloc, CTLFLAG_RDTUN, &maxalloc,
- 0, "Maximum number of queue items to allocate");
+ 0, "Maximum number of non-data queue items to allocate");
TUNABLE_INT("net.graph.maxdata", &maxdata);
-SYSCTL_INT(_net_graph, OID_AUTO, maxdata, CTLFLAG_RW | CTLFLAG_TUN, &maxdata,
- 0, "Maximum number of queue data items to allocate");
+SYSCTL_INT(_net_graph, OID_AUTO, maxdata, CTLFLAG_RDTUN, &maxdata,
+ 0, "Maximum number of data queue items to allocate");
#ifdef NETGRAPH_DEBUG
static TAILQ_HEAD(, ng_item) ng_itemlist = TAILQ_HEAD_INITIALIZER(ng_itemlist);
@@ -2868,23 +2868,25 @@ static int allocated; /* number of items malloc'd */
* an interrupt.
*/
static __inline item_p
-ng_getqblk(int flags)
+ng_alloc_item(int type, int flags)
{
- item_p item = NULL;
- int wait;
+ item_p item;
- wait = (flags & NG_WAITOK) ? M_WAITOK : M_NOWAIT;
+ KASSERT(((type & ~NGQF_TYPE) == 0),
+ ("%s: incorrect item type: %d", __func__, type));
- item = uma_zalloc(ng_qzone, wait | M_ZERO);
+ item = uma_zalloc((type == NGQF_DATA)?ng_qdzone:ng_qzone,
+ ((flags & NG_WAITOK) ? M_WAITOK : M_NOWAIT) | M_ZERO);
-#ifdef NETGRAPH_DEBUG
if (item) {
- mtx_lock(&ngq_mtx);
- TAILQ_INSERT_TAIL(&ng_itemlist, item, all);
- allocated++;
- mtx_unlock(&ngq_mtx);
- }
+ item->el_flags = type;
+#ifdef NETGRAPH_DEBUG
+ mtx_lock(&ngq_mtx);
+ TAILQ_INSERT_TAIL(&ng_itemlist, item, all);
+ allocated++;
+ mtx_unlock(&ngq_mtx);
#endif
+ }
return (item);
}
@@ -2904,7 +2906,6 @@ ng_free_item(item_p item)
*/
switch (item->el_flags & NGQF_TYPE) {
case NGQF_DATA:
- atomic_subtract_int(&useddata, 1);
/* If we have an mbuf still attached.. */
NG_FREE_M(_NGI_M(item));
break;
@@ -2930,7 +2931,39 @@ ng_free_item(item_p item)
allocated--;
mtx_unlock(&ngq_mtx);
#endif
- uma_zfree(ng_qzone, item);
+ uma_zfree(((item->el_flags & NGQF_TYPE) == NGQF_DATA)?
+ ng_qdzone:ng_qzone, item);
+}
+
+/*
+ * Change type of the queue entry.
+ * Possibly reallocates it from another UMA zone.
+ */
+static __inline item_p
+ng_realloc_item(item_p pitem, int type, int flags)
+{
+ item_p item;
+ int from, to;
+
+ KASSERT((pitem != NULL), ("%s: can't reallocate NULL", __func__));
+ KASSERT(((type & ~NGQF_TYPE) == 0),
+ ("%s: incorrect item type: %d", __func__, type));
+
+ from = ((pitem->el_flags & NGQF_TYPE) == NGQF_DATA);
+ to = (type == NGQF_DATA);
+ if (from != to) {
+ /* If reallocation is required do it and copy item. */
+ if ((item = ng_alloc_item(type, flags)) == NULL) {
+ ng_free_item(pitem);
+ return (NULL);
+ }
+ *item = *pitem;
+ ng_free_item(pitem);
+ } else
+ item = pitem;
+ item->el_flags = (item->el_flags & ~NGQF_TYPE) | type;
+
+ return (item);
}
/************************************************************************
@@ -3031,6 +3064,9 @@ ngb_mod_event(module_t mod, int event, void *data)
ng_qzone = uma_zcreate("NetGraph items", sizeof(struct ng_item),
NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, 0);
uma_zone_set_max(ng_qzone, maxalloc);
+ ng_qdzone = uma_zcreate("NetGraph data items", sizeof(struct ng_item),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, 0);
+ uma_zone_set_max(ng_qdzone, maxdata);
netisr_register(NETISR_NETGRAPH, (netisr_t *)ngintr, NULL,
NETISR_MPSAFE);
break;
@@ -3311,17 +3347,12 @@ ng_package_data(struct mbuf *m, int flags)
{
item_p item;
- if (atomic_fetchadd_int(&useddata, 1) >= maxdata) {
- atomic_subtract_int(&useddata, 1);
- NG_FREE_M(m);
- return (NULL);
- }
- if ((item = ng_getqblk(flags)) == NULL) {
+ if ((item = ng_alloc_item(NGQF_DATA, flags)) == NULL) {
NG_FREE_M(m);
return (NULL);
}
ITEM_DEBUG_CHECKS;
- item->el_flags = NGQF_DATA | NGQF_READER;
+ item->el_flags |= NGQF_READER;
NGI_M(item) = m;
return (item);
}
@@ -3338,16 +3369,16 @@ ng_package_msg(struct ng_mesg *msg, int flags)
{
item_p item;
- if ((item = ng_getqblk(flags)) == NULL) {
+ if ((item = ng_alloc_item(NGQF_MESG, flags)) == NULL) {
NG_FREE_MSG(msg);
return (NULL);
}
ITEM_DEBUG_CHECKS;
/* Messages items count as writers unless explicitly exempted. */
if (msg->header.cmd & NGM_READONLY)
- item->el_flags = NGQF_MESG | NGQF_READER;
+ item->el_flags |= NGQF_READER;
else
- item->el_flags = NGQF_MESG | NGQF_WRITER;
+ item->el_flags |= NGQF_WRITER;
/*
* Set the current lasthook into the queue item
*/
@@ -3474,13 +3505,13 @@ ng_package_msg_self(node_p here, hook_p hook, struct ng_mesg *msg)
* If there is a HOOK argument, then use that in preference
* to the address.
*/
- if ((item = ng_getqblk(NG_NOFLAGS)) == NULL) {
+ if ((item = ng_alloc_item(NGQF_MESG, NG_NOFLAGS)) == NULL) {
NG_FREE_MSG(msg);
return (NULL);
}
/* Fill out the contents */
- item->el_flags = NGQF_MESG | NGQF_WRITER;
+ item->el_flags |= NGQF_WRITER;
NG_NODE_REF(here);
NGI_SET_NODE(item, here);
if (hook) {
@@ -3509,10 +3540,10 @@ ng_send_fn1(node_p node, hook_p hook, ng_item_fn *fn, void * arg1, int arg2,
{
item_p item;
- if ((item = ng_getqblk(flags)) == NULL) {
+ if ((item = ng_alloc_item(NGQF_FN, flags)) == NULL) {
return (ENOMEM);
}
- item->el_flags = NGQF_FN | NGQF_WRITER;
+ item->el_flags |= NGQF_WRITER;
NG_NODE_REF(node); /* and one for the item */
NGI_SET_NODE(item, node);
if (hook) {
@@ -3547,15 +3578,16 @@ ng_send_fn2(node_p node, hook_p hook, item_p pitem, ng_item_fn2 *fn, void *arg1,
* if we can't use supplied one.
*/
if (pitem == NULL || (flags & NG_REUSE_ITEM) == 0) {
- if ((item = ng_getqblk(flags)) == NULL)
+ if ((item = ng_alloc_item(NGQF_FN2, flags)) == NULL)
return (ENOMEM);
+ if (pitem != NULL)
+ item->apply = pitem->apply;
} else {
- if ((pitem->el_flags & NGQF_TYPE) == NGQF_DATA)
- atomic_subtract_int(&useddata, 1);
- item = pitem;
+ if ((item = ng_realloc_item(pitem, NGQF_FN2, flags)) == NULL)
+ return (ENOMEM);
}
- item->el_flags = NGQF_FN2 | NGQF_WRITER;
+ item->el_flags = (item->el_flags & ~NGQF_RW) | NGQF_WRITER;
NG_NODE_REF(node); /* and one for the item */
NGI_SET_NODE(item, node);
if (hook) {
@@ -3565,8 +3597,6 @@ ng_send_fn2(node_p node, hook_p hook, item_p pitem, ng_item_fn2 *fn, void *arg1,
NGI_FN2(item) = fn;
NGI_ARG1(item) = arg1;
NGI_ARG2(item) = arg2;
- if (pitem != NULL && (flags & NG_REUSE_ITEM) == 0)
- item->apply = pitem->apply;
return(ng_snd_item(item, flags));
}
@@ -3588,10 +3618,10 @@ ng_callout(struct callout *c, node_p node, hook_p hook, int ticks,
{
item_p item, oitem;
- if ((item = ng_getqblk(NG_NOFLAGS)) == NULL)
+ if ((item = ng_alloc_item(NGQF_FN, NG_NOFLAGS)) == NULL)
return (ENOMEM);
- item->el_flags = NGQF_FN | NGQF_WRITER;
+ item->el_flags |= NGQF_WRITER;
NG_NODE_REF(node); /* and one for the item */
NGI_SET_NODE(item, node);
if (hook) {
OpenPOWER on IntegriCloud