1f08c3bdfSopenharmony_ci/******************************************************************************/ 2f08c3bdfSopenharmony_ci/* */ 3f08c3bdfSopenharmony_ci/* Copyright (c) International Business Machines Corp., 2007 */ 4f08c3bdfSopenharmony_ci/* */ 5f08c3bdfSopenharmony_ci/* This program is free software; you can redistribute it and/or modify */ 6f08c3bdfSopenharmony_ci/* it under the terms of the GNU General Public License as published by */ 7f08c3bdfSopenharmony_ci/* the Free Software Foundation; either version 2 of the License, or */ 8f08c3bdfSopenharmony_ci/* (at your option) any later version. */ 9f08c3bdfSopenharmony_ci/* */ 10f08c3bdfSopenharmony_ci/* This program is distributed in the hope that it will be useful, */ 11f08c3bdfSopenharmony_ci/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 12f08c3bdfSopenharmony_ci/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ 13f08c3bdfSopenharmony_ci/* the GNU General Public License for more details. */ 14f08c3bdfSopenharmony_ci/* */ 15f08c3bdfSopenharmony_ci/* You should have received a copy of the GNU General Public License */ 16f08c3bdfSopenharmony_ci/* along with this program; if not, write to the Free Software */ 17f08c3bdfSopenharmony_ci/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 18f08c3bdfSopenharmony_ci/* */ 19f08c3bdfSopenharmony_ci/******************************************************************************/ 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci/******************************************************************************/ 22f08c3bdfSopenharmony_ci/* */ 23f08c3bdfSopenharmony_ci/* File: cpuctl_test03.c */ 24f08c3bdfSopenharmony_ci/* */ 25f08c3bdfSopenharmony_ci/* Description: This is a c program that tests the cpucontroller fairness of */ 26f08c3bdfSopenharmony_ci/* scheduling the tasks according to their group shares. This */ 27f08c3bdfSopenharmony_ci/* testcase tests the scheduling fairness with respect to number */ 28f08c3bdfSopenharmony_ci/* of classes and number of jobs in each class */ 29f08c3bdfSopenharmony_ci/* */ 30f08c3bdfSopenharmony_ci/* Total Tests: 1 */ 31f08c3bdfSopenharmony_ci/* */ 32f08c3bdfSopenharmony_ci/* Test 6: N X M (N groups with M tasks each) */ 33f08c3bdfSopenharmony_ci/* Test 7: N*M X 1 (N*M groups with 1 task each) */ 34f08c3bdfSopenharmony_ci/* Test 8: 1 X N*M (1 group with N*M tasks each) */ 35f08c3bdfSopenharmony_ci/* */ 36f08c3bdfSopenharmony_ci/* Test Name: cpu_controller_test03 */ 37f08c3bdfSopenharmony_ci/* */ 38f08c3bdfSopenharmony_ci/* Test Assertion */ 39f08c3bdfSopenharmony_ci/* Please refer to the file cpuctl_testplan.txt */ 40f08c3bdfSopenharmony_ci/* */ 41f08c3bdfSopenharmony_ci/* Author: Sudhir Kumar skumar@linux.vnet.ibm.com */ 42f08c3bdfSopenharmony_ci/* */ 43f08c3bdfSopenharmony_ci/* History: */ 44f08c3bdfSopenharmony_ci/* Created- 20/12/2007 -Sudhir Kumar <skumar@linux.vnet.ibm.com> */ 45f08c3bdfSopenharmony_ci/* */ 46f08c3bdfSopenharmony_ci/******************************************************************************/ 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_ci#include <unistd.h> 49f08c3bdfSopenharmony_ci#include <math.h> 50f08c3bdfSopenharmony_ci#include <signal.h> 51f08c3bdfSopenharmony_ci#include <stdio.h> 52f08c3bdfSopenharmony_ci#include <stdlib.h> 53f08c3bdfSopenharmony_ci#include <string.h> 54f08c3bdfSopenharmony_ci#include <sys/resource.h> 55f08c3bdfSopenharmony_ci#include <sys/syscall.h> 56f08c3bdfSopenharmony_ci#include <sys/stat.h> 57f08c3bdfSopenharmony_ci#include <fcntl.h> 58f08c3bdfSopenharmony_ci#include <sys/time.h> 59f08c3bdfSopenharmony_ci#include <sys/types.h> 60f08c3bdfSopenharmony_ci#include <time.h> 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci#include "../libcontrollers/libcontrollers.h" 63f08c3bdfSopenharmony_ci#include "test.h" /* LTP harness APIs */ 64f08c3bdfSopenharmony_ci#include "safe_macros.h" 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_ci#define TIME_INTERVAL 30 /* Time interval in seconds */ 67f08c3bdfSopenharmony_ci#define NUM_INTERVALS 2 /* How many iterations of TIME_INTERVAL */ 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_cichar *TCID = "cpuctl_test03"; 70f08c3bdfSopenharmony_ciint TST_TOTAL = 3; 71f08c3bdfSopenharmony_cipid_t scriptpid; 72f08c3bdfSopenharmony_cichar path[] = "/dev/cpuctl"; 73f08c3bdfSopenharmony_ciextern void cleanup(void) 74f08c3bdfSopenharmony_ci{ 75f08c3bdfSopenharmony_ci kill(scriptpid, SIGUSR1); /* Inform the shell to do cleanup */ 76f08c3bdfSopenharmony_ci tst_exit(); /* Report exit status */ 77f08c3bdfSopenharmony_ci} 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ciint main(void) 80f08c3bdfSopenharmony_ci{ 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_ci int test_num; 83f08c3bdfSopenharmony_ci int task_num; 84f08c3bdfSopenharmony_ci int len; 85f08c3bdfSopenharmony_ci int num_cpus; /* Total time = TIME_INTERVAL *num_cpus in the machine */ 86f08c3bdfSopenharmony_ci char mygroup[FILENAME_MAX], mytaskfile[FILENAME_MAX]; 87f08c3bdfSopenharmony_ci char mysharesfile[FILENAME_MAX], ch; 88f08c3bdfSopenharmony_ci /* Following variables are to capture parameters from script */ 89f08c3bdfSopenharmony_ci char *group_num_p, *mygroup_p, *script_pid_p, *num_cpus_p, *test_num_p, 90f08c3bdfSopenharmony_ci *task_num_p; 91f08c3bdfSopenharmony_ci pid_t pid; 92f08c3bdfSopenharmony_ci int mygroup_num, /* A number attached with a group */ 93f08c3bdfSopenharmony_ci fd, /* A descriptor to open a fifo for synchronized start */ 94f08c3bdfSopenharmony_ci counter = 0; /* To take n number of readings */ 95f08c3bdfSopenharmony_ci double total_cpu_time, /* Accumulated cpu time */ 96f08c3bdfSopenharmony_ci delta_cpu_time, /* Time the task could run on cpu(s) (in an interval) */ 97f08c3bdfSopenharmony_ci prev_cpu_time = 0; 98f08c3bdfSopenharmony_ci double exp_cpu_time; /* Expected time in % as obtained by shares calculation */ 99f08c3bdfSopenharmony_ci struct rusage cpu_usage; 100f08c3bdfSopenharmony_ci time_t current_time, prev_time, delta_time; 101f08c3bdfSopenharmony_ci unsigned int fmyshares, num_tasks; /* f-> from file. num_tasks is tasks in this group */ 102f08c3bdfSopenharmony_ci struct sigaction newaction, oldaction; 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci mygroup_num = -1; 105f08c3bdfSopenharmony_ci num_cpus = 0; 106f08c3bdfSopenharmony_ci task_num = 0; 107f08c3bdfSopenharmony_ci test_num = 0; 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci /* Signal handling for alarm */ 110f08c3bdfSopenharmony_ci sigemptyset(&newaction.sa_mask); 111f08c3bdfSopenharmony_ci newaction.sa_handler = signal_handler_alarm; 112f08c3bdfSopenharmony_ci newaction.sa_flags = 0; 113f08c3bdfSopenharmony_ci sigaction(SIGALRM, &newaction, &oldaction); 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci /* Collect the parameters passed by the script */ 116f08c3bdfSopenharmony_ci group_num_p = getenv("GROUP_NUM"); 117f08c3bdfSopenharmony_ci mygroup_p = getenv("MYGROUP"); 118f08c3bdfSopenharmony_ci script_pid_p = getenv("SCRIPT_PID"); 119f08c3bdfSopenharmony_ci num_cpus_p = getenv("NUM_CPUS"); 120f08c3bdfSopenharmony_ci test_num_p = getenv("TEST_NUM"); 121f08c3bdfSopenharmony_ci task_num_p = getenv("TASK_NUM"); 122f08c3bdfSopenharmony_ci /* Check if all of them are valid */ 123f08c3bdfSopenharmony_ci if ((test_num_p != NULL) 124f08c3bdfSopenharmony_ci && (((test_num = atoi(test_num_p)) <= 8) 125f08c3bdfSopenharmony_ci && ((test_num = atoi(test_num_p)) >= 6))) { 126f08c3bdfSopenharmony_ci if ((group_num_p != NULL) && (mygroup_p != NULL) 127f08c3bdfSopenharmony_ci && (script_pid_p != NULL) && (num_cpus_p != NULL) 128f08c3bdfSopenharmony_ci && (task_num_p != NULL)) { 129f08c3bdfSopenharmony_ci mygroup_num = atoi(group_num_p); 130f08c3bdfSopenharmony_ci scriptpid = atoi(script_pid_p); 131f08c3bdfSopenharmony_ci num_cpus = atoi(num_cpus_p); 132f08c3bdfSopenharmony_ci task_num = atoi(task_num_p); 133f08c3bdfSopenharmony_ci sprintf(mygroup, "%s", mygroup_p); 134f08c3bdfSopenharmony_ci } else { 135f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, 136f08c3bdfSopenharmony_ci "Invalid other input parameters"); 137f08c3bdfSopenharmony_ci } 138f08c3bdfSopenharmony_ci } else { 139f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "Invalid test number passed"); 140f08c3bdfSopenharmony_ci } 141f08c3bdfSopenharmony_ci 142f08c3bdfSopenharmony_ci sprintf(mytaskfile, "%s", mygroup); 143f08c3bdfSopenharmony_ci sprintf(mysharesfile, "%s", mygroup); 144f08c3bdfSopenharmony_ci strcat(mytaskfile, "/tasks"); 145f08c3bdfSopenharmony_ci strcat(mysharesfile, "/cpu.shares"); 146f08c3bdfSopenharmony_ci pid = getpid(); 147f08c3bdfSopenharmony_ci write_to_file(mytaskfile, "a", pid); /* Assign the task to it's group */ 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_ci fd = SAFE_OPEN(cleanup, "./myfifo", 0); 150f08c3bdfSopenharmony_ci 151f08c3bdfSopenharmony_ci read(fd, &ch, 1); /* To block all tasks here and fire them up at the same time */ 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci /* 154f08c3bdfSopenharmony_ci * We now calculate the expected % cpu time of this task by getting 155f08c3bdfSopenharmony_ci * it's group's shares, the total shares of all the groups and the 156f08c3bdfSopenharmony_ci * number of tasks in this group. 157f08c3bdfSopenharmony_ci */ 158f08c3bdfSopenharmony_ci FLAG = 0; 159f08c3bdfSopenharmony_ci total_shares = 0; 160f08c3bdfSopenharmony_ci shares_pointer = &total_shares; 161f08c3bdfSopenharmony_ci len = strlen(path); 162f08c3bdfSopenharmony_ci if (!strncpy(fullpath, path, len)) 163f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "Could not copy directory path %s ", 164f08c3bdfSopenharmony_ci path); 165f08c3bdfSopenharmony_ci 166f08c3bdfSopenharmony_ci if (scan_shares_files(shares_pointer) != 0) 167f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, 168f08c3bdfSopenharmony_ci "From function scan_shares_files in %s ", fullpath); 169f08c3bdfSopenharmony_ci 170f08c3bdfSopenharmony_ci /* return val: -1 in case of function error, else 2 is min share value */ 171f08c3bdfSopenharmony_ci if ((fmyshares = read_shares_file(mysharesfile)) < 2) 172f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "in reading shares files %s ", 173f08c3bdfSopenharmony_ci mysharesfile); 174f08c3bdfSopenharmony_ci 175f08c3bdfSopenharmony_ci if ((read_file(mytaskfile, GET_TASKS, &num_tasks)) < 0) 176f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, "in reading tasks files %s ", 177f08c3bdfSopenharmony_ci mytaskfile); 178f08c3bdfSopenharmony_ci 179f08c3bdfSopenharmony_ci exp_cpu_time = (double)(fmyshares * 100) / (total_shares * num_tasks); 180f08c3bdfSopenharmony_ci 181f08c3bdfSopenharmony_ci prev_time = time(NULL); /* Note down the time */ 182f08c3bdfSopenharmony_ci 183f08c3bdfSopenharmony_ci while (1) { 184f08c3bdfSopenharmony_ci /* Need to run some cpu intensive task, which also frequently checks the timer value */ 185f08c3bdfSopenharmony_ci double f = 274.345, mytime; /*just a float number to take sqrt */ 186f08c3bdfSopenharmony_ci alarm(TIME_INTERVAL); 187f08c3bdfSopenharmony_ci timer_expired = 0; 188f08c3bdfSopenharmony_ci while (!timer_expired) /* Let the task run on cpu for TIME_INTERVAL */ 189f08c3bdfSopenharmony_ci f = sqrt(f * f); /* Time of this operation should not be high otherwise we can 190f08c3bdfSopenharmony_ci * exceed the TIME_INTERVAL to measure cpu usage 191f08c3bdfSopenharmony_ci */ 192f08c3bdfSopenharmony_ci current_time = time(NULL); 193f08c3bdfSopenharmony_ci delta_time = current_time - prev_time; /* Duration in case its not exact TIME_INTERVAL */ 194f08c3bdfSopenharmony_ci 195f08c3bdfSopenharmony_ci getrusage(0, &cpu_usage); 196f08c3bdfSopenharmony_ci total_cpu_time = (cpu_usage.ru_utime.tv_sec + cpu_usage.ru_utime.tv_usec * 1e-6 + /* user time */ 197f08c3bdfSopenharmony_ci cpu_usage.ru_stime.tv_sec + cpu_usage.ru_stime.tv_usec * 1e-6); /* system time */ 198f08c3bdfSopenharmony_ci delta_cpu_time = total_cpu_time - prev_cpu_time; 199f08c3bdfSopenharmony_ci 200f08c3bdfSopenharmony_ci prev_cpu_time = total_cpu_time; 201f08c3bdfSopenharmony_ci prev_time = current_time; 202f08c3bdfSopenharmony_ci 203f08c3bdfSopenharmony_ci /* calculate % cpu time each task gets */ 204f08c3bdfSopenharmony_ci if (delta_time > TIME_INTERVAL) 205f08c3bdfSopenharmony_ci mytime = 206f08c3bdfSopenharmony_ci (delta_cpu_time * 100) / (delta_time * num_cpus); 207f08c3bdfSopenharmony_ci else 208f08c3bdfSopenharmony_ci mytime = 209f08c3bdfSopenharmony_ci (delta_cpu_time * 100) / (TIME_INTERVAL * num_cpus); 210f08c3bdfSopenharmony_ci 211f08c3bdfSopenharmony_ci fprintf(stdout, "Grp:-%3d task-%3d:CPU TIME{calc:-%6.2f(s)i.e. %6.2f(%%) exp:-%6.2f(%%)}\ 212f08c3bdfSopenharmony_ci in %lu (s) INTERVAL\n", mygroup_num, task_num, delta_cpu_time, mytime, 213f08c3bdfSopenharmony_ci exp_cpu_time, delta_time); 214f08c3bdfSopenharmony_ci 215f08c3bdfSopenharmony_ci counter++; 216f08c3bdfSopenharmony_ci 217f08c3bdfSopenharmony_ci if (counter >= NUM_INTERVALS) { /* Take n sets of readings for each shares value */ 218f08c3bdfSopenharmony_ci switch (test_num) { 219f08c3bdfSopenharmony_ci case 6: /* Test 06 */ 220f08c3bdfSopenharmony_ci case 7: /* Test 07 */ 221f08c3bdfSopenharmony_ci case 8: /* Test 08 */ 222f08c3bdfSopenharmony_ci exit(0); /* This task is done with its job */ 223f08c3bdfSopenharmony_ci break; 224f08c3bdfSopenharmony_ci default: 225f08c3bdfSopenharmony_ci tst_brkm(TBROK, cleanup, 226f08c3bdfSopenharmony_ci "Invalid test number passed"); 227f08c3bdfSopenharmony_ci break; 228f08c3bdfSopenharmony_ci 229f08c3bdfSopenharmony_ci } /* end switch */ 230f08c3bdfSopenharmony_ci } /* end if */ 231f08c3bdfSopenharmony_ci } /* end while */ 232f08c3bdfSopenharmony_ci} /* end main */ 233