/* Minimum size for a word copy to be convenient */ #define BYTES_LONG sizeof(long) #define WORD_MASK (BYTES_LONG - 1) #define MIN_THRESHOLD (BYTES_LONG * 2)
/* convenience union to avoid cast between different pointer types */ union types {
u8 *as_u8; unsignedlong *as_ulong;
uintptr_t as_uptr;
};
void *memcpy(void *dest, constvoid *src, size_t count)
{ union const_types s = { .as_u8 = src }; union types d = { .as_u8 = dest }; int distance = 0;
if (count < MIN_THRESHOLD) goto copy_remainder;
/* Copy a byte at time until destination is aligned. */ for (; d.as_uptr & WORD_MASK; count--)
*d.as_u8++ = *s.as_u8++;
distance = s.as_uptr & WORD_MASK;
if (distance) { unsignedlong last, next;
/* * s is distance bytes ahead of d, and d just reached * the alignment boundary. Move s backward to word align it * and shift data to compensate for distance, in order to do * word-by-word copy.
*/
s.as_u8 -= distance;
next = s.as_ulong[0]; for (; count >= BYTES_LONG; count -= BYTES_LONG) {
last = next;
next = s.as_ulong[1];
d.as_ulong[0] = last >> (distance * 8) |
next << ((BYTES_LONG - distance) * 8);
d.as_ulong++;
s.as_ulong++;
}
/* Restore s with the original offset. */
s.as_u8 += distance;
} else { /* * If the source and dest lower bits are the same, do a simple * 32/64 bit wide copy.
*/ for (; count >= BYTES_LONG; count -= BYTES_LONG)
*d.as_ulong++ = *s.as_ulong++;
}
copy_remainder: while (count--)
*d.as_u8++ = *s.as_u8++;
return dest;
}
EXPORT_SYMBOL(memcpy);
/* * Simply check if the buffer overlaps an call memcpy() in case, * otherwise do a simple one byte at time backward copy.
*/ void *memmove(void *dest, constvoid *src, size_t count)
{ if (dest < src || src + count <= dest) return memcpy(dest, src, count);
if (dest > src) { constchar *s = src + count; char *tmp = dest + count;
while (count--)
*--tmp = *--s;
} return dest;
}
EXPORT_SYMBOL(memmove);
void *memset(void *s, int c, size_t count)
{ union types dest = { .as_u8 = s };
if (count >= MIN_THRESHOLD) { unsignedlong cu = (unsignedlong)c;
/* Compose an ulong with 'c' repeated 4/8 times */
cu |= cu << 8;
cu |= cu << 16; /* Suppress warning on 32 bit machines */
cu |= (cu << 16) << 16;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.