- #!/usr/bin/ksh93
- #
- # count_timer_syscalls.ksh- Count timer syscalls
- #
- # Tests whether clock_gettime() is implemented via traditional
- # syscalls or uses a shortcut (e.g. via shared memory/Linux VDSO)
- #
- # Written by Roland Mainz <roland.mainz@nrubsig.org>
- #
- builtin cat
- builtin wc
- #builtin rm
- set -o nounset
- function enumerate_clock_sources
- {
- typeset s
- typeset dummy aname avalue
- nameref ar="$1"
- s="$( clang -E -dM -m32 -include time.h - < '/dev/null' | \
- egrep \
- '#[[:space:]]*define[[:space:]]+CLOCK_.+[[:space:]]+[[:digit:]]+'
- )"
- while read dummy aname avalue ; do
- if [[ \
- "${aname}" != ~(El)CLOCK_ || \
- "${avalue}" != ~(Elr)[[:digit:]]+ ]] ; then
- continue
- fi
- integer ar["$aname"].value
- ar["$aname"].name="${aname}"
- ar["$aname"].value="${avalue}"
- done <<<"$s"
- return 0
- }
- function generate_test_code
- {
- nameref ar="$1"
- integer num_testruns=$2
- set -o errexit
- set -o nounset
- printf $"## Generating test code...\n"
- rm -f \
- 'generated_count_timer_syscalls.c' \
- 'generated_count_timer_syscalls'
- {
- cat <<EOF
- /*
- * count_timer_syscalls.c - runs timer NUM_TESTRUNS times,
- * strace can then be used to count syscalls
- *
- * Compile with:
- * $ clang -g -Wall -Wextra count_timer_syscalls.c
- *
- * Written by Roland Mainz <roland.mainz@nrubsig.org>
- *
- */
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <time.h>
- #include <sched.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #ifndef CLOCK_INVALID
- #define CLOCK_INVALID -1
- #endif
- #define NSEC_PER_SEC (1000000000LL)
- #define NUM_TESTRUNS (${num_testruns}UL)
- static
- clockid_t get_clockid(int fd)
- {
- const int CLOCKFD = 3;
- return (((unsigned int) ~fd) << 3) | CLOCKFD;
- }
- static
- void test_loop_on_clock(clockid_t clkid, unsigned long num_cycles)
- {
- struct timespec ts;
- unsigned long cycles;
- for(cycles = 0UL ; cycles < num_cycles ; cycles++)
- {
- (void)clock_gettime(clkid, &ts);
- (void)ts;
- }
- }
- int main(int ac, char *av[])
- {
- const char *clockname = av[1];
- (void)puts("# start.");
- if ((ac != 2) || (!clockname)) {
- (void)fprintf(stderr, "%s: Missing clockname argument\n", av[0]);
- return EXIT_FAILURE;
- }
- if (!strcmp(clockname, "nic")) {
- int fd;
- clockid_t clkid;
- const char *devicename = "/dev/ptp0";
- fd = open(devicename, O_RDWR);
- if (fd < 0) {
- (void)fprintf(stderr, "opening %s: %s\n", devicename,
- strerror(errno));
- return(EXIT_FAILURE);
- }
- clkid = get_clockid(fd);
- if (CLOCK_INVALID == clkid) {
- (void)fprintf(stderr, "failed to read clock id\n");
- return(EXIT_FAILURE);
- }
- (void)printf("## test run using nic clock\n");
- test_loop_on_clock(clkid, NUM_TESTRUNS);
- (void)close(fd);
- EOF
- typeset i
- for i in "${!ar[@]}" ; do
- typeset name="${ar[$i].name}"
- printf '\t} else if (!strcmp(clockname, "%s")) {\n' "$name"
- printf '\t\t(void)printf("## test run using %s\\n");\n' "$name"
- printf '\n'
- printf '\t\ttest_loop_on_clock(%s, NUM_TESTRUNS);\n' "$name"
- done
- cat <<EOF
- } else {
- (void)fprintf(stderr, "%s: Unknown clockname argument %s\n",
- av[0], clockname);
- return EXIT_FAILURE;
- }
- (void)puts("# end.");
- return(EXIT_SUCCESS);
- }
- EOF
- } >"generated_count_timer_syscalls.c"
- return 0
- }
- function compile_test_code
- {
- set -o errexit
- printf $"## Compiling test code...\n"
- clang -m32 -g -Wall -Wextra \
- -o generated_count_timer_syscalls \
- generated_count_timer_syscalls.c
- return 0
- }
- function run_tests
- {
- nameref ar="$1"
- compound cmd
- typeset cmd.output
- integer cmd.exit_code
- typeset i
- printf $"## Running tests...\n"
- for i in "${!ar[@]}" ; do
- nameref n=ar["$i"]
- printf $"Probing %q...\n" "${n.name}"
- cmd.output="${ strace ./generated_count_timer_syscalls "${n.name}" 2>&1 ; cmd.exit_code="$?" ; }"
- integer n.num_syscalls_clock_gettime="${ egrep 'clock_gettime' <<<"${cmd.output}" | wc -l ;}"
- integer n.num_syscalls_total="${ wc -l <<<"${cmd.output}" ; }"
- integer n.exit_code=${cmd.exit_code}
- done
- }
- function print_results
- {
- nameref c=$1
- set -o nounset
- printf $"## Raw test results:\n"
- print -v c
- printf $"## Summary of test results for %q:\n" "${c.uname}"
- nameref ar="c.clock_names"
- for i in "${!ar[@]}" ; do
- nameref n=ar["$i"]
- printf $"Clock name %-20s \t" ${n.name}
- if (( (n.exit_code != 0) || (n.num_syscalls_total < 30) )) ; then
- printf $"TEST FAILED\n"
- elif (( n.num_syscalls_clock_gettime >= c.num_testruns )) ; then
- printf $"uses traditional syscalls\n"
- elif (( n.num_syscalls_clock_gettime <= 1 )) ; then
- printf $"uses shortcut\n"
- else
- printf $"Data inconclusive\n"
- fi
- done
- return 0
- }
- function main
- {
- compound c
- compound -A c.clock_names
- integer c.num_testruns=32100
- typeset c.uname="$(uname -a)"
- typeset c.hostname="$(hostname)"
- if ! enumerate_clock_sources c.clock_names ; then
- print -u2 -f $"%s: Could not enumerate clock names.\n" "$1"
- return 1
- fi
- if ! generate_test_code c.clock_names ${c.num_testruns} ; then
- print -u2 -f $"%s: Could not generate test code.\n" "$1"
- return 1
- fi
- if ! compile_test_code ; then
- print -u2 -f $"%s: Could not compile test code.\n" "$1"
- return 1
- fi
- run_tests c.clock_names
- print_results c
- print $"## Done."
- return 0
- }
- main "$@"
- # EOF.
count_timer_syscalls.ksh
Posted by Anonymous on Sat 17th Sep 2022 15:52
raw | new post
modification of post by Anonymous (view diff)
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.