2023-03-14 21:08:25 +08:00
|
|
|
#
|
|
|
|
|
# For a description of the syntax of this configuration file,
|
|
|
|
|
# see the file kconfig-language.txt in the NuttX tools repository.
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC
|
|
|
|
|
tristate "arch-specific libc function test"
|
|
|
|
|
default n
|
|
|
|
|
---help---
|
|
|
|
|
Enable the arch libc test
|
|
|
|
|
|
|
|
|
|
if TESTING_ARCH_LIBC
|
|
|
|
|
|
testing/libc/arch_libc: Add tests for all string/memory functions.
The arch_libc test only covered strcpy, so the architecture optimized
implementations of the remaining string and memory routines were never
exercised by the test suite.
Extend the test to also cover memcpy, memmove, memset, memcmp, memchr,
strlen, strcmp, strchr, strncmp, strnlen, strncpy, stpcpy, strcat and
strrchr:
* Every function gets a correctness test that sweeps the buffer
alignment and the transfer size and compares the result against the
expected value.
* Every function gets a speed test that reports the average cycle count
measured with perf_gettime().
* Every individual test is selected by its own
CONFIG_TESTING_ARCH_LIBC_<FUNC> option (default y), so a target can
drop the ones it does not need.
Impact: test only. Nothing is built unless CONFIG_TESTING_ARCH_LIBC
(default n) is selected, so no existing board configuration changes.
Testing: built and ran sim:nsh on Linux x86_64 (Ubuntu 24.04,
gcc 13.3.0) with CONFIG_TESTING_ARCH_LIBC=y. All 15 enabled functions
report PASSED and "arch_libc_test Passed".
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2026-03-13 16:33:37 +08:00
|
|
|
config TESTING_ARCH_LIBC_MEMCHR
|
|
|
|
|
bool "test memchr"
|
|
|
|
|
default y
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_MEMCMP
|
|
|
|
|
bool "test memcmp"
|
|
|
|
|
default y
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_MEMCPY
|
|
|
|
|
bool "test memcpy"
|
|
|
|
|
default y
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_MEMMOVE
|
|
|
|
|
bool "test memmove"
|
|
|
|
|
default y
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_MEMSET
|
|
|
|
|
bool "test memset"
|
|
|
|
|
default y
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_STRCHR
|
|
|
|
|
bool "test strchr"
|
|
|
|
|
default y
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_STRCMP
|
|
|
|
|
bool "test strcmp"
|
|
|
|
|
default y
|
|
|
|
|
|
2023-03-14 21:08:25 +08:00
|
|
|
config TESTING_ARCH_LIBC_STRCPY
|
|
|
|
|
bool "test strcpy"
|
2025-01-03 15:17:16 +08:00
|
|
|
default y
|
2023-03-14 21:08:25 +08:00
|
|
|
|
testing/libc/arch_libc: Test memccpy and stpncpy.
Neither is covered here, and both are overridable, so a machine or libc
implementation of either goes in unmeasured and unchecked.
memccpy is checked with the search character present, where the copy
stops just past it and the result points there, and absent, where the
whole length is copied and the result is NULL. stpncpy is checked
against every capacity from zero to four past the length, for the
content, the zero padding beyond the terminator, and the returned
pointer, which is the terminator when the string fits and one past the
end when it does not.
Both sweep all sixty four source and destination alignment pairs, and
both are added to the benchmark, which now covers nineteen functions.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-08-15 16:20:30 +08:00
|
|
|
config TESTING_ARCH_LIBC_MEMCCPY
|
|
|
|
|
bool "test memccpy"
|
|
|
|
|
default y
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_STPNCPY
|
|
|
|
|
bool "test stpncpy"
|
|
|
|
|
default y
|
|
|
|
|
|
testing/libc/arch_libc: Test strlcpy.
strlcpy is the one function in this directory's reach that nothing here
covers, and a machine directory may override it like any other.
Sweep every source and destination alignment pair against sizes 1 to 64,
and for each of those every capacity from zero to one past the length.
Check the return value, which is the length of src whether or not the
copy fit, the truncation point, the content, that a capacity of zero
writes nothing at all, and that nothing lands past the terminator.
The alignment pairs are the point. An implementation that walks one of
the two pointers to a boundary and then copies a register at a time is
correct whenever the two agree, so a test that only ever passes matching
alignments says nothing about it.
The timing half is guarded. perf_gettime() is not a system call, so an
application reaches it only where the C library builds its own copy or
where the application and the kernel are one image; calling it
unconditionally leaves the test unbuildable on a kernel build, which is
where the correctness half is still wanted.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-08-15 15:13:10 +08:00
|
|
|
config TESTING_ARCH_LIBC_STRLCPY
|
|
|
|
|
bool "test strlcpy"
|
|
|
|
|
default y
|
|
|
|
|
|
testing/libc/arch_libc: Add tests for all string/memory functions.
The arch_libc test only covered strcpy, so the architecture optimized
implementations of the remaining string and memory routines were never
exercised by the test suite.
Extend the test to also cover memcpy, memmove, memset, memcmp, memchr,
strlen, strcmp, strchr, strncmp, strnlen, strncpy, stpcpy, strcat and
strrchr:
* Every function gets a correctness test that sweeps the buffer
alignment and the transfer size and compares the result against the
expected value.
* Every function gets a speed test that reports the average cycle count
measured with perf_gettime().
* Every individual test is selected by its own
CONFIG_TESTING_ARCH_LIBC_<FUNC> option (default y), so a target can
drop the ones it does not need.
Impact: test only. Nothing is built unless CONFIG_TESTING_ARCH_LIBC
(default n) is selected, so no existing board configuration changes.
Testing: built and ran sim:nsh on Linux x86_64 (Ubuntu 24.04,
gcc 13.3.0) with CONFIG_TESTING_ARCH_LIBC=y. All 15 enabled functions
report PASSED and "arch_libc_test Passed".
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2026-03-13 16:33:37 +08:00
|
|
|
config TESTING_ARCH_LIBC_STRLEN
|
|
|
|
|
bool "test strlen"
|
|
|
|
|
default y
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_STRNCMP
|
|
|
|
|
bool "test strncmp"
|
|
|
|
|
default y
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_STRNLEN
|
|
|
|
|
bool "test strnlen"
|
|
|
|
|
default y
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_STRNCPY
|
|
|
|
|
bool "test strncpy"
|
|
|
|
|
default y
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_STPCPY
|
|
|
|
|
bool "test stpcpy"
|
|
|
|
|
default y
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_STRCAT
|
|
|
|
|
bool "test strcat"
|
|
|
|
|
default y
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_STRRCHR
|
|
|
|
|
bool "test strrchr"
|
|
|
|
|
default y
|
|
|
|
|
|
testing/libc/arch_libc: Add strchrnul test and sweep size boundaries.
Add test_strchrnul() and speed_strchrnul(), selected by the new
CONFIG_TESTING_ARCH_LIBC_STRCHRNUL option, covering the hit, miss and
NUL cases.
Sweep alignment 0..7 and the boundary sizes {0, 1, 7, 8, 9, 15, 16, 17,
31, 32, 33, 63, 64, 65, 127, 128, 129, 255, 256, 257} in the scan
function tests (memcmp, memchr, strlen, strcmp, strchr, strncmp,
strnlen, strrchr) and in memmove. Those sizes sit on the 8 and 16 byte
chunk edges and on the sub-word tails, so vectorized (NEON/MVE) and
word-at-a-time implementations are stressed exactly at their alignment
and size boundaries instead of only at "nice" lengths. memmove is
additionally exercised across four overlap layouts: forward, backward,
contained and adjacent.
Impact: test only, selected by CONFIG_TESTING_ARCH_LIBC (default n).
Testing: built and ran qemu-armv7a:nsh (Cortex-A7, generic C
implementation) and sim:nsh on Linux x86_64 (Ubuntu 24.04, gcc 13.3.0)
with CONFIG_TESTING_ARCH_LIBC=y. All 16 enabled functions report
PASSED and "arch_libc_test Passed". These tests pass against the
generic C routines, which establishes the correctness baseline before
architecture optimized assembly is introduced.
Signed-off-by: anjiahao <anjiahao@xiaomi.com>
2026-07-01 16:02:13 +08:00
|
|
|
config TESTING_ARCH_LIBC_STRCHRNUL
|
|
|
|
|
bool "test strchrnul"
|
|
|
|
|
default y
|
|
|
|
|
|
testing/libc/arch_libc: Add a throughput benchmark.
The existing speed checks time one call at one size, 128 bytes, with both
operands aligned. A machine implementation usually takes its wide path
only when the pointers satisfy some alignment condition, so that single
point reports the best case and says nothing about the rest of the input
space.
Measure the same functions across a size sweep and every source and
destination alignment pair instead, plus strlcpy. On rv64 the difference
this exposes is not marginal:
strcpy 32768 B s+0/d+0 2938.0 MB/s
strcpy 32768 B s+1/d+1 2942.0 MB/s
strcpy 32768 B s+1/d+2 626.0 MB/s
memcmp 32768 B s+0/d+0 412.4 MB/s
memcmp 32768 B s+1/d+2 41.0 MB/s
Two pointers misaligned by the same amount run at the aligned rate;
misaligned by different amounts they fall to a tenth of it. Neither
number is visible from an aligned measurement alone.
A function with no machine implementation reports the same rate at every
alignment, so the sweep also shows which of them a machine directory
actually covers.
Each result reports MB/s, which compares across machines, and cycles per
byte where perf_gettime() is reachable from an application, both from one
timed loop. strcat starts from an empty destination on each turn, since
appending to the last result would grow it without bound, so its figure
includes that store.
It sits behind TESTING_ARCH_LIBC_BENCH, default n, because a measurement
runs for a fixed interval and a full sweep takes about a minute.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-08-15 13:19:20 +08:00
|
|
|
config TESTING_ARCH_LIBC_BENCH
|
|
|
|
|
bool "throughput benchmark"
|
|
|
|
|
default n
|
|
|
|
|
---help---
|
|
|
|
|
Measure each function across a size sweep and every source and
|
|
|
|
|
destination alignment pair, reporting MB/s and cycles per byte.
|
|
|
|
|
An implementation usually takes its wide path only when the
|
|
|
|
|
pointers meet some alignment condition, so an aligned measurement
|
|
|
|
|
alone does not show what the rest of the input space costs.
|
|
|
|
|
|
|
|
|
|
if TESTING_ARCH_LIBC_BENCH
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_BENCH_BUFSIZE
|
|
|
|
|
int "benchmark buffer size"
|
|
|
|
|
default 262144
|
|
|
|
|
---help---
|
|
|
|
|
Size of each of the two buffers the benchmark allocates.
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_BENCH_MINMS
|
|
|
|
|
int "minimum milliseconds per measurement"
|
|
|
|
|
default 250
|
|
|
|
|
---help---
|
|
|
|
|
Each measurement repeats until it has run for at least this long.
|
|
|
|
|
|
|
|
|
|
endif
|
|
|
|
|
|
2023-03-14 21:08:25 +08:00
|
|
|
config TESTING_ARCH_LIBC_PROGNAME
|
|
|
|
|
string "Program name"
|
|
|
|
|
default "arch_libctest"
|
|
|
|
|
---help---
|
|
|
|
|
This is the name of the program that will be used when the NSH ELF
|
|
|
|
|
program is installed.
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_PRIORITY
|
|
|
|
|
int "arch libc test priority"
|
|
|
|
|
default 100
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_STACKSIZE
|
|
|
|
|
int "arch libc test stack size"
|
|
|
|
|
default DEFAULT_TASK_STACKSIZE
|
|
|
|
|
|
|
|
|
|
config TESTING_ARCH_LIBC_VERBOSE
|
|
|
|
|
bool "Verbose output"
|
|
|
|
|
default n
|
|
|
|
|
|
|
|
|
|
endif
|