Alexander Kolbasov
2008-Oct-02 05:28 UTC
[crossbow-discuss] Comments for squeue.c; part 2.
1.
566 squeue_enter(squeue_t *sqp, mblk_t *mp, mblk_t *tail, uint32_t cnt,
Why cnt is declared as uint32_t (fixed size?) Why not just int or uint_t?
554 * squeue_enter() - enter squeue sqp with mblk mp (which can be
555 * a chain), while tail points to the end and cnt in number of
556 * mblks in the chain.
It is not quite clear what is a tail (and why it is needed as well)
558 * For a chain of single packet (i.e. mp == tail), go through the
559 * fast path if no one is processing the squeue and nothing is queued.
Is single packet case cnt == 1 or mp == tail or both or one of these? Or is it
chain_size == 1? What is the diferece between the cnt and chain_size?
Also, there is a lot of mentioning of ''fast-path'' without any
explanation of
what it actually means.
Also, the comment for the function should mentioned that for any processed
messages the corresponding connp looses one reference (and explain why this is
done this way).
2.
581 * ''interrupt'' is set when the packet is coming
from below
582 * either through a soft ring worker thread that directly
583 * called ip_input() (tag == SQTAG_IP_INPUT_RX_RING) or
584 * when we are being invoked from a NIC interrupt context.
This seems like a hack. First of all, why is processing by poll thread should be
treated in the same way as the real interrupt handler (which is quite different
beast)? Second, I don''t like the use of tags in this context. Can an
explicit
flag be passed to squeue_enter when there is a need to do something special?
3.
593 * Try to process the packet if SQ_FILL flag is not set and
594 * we are allowed to process the squeue. The SQ_NODRAIN is
595 * ignored if the packet chain consists of more than 1 packet.
596 */
597 if (!(sqp->sq_state & SQS_PROC) &&
598 ((process_flag == SQ_PROCESS) || (process_flag == SQ_NODRAIN
&&
599 sqp->sq_first == NULL))) {
The comment and the code do not agree with each other.
4.
614 * We are the chain of 1 packet so
615 * go through this fast path.
The comment is confusing (especially since there is no explanation of fast
path). Can you say something like "request for processing a single packet
can be
completed by the caller if there are no other messages on the squeue".
5.
617 ASSERT(mp->b_prev != NULL);
618 ASSERT(mp->b_queue != NULL);
Should these ASSERTS be satisfied for every message in a chain? Should the check
be done at the beginning of the function rather than here?
6.
630 if (connp->conn_sqp == sqp) {
...
642 } else {
643 SQUEUE_ENTER_ONE(connp->conn_sqp, mp,
proc,
644 connp, chain_size, SQ_FILL,
645 SQTAG_SQUEUE_CHANGE);
646 }
Why clear all fields in mp just to set them back here? The check for conn_sqp
could have been done earlier eliminating the need for calling SQUEUE_ENTER_ONE -
a plain squeue_enter could be called instead.
Also it seems that changing the tag here is wrong. What matters is who placed
the message on the squeue - which was indicated by the original tag. The fact
that it was replaced to another squeue is much less interesting for debugging
the source of the message.
7.
647 ASSERT(MUTEX_NOT_HELD(&sqp->sq_lock));
What is the point of this ASSERT? Is it to verify that the callback function
didn''t grab sq_lock and forgot to release it? Even this is so, the next
line
will cause recursive mutex enter panic anyway.
8.
651 if (sqp->sq_first == NULL ||
652 process_flag == SQ_NODRAIN) {
653 if (sqp->sq_first != NULL) {
654 squeue_worker_wakeup(sqp);
655 } else {
661 mutex_exit(&sqp->sq_lock);
662 }
663 return;
664 }
The sqp->sq_first is needlessly checked two times.
if (sqp->sq_first == NULL) {
mutex_exit(sq_lock);
return;
} else if (process_flag == SQ_NODRAIN) {
squeue_worker_wakeup(sqp); /* drops sq_lock */
return;
}
is both simpler and more efficient.
8.
681 sqp->sq_isintr = interrupt;
Do we want to distinguish here between the real interrupt and the case of
polling thread calling squeue_enter()?
9.
683 now = gethrtime();
684 if (interrupt) {
685 sqp->sq_drain(sqp, SQS_ENTER, now +
686 squeue_intrdrain_ns);
Since squeue_intrdrain_ns is a constant and squeue_drain can get the current
time by itself and squeue_drain wants to know whether it is called in interrupt
context or non-interrupt context, wouldn''t it be more straightforward
to pass
''interrupt'' flag instead of the time to squeue_drain?
10.
698 sqp->sq_run = NULL;
This was already done in line 650.
11.
703 * We let a thread processing a squeue reenter only
704 * once. This helps the case of incoming connection
705 * where a SYN-ACK-ACK that triggers the conn_ind
706 * doesn''t have to queue the packet if listener
and
707 * eager are on the same squeue. Also helps the
708 * loopback connection where the two ends are bound
709 * to the same squeue (which is typical on single
710 * CPU machines).
711 * We let the thread reenter only once for the fear
712 * of stack getting blown with multiple traversal.
This whole comment is pretty bad in explaining what it tries to explain. Th
whole reenter thing is quite a hack that at least requires clear explanation.
12.
715 if (!(sqp->sq_state & SQS_REENTER) &&
716 (process_flag != SQ_FILL) && (sqp->sq_first
== NULL) &&
717 (sqp->sq_run == curthread) && (cnt == 1)
&&
718 (connp->conn_on_sqp == B_FALSE)) {
How can it happen that sq_run != NULL && connp->conn_on_sqp ==
B_FALSE?
13.
630 if (connp->conn_sqp == sqp) {
631 SQUEUE_DBG_SET(sqp, interrupt, mp, proc,
connp,
632 tag);
...
This big chunk of code is repeated several times in the code. Can it become a
function or a macro?
14.
756 * one or more paquets on the queue. Enqueue the
spelling in paquets.
