Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Feb 2001 14:09:30 +0000
From:      Ian Dowse <iedowse@maths.tcd.ie>
To:        Boris Popov <bp@butya.kz>
Cc:        freebsd-arch@freebsd.org, freebsd-net@freebsd.org, iedowse@maths.tcd.ie
Subject:   Re: CFR: Sequential mbuf read/write extensions 
Message-ID:   <200102121409.aa34378@salmon.maths.tcd.ie>
In-Reply-To: Your message of "Fri, 09 Feb 2001 08:30:48 %2B0600." <Pine.BSF.4.21.0102090752290.24710-100000@lion.butya.kz> 

next in thread | previous in thread | raw e-mail | index | archive | help
In message <Pine.BSF.4.21.0102090752290.24710-100000@lion.butya.kz>, 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 majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi? <200102121409.aa34378>