169 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * getrusage03_child.c - a child program executed by getrusage03
 | |
|  *
 | |
|  * Copyright (C) 2011  Red Hat, Inc.
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of version 2 of the GNU General Public
 | |
|  * License as published by the Free Software Foundation.
 | |
|  *
 | |
|  * This program is distributed in the hope that it would be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | |
|  *
 | |
|  * Further, this software is distributed without any warranty that it
 | |
|  * is free of the rightful claim of any third person regarding
 | |
|  * infringement or the like.  Any license provided herein, whether
 | |
|  * implied or otherwise, applies only to this software file.  Patent
 | |
|  * licenses, if any, provided herein do not apply to combinations of
 | |
|  * this program with other software, or any other product whatsoever.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program; if not, write the Free Software
 | |
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
|  * 02110-1301, USA.
 | |
|  */
 | |
| #include <sys/types.h>
 | |
| #include <sys/resource.h>
 | |
| #include <sys/time.h>
 | |
| #include <sys/wait.h>
 | |
| #include <errno.h>
 | |
| #include <unistd.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <limits.h>
 | |
| 
 | |
| #include "test.h"
 | |
| #include "safe_macros.h"
 | |
| 
 | |
| char *TCID = "getrusage03_child";
 | |
| int TST_TOTAL = 1;
 | |
| 
 | |
| #define DELTA_MAX	10240
 | |
| 
 | |
| static int opt_consume, opt_grand, opt_show, opt_self, opt_child;
 | |
| static char *consume_str, *grand_consume_str, *self_str, *child_str;
 | |
| 
 | |
| option_t child_options[] = {
 | |
| 	{"n:", &opt_consume, &consume_str},
 | |
| 	{"g:", &opt_grand, &grand_consume_str},
 | |
| 	{"v", &opt_show, NULL},
 | |
| 	{"s:", &opt_self, &self_str},
 | |
| 	{"l:", &opt_child, &child_str},
 | |
| 	{NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| static void usage(void);
 | |
| static void consume(int mega);
 | |
| static void setup(void);
 | |
| static void cleanup(void);
 | |
| 
 | |
| int main(int argc, char *argv[])
 | |
| {
 | |
| 	int lc;
 | |
| 	pid_t pid;
 | |
| 	long maxrss_self, maxrss_children, delta;
 | |
| 	long consume_nr, grand_consume_nr, self_nr, child_nr;
 | |
| 	struct rusage ru;
 | |
| 
 | |
| 	tst_parse_opts(argc, argv, child_options, usage);
 | |
| 
 | |
| 	setup();
 | |
| 
 | |
| 	for (lc = 0; TEST_LOOPING(lc); lc++) {
 | |
| 		tst_count = 0;
 | |
| 
 | |
| 		if (opt_consume) {
 | |
| 			consume_nr = SAFE_STRTOL(cleanup,
 | |
| 						 consume_str, 0, LONG_MAX);
 | |
| 			tst_resm(TINFO, "child allocate %ldMB", consume_nr);
 | |
| 			consume(consume_nr);
 | |
| 		}
 | |
| 
 | |
| 		if (opt_grand) {
 | |
| 			grand_consume_nr = SAFE_STRTOL(cleanup,
 | |
| 						       grand_consume_str, 0,
 | |
| 						       LONG_MAX);
 | |
| 			tst_resm(TINFO, "grandchild allocate %ldMB",
 | |
| 				 grand_consume_nr);
 | |
| 			switch (pid = fork()) {
 | |
| 			case -1:
 | |
| 				tst_brkm(TBROK, cleanup, "fork");
 | |
| 			case 0:
 | |
| 				consume(grand_consume_nr);
 | |
| 				exit(0);
 | |
| 			default:
 | |
| 				break;
 | |
| 			}
 | |
| 			while (waitpid(-1, &pid, WUNTRACED | WCONTINUED) > 0)
 | |
| 				if (WEXITSTATUS(pid) != 0)
 | |
| 					tst_brkm(TBROK | TERRNO, cleanup,
 | |
| 						 "child exit status is not 0");
 | |
| 		}
 | |
| 
 | |
| 		if (opt_show) {
 | |
| 			SAFE_GETRUSAGE(cleanup, RUSAGE_SELF, &ru);
 | |
| 			maxrss_self = ru.ru_maxrss;
 | |
| 			SAFE_GETRUSAGE(cleanup, RUSAGE_CHILDREN, &ru);
 | |
| 			maxrss_children = ru.ru_maxrss;
 | |
| 			tst_resm(TINFO, "exec.self = %ld, exec.children = %ld",
 | |
| 				 maxrss_self, maxrss_children);
 | |
| 			if (opt_self) {
 | |
| 				self_nr = SAFE_STRTOL(cleanup,
 | |
| 						      self_str, 0, LONG_MAX);
 | |
| 				delta = maxrss_self - self_nr;
 | |
| 				if (delta >= -DELTA_MAX && delta <= DELTA_MAX)
 | |
| 					tst_resm(TPASS,
 | |
| 						 "initial.self ~= exec.self");
 | |
| 				else
 | |
| 					tst_resm(TFAIL,
 | |
| 						 "initial.self !~= exec.self");
 | |
| 			}
 | |
| 			if (opt_child) {
 | |
| 				child_nr = SAFE_STRTOL(cleanup,
 | |
| 						       child_str, 0, LONG_MAX);
 | |
| 				delta = maxrss_children - child_nr;
 | |
| 				if (delta >= -DELTA_MAX && delta <= DELTA_MAX)
 | |
| 					tst_resm(TPASS,
 | |
| 						 "initial.children ~= exec.children");
 | |
| 				else
 | |
| 					tst_resm(TFAIL,
 | |
| 						 "initial.children !~= exec.children");
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	cleanup();
 | |
| 	tst_exit();
 | |
| }
 | |
| 
 | |
| static void usage(void)
 | |
| {
 | |
| 	printf("  -n NUM  consume NUM MB size\n");
 | |
| 	printf("  -g NUM  grandchild consume NUM MB size\n");
 | |
| 	printf("  -v      verbose mode, show rusage info\n");
 | |
| 	printf("  -s NUM  compare rusage_self.maxrss with given NUM\n");
 | |
| 	printf("  -l NUM  compare rusage_children.maxrss with given NUM\n");
 | |
| }
 | |
| 
 | |
| static void consume(int mega)
 | |
| {
 | |
| 	size_t sz;
 | |
| 	void *ptr;
 | |
| 
 | |
| 	sz = mega * 1024 * 1024;
 | |
| 	ptr = SAFE_MALLOC(cleanup, sz);
 | |
| 	memset(ptr, 0, sz);
 | |
| }
 | |
| 
 | |
| static void setup(void)
 | |
| {
 | |
| 	tst_sig(FORK, DEF_HANDLER, cleanup);
 | |
| 
 | |
| 	TEST_PAUSE;
 | |
| }
 | |
| 
 | |
| static void cleanup(void)
 | |
| {
 | |
| }
 |