Praveen
Praveen

Reputation: 406

Aligning both source and destination address in memcpy

I want to write a memcpy code which does word by word copy instead of byte by byte to increase speed. (Though I need to do some byte by byte copy for the last or few bytes). So I want my source and destination address to be aligned properly. I saw the implementation of memcpy in glibc https://fossies.org/dox/glibc-2.22/string_2memcpy_8c_source.html it does alignment only for destination address. But even if source address is not properly aligned it will result bus error (consider Alignment Checking is enabled in my cpu) I'm not sure how to make both source and destination to be aligned properly. Because if I try to align source by copying few bytes by byte by byte, it will also change the destination address, so at first the destination address which was aligned at first properly might not be aligned properly now. So is there any way to align both?. Please help me.

void  memcpy(void  *dst,  void  *src,int  size)
{
   if(size >= 8)
   {
     while(size/8) /* code will give sigbus error if src = 0x10003 and dst = 0x100000 */ 
     {
       *((double*)dst)++  =  *((double*)src)++; 
        size  =  size  -  8;
     }
   }

   while(size--)
   {
     *((char*)dst)++  =  *((char*)src)++;
   }
}

Upvotes: 5

Views: 11531

Answers (2)

ryyker
ryyker

Reputation: 23228

...so at first the destination address which was aligned at first properly might not be aligned properly now. So is there any way to align both?

I found this article on memcpy optimization which I believe discusses what you are trying to do in length...

modified-GNU algorithm:

void * memcpy(void * dst, void const * src, size_t len)
{
    long * plDst = (long *) dst;
    long const * plSrc = (long const *) src;

    if (!(src & 0xFFFFFFFC) && !(dst & 0xFFFFFFFC))
    {
        while (len >= 4)
    {
            *plDst++ = *plSrc++;
            len -= 4;
        }
    }

    char * pcDst = (char *) plDst;
    char const * pcDst = (char const *) plSrc;

    while (len--)
    {
        *pcDst++ = *pcSrc++;
    }

    return (dst);
} 

Upvotes: 1

Andrew Klitzke
Andrew Klitzke

Reputation: 104

With the glibc memcpy code you included, there is no way to call the function without the memory already being aligned. If you were to write your own, the way I see it, there are two of possible alignments for the memcpy:

1) Both of the buffers are offset from a four-byte boundary by the same amount, or both are already on a four-byte boundary. (src % 4 == dst % 4) In this case, copying the first few bytes byte-by-byte then using the alignment of only the destination address is fine.

2) The buffers are not both on the same boundary. (src % 4 != dst % 4) In this case, in order to copy from one alignment to another, one word at a time, the processor would have to follow a process similar to the one below:

Load the new word
Split it into an upper half and lower half. 
Shift the upper half down
Shift the lower half up
Add the upper half the previous lower half. 
Store the combined copy to memory
Repeat

I'm not sure this would be any faster than just copying byte-by-byte. Halfword-by-halfword might be faster if your processor architecture allows it and both buffers are aligned on the halfword, although most memcpy implementations I've seen on architectures that support halfword load/store already do that.

Upvotes: 0

Related Questions