1/******************************************************************************/ 2/* */ 3/* Copyright (c) International Business Machines Corp., 2008 */ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 18/* */ 19/******************************************************************************/ 20 21/******************************************************************************/ 22/* */ 23/* File: memctl_test01.c */ 24/* */ 25/* Description: This is a c program that allocates memory in chunks of size */ 26/* as given by the calling script. The program touches all the */ 27/* allocated pages by writing a string on each page. */ 28/* */ 29/* Total Tests: 3 */ 30/* */ 31/* Test Name: mem_controller_test01-03 */ 32/* */ 33/* */ 34/* Test Assertion */ 35/* Please refer to the file memctl_testplan.txt */ 36/* */ 37/* Author: Sudhir Kumar skumar@linux.vnet.ibm.com */ 38/* */ 39/* History: */ 40/* Created 12/03/2008 Sudhir Kumar <skumar@linux.vnet.ibm.com> */ 41/* Modified 11/05/2008 Sudhir Kumar <skumar@linux.vnet.ibm.com> */ 42/* */ 43/******************************************************************************/ 44 45#include <stdio.h> 46#include <string.h> 47#include <unistd.h> 48 49#include "libcontrollers.h" 50#include "test.h" 51 52char *TCID = "memory_controller_test01-03"; 53int TST_TOTAL = 3; 54 55pid_t scriptpid; 56typedef size_t record_t; 57record_t **array_of_chunks; 58record_t tmp; 59int num_of_chunks, chunk_size, test_num, limit; 60 61void cleanup(); 62void signal_handler_sigusr1(int signal); 63void signal_handler_sigusr2(int signal); 64int allocate_memory(void); 65 66int main(void) 67{ 68 int ret; 69 char mygroup[FILENAME_MAX], mytaskfile[FILENAME_MAX]; 70 char *mygroup_p, *script_pid_p, *test_num_p, *chunk_size_p; 71 char *num_chunks_p; 72 struct sigaction newaction1, newaction2, oldaction1, oldaction2; 73 74 /* Capture variables from the script environment */ 75 test_num_p = getenv("TEST_NUM"); 76 mygroup_p = getenv("MYGROUP"); 77 script_pid_p = getenv("SCRIPT_PID"); 78 chunk_size_p = getenv("CHUNK_SIZE"); 79 num_chunks_p = getenv("NUM_CHUNKS"); 80 81 if (test_num_p != NULL && mygroup_p != NULL && script_pid_p != NULL && 82 chunk_size_p != NULL && num_chunks_p != NULL) { 83 scriptpid = atoi(script_pid_p); 84 test_num = atoi(test_num_p); 85 chunk_size = atoi(chunk_size_p); 86 num_of_chunks = atoi(num_chunks_p); 87 sprintf(mygroup, "%s", mygroup_p); 88 } else { 89 tst_brkm(TBROK, cleanup, 90 "invalid parameters received from script\n"); 91 } 92 93 /* XXX (garrcoop): this section really needs error handling. */ 94 95 /* Signal handling for SIGUSR1 received from script */ 96 sigemptyset(&newaction1.sa_mask); 97 newaction1.sa_handler = signal_handler_sigusr1; 98 newaction1.sa_flags = 0; 99 sigaction(SIGUSR1, &newaction1, &oldaction1); 100 101 /* Signal handling for SIGUSR2 received from script */ 102 sigemptyset(&newaction2.sa_mask); 103 newaction2.sa_handler = signal_handler_sigusr2; 104 newaction2.sa_flags = 0; 105 sigaction(SIGUSR2, &newaction2, &oldaction2); 106 107 sprintf(mytaskfile, "%s", mygroup); 108 strcat(mytaskfile, "/tasks"); 109 /* Assign the task to it's group */ 110 write_to_file(mytaskfile, "a", getpid()); /* Assign the task to it's group */ 111 112 ret = allocate_memory(); /*should i check ret? */ 113 114 cleanup(); 115 116 tst_exit(); 117} 118 119/* 120 * Function: cleanup() 121 * signals for system cleanup in case test breaks 122 */ 123void cleanup(void) 124{ 125 if (kill(scriptpid, SIGUSR1) == -1) 126 tst_resm(TWARN | TERRNO, "kill failed"); 127} 128 129/* 130 * Function: signal_handler_sigusr1() 131 * signal handler for the new action 132 */ 133 134void signal_handler_sigusr1(int signal) 135{ 136 int i; 137 (void) signal; 138 for (i = 0; i < num_of_chunks; ++i) 139 free(array_of_chunks[i]); 140 free(array_of_chunks); 141 exit(0); 142} 143 144/* 145 * Function: signal_handler_sigusr2() 146 * signal handler for the new action 147 */ 148 149void signal_handler_sigusr2(int signal) 150{ 151 int i; 152 (void) signal; 153 for (i = 0; i < num_of_chunks; ++i) 154 free(array_of_chunks[i]); 155 free(array_of_chunks); 156 if (test_num == 4) { 157 /* Allocate different amount of memory for second step */ 158 chunk_size = 5242880; /* 5 MB chunks */ 159 num_of_chunks = 15; 160 } 161 allocate_memory(); 162} 163 164int allocate_memory(void) 165{ 166 int i, j; 167 /* 168 * Allocate array which contains base addresses of all chunks 169 */ 170 array_of_chunks = malloc(sizeof(record_t *) * num_of_chunks); 171 if (array_of_chunks == NULL) 172 tst_brkm(TBROK, cleanup, 173 "Memory allocation failed for array_of_chunks"); 174 /* 175 * Allocate chunks of memory 176 */ 177 178 for (i = 0; i < num_of_chunks; ++i) { 179 array_of_chunks[i] = malloc(chunk_size); 180 if (array_of_chunks[i] == NULL) 181 tst_brkm(TBROK, cleanup, 182 "Memory allocation failed for chunks. Try smaller chunk size"); 183 } 184 185 /* 186 * Touch all the pages of allocated memory by writing some string 187 */ 188 limit = chunk_size / sizeof(record_t); 189 190 for (i = 0; i < num_of_chunks; ++i) 191 for (j = 0; j < limit; ++j) 192 array_of_chunks[i][j] = 0xaa; 193 194 /* 195 * Just keep on accessing the allocated pages and do nothing relevant 196 */ 197 while (1) { 198 for (i = 0; i < num_of_chunks; ++i) 199 for (j = 0; j < limit; ++j) 200 tmp = array_of_chunks[i][j]; 201 } 202 return 0; 203} 204