1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /****************************************************************************** |
3 | * |
4 | * Copyright © International Business Machines Corp., 2009 |
5 | * |
6 | * DESCRIPTION |
7 | * Test if FUTEX_WAIT op returns -EWOULDBLOCK if the futex value differs |
8 | * from the expected one. |
9 | * |
10 | * AUTHOR |
11 | * Gowrishankar <gowrishankar.m@in.ibm.com> |
12 | * |
13 | * HISTORY |
14 | * 2009-Nov-14: Initial version by Gowrishankar <gowrishankar.m@in.ibm.com> |
15 | * |
16 | *****************************************************************************/ |
17 | |
18 | #include <errno.h> |
19 | #include <getopt.h> |
20 | #include <stdio.h> |
21 | #include <stdlib.h> |
22 | #include <string.h> |
23 | #include <time.h> |
24 | #include "futextest.h" |
25 | #include "futex2test.h" |
26 | #include "logging.h" |
27 | |
28 | #define TEST_NAME "futex-wait-wouldblock" |
29 | #define timeout_ns 100000 |
30 | |
31 | void usage(char *prog) |
32 | { |
33 | printf("Usage: %s\n" , prog); |
34 | printf(" -c Use color\n" ); |
35 | printf(" -h Display this help message\n" ); |
36 | printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n" , |
37 | VQUIET, VCRITICAL, VINFO); |
38 | } |
39 | |
40 | int main(int argc, char *argv[]) |
41 | { |
42 | struct timespec to = {.tv_sec = 0, .tv_nsec = timeout_ns}; |
43 | futex_t f1 = FUTEX_INITIALIZER; |
44 | int res, ret = RET_PASS; |
45 | int c; |
46 | struct futex_waitv waitv = { |
47 | .uaddr = (uintptr_t)&f1, |
48 | .val = f1+1, |
49 | .flags = FUTEX_32, |
50 | .__reserved = 0 |
51 | }; |
52 | |
53 | while ((c = getopt(argc, argv, "cht:v:" )) != -1) { |
54 | switch (c) { |
55 | case 'c': |
56 | log_color(1); |
57 | break; |
58 | case 'h': |
59 | usage(prog: basename(argv[0])); |
60 | exit(0); |
61 | case 'v': |
62 | log_verbosity(atoi(optarg)); |
63 | break; |
64 | default: |
65 | usage(prog: basename(argv[0])); |
66 | exit(1); |
67 | } |
68 | } |
69 | |
70 | ksft_print_header(); |
71 | ksft_set_plan(2); |
72 | ksft_print_msg("%s: Test the unexpected futex value in FUTEX_WAIT\n" , |
73 | basename(argv[0])); |
74 | |
75 | info("Calling futex_wait on f1: %u @ %p with val=%u\n" , f1, &f1, f1+1); |
76 | res = futex_wait(&f1, f1+1, &to, FUTEX_PRIVATE_FLAG); |
77 | if (!res || errno != EWOULDBLOCK) { |
78 | ksft_test_result_fail("futex_wait returned: %d %s\n" , |
79 | res ? errno : res, |
80 | res ? strerror(errno) : "" ); |
81 | ret = RET_FAIL; |
82 | } else { |
83 | ksft_test_result_pass("futex_wait\n" ); |
84 | } |
85 | |
86 | if (clock_gettime(CLOCK_MONOTONIC, &to)) { |
87 | error("clock_gettime failed\n" , errno); |
88 | return errno; |
89 | } |
90 | |
91 | to.tv_nsec += timeout_ns; |
92 | |
93 | if (to.tv_nsec >= 1000000000) { |
94 | to.tv_sec++; |
95 | to.tv_nsec -= 1000000000; |
96 | } |
97 | |
98 | info("Calling futex_waitv on f1: %u @ %p with val=%u\n" , f1, &f1, f1+1); |
99 | res = futex_waitv(&waitv, 1, 0, &to, CLOCK_MONOTONIC); |
100 | if (!res || errno != EWOULDBLOCK) { |
101 | ksft_test_result_pass("futex_waitv returned: %d %s\n" , |
102 | res ? errno : res, |
103 | res ? strerror(errno) : "" ); |
104 | ret = RET_FAIL; |
105 | } else { |
106 | ksft_test_result_pass("futex_waitv\n" ); |
107 | } |
108 | |
109 | ksft_print_cnts(); |
110 | return ret; |
111 | } |
112 | |