1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14 #ifndef CEPH_INLINE_MEMORY_H
15 #define CEPH_INLINE_MEMORY_H
16
17 #if defined(__GNUC__)
18
19 // optimize for the common case, which is very small copies
20 static inline void *maybe_inline_memcpy(void *dest, const void *src, size_t l,
21 size_t inline_len)
22 __attribute__((always_inline));
23
24 void *maybe_inline_memcpy(void *dest, const void *src, size_t l,
25 size_t inline_len)
26 {
(1) Event cond_false: |
Condition "l > inline_len", taking false branch. |
27 if (l > inline_len) {
28 return memcpy(dest, src, l);
(2) Event if_end: |
End of if statement. |
29 }
(3) Event switch: |
Switch case value "8UL". |
30 switch (l) {
(4) Event switch_case: |
Reached case "8UL". |
31 case 8:
(5) Event access_dbuff_const: |
Calling "__builtin_memcpy" indexes array "src" with index "8UL" at byte position 7. |
32 return __builtin_memcpy(dest, src, 8);
33 case 4:
34 return __builtin_memcpy(dest, src, 4);
35 case 3:
36 return __builtin_memcpy(dest, src, 3);
37 case 2:
38 return __builtin_memcpy(dest, src, 2);
39 case 1:
40 return __builtin_memcpy(dest, src, 1);
41 default:
42 int cursor = 0;
43 while (l >= sizeof(uint64_t)) {
44 __builtin_memcpy((char*)dest + cursor, (char*)src + cursor,
45 sizeof(uint64_t));
46 cursor += sizeof(uint64_t);
47 l -= sizeof(uint64_t);
48 }
49 while (l >= sizeof(uint32_t)) {
50 __builtin_memcpy((char*)dest + cursor, (char*)src + cursor,
51 sizeof(uint32_t));
52 cursor += sizeof(uint32_t);
53 l -= sizeof(uint32_t);
54 }
55 while (l > 0) {
56 *((char*)dest + cursor) = *((char*)src + cursor);
57 cursor++;
58 l--;
59 }
60 }
61 return dest;
62 }
63
64 #else
65
66 #define maybe_inline_memcpy(d, s, l, x) memcpy(d, s, l)
67
68 #endif
69
70
71 #if defined(__GNUC__) && defined(__x86_64__)
72
73 namespace ceph {
74 typedef unsigned uint128_t __attribute__ ((mode (TI)));
75 }
76 using ceph::uint128_t;
77
78 static inline bool mem_is_zero(const char *data, size_t len)
79 __attribute__((always_inline));
80
81 bool mem_is_zero(const char *data, size_t len)
82 {
83 // we do have XMM registers in x86-64, so if we need to check at least
84 // 16 bytes, make use of them
85 if (len / sizeof(uint128_t) > 0) {
86 // align data pointer to 16 bytes, otherwise it'll segfault due to bug
87 // in (at least some) GCC versions (using MOVAPS instead of MOVUPS).
88 // check up to 15 first bytes while at it.
89 while (((unsigned long long)data) & 15) {
90 if (*(uint8_t*)data != 0) {
91 return false;
92 }
93 data += sizeof(uint8_t);
94 --len;
95 }
96
97 const char* data_start = data;
98 const char* max128 = data + (len / sizeof(uint128_t))*sizeof(uint128_t);
99
100 while (data < max128) {
101 if (*(uint128_t*)data != 0) {
102 return false;
103 }
104 data += sizeof(uint128_t);
105 }
106 len -= (data - data_start);
107 }
108
109 const char* max = data + len;
110 const char* max32 = data + (len / sizeof(uint32_t))*sizeof(uint32_t);
111 while (data < max32) {
112 if (*(uint32_t*)data != 0) {
113 return false;
114 }
115 data += sizeof(uint32_t);
116 }
117 while (data < max) {
118 if (*(uint8_t*)data != 0) {
119 return false;
120 }
121 data += sizeof(uint8_t);
122 }
123 return true;
124 }
125
126 #else // gcc and x86_64
127
128 static inline bool mem_is_zero(const char *data, size_t len) {
129 const char *end = data + len;
130 const char* end64 = data + (len / sizeof(uint64_t))*sizeof(uint64_t);
131
132 while (data < end64) {
133 if (*(uint64_t*)data != 0) {
134 return false;
135 }
136 data += sizeof(uint64_t);
137 }
138
139 while (data < end) {
140 if (*data != 0) {
141 return false;
142 }
143 ++data;
144 }
145 return true;
146 }
147
148 #endif // !x86_64
149
150 #endif
151