0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/types.h>
0010 #include <linux/module.h>
0011
0012
0013 #define BYTES_LONG sizeof(long)
0014 #define WORD_MASK (BYTES_LONG - 1)
0015 #define MIN_THRESHOLD (BYTES_LONG * 2)
0016
0017
0018 union types {
0019 u8 *as_u8;
0020 unsigned long *as_ulong;
0021 uintptr_t as_uptr;
0022 };
0023
0024 union const_types {
0025 const u8 *as_u8;
0026 unsigned long *as_ulong;
0027 uintptr_t as_uptr;
0028 };
0029
0030 void *memcpy(void *dest, const void *src, size_t count)
0031 {
0032 union const_types s = { .as_u8 = src };
0033 union types d = { .as_u8 = dest };
0034 int distance = 0;
0035
0036 if (count < MIN_THRESHOLD)
0037 goto copy_remainder;
0038
0039
0040 for (; d.as_uptr & WORD_MASK; count--)
0041 *d.as_u8++ = *s.as_u8++;
0042
0043 distance = s.as_uptr & WORD_MASK;
0044
0045 if (distance) {
0046 unsigned long last, next;
0047
0048
0049
0050
0051
0052
0053
0054 s.as_u8 -= distance;
0055
0056 next = s.as_ulong[0];
0057 for (; count >= BYTES_LONG; count -= BYTES_LONG) {
0058 last = next;
0059 next = s.as_ulong[1];
0060
0061 d.as_ulong[0] = last >> (distance * 8) |
0062 next << ((BYTES_LONG - distance) * 8);
0063
0064 d.as_ulong++;
0065 s.as_ulong++;
0066 }
0067
0068
0069 s.as_u8 += distance;
0070 } else {
0071
0072
0073
0074
0075 for (; count >= BYTES_LONG; count -= BYTES_LONG)
0076 *d.as_ulong++ = *s.as_ulong++;
0077 }
0078
0079 copy_remainder:
0080 while (count--)
0081 *d.as_u8++ = *s.as_u8++;
0082
0083 return dest;
0084 }
0085 EXPORT_SYMBOL(memcpy);
0086
0087
0088
0089
0090
0091 void *memmove(void *dest, const void *src, size_t count)
0092 {
0093 if (dest < src || src + count <= dest)
0094 return memcpy(dest, src, count);
0095
0096 if (dest > src) {
0097 const char *s = src + count;
0098 char *tmp = dest + count;
0099
0100 while (count--)
0101 *--tmp = *--s;
0102 }
0103 return dest;
0104 }
0105 EXPORT_SYMBOL(memmove);
0106
0107 void *memset(void *s, int c, size_t count)
0108 {
0109 union types dest = { .as_u8 = s };
0110
0111 if (count >= MIN_THRESHOLD) {
0112 unsigned long cu = (unsigned long)c;
0113
0114
0115 cu |= cu << 8;
0116 cu |= cu << 16;
0117
0118 cu |= (cu << 16) << 16;
0119
0120 for (; count && dest.as_uptr & WORD_MASK; count--)
0121 *dest.as_u8++ = c;
0122
0123
0124 for (; count >= BYTES_LONG; count -= BYTES_LONG)
0125 *dest.as_ulong++ = cu;
0126 }
0127
0128
0129 while (count--)
0130 *dest.as_u8++ = c;
0131
0132 return s;
0133 }
0134 EXPORT_SYMBOL(memset);