1 /*
2 * getrusage03_child.c - a child program executed by getrusage03
3 *
4 * Copyright (C) 2011 Red Hat, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * Further, this software is distributed without any warranty that it
14 * is free of the rightful claim of any third person regarding
15 * infringement or the like. Any license provided herein, whether
16 * implied or otherwise, applies only to this software file. Patent
17 * licenses, if any, provided herein do not apply to combinations of
18 * this program with other software, or any other product whatsoever.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 * 02110-1301, USA.
24 */
25 #include <sys/types.h>
26 #include <sys/resource.h>
27 #include <sys/time.h>
28 #include <sys/wait.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "test.h"
36 #include "safe_macros.h"
37
38 char *TCID = "getrusage03_child";
39 int TST_TOTAL = 1;
40
41 #define DELTA_MAX 10240
42
43 static int opt_consume, opt_grand, opt_show, opt_self, opt_child;
44 static char *consume_str, *grand_consume_str, *self_str, *child_str;
45
46 option_t child_options[] = {
47 {"n:", &opt_consume, &consume_str},
48 {"g:", &opt_grand, &grand_consume_str},
49 {"v", &opt_show, NULL},
50 {"s:", &opt_self, &self_str},
51 {"l:", &opt_child, &child_str},
52 {NULL, NULL, NULL}
53 };
54
55 static void usage(void);
56 static void consume(int mega);
57 static void setup(void);
58 static void cleanup(void);
59
main(int argc,char * argv[])60 int main(int argc, char *argv[])
61 {
62 int lc;
63 pid_t pid;
64 long maxrss_self, maxrss_children, delta;
65 long consume_nr, grand_consume_nr, self_nr, child_nr;
66 struct rusage ru;
67
68 tst_parse_opts(argc, argv, child_options, usage);
69
70 setup();
71
72 for (lc = 0; TEST_LOOPING(lc); lc++) {
73 tst_count = 0;
74
75 if (opt_consume) {
76 consume_nr = SAFE_STRTOL(cleanup,
77 consume_str, 0, LONG_MAX);
78 tst_resm(TINFO, "child allocate %ldMB", consume_nr);
79 consume(consume_nr);
80 }
81
82 if (opt_grand) {
83 grand_consume_nr = SAFE_STRTOL(cleanup,
84 grand_consume_str, 0,
85 LONG_MAX);
86 tst_resm(TINFO, "grandchild allocate %ldMB",
87 grand_consume_nr);
88 switch (pid = fork()) {
89 case -1:
90 tst_brkm(TBROK, cleanup, "fork");
91 case 0:
92 consume(grand_consume_nr);
93 exit(0);
94 default:
95 break;
96 }
97 while (waitpid(-1, &pid, WUNTRACED | WCONTINUED) > 0)
98 if (WEXITSTATUS(pid) != 0)
99 tst_brkm(TBROK | TERRNO, cleanup,
100 "child exit status is not 0");
101 }
102
103 if (opt_show) {
104 SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru);
105 maxrss_self = ru.ru_maxrss;
106 SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru);
107 maxrss_children = ru.ru_maxrss;
108 tst_resm(TINFO, "exec.self = %ld, exec.children = %ld",
109 maxrss_self, maxrss_children);
110 if (opt_self) {
111 self_nr = SAFE_STRTOL(cleanup,
112 self_str, 0, LONG_MAX);
113 delta = maxrss_self - self_nr;
114 if (delta >= -DELTA_MAX && delta <= DELTA_MAX)
115 tst_resm(TPASS,
116 "initial.self ~= exec.self");
117 else
118 tst_resm(TFAIL,
119 "initial.self !~= exec.self");
120 }
121 if (opt_child) {
122 child_nr = SAFE_STRTOL(cleanup,
123 child_str, 0, LONG_MAX);
124 delta = maxrss_children - child_nr;
125 if (delta >= -DELTA_MAX && delta <= DELTA_MAX)
126 tst_resm(TPASS,
127 "initial.children ~= exec.children");
128 else
129 tst_resm(TFAIL,
130 "initial.children !~= exec.children");
131 }
132 }
133 }
134
135 cleanup();
136 tst_exit();
137 }
138
usage(void)139 static void usage(void)
140 {
141 printf(" -n NUM consume NUM MB size\n");
142 printf(" -g NUM grandchild consume NUM MB size\n");
143 printf(" -v verbose mode, show rusage info\n");
144 printf(" -s NUM compare rusage_self.maxrss with given NUM\n");
145 printf(" -l NUM compare rusage_children.maxrss with given NUM\n");
146 }
147
consume(int mega)148 static void consume(int mega)
149 {
150 size_t sz;
151 void *ptr;
152
153 sz = mega * 1024 * 1024;
154 ptr = SAFE_MALLOC(cleanup, sz);
155 memset(ptr, 0, sz);
156 }
157
setup(void)158 static void setup(void)
159 {
160 tst_sig(FORK, DEF_HANDLER, cleanup);
161
162 TEST_PAUSE;
163 }
164
cleanup(void)165 static void cleanup(void)
166 {
167 }
168