Learning notes of memcpy source code under glibc

Keywords: REST less

I've always heard that memcpy has memory overlap. I want to see why it has this problem?

glib version 2.15

#include <string.h>
#include <memcopy.h>
#include <pagecopy.h>
 
#undef memcpy
 
void *
memcpy (dstpp, srcpp, len)
     void *dstpp;
     const void *srcpp;
     size_t len;
{
  unsigned long int dstp = (long int) dstpp;
  unsigned long int srcp = (long int) srcpp;
 
  /* Copy from the beginning to the end.  */
 
  /* If there not too few bytes to copy, use word copy.  */
  if (len >= OP_T_THRES)
    {
      /* Copy just a few bytes to make DSTP aligned.  */
      len -= (-dstp) % OPSIZ;
      BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);
 
      /* Copy whole pages from SRCP to DSTP by virtual address manipulation,
	 as much as possible.  */
 
      PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);
 
      /* Copy from SRCP to DSTP taking advantage of the known alignment of
	 DSTP.  Number of bytes remaining is put in the third argument,
	 i.e. in LEN.  This number may vary from machine to machine.  */
 
      WORD_COPY_FWD (dstp, srcp, len, len);
 
      /* Fall out and copy the tail.  */
    }
 
  /* There are just a few bytes to copy.  Use byte memory operations.  */
  BYTE_COPY_FWD (dstp, srcp, len);
 
  return dstpp;
}
libc_hidden_builtin_def (memcpy)

We analyze step by step:

  • Function parameter void * memcpy (dstpp, srcpp, len) void *dstpp; const void *srcpp; size_t len;
    This parameter form can be ignored temporarily. void * destpp represents the destination address, const void * srcpp represents the source address, and sizeļ¹ len represents the length

  • Address is converted to unsigned long int for saving

    unsigned long int dstp = (long int) dstpp;
    unsigned long int srcp = (long int) srcpp;
    
  • If the number of copies is less than OP? T? Thres, execute byte? Copy? FWD (DSTP, SRCP, len);
    Where OP? T? Tres is set according to different systems, and its value is 16 on my computer

#define BYTE_COPY_FWD(dst_bp, src_bp, nbytes)				      \
 do									      \
   {									      \
     size_t __nbytes = (nbytes);					      \
     while (__nbytes > 0)						      \
   {								      \
     byte __x = ((byte *) src_bp)[0];				      \
     src_bp += 1;							      \
     __nbytes -= 1;						      \
     ((byte *) dst_bp)[0] = __x;					      \
     dst_bp += 1;							      \
   }								      \
   } while (0)

We can see clearly that it is a byte by byte copy

  • If the number of bytes copied is too large, memory alignment must be involved

     len -= (-dstp) % OPSIZ;
    BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);
    

Here we use the trick len -= (-dstp)%OPSIZ;
Let's explain this formula

Among them (- DSTP)% opsiz uses one byte for alignment, and the rest is processed directly according to the method of virtual page processing
PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);
However, due to too many restrictions, the special platform will adopt the method of page copy

  • We also have word? Copy? FWD (DSTP, SRCP, len, len); copy
#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes)		      \
  do									      \
    {									      \
      if (src_bp % OPSIZ == 0)						      \
	_wordcopy_fwd_aligned (dst_bp, src_bp, (nbytes) / OPSIZ);	      \
      else								      \
	_wordcopy_fwd_dest_aligned (dst_bp, src_bp, (nbytes) / OPSIZ);	      \
      src_bp += (nbytes) & -OPSIZ;					      \
      dst_bp += (nbytes) & -OPSIZ;					      \
      (nbytes_left) = (nbytes) % OPSIZ;					      \
    } while (0)
  • Using the method of word copy to copy one word by one word is the key of memcpy optimization. The optimization condition is that the copy address is in the alignment boundary.

To summarize:

  • Save the address with unsigned long int first
  • Then determine the size of the copy to be copied. If it is smaller than OP_T_THRES, copy directly in single byte.
  • If greater than OP? T? Thres, align first. The parts that need to be aligned are then copied as single bytes. The aligned ones are copied according to the page, and the rest can be copied according to one word at the boundary.
67 original articles published, 65 praised, 40000 visitors+
Private letter follow

Posted by AE117 on Sat, 22 Feb 2020 22:27:57 -0800