]> granicus.if.org Git - strace/blob - tests/move_pages.c
strace: terminate itself if interrupted by a signal
[strace] / tests / move_pages.c
1 /*
2  * Check decoding of move_pages syscall.
3  *
4  * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
5  * Copyright (c) 2016-2018 The strace developers.
6  * All rights reserved.
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #include "tests.h"
12 #include <asm/unistd.h>
13
14 #ifdef __NR_move_pages
15
16 # include <errno.h>
17 # include <stdio.h>
18 # include <unistd.h>
19
20 # define MAX_STRLEN 3
21
22 static void
23 print_page_array(const void **const pages,
24                  const unsigned long count,
25                  const unsigned int offset)
26 {
27         if (!count) {
28                 printf("%s", pages ? "[]" : "NULL");
29                 return;
30         }
31         if (count <= offset) {
32                 printf("%p", pages);
33                 return;
34         }
35         printf("[");
36         unsigned long i;
37         for (i = 0; i < count; ++i) {
38                 if (i)
39                         printf(", ");
40                 if (i + offset < count) {
41                         if (i >= MAX_STRLEN) {
42                                 printf("...");
43                                 break;
44                         }
45                 } else {
46                         printf("... /* %p */", pages + i);
47                         break;
48                 }
49                 const void *const addr = pages[i];
50                 if (addr)
51                         printf("%p", addr);
52                 else
53                         printf("NULL");
54         }
55         printf("]");
56 }
57
58 static void
59 print_node_array(const int *const nodes,
60                  const unsigned long count,
61                  const unsigned int offset)
62 {
63         if (!count) {
64                 printf("%s", nodes ? "[]" : "NULL");
65                 return;
66         }
67         if (count <= offset) {
68                 printf("%p", nodes);
69                 return;
70         }
71         printf("[");
72         unsigned long i;
73         for (i = 0; i < count; ++i) {
74                 if (i)
75                         printf(", ");
76                 if (i + offset < count) {
77                         if (i >= MAX_STRLEN) {
78                                 printf("...");
79                                 break;
80                         }
81                 } else {
82                         printf("... /* %p */", nodes + i);
83                         break;
84                 }
85                 printf("%d", nodes[i]);
86         }
87         printf("]");
88 }
89
90 static void
91 print_status_array(const int *const status, const unsigned long count)
92 {
93         if (!count) {
94                 printf("%s", status ? "[]" : "NULL");
95                 return;
96         }
97         printf("[");
98         unsigned long i;
99         for (i = 0; i < count; ++i) {
100                 if (i)
101                         printf(", ");
102                 if (i >= MAX_STRLEN) {
103                         printf("...");
104                         break;
105                 }
106                 if (status[i] >= 0) {
107                         printf("%d", status[i]);
108                 } else {
109                         errno = -status[i];
110                         printf("-%s", errno2name());
111                 }
112         }
113         printf("]");
114 }
115
116 static void
117 print_stat_pages(const unsigned long pid, const unsigned long count,
118                  const void **const pages, int *const status)
119 {
120         const unsigned long flags = (unsigned long) 0xfacefeed00000002ULL;
121
122         long rc = syscall(__NR_move_pages,
123                           pid, count, pages, NULL, status, flags);
124         const char *errstr = sprintrc(rc);
125         printf("move_pages(%d, %lu, ", (int) pid, count);
126         print_page_array(pages, count, 0);
127         printf(", NULL, ");
128         if (rc) {
129                 if (count)
130                         printf("%p", status);
131                 else
132                         printf("[]");
133         } else {
134                 print_status_array(status, count);
135         }
136         printf(", MPOL_MF_MOVE) = %s\n", errstr);
137 }
138
139 static void
140 print_move_pages(const unsigned long pid,
141                  unsigned long count,
142                  const unsigned int offset,
143                  const void **const pages,
144                  int *const nodes,
145                  int *const status)
146 {
147         const unsigned long flags = (unsigned long) 0xfacefeed00000004ULL;
148         count += offset;
149
150         long rc = syscall(__NR_move_pages,
151                           pid, count, pages, nodes, status, flags);
152         const char *errstr = sprintrc(rc);
153         printf("move_pages(%d, %lu, ", (int) pid, count);
154         print_page_array(pages, count, offset);
155         printf(", ");
156         print_node_array(nodes, count, offset);
157         printf(", ");
158         if (count)
159                 printf("%p", status);
160         else
161                 printf("[]");
162         printf(", MPOL_MF_MOVE_ALL) = %s\n", errstr);
163 }
164
165 int
166 main(void)
167 {
168         const unsigned long pid =
169                 (unsigned long) 0xfacefeed00000000ULL | getpid();
170         unsigned long count = 1;
171         const unsigned page_size = get_page_size();
172         const void *const page = tail_alloc(page_size);
173         const void *const efault = page + page_size;
174         TAIL_ALLOC_OBJECT_VAR_PTR(const void *, pages);
175         TAIL_ALLOC_OBJECT_VAR_PTR(int, nodes);
176         TAIL_ALLOC_OBJECT_VAR_PTR(int, status);
177
178         print_stat_pages(pid, 0, pages, status);
179         print_move_pages(pid, 0, 0, pages, nodes, status);
180         print_move_pages(pid, 0, 1, pages + 1, nodes + 1, status + 1);
181
182         *pages = page;
183         print_stat_pages(pid, count, pages, status);
184         *nodes = 0xdeadbee1;
185         print_move_pages(pid, count, 0, pages, nodes, status);
186         print_move_pages(pid, count, 1, pages, nodes, status);
187
188         ++count;
189         --status;
190         *(--pages) = efault;
191         print_stat_pages(pid, count, pages, status);
192         *(--nodes) = 0xdeadbee2;
193         print_move_pages(pid, count, 0, pages, nodes, status);
194         print_move_pages(pid, count, 1, pages, nodes, status);
195
196         ++count;
197         --status;
198         *(--pages) = nodes;
199         print_stat_pages(pid, count, pages, status);
200         *(--nodes) = 0xdeadbee3;
201         print_move_pages(pid, count, 0, pages, nodes, status);
202         print_move_pages(pid, count, 1, pages, nodes, status);
203
204         ++count;
205         --status;
206         *(--pages) = status;
207         print_stat_pages(pid, count, pages, status);
208         *(--nodes) = 0xdeadbee4;
209         print_move_pages(pid, count, 0, pages, nodes, status);
210         print_move_pages(pid, count, 1, pages, nodes, status);
211
212         puts("+++ exited with 0 +++");
213         return 0;
214 }
215
216 #else
217
218 SKIP_MAIN_UNDEFINED("__NR_move_pages")
219
220 #endif