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 | * Wait on uninitialized heap. It shold be zero and FUTEX_WAIT should |
9 | * return immediately. This test is intent to test zero page handling in |
10 | * futex. |
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 <pthread.h> |
21 | #include <stdio.h> |
22 | #include <stdlib.h> |
23 | #include <sys/mman.h> |
24 | #include <syscall.h> |
25 | #include <sys/types.h> |
26 | #include <sys/stat.h> |
27 | #include <unistd.h> |
28 | #include <errno.h> |
29 | #include <linux/futex.h> |
30 | #include <libgen.h> |
31 | |
32 | #include "logging.h" |
33 | #include "futextest.h" |
34 | |
35 | #define TEST_NAME "futex-wait-uninitialized-heap" |
36 | #define WAIT_US 5000000 |
37 | |
38 | static int child_blocked = 1; |
39 | static int child_ret; |
40 | void *buf; |
41 | |
42 | void usage(char *prog) |
43 | { |
44 | printf("Usage: %s\n" , prog); |
45 | printf(" -c Use color\n" ); |
46 | printf(" -h Display this help message\n" ); |
47 | printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n" , |
48 | VQUIET, VCRITICAL, VINFO); |
49 | } |
50 | |
51 | void *wait_thread(void *arg) |
52 | { |
53 | int res; |
54 | |
55 | child_ret = RET_PASS; |
56 | res = futex_wait(buf, 1, NULL, 0); |
57 | child_blocked = 0; |
58 | |
59 | if (res != 0 && errno != EWOULDBLOCK) { |
60 | error("futex failure\n" , errno); |
61 | child_ret = RET_ERROR; |
62 | } |
63 | pthread_exit(NULL); |
64 | } |
65 | |
66 | int main(int argc, char **argv) |
67 | { |
68 | int c, ret = RET_PASS; |
69 | long page_size; |
70 | pthread_t thr; |
71 | |
72 | while ((c = getopt(argc, argv, "chv:" )) != -1) { |
73 | switch (c) { |
74 | case 'c': |
75 | log_color(1); |
76 | break; |
77 | case 'h': |
78 | usage(prog: basename(argv[0])); |
79 | exit(0); |
80 | case 'v': |
81 | log_verbosity(atoi(optarg)); |
82 | break; |
83 | default: |
84 | usage(prog: basename(argv[0])); |
85 | exit(1); |
86 | } |
87 | } |
88 | |
89 | page_size = sysconf(_SC_PAGESIZE); |
90 | |
91 | buf = mmap(NULL, page_size, PROT_READ|PROT_WRITE, |
92 | MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); |
93 | if (buf == (void *)-1) { |
94 | error("mmap\n" , errno); |
95 | exit(1); |
96 | } |
97 | |
98 | ksft_print_header(); |
99 | ksft_set_plan(1); |
100 | ksft_print_msg("%s: Test the uninitialized futex value in FUTEX_WAIT\n" , |
101 | basename(argv[0])); |
102 | |
103 | |
104 | ret = pthread_create(&thr, NULL, wait_thread, NULL); |
105 | if (ret) { |
106 | error("pthread_create\n" , errno); |
107 | ret = RET_ERROR; |
108 | goto out; |
109 | } |
110 | |
111 | info("waiting %dus for child to return\n" , WAIT_US); |
112 | usleep(WAIT_US); |
113 | |
114 | ret = child_ret; |
115 | if (child_blocked) { |
116 | fail("child blocked in kernel\n" ); |
117 | ret = RET_FAIL; |
118 | } |
119 | |
120 | out: |
121 | print_result(TEST_NAME, ret); |
122 | return ret; |
123 | } |
124 | |