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