In message <[EMAIL PROTECTED]>, Boris Popo
v writes:
> No, in the current implementation mb_get* functions will work
>properly. But mb_put* will fail. This can be avoided by implementing
>alignment-safe set* macros (which can be written in two variants - first
>form is for aligned objects and second for bad aligned ones).
Ah, I missed the details of how the mb_get functions work - you
just perform a byte-by-byte copy into the destination. Great! I
wonder if it makes sense to do something similar for the mb_put
functions too?
BTW, I'd recommend making MB_PUT() a more 'normal' macro, or even
calling mb_fit directly from the mb_put functions - the implicit
declaration of 'p' and use of 'mbp' is confusing. If mb_fit was
changed to return a void *, the code wouldn't look too bad, and
would be less magic. e.g.:
int
mb_put_byte(struct mbdata *mbp, u_int8_t x)
{
u_int8_t *p;
if ((p = mb_fit(mbp, sizeof(*p))) == NULL)
return (ENUBUFS);
*p = x;
return (0);
}
> Hmm, since so_send() can fail and some erros can be recovered by
>another call to so_send(), I'm just called m_copym() to duplicate the mbuf
>chain and give it to so_send().
This is reasonable for a client of an RPC-type protocol, but the
server side may wish to give the reply to the sosend function and
ignore errors - NFS does this for example. It seems natural to call
the _init function to clobber any state, though the semantics aren't
that important. There just needs to be a defined way of disassociating
the chain from the mbdata struct so that mb_done will not free it.
If you are going to split struct mbdata into two structs, you can
probably optimise operations a bit by storing the right information
for each case. For the build case, maybe:
struct mbuf *mb_top; /* head of chain */
struct mbuf *mb_cur; /* current (last) mbuf in chain */
int mb_mleft; /* bytes remaining in mb_cur */
int mb_count; /* total bytes in chain */
Storing the number of bytes remaining in the current mbuf as
'mb_mleft' avoids using M_TRAILINGSPACE() which expands to quite
a complex expression. The current offset is not explicitly stored
in mbdata, but evaluating 'mtod(m, char *) + m->m_len' is cheap.
An optimised case at the start of mb_fit could look like
m = mbp->mb_cur;
if (mbp->mb_top != NULL && size <= mbp->mb_mleft) {
mbp->mb_mleft -= size;
mbp->mb_count += size;
bpos = mtod(m, char *) + m->m_len;
m->m_len += size;
return (bpos);
}
but I guess worrying about minor optimisations like these probably
isn't too important now :-) For the breakdown, you probably only
need:
struct mbuf *mb_top; /* head of chain */
struct mbuf *mb_cur; /* current mbuf in chain */
u_char *mb_pos; /* current position in mb_cur */
Ian
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-net" in the body of the message