Home | History | Annotate | Download | only in getrusage
      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 #include <limits.h>
     35 
     36 #include "test.h"
     37 #include "safe_macros.h"
     38 
     39 char *TCID = "getrusage03_child";
     40 int TST_TOTAL = 1;
     41 
     42 #define DELTA_MAX	10240
     43 
     44 static int opt_consume, opt_grand, opt_show, opt_self, opt_child;
     45 static char *consume_str, *grand_consume_str, *self_str, *child_str;
     46 
     47 option_t child_options[] = {
     48 	{"n:", &opt_consume, &consume_str},
     49 	{"g:", &opt_grand, &grand_consume_str},
     50 	{"v", &opt_show, NULL},
     51 	{"s:", &opt_self, &self_str},
     52 	{"l:", &opt_child, &child_str},
     53 	{NULL, NULL, NULL}
     54 };
     55 
     56 static void usage(void);
     57 static void consume(int mega);
     58 static void setup(void);
     59 static void cleanup(void);
     60 
     61 int main(int argc, char *argv[])
     62 {
     63 	int lc;
     64 	pid_t pid;
     65 	long maxrss_self, maxrss_children, delta;
     66 	long consume_nr, grand_consume_nr, self_nr, child_nr;
     67 	struct rusage ru;
     68 
     69 	tst_parse_opts(argc, argv, child_options, usage);
     70 
     71 	setup();
     72 
     73 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     74 		tst_count = 0;
     75 
     76 		if (opt_consume) {
     77 			consume_nr = SAFE_STRTOL(cleanup,
     78 						 consume_str, 0, LONG_MAX);
     79 			tst_resm(TINFO, "child allocate %ldMB", consume_nr);
     80 			consume(consume_nr);
     81 		}
     82 
     83 		if (opt_grand) {
     84 			grand_consume_nr = SAFE_STRTOL(cleanup,
     85 						       grand_consume_str, 0,
     86 						       LONG_MAX);
     87 			tst_resm(TINFO, "grandchild allocate %ldMB",
     88 				 grand_consume_nr);
     89 			switch (pid = fork()) {
     90 			case -1:
     91 				tst_brkm(TBROK, cleanup, "fork");
     92 			case 0:
     93 				consume(grand_consume_nr);
     94 				exit(0);
     95 			default:
     96 				break;
     97 			}
     98 			while (waitpid(-1, &pid, WUNTRACED | WCONTINUED) > 0)
     99 				if (WEXITSTATUS(pid) != 0)
    100 					tst_brkm(TBROK | TERRNO, cleanup,
    101 						 "child exit status is not 0");
    102 		}
    103 
    104 		if (opt_show) {
    105 			SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru);
    106 			maxrss_self = ru.ru_maxrss;
    107 			SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru);
    108 			maxrss_children = ru.ru_maxrss;
    109 			tst_resm(TINFO, "exec.self = %ld, exec.children = %ld",
    110 				 maxrss_self, maxrss_children);
    111 			if (opt_self) {
    112 				self_nr = SAFE_STRTOL(cleanup,
    113 						      self_str, 0, LONG_MAX);
    114 				delta = maxrss_self - self_nr;
    115 				if (delta >= -DELTA_MAX && delta <= DELTA_MAX)
    116 					tst_resm(TPASS,
    117 						 "initial.self ~= exec.self");
    118 				else
    119 					tst_resm(TFAIL,
    120 						 "initial.self !~= exec.self");
    121 			}
    122 			if (opt_child) {
    123 				child_nr = SAFE_STRTOL(cleanup,
    124 						       child_str, 0, LONG_MAX);
    125 				delta = maxrss_children - child_nr;
    126 				if (delta >= -DELTA_MAX && delta <= DELTA_MAX)
    127 					tst_resm(TPASS,
    128 						 "initial.children ~= exec.children");
    129 				else
    130 					tst_resm(TFAIL,
    131 						 "initial.children !~= exec.children");
    132 			}
    133 		}
    134 	}
    135 
    136 	cleanup();
    137 	tst_exit();
    138 }
    139 
    140 static void usage(void)
    141 {
    142 	printf("  -n NUM  consume NUM MB size\n");
    143 	printf("  -g NUM  grandchild consume NUM MB size\n");
    144 	printf("  -v      verbose mode, show rusage info\n");
    145 	printf("  -s NUM  compare rusage_self.maxrss with given NUM\n");
    146 	printf("  -l NUM  compare rusage_children.maxrss with given NUM\n");
    147 }
    148 
    149 static void consume(int mega)
    150 {
    151 	size_t sz;
    152 	void *ptr;
    153 
    154 	sz = mega * 1024 * 1024;
    155 	ptr = SAFE_MALLOC(cleanup, sz);
    156 	memset(ptr, 0, sz);
    157 }
    158 
    159 static void setup(void)
    160 {
    161 	tst_sig(FORK, DEF_HANDLER, cleanup);
    162 
    163 	TEST_PAUSE;
    164 }
    165 
    166 static void cleanup(void)
    167 {
    168 }
    169