Skip to content

Commit b3e4532

Browse files
olsajiriacmel
authored andcommitted
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>
1 parent 05e91e7 commit b3e4532

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

tools/include/linux/string.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,5 @@ extern char * __must_check skip_spaces(const char *);
4646

4747
extern char *strim(char *);
4848

49+
extern void *memchr_inv(const void *start, int c, size_t bytes);
4950
#endif /* _TOOLS_LINUX_STRING_H_ */

tools/lib/string.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,61 @@ char *strreplace(char *s, char old, char new)
168168
*s = new;
169169
return s;
170170
}
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+
}

0 commit comments

Comments
 (0)