za-fork.c (2949B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2022 ARM Limited. 4 * Original author: Mark Brown <broonie@kernel.org> 5 */ 6 7// SPDX-License-Identifier: GPL-2.0-only 8 9#include <linux/sched.h> 10#include <linux/wait.h> 11 12#define EXPECTED_TESTS 1 13 14static void putstr(const char *str) 15{ 16 write(1, str, strlen(str)); 17} 18 19static void putnum(unsigned int num) 20{ 21 char c; 22 23 if (num / 10) 24 putnum(num / 10); 25 26 c = '0' + (num % 10); 27 write(1, &c, 1); 28} 29 30static int tests_run; 31static int tests_passed; 32static int tests_failed; 33static int tests_skipped; 34 35static void print_summary(void) 36{ 37 if (tests_passed + tests_failed + tests_skipped != EXPECTED_TESTS) 38 putstr("# UNEXPECTED TEST COUNT: "); 39 40 putstr("# Totals: pass:"); 41 putnum(tests_passed); 42 putstr(" fail:"); 43 putnum(tests_failed); 44 putstr(" xfail:0 xpass:0 skip:"); 45 putnum(tests_skipped); 46 putstr(" error:0\n"); 47} 48 49int fork_test(void); 50int verify_fork(void); 51 52/* 53 * If we fork the value in the parent should be unchanged and the 54 * child should start with the same value. This is called from the 55 * fork_test() asm function. 56 */ 57int fork_test_c(void) 58{ 59 pid_t newpid, waiting; 60 int child_status, parent_result; 61 62 newpid = fork(); 63 if (newpid == 0) { 64 /* In child */ 65 if (!verify_fork()) { 66 putstr("# ZA state invalid in child\n"); 67 exit(0); 68 } else { 69 exit(1); 70 } 71 } 72 if (newpid < 0) { 73 putstr("# fork() failed: -"); 74 putnum(-newpid); 75 putstr("\n"); 76 return 0; 77 } 78 79 parent_result = verify_fork(); 80 if (!parent_result) 81 putstr("# ZA state invalid in parent\n"); 82 83 for (;;) { 84 waiting = waitpid(newpid, &child_status, 0); 85 86 if (waiting < 0) { 87 if (errno == EINTR) 88 continue; 89 putstr("# waitpid() failed: "); 90 putnum(errno); 91 putstr("\n"); 92 return 0; 93 } 94 if (waiting != newpid) { 95 putstr("# waitpid() returned wrong PID\n"); 96 return 0; 97 } 98 99 if (!WIFEXITED(child_status)) { 100 putstr("# child did not exit\n"); 101 return 0; 102 } 103 104 return WEXITSTATUS(child_status) && parent_result; 105 } 106} 107 108#define run_test(name) \ 109 if (name()) { \ 110 tests_passed++; \ 111 } else { \ 112 tests_failed++; \ 113 putstr("not "); \ 114 } \ 115 putstr("ok "); \ 116 putnum(++tests_run); \ 117 putstr(" " #name "\n"); 118 119int main(int argc, char **argv) 120{ 121 int ret, i; 122 123 putstr("TAP version 13\n"); 124 putstr("1.."); 125 putnum(EXPECTED_TESTS); 126 putstr("\n"); 127 128 putstr("# PID: "); 129 putnum(getpid()); 130 putstr("\n"); 131 132 /* 133 * This test is run with nolibc which doesn't support hwcap and 134 * it's probably disproportionate to implement so instead check 135 * for the default vector length configuration in /proc. 136 */ 137 ret = open("/proc/sys/abi/sme_default_vector_length", O_RDONLY, 0); 138 if (ret >= 0) { 139 run_test(fork_test); 140 141 } else { 142 putstr("# SME support not present\n"); 143 144 for (i = 0; i < EXPECTED_TESTS; i++) { 145 putstr("ok "); 146 putnum(i); 147 putstr(" skipped\n"); 148 } 149 150 tests_skipped += EXPECTED_TESTS; 151 } 152 153 print_summary(); 154 155 return 0; 156}