cpuctl_test01.c revision 6b78bd97ae956c84863ab786cb34f5ce592d2300
1/******************************************************************************/
2/*                                                                            */
3/* Copyright (c) International Business Machines  Corp., 2007                 */
4/*                                                                            */
5/* This program is free software;  you can redistribute it and/or modify      */
6/* it under the terms of the GNU General Public License as published by       */
7/* the Free Software Foundation; either version 2 of the License, or          */
8/* (at your option) any later version.                                        */
9/*                                                                            */
10/* This program is distributed in the hope that it will be useful,            */
11/* but WITHOUT ANY WARRANTY;  without even the implied warranty of            */
12/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See                  */
13/* the GNU General Public License for more details.                           */
14/*                                                                            */
15/* You should have received a copy of the GNU General Public License          */
16/* along with this program;  if not, write to the Free Software               */
17/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA    */
18/*                                                                            */
19/******************************************************************************/
20
21/******************************************************************************/
22/*                                                                            */
23/* File:        cpuctl_test01.c                                               */
24/*                                                                            */
25/* Description: This is a c program that tests the cpucontroller fairness of  */
26/*              scheduling the tasks according to their group shares. This    */
27/*              testcase tests the ability of the cpu controller to provide   */
28/*              fairness for share values (absolute).                         */
29/*                                                                            */
30/* Total Tests: 2                                                             */
31/*                                                                            */
32/* Test Name:   cpu_controller_test01                                         */
33/*                                                                            */
34/* Test Assertion                                                             */
35/*              Please refer to the file cpuctl_testplan.txt                  */
36/*                                                                            */
37/* Author:      Sudhir Kumar sudhirkumarmalik@in.ibm.com                      */
38/*                                                                            */
39/* History:                                                                   */
40/* Created-     20/12/2007 -Sudhir Kumar sudhirkumarmalik@in.ibm.com          */
41/*                                                                            */
42/******************************************************************************/
43
44/* Standard Include Files */
45#include <unistd.h>
46#include <math.h>
47#include <signal.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51#include <sys/resource.h>
52#include <sys/syscall.h>
53#include <sys/time.h>
54#include <sys/types.h>
55#include <time.h>
56#include <unistd.h>
57
58#include "test.h"		/* LTP harness APIs*/
59
60#define TIME_INTERVAL	60	/* Time interval in seconds*/
61#define NUM_INTERVALS	3       /* How many iterations of TIME_INTERVAL */
62#define NUM_SETS	7	/* How many share values (with same ratio)*/
63#define MULTIPLIER   	10      /* decides the rate at which share value gets multiplied*/
64
65extern int Tst_count;
66char *TCID = "cpu_controller_test01";
67int TST_TOTAL = 1;
68pid_t scriptpid;
69extern void
70cleanup()
71{
72	kill (scriptpid, SIGUSR1);/* Inform the shell to do cleanup*/
73	tst_exit ();		/* Report exit status*/
74}
75
76int write_to_file (char * file, const char* mode, unsigned int value);
77void signal_handler_alarm (int signal );
78int timer_expired = 0;
79
80int main(int argc, char* argv[])
81{
82
83	int num_cpus;			/* To calculate cpu time in %*/
84	char mygroup[32], mytaskfile[32], mysharesfile[32], ch;
85	pid_t pid;
86	int my_group_num,	        /* A number attached with a group*/
87		fd,          	        /* A descriptor to open a fifo for synchronized start*/
88		first_counter =0,  	/* To take n number of readings*/
89		second_counter=0;      	/* To track number of times the base value of shares has been changed*/
90	double total_cpu_time,  	/* Accumulated cpu time*/
91		delta_cpu_time,  	/* Time the task could run on cpu(s) (in an interval)*/
92		prev_cpu_time=0;
93	struct rusage cpu_usage;
94	time_t current_time, prev_time, delta_time;
95	unsigned long int myshares = 1;	/* Simply the base value to start with*/
96	struct sigaction newaction, oldaction;
97	/* Signal handling for alarm*/
98	sigemptyset (&newaction.sa_mask);
99	newaction.sa_handler = signal_handler_alarm;
100	newaction.sa_flags=0;
101	sigaction (SIGALRM, &newaction, &oldaction);
102
103	/* Check if all parameters passed are correct*/
104	if ((argc < 5) || ((my_group_num = atoi(argv[1])) <= 0) || ((scriptpid = atoi(argv[3])) <= 0) || ((num_cpus = atoi(argv[4])) <= 0))
105	{
106		tst_brkm (TBROK, cleanup, "Invalid input parameters\n");
107	}
108
109	myshares *= my_group_num;
110	sprintf(mygroup,"%s", argv[2]);
111	sprintf(mytaskfile, "%s", mygroup);
112	sprintf(mysharesfile, "%s", mygroup);
113	strcat (mytaskfile,"/tasks");
114	strcat (mysharesfile,"/cpu.shares");
115	pid = getpid();
116	write_to_file (mytaskfile, "a", pid);    /* Assign the task to it's group*/
117	write_to_file (mysharesfile, "w", myshares);
118
119	fd = open ("./myfifo", 0);
120	if (fd == -1)
121	{
122		tst_brkm (TBROK, cleanup, "Could not open fifo for synchronization");
123	}
124
125	fprintf(stdout,"\ntask-%d SHARES=%lu\n",my_group_num, myshares);
126	read (fd, &ch, 1);	         /* To block all tasks here and fire them up at the same time*/
127	prev_time = time (NULL);	 /* Note down the time*/
128
129	while (1)
130	{
131		/* Need to run some cpu intensive task, which also frequently checks the timer value*/
132		double f = 274.345, mytime;	/*just a float number to take sqrt*/
133		alarm (TIME_INTERVAL);
134		timer_expired = 0;
135		while (!timer_expired)	/* Let the task run on cpu for TIME_INTERVAL*/
136			f = sqrt (f*f); /* Time of this operation should not be high otherwise we can
137					 * exceed the TIME_INTERVAL to measure cpu usage
138					 */
139			current_time = time (NULL);
140			delta_time = current_time - prev_time;	/* Duration in case it is not exact TIME_INTERVAL*/
141
142			getrusage (0, &cpu_usage);
143			total_cpu_time = (cpu_usage.ru_utime.tv_sec + cpu_usage.ru_utime.tv_usec * 1e-6 + /* user time*/
144					cpu_usage.ru_stime.tv_sec + cpu_usage.ru_stime.tv_usec * 1e-6) ;  /* system time*/
145					delta_cpu_time = total_cpu_time - prev_cpu_time;
146
147			prev_cpu_time = total_cpu_time;
148			prev_time = current_time;
149			if (delta_time > TIME_INTERVAL)
150				mytime =  (delta_cpu_time * 100) / (delta_time * num_cpus);
151			else
152				mytime =  (delta_cpu_time * 100) / (TIME_INTERVAL * num_cpus);
153
154			fprintf (stdout,"PID: %u\ttask-%d:cpu time ---> %6.3f\%(%fs) --->%lu(shares)\tinterval:%lu\n",getpid(),my_group_num, mytime, delta_cpu_time, myshares, delta_time);
155			first_counter++;
156
157			if (first_counter >= NUM_INTERVALS)	 /* Take n sets of readings for each shares value*/
158			{
159				first_counter = 0;
160				second_counter++;
161				if (second_counter >= NUM_SETS)
162					exit (0);		/* This task is done with its job*/
163				myshares = MULTIPLIER * myshares;	/* Keep same ratio but change values*/
164				write_to_file (mysharesfile, "w", myshares);
165				fprintf(stdout,"\ntask-%d SHARES=%lu\n",my_group_num, myshares);
166			}/* end if*/
167        }/* end while*/
168}/* end main*/
169
170
171int write_to_file (char *file, const char *mode, unsigned int value)
172{
173	FILE *fp;
174	fp = fopen (file, mode);
175	if (fp == NULL)
176	{
177		tst_brkm (TBROK, cleanup, "Could not open file %s for writing", file);
178	}
179	fprintf (fp, "%u\n", value);
180	fclose (fp);
181	return 0;
182}
183
184void signal_handler_alarm (int signal)
185{
186	timer_expired = 1;
187}
188