Cleanup and tune ng_snd_item() function as it is one of the

most busy netgraph functions.
Tune stack protection constants to avoid division operation.
This commit is contained in:
mav 2008-02-06 18:50:40 +00:00
parent e6ee3bcfea
commit a51f95cd58

View File

@ -2281,115 +2281,69 @@ ng_snd_item(item_p item, int flags)
struct ng_queue *ngq; struct ng_queue *ngq;
int error = 0; int error = 0;
if (item == NULL) { /* We are sending item, so it must be present! */
TRAP_ERROR(); KASSERT(item != NULL, ("ng_snd_item: item is NULL"));
return (EINVAL); /* failed to get queue element */
}
#ifdef NETGRAPH_DEBUG #ifdef NETGRAPH_DEBUG
_ngi_check(item, __FILE__, __LINE__); _ngi_check(item, __FILE__, __LINE__);
#endif #endif
/* Item was sent once more, postpone apply() call. */
if (item->apply) if (item->apply)
refcount_acquire(&item->apply->refs); refcount_acquire(&item->apply->refs);
node = NGI_NODE(item); node = NGI_NODE(item);
if (node == NULL) { /* Node is never optional. */
TRAP_ERROR(); KASSERT(node != NULL, ("ng_snd_item: node is NULL"));
ERROUT(EINVAL); /* No address */
}
hook = NGI_HOOK(item); hook = NGI_HOOK(item);
switch(item->el_flags & NGQF_TYPE) { /* Valid hook and mbuf are mandatory for data. */
case NGQF_DATA: if ((item->el_flags & NGQF_TYPE) == NGQF_DATA) {
/* KASSERT(hook != NULL, ("ng_snd_item: hook for data is NULL"));
* DATA MESSAGE
* Delivered to a node via a non-optional hook.
* Both should be present in the item even though
* the node is derivable from the hook.
* References are held on both by the item.
*/
/* Protect nodes from sending NULL pointers
* to each other
*/
if (NGI_M(item) == NULL) if (NGI_M(item) == NULL)
ERROUT(EINVAL); ERROUT(EINVAL);
CHECK_DATA_MBUF(NGI_M(item)); CHECK_DATA_MBUF(NGI_M(item));
if (hook == NULL) {
TRAP_ERROR();
ERROUT(EINVAL);
}
if ((NG_HOOK_NOT_VALID(hook))
|| (NG_NODE_NOT_VALID(NG_HOOK_NODE(hook)))) {
ERROUT(ENOTCONN);
}
break;
case NGQF_MESG:
/*
* CONTROL MESSAGE
* Delivered to a node.
* Hook is optional.
* References are held by the item on the node and
* the hook if it is present.
*/
break;
case NGQF_FN:
case NGQF_FN2:
break;
default:
TRAP_ERROR();
ERROUT(EINVAL);
}
switch(item->el_flags & NGQF_RW) {
case NGQF_READER:
rw = NGQRW_R;
break;
case NGQF_WRITER:
rw = NGQRW_W;
break;
default:
panic("%s: invalid item flags %lx", __func__, item->el_flags);
} }
/* /*
* If the node specifies single threading, force writer semantics. * If the item or the node specifies single threading, force
* Similarly, the node may say one hook always produces writers. * writer semantics. Similarly, the node may say one hook always
* These are overrides. * produces writers. These are overrides.
*/ */
if ((node->nd_flags & NGF_FORCE_WRITER) if (((item->el_flags & NGQF_RW) == NGQRW_W) ||
|| (hook && (hook->hk_flags & HK_FORCE_WRITER))) (node->nd_flags & NGF_FORCE_WRITER) ||
rw = NGQRW_W; (hook && (hook->hk_flags & HK_FORCE_WRITER))) {
rw = NGQRW_W;
} else {
rw = NGQRW_R;
}
/* /*
* If sender or receiver requests queued delivery or stack usage * If sender or receiver requests queued delivery or stack usage
* level is dangerous - enqueue message. * level is dangerous - enqueue message.
*/ */
queue = 0;
if ((flags & NG_QUEUE) || (hook && (hook->hk_flags & HK_QUEUE))) { if ((flags & NG_QUEUE) || (hook && (hook->hk_flags & HK_QUEUE))) {
queue = 1; queue = 1;
} } else {
queue = 0;
#ifdef GET_STACK_USAGE #ifdef GET_STACK_USAGE
else {
/* /*
* Most of netgraph nodes have small stack consumption and * Most of netgraph nodes have small stack consumption and
* for them 20% of free stack space is more than enough. * for them 25% of free stack space is more than enough.
* Nodes/hooks with higher stack usage should be marked as * Nodes/hooks with higher stack usage should be marked as
* HI_STACK. For them 50% of stack will be guaranteed then. * HI_STACK. For them 50% of stack will be guaranteed then.
* XXX: Values 50% (64/128) and 80% (100/128) are completely * XXX: Values 25% and 50% are completely empirical.
* empirical.
*/ */
size_t st, su; size_t st, su, sl;
GET_STACK_USAGE(st, su); GET_STACK_USAGE(st, su);
su = (su * 128) / st; sl = st - su;
if ((su > 100) || if ((sl * 4 < st) ||
((su > 64) && ((node->nd_flags & NGF_HI_STACK) || ((sl * 2 < st) && ((node->nd_flags & NGF_HI_STACK) ||
(hook && (hook->hk_flags & HK_HI_STACK))))) { (hook && (hook->hk_flags & HK_HI_STACK))))) {
queue = 1; queue = 1;
} }
}
#endif #endif
}
ngq = &node->nd_input_queue; ngq = &node->nd_input_queue;
if (queue) { if (queue) {
@ -2401,10 +2355,7 @@ ng_snd_item(item_p item, int flags)
ng_queue_rw(ngq, item, rw); ng_queue_rw(ngq, item, rw);
NG_QUEUE_UNLOCK(ngq); NG_QUEUE_UNLOCK(ngq);
if (flags & NG_PROGRESS) return ((flags & NG_PROGRESS) ? EINPROGRESS : 0);
return (EINPROGRESS);
else
return (0);
} }
/* /*
@ -2417,12 +2368,9 @@ ng_snd_item(item_p item, int flags)
item = ng_acquire_write(ngq, item); item = ng_acquire_write(ngq, item);
if (item == NULL) { /* Item was queued while trying to get permission. */
if (flags & NG_PROGRESS) if (item == NULL)
return (EINPROGRESS); return ((flags & NG_PROGRESS) ? EINPROGRESS : 0);
else
return (0);
}
#ifdef NETGRAPH_DEBUG #ifdef NETGRAPH_DEBUG
_ngi_check(item, __FILE__, __LINE__); _ngi_check(item, __FILE__, __LINE__);
@ -2437,9 +2385,8 @@ ng_snd_item(item_p item, int flags)
* whatever we just did caused it.. whatever we do, DO NOT * whatever we just did caused it.. whatever we do, DO NOT
* access the node again! * access the node again!
*/ */
if (NG_NODE_UNREF(node) == 0) { if (NG_NODE_UNREF(node) == 0)
return (error); return (error);
}
NG_QUEUE_LOCK(ngq); NG_QUEUE_LOCK(ngq);
if (NEXT_QUEUED_ITEM_CAN_PROCEED(ngq)) if (NEXT_QUEUED_ITEM_CAN_PROCEED(ngq))
@ -2449,7 +2396,7 @@ ng_snd_item(item_p item, int flags)
return (error); return (error);
done: done:
/* Apply callback. */ /* If was not sent, apply callback here. */
if (item->apply != NULL && refcount_release(&item->apply->refs)) if (item->apply != NULL && refcount_release(&item->apply->refs))
(*item->apply->apply)(item->apply->context, error); (*item->apply->apply)(item->apply->context, error);
@ -2472,6 +2419,10 @@ ng_apply_item(node_p node, item_p item, int rw)
ng_rcvmsg_t *rcvmsg; ng_rcvmsg_t *rcvmsg;
struct ng_apply_info *apply; struct ng_apply_info *apply;
/* Node and item are never optional. */
KASSERT(node != NULL, ("ng_apply_item: node is NULL"));
KASSERT(item != NULL, ("ng_apply_item: item is NULL"));
NGI_GET_HOOK(item, hook); /* clears stored hook */ NGI_GET_HOOK(item, hook); /* clears stored hook */
#ifdef NETGRAPH_DEBUG #ifdef NETGRAPH_DEBUG
_ngi_check(item, __FILE__, __LINE__); _ngi_check(item, __FILE__, __LINE__);
@ -2484,9 +2435,9 @@ ng_apply_item(node_p node, item_p item, int rw)
/* /*
* Check things are still ok as when we were queued. * Check things are still ok as when we were queued.
*/ */
if ((hook == NULL) KASSERT(hook != NULL, ("ng_apply_item: hook for data is NULL"));
|| NG_HOOK_NOT_VALID(hook) if (NG_HOOK_NOT_VALID(hook) ||
|| NG_NODE_NOT_VALID(node) ) { NG_NODE_NOT_VALID(node)) {
error = EIO; error = EIO;
NG_FREE_ITEM(item); NG_FREE_ITEM(item);
break; break;
@ -2579,11 +2530,10 @@ ng_apply_item(node_p node, item_p item, int rw)
if (hook) if (hook)
NG_HOOK_UNREF(hook); NG_HOOK_UNREF(hook);
if (rw == NGQRW_R) { if (rw == NGQRW_R)
ng_leave_read(&node->nd_input_queue); ng_leave_read(&node->nd_input_queue);
} else { else
ng_leave_write(&node->nd_input_queue); ng_leave_write(&node->nd_input_queue);
}
/* Apply callback. */ /* Apply callback. */
if (apply != NULL && refcount_release(&apply->refs)) if (apply != NULL && refcount_release(&apply->refs))
@ -3507,7 +3457,6 @@ ng_package_data(struct mbuf *m, int flags)
} }
ITEM_DEBUG_CHECKS; ITEM_DEBUG_CHECKS;
item->el_flags = NGQF_DATA | NGQF_READER; item->el_flags = NGQF_DATA | NGQF_READER;
item->el_next = NULL;
NGI_M(item) = m; NGI_M(item) = m;
return (item); return (item);
} }
@ -3534,7 +3483,6 @@ ng_package_msg(struct ng_mesg *msg, int flags)
item->el_flags = NGQF_MESG | NGQF_READER; item->el_flags = NGQF_MESG | NGQF_READER;
else else
item->el_flags = NGQF_MESG | NGQF_WRITER; item->el_flags = NGQF_MESG | NGQF_WRITER;
item->el_next = NULL;
/* /*
* Set the current lasthook into the queue item * Set the current lasthook into the queue item
*/ */
@ -3669,7 +3617,6 @@ ng_package_msg_self(node_p here, hook_p hook, struct ng_mesg *msg)
/* Fill out the contents */ /* Fill out the contents */
item->el_flags = NGQF_MESG | NGQF_WRITER; item->el_flags = NGQF_MESG | NGQF_WRITER;
item->el_next = NULL;
NG_NODE_REF(here); NG_NODE_REF(here);
NGI_SET_NODE(item, here); NGI_SET_NODE(item, here);
if (hook) { if (hook) {