Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools lib: Adopt memchr_inv() from kernel

We'll use it to check for undefined/zero data.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Suggested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexey Budankov <alexey.budankov@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <songliubraving@fb.com>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lore.kernel.org/lkml/20201126170026.2619053-6-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Jiri Olsa and committed by
Arnaldo Carvalho de Melo
b3e45327 05e91e7f

+59
+1
tools/include/linux/string.h
··· 46 46 47 47 extern char *strim(char *); 48 48 49 + extern void *memchr_inv(const void *start, int c, size_t bytes); 49 50 #endif /* _TOOLS_LINUX_STRING_H_ */
+58
tools/lib/string.c
··· 168 168 *s = new; 169 169 return s; 170 170 } 171 + 172 + static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes) 173 + { 174 + while (bytes) { 175 + if (*start != value) 176 + return (void *)start; 177 + start++; 178 + bytes--; 179 + } 180 + return NULL; 181 + } 182 + 183 + /** 184 + * memchr_inv - Find an unmatching character in an area of memory. 185 + * @start: The memory area 186 + * @c: Find a character other than c 187 + * @bytes: The size of the area. 188 + * 189 + * returns the address of the first character other than @c, or %NULL 190 + * if the whole buffer contains just @c. 191 + */ 192 + void *memchr_inv(const void *start, int c, size_t bytes) 193 + { 194 + u8 value = c; 195 + u64 value64; 196 + unsigned int words, prefix; 197 + 198 + if (bytes <= 16) 199 + return check_bytes8(start, value, bytes); 200 + 201 + value64 = value; 202 + value64 |= value64 << 8; 203 + value64 |= value64 << 16; 204 + value64 |= value64 << 32; 205 + 206 + prefix = (unsigned long)start % 8; 207 + if (prefix) { 208 + u8 *r; 209 + 210 + prefix = 8 - prefix; 211 + r = check_bytes8(start, value, prefix); 212 + if (r) 213 + return r; 214 + start += prefix; 215 + bytes -= prefix; 216 + } 217 + 218 + words = bytes / 8; 219 + 220 + while (words) { 221 + if (*(u64 *)start != value64) 222 + return check_bytes8(start, value, 8); 223 + start += 8; 224 + words--; 225 + } 226 + 227 + return check_bytes8(start, value, bytes % 8); 228 + }