1// SPDX-License-Identifier: GPL-2.0-or-later 2/* Copyright 2023 Mike Galbraith <efault-AT-gmx.de> */ 3/* Copyright 2023 Wei Gao <wegao@suse.com> */ 4/*\ 5 * 6 * [Description] 7 * 8 * Thread starvation test. On fauluty kernel the test timeouts. 9 * 10 * Original reproducer taken from: 11 * https://lore.kernel.org/lkml/9fd2c37a05713c206dcbd5866f67ce779f315e9e.camel@gmx.de/ 12 */ 13 14#define _GNU_SOURCE 15#include <stdio.h> 16#include <signal.h> 17#include <unistd.h> 18#include <sys/types.h> 19#include <sys/wait.h> 20#include <stdlib.h> 21#include <sched.h> 22 23#include "tst_test.h" 24 25static char *str_loop; 26static long loop = 2000000; 27static char *str_timeout; 28static int timeout = 240; 29 30static int wait_for_pid(pid_t pid) 31{ 32 int status, ret; 33 34again: 35 ret = waitpid(pid, &status, 0); 36 if (ret == -1) { 37 if (errno == EINTR) 38 goto again; 39 40 return -1; 41 } 42 43 if (WIFSIGNALED(status)) 44 return 0; 45 46 return -1; 47} 48 49static void setup(void) 50{ 51 cpu_set_t mask; 52 53 CPU_ZERO(&mask); 54 55 CPU_SET(0, &mask); 56 57 TST_EXP_POSITIVE(sched_setaffinity(0, sizeof(mask), &mask)); 58 59 if (tst_parse_long(str_loop, &loop, 1, LONG_MAX)) 60 tst_brk(TBROK, "Invalid number of loop number '%s'", str_loop); 61 62 if (tst_parse_int(str_timeout, &timeout, 1, INT_MAX)) 63 tst_brk(TBROK, "Invalid number of timeout '%s'", str_timeout); 64 65 tst_set_max_runtime(timeout); 66} 67 68static void handler(int sig LTP_ATTRIBUTE_UNUSED) 69{ 70 if (loop > 0) 71 --loop; 72} 73 74static void child(void) 75{ 76 pid_t ppid = getppid(); 77 78 TST_CHECKPOINT_WAIT(0); 79 80 while (1) 81 SAFE_KILL(ppid, SIGUSR1); 82} 83 84static void do_test(void) 85{ 86 pid_t child_pid; 87 88 child_pid = SAFE_FORK(); 89 90 if (!child_pid) 91 child(); 92 93 SAFE_SIGNAL(SIGUSR1, handler); 94 TST_CHECKPOINT_WAKE(0); 95 96 while (loop) 97 sleep(1); 98 99 SAFE_KILL(child_pid, SIGTERM); 100 TST_EXP_PASS(wait_for_pid(child_pid)); 101} 102 103static struct tst_test test = { 104 .test_all = do_test, 105 .setup = setup, 106 .forks_child = 1, 107 .options = (struct tst_option[]) { 108 {"l:", &str_loop, "Number of loops (default 2000000)"}, 109 {"t:", &str_timeout, "Max timeout (default 240s)"}, 110 {} 111 }, 112 .needs_checkpoints = 1, 113}; 114