1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /****************************************************************************** |
3 | * |
4 | * Copyright FUJITSU LIMITED 2010 |
5 | * Copyright KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> |
6 | * |
7 | * DESCRIPTION |
8 | * Internally, Futex has two handling mode, anon and file. The private file |
9 | * mapping is special. At first it behave as file, but after write anything |
10 | * it behave as anon. This test is intent to test such case. |
11 | * |
12 | * AUTHOR |
13 | * KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> |
14 | * |
15 | * HISTORY |
16 | * 2010-Jan-6: Initial version by KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> |
17 | * |
18 | *****************************************************************************/ |
19 | |
20 | #include <stdio.h> |
21 | #include <stdlib.h> |
22 | #include <syscall.h> |
23 | #include <unistd.h> |
24 | #include <errno.h> |
25 | #include <linux/futex.h> |
26 | #include <pthread.h> |
27 | #include <libgen.h> |
28 | #include <signal.h> |
29 | |
30 | #include "logging.h" |
31 | #include "futextest.h" |
32 | |
33 | #define TEST_NAME "futex-wait-private-mapped-file" |
34 | #define PAGE_SZ 4096 |
35 | |
36 | char pad[PAGE_SZ] = {1}; |
37 | futex_t val = 1; |
38 | char pad2[PAGE_SZ] = {1}; |
39 | |
40 | #define WAKE_WAIT_US 3000000 |
41 | struct timespec wait_timeout = { .tv_sec = 5, .tv_nsec = 0}; |
42 | |
43 | void usage(char *prog) |
44 | { |
45 | printf("Usage: %s\n" , prog); |
46 | printf(" -c Use color\n" ); |
47 | printf(" -h Display this help message\n" ); |
48 | printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n" , |
49 | VQUIET, VCRITICAL, VINFO); |
50 | } |
51 | |
52 | void *thr_futex_wait(void *arg) |
53 | { |
54 | int ret; |
55 | |
56 | info("futex wait\n" ); |
57 | ret = futex_wait(&val, 1, &wait_timeout, 0); |
58 | if (ret && errno != EWOULDBLOCK && errno != ETIMEDOUT) { |
59 | error("futex error.\n" , errno); |
60 | print_result(TEST_NAME, RET_ERROR); |
61 | exit(RET_ERROR); |
62 | } |
63 | |
64 | if (ret && errno == ETIMEDOUT) |
65 | fail("waiter timedout\n" ); |
66 | |
67 | info("futex_wait: ret = %d, errno = %d\n" , ret, errno); |
68 | |
69 | return NULL; |
70 | } |
71 | |
72 | int main(int argc, char **argv) |
73 | { |
74 | pthread_t thr; |
75 | int ret = RET_PASS; |
76 | int res; |
77 | int c; |
78 | |
79 | while ((c = getopt(argc, argv, "chv:" )) != -1) { |
80 | switch (c) { |
81 | case 'c': |
82 | log_color(1); |
83 | break; |
84 | case 'h': |
85 | usage(prog: basename(argv[0])); |
86 | exit(0); |
87 | case 'v': |
88 | log_verbosity(atoi(optarg)); |
89 | break; |
90 | default: |
91 | usage(prog: basename(argv[0])); |
92 | exit(1); |
93 | } |
94 | } |
95 | |
96 | ksft_print_header(); |
97 | ksft_set_plan(1); |
98 | ksft_print_msg( |
99 | "%s: Test the futex value of private file mappings in FUTEX_WAIT\n" , |
100 | basename(argv[0])); |
101 | |
102 | ret = pthread_create(&thr, NULL, thr_futex_wait, NULL); |
103 | if (ret < 0) { |
104 | fprintf(stderr, "pthread_create error\n" ); |
105 | ret = RET_ERROR; |
106 | goto out; |
107 | } |
108 | |
109 | info("wait a while\n" ); |
110 | usleep(WAKE_WAIT_US); |
111 | val = 2; |
112 | res = futex_wake(&val, 1, 0); |
113 | info("futex_wake %d\n" , res); |
114 | if (res != 1) { |
115 | fail("FUTEX_WAKE didn't find the waiting thread.\n" ); |
116 | ret = RET_FAIL; |
117 | } |
118 | |
119 | info("join\n" ); |
120 | pthread_join(thr, NULL); |
121 | |
122 | out: |
123 | print_result(TEST_NAME, ret); |
124 | return ret; |
125 | } |
126 | |