xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/getrusage/getrusage03.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2011  Red Hat, Inc.
4  * Copyright (C) 2021 Xie Ziyao <[email protected]>
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Test ru_maxrss behaviors in struct rusage.
11  *
12  * This test program is backported from upstream commit: 1f10206cf8e9, which
13  * fills ru_maxrss value in struct rusage according to rss hiwater mark. To
14  * make sure this feature works correctly, a series of tests are executed in
15  * this program.
16  */
17 
18 #include <stdlib.h>
19 #include <stdio.h>
20 
21 #include "tst_test.h"
22 #include "getrusage03.h"
23 
24 #define TESTBIN "getrusage03_child"
25 
26 static struct rusage ru;
27 static long maxrss_init;
28 
29 static const char *const resource[] = {
30 	TESTBIN,
31 	NULL,
32 };
33 
inherit_fork1(void)34 static void inherit_fork1(void)
35 {
36 	SAFE_GETRUSAGE(RUSAGE_SELF, &ru);
37 	maxrss_init = ru.ru_maxrss;
38 
39 	if (!SAFE_FORK()) {
40 		SAFE_GETRUSAGE(RUSAGE_SELF, &ru);
41 
42 		if (is_in_delta(maxrss_init - ru.ru_maxrss))
43 			tst_res(TPASS, "initial.self ~= child.self");
44 		else
45 			tst_res(TFAIL, "child.self = %li, expected %li",
46 				ru.ru_maxrss, maxrss_init);
47 		exit(0);
48 	}
49 	tst_reap_children();
50 }
51 
inherit_fork2(void)52 static void inherit_fork2(void)
53 {
54 	SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru);
55 
56 	if (is_in_delta(ru.ru_maxrss - 102400))
57 		tst_res(TPASS, "initial.children ~= 100MB");
58 	else
59 		tst_res(TFAIL, "initial.children = %li, expected %i",
60 			ru.ru_maxrss, 102400);
61 
62 	if (!SAFE_FORK()) {
63 		SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru);
64 
65 		if (!ru.ru_maxrss)
66 			tst_res(TPASS, "child.children == 0");
67 		else
68 			tst_res(TFAIL, "child.children = %li, expected %i",
69 				ru.ru_maxrss, 0);
70 		exit(0);
71 	}
72 	tst_reap_children();
73 }
74 
grandchild_maxrss(void)75 static void grandchild_maxrss(void)
76 {
77 	if (!SAFE_FORK())
78 		SAFE_EXECLP("getrusage03_child", "getrusage03_child",
79 			    "grand_consume", "300", NULL);
80 	tst_reap_children();
81 	SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru);
82 
83 	if (is_in_delta(ru.ru_maxrss - 307200))
84 		tst_res(TPASS, "child.children ~= 300MB");
85 	else
86 		tst_res(TFAIL, "child.children = %li, expected %i",
87 			ru.ru_maxrss, 307200);
88 }
89 
zombie(void)90 static void zombie(void)
91 {
92 	SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru);
93 	maxrss_init = ru.ru_maxrss;
94 
95 	pid_t pid = SAFE_FORK();
96 
97 	if (!pid)
98 		SAFE_EXECLP("getrusage03_child", "getrusage03_child",
99 			    "consume", "400", NULL);
100 
101 	TST_PROCESS_STATE_WAIT(pid, 'Z', 0);
102 	SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru);
103 	if (is_in_delta(ru.ru_maxrss - maxrss_init))
104 		tst_res(TPASS, "initial.children ~= pre_wait.children");
105 	else
106 		tst_res(TFAIL, "pre_wait.children = %li, expected %li",
107 			ru.ru_maxrss, maxrss_init);
108 
109 	tst_reap_children();
110 	SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru);
111 	if (is_in_delta(ru.ru_maxrss - 409600))
112 		tst_res(TPASS, "post_wait.children ~= 400MB");
113 	else
114 		tst_res(TFAIL, "post_wait.children = %li, expected %i",
115 			ru.ru_maxrss, 409600);
116 }
117 
sig_ign(void)118 static void sig_ign(void)
119 {
120 	SAFE_SIGNAL(SIGCHLD, SIG_IGN);
121 	SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru);
122 	maxrss_init = ru.ru_maxrss;
123 
124 	pid_t pid = SAFE_FORK();
125 
126 	if (!pid)
127 		SAFE_EXECLP("getrusage03_child", "getrusage03_child",
128 			    "consume", "500", NULL);
129 
130 	TST_PROCESS_EXIT_WAIT(pid, 0);
131 	SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru);
132 	if (is_in_delta(ru.ru_maxrss - maxrss_init))
133 		tst_res(TPASS, "initial.children ~= after_zombie.children");
134 	else
135 		tst_res(TFAIL, "after_zombie.children = %li, expected %li",
136 			ru.ru_maxrss, maxrss_init);
137 
138 	SAFE_SIGNAL(SIGCHLD, SIG_DFL);
139 }
140 
inherit_exec(void)141 static void inherit_exec(void)
142 {
143 	if (!SAFE_FORK()) {
144 		char str_maxrss_self[BUFSIZ], str_maxrss_child[BUFSIZ];
145 
146 		SAFE_GETRUSAGE(RUSAGE_SELF, &ru);
147 		sprintf(str_maxrss_self, "%ld", ru.ru_maxrss);
148 		SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru);
149 		sprintf(str_maxrss_child, "%ld", ru.ru_maxrss);
150 
151 		SAFE_EXECLP("getrusage03_child", "getrusage03_child",
152 			    "compare", str_maxrss_self, str_maxrss_child, NULL);
153 	}
154 	tst_reap_children();
155 }
156 
157 void (*testfunc_list[])(void) = {
158 	inherit_fork1, inherit_fork2, grandchild_maxrss,
159 	zombie, sig_ign, inherit_exec
160 };
161 
run(unsigned int i)162 static void run(unsigned int i)
163 {
164 	if (!SAFE_FORK()) {
165 		if (!SAFE_FORK()) {
166 			consume_mb(100);
167 			exit(0);
168 		}
169 
170 		SAFE_WAIT(NULL);
171 
172 		testfunc_list[i]();
173 	}
174 }
175 
176 static struct tst_test test = {
177 	.forks_child = 1,
178 	.child_needs_reinit = 1,
179 	.resource_files = resource,
180 	.min_mem_avail = 512,
181 	.tags = (const struct tst_tag[]) {
182 		{"linux-git", "1f10206cf8e9"},
183 		{}
184 	},
185 	.test = run,
186 	.tcnt = ARRAY_SIZE(testfunc_list),
187 	.caps = (struct tst_cap []) {
188 		TST_CAP(TST_CAP_REQ, CAP_IPC_LOCK),
189 		{}
190 	},
191 };
192