1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
4 * Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
5 */
6
7 #ifndef FUTEX_UTILS_H__
8 #define FUTEX_UTILS_H__
9
10 #include <stdio.h>
11 #include <stdlib.h>
12
13 #if __NR_futex != __LTP__NR_INVALID_SYSCALL && __NR_futex_time64 != __LTP__NR_INVALID_SYSCALL
14 # define FUTEX_VARIANTS 2
15 #else
16 # define FUTEX_VARIANTS 1
17 #endif
18
futex_variant(void)19 static inline struct futex_test_variants futex_variant(void)
20 {
21 struct futex_test_variants variants[] = {
22 #if (__NR_futex != __LTP__NR_INVALID_SYSCALL)
23 { .fntype = FUTEX_FN_FUTEX, .desc = "syscall with old kernel spec" },
24 #endif
25
26 #if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL)
27 { .fntype = FUTEX_FN_FUTEX64, .desc = "syscall time64 with kernel spec" },
28 #endif
29 };
30
31 return variants[tst_variant];
32 }
33
34 /*
35 * Wait for nr_threads to be sleeping
36 */
wait_for_threads(unsigned int nr_threads)37 static inline int wait_for_threads(unsigned int nr_threads)
38 {
39 char thread_state, name[1024];
40 DIR *dir;
41 struct dirent *dent;
42 unsigned int cnt = 0;
43
44 snprintf(name, sizeof(name), "/proc/%i/task/", getpid());
45
46 dir = SAFE_OPENDIR(name);
47
48 while ((dent = SAFE_READDIR(dir))) {
49 /* skip ".", ".." and the main thread */
50 if (atoi(dent->d_name) == getpid() || atoi(dent->d_name) == 0)
51 continue;
52
53 snprintf(name, sizeof(name), "/proc/%i/task/%s/stat",
54 getpid(), dent->d_name);
55
56 SAFE_FILE_SCANF(name, "%*i %*s %c", &thread_state);
57
58 if (thread_state != 'S') {
59 tst_res(TINFO, "Thread %s not sleeping yet", dent->d_name);
60 SAFE_CLOSEDIR(dir);
61 return 1;
62 }
63 cnt++;
64 }
65
66 SAFE_CLOSEDIR(dir);
67
68 if (cnt != nr_threads) {
69 tst_res(TINFO, "%u threads sleeping, expected %u", cnt,
70 nr_threads);
71 }
72
73 return 0;
74 }
75
76 #endif /* FUTEX_UTILS_H__ */
77