Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Aug 2012 02:55:54 GMT
From:      Bruce Evans <bde@FreeBSD.org>
To:        freebsd-hackers@FreeBSD.org, jhb@FreeBSD.org
Cc:        freebsd-net@FreeBSD.org, mitya@cabletv.dp.ua
Subject:   Re: Replace bcopy() to update ether_addr
Message-ID:  <201208220255.q7M2tsxa020280@ref10-i386.freebsd.org>
In-Reply-To: <201208210943.08341.jhb@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
jhb wrote:
> On Monday, August 20, 2012 10:46:12 am Mitya wrote:
> > ...
> > I propose this solution.
> > 
> > In file /usr/src/include/net/ethernet.h add this lines:
> > 
> > static inline void ether_addr_copy(ether_addr* src, ether_addr* dst) {
> > #if defined(__i386__) || defined(__amd64__)
> >      *dst = *src;
> > #else
> >      bcopy(src, dst, ETHER_ADDR_LEN);
> > #endif
> > }
> 
> Doesn't '*dst = *src' just work on all platforms?

It does when you have an actual struct, but often in networking code
you only have an array of bytes, and then casting the pointers from
uint8_t * to full object pointers fails iff there is an alignment
problem.

Even on i386, it may be pessimal to use struct copying for 6 bytes,
The bytes should be copied as 4+2 or 2+4 depending on alignment of the
first bytes.  Oops, not even that -- this reminds me of a problem with
penalties for mismatched loads and stores which affects at least
AthlonXP and Athlon64 significantly (10-20 cycle penalty = enough to
copy 80-160 bytes unpenalized).  The 6 should probably be copied as
2+2+2 or even as 1+1+1+1+1+1 to match previous stores and later loads,
also as 2+2+2, etc.  But if the 6 are part of another struct, they
might be accessed as 8+0 or 4+4 as part of copying the full struct.
gcc is not smart about this.

Bruce



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