blob: 8b93413501e3fb92c3bd77080114454ec8a21deb [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
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 * FILE : mtest01.c
22 * DESCRIPTION : mallocs memory <chunksize> at a time until malloc fails.
23 * HISTORY:
24 * 04/10/2001 Paul Larson (plars@us.ibm.com)
25 * written
iyermanoj822caf52001-11-09 22:43:09 +000026 * 11/09/2001 Manoj Iyer (manjo@austin.ibm.com)
robbiew94a8bf12003-05-13 19:05:04 +000027 * Modified.
28 * - Removed compile warnings.
29 * - Added header file #include <unistd.h> definition for getopt()
30 * 05/13/2003 Robbie Williamson (robbiew@us.ibm.com)
31 * Modified.
32 * - Rewrote the test to be able to execute on large memory machines.
plars865695b2001-08-27 22:15:12 +000033 *
34 */
35
36#include <stdlib.h>
37#include <stdio.h>
iyermanoj822caf52001-11-09 22:43:09 +000038#include <unistd.h>
robbiew94a8bf12003-05-13 19:05:04 +000039#include <signal.h>
robbiewf5505642003-05-21 16:55:45 +000040#include <limits.h>
robbiew94a8bf12003-05-13 19:05:04 +000041#include <sys/sysinfo.h>
42#include <sys/types.h>
43#include <sys/wait.h>
plars865695b2001-08-27 22:15:12 +000044
robbiewb56c5d42003-06-11 15:37:22 +000045int pid_count = 0;
46
47void handler(int signo)
48{
49 pid_count++;
50}
51
52
plars865695b2001-08-27 22:15:12 +000053int main(int argc, char* argv[]) {
54 char* mem;
robbiew94a8bf12003-05-13 19:05:04 +000055 float percent;
robbiew15226cd2002-04-10 16:10:40 +000056 unsigned int maxpercent=0, dowrite=0, verbose=0, j, c;
robbiew94a8bf12003-05-13 19:05:04 +000057 unsigned long bytecount, alloc_bytes;
58 unsigned long long original_maxbytes,maxbytes=0;
59 unsigned long long pre_mem, post_mem;
plars865695b2001-08-27 22:15:12 +000060 extern char* optarg;
robbiewf3a83d52002-05-28 16:26:16 +000061 int chunksize = 1024*1024; /* one meg at a time by default */
plars865695b2001-08-27 22:15:12 +000062 struct sysinfo sstats;
robbiewb56c5d42003-06-11 15:37:22 +000063 int i,pid_cntr;
robbiew94a8bf12003-05-13 19:05:04 +000064 pid_t pid,pid_list[1000];
65
66 for (i=0;i<1000;i++)
67 pid_list[i]=(pid_t)0;
plars865695b2001-08-27 22:15:12 +000068
69 while((c=getopt(argc, argv, "c:b:p:wvh")) != EOF) {
70 switch((char)c) {
71 case 'c':
72 chunksize = atoi(optarg);
73 break;
74 case 'b':
robbiew94a8bf12003-05-13 19:05:04 +000075 maxbytes = atoll(optarg);
plars865695b2001-08-27 22:15:12 +000076 break;
77 case 'p':
78 maxpercent = atoi(optarg);
robbiewb56c5d42003-06-11 15:37:22 +000079 if (maxpercent <= 0){
80 printf("ERROR: -p option requires number greater than 0\n");
81 exit(1);}
82 if (maxpercent > 99){
83 printf("ERROR: -p option cannot be greater than 99\n");
84 exit(1);}
plars865695b2001-08-27 22:15:12 +000085 break;
86 case 'w':
87 dowrite = 1;
88 break;
89 case 'v':
90 verbose = 1;
91 break;
92 case 'h':
93 default:
94 printf("Usage: %s [-c <bytes>] [-b <bytes>|-p <percent>] [-v]\n", argv[0]);
95 printf("\t-c <num>\tsize of chunk in bytes to malloc on each pass\n");
96 printf("\t-b <bytes>\tmaximum number of bytes to allocate before stopping\n");
97 printf("\t-p <bytes>\tpercent of total memory used at which the program stops\n");
98 printf("\t-w\t\twrite to the memory after allocating\n");
99 printf("\t-v\t\tverbose\n");
100 printf("\t-h\t\tdisplay usage\n");
101 exit(-1);
102 }
103 }
104
robbiew94a8bf12003-05-13 19:05:04 +0000105 sysinfo(&sstats);
plars865695b2001-08-27 22:15:12 +0000106 if(maxpercent) {
robbiew94a8bf12003-05-13 19:05:04 +0000107 unsigned long long total_ram, total_free, D, C;
108 percent=(float)maxpercent/100.00;
109
110 total_ram=sstats.totalram;
111 total_ram=total_ram+sstats.totalswap;
112
113 total_free=sstats.freeram;
114 total_free=total_free+sstats.freeswap;
115
116 /* Total memory used needed to reach maxpercent */
117 D = percent*(sstats.mem_unit*total_ram);
118 printf("Total memory used needed to reach maxpercent = %llu kbytes\n",D/1024);
plars865695b2001-08-27 22:15:12 +0000119
120 /* Total memory already used */
robbiew94a8bf12003-05-13 19:05:04 +0000121 C = sstats.mem_unit*(total_ram-total_free);
122 printf("Total memory already used on system = %llu kbytes\n",C/1024);
123
124 /* Total Free Pre-Test RAM */
125 pre_mem = sstats.mem_unit*total_free;
plars865695b2001-08-27 22:15:12 +0000126
127 /* Are we already using more than maxpercent? */
128 if(C>D) {
129 printf("More memory than the maximum amount you specified is already being used\n");
130 exit(1);
131 }
robbiew94a8bf12003-05-13 19:05:04 +0000132 else
133 pre_mem = sstats.mem_unit*total_free;
134
plars865695b2001-08-27 22:15:12 +0000135
136 /* set maxbytes to the extra amount we want to allocate */
137 maxbytes = D-C;
robbiew94a8bf12003-05-13 19:05:04 +0000138 printf("Filling up %d%% of ram which is %llu kbytes\n",maxpercent,maxbytes/1024);
plars865695b2001-08-27 22:15:12 +0000139 }
robbiew94a8bf12003-05-13 19:05:04 +0000140 original_maxbytes=maxbytes;
141 i=0;
robbiewb56c5d42003-06-11 15:37:22 +0000142 pid_cntr=0;
robbiew94a8bf12003-05-13 19:05:04 +0000143 pid=fork();
robbiewb56c5d42003-06-11 15:37:22 +0000144 if (pid != 0)
145 pid_cntr++;
146 pid_list[i]=pid;
robbiewf5505642003-05-21 16:55:45 +0000147
148#if __WORDSIZE==32
robbiew94a8bf12003-05-13 19:05:04 +0000149 while( (pid!=0) && (maxbytes > 1024*1024*1024) )
150 {
151 i++;
152 maxbytes=maxbytes-(1024*1024*1024);
153 pid=fork();
154 if (pid != 0)
robbiewb56c5d42003-06-11 15:37:22 +0000155 pid_cntr++;
robbiew94a8bf12003-05-13 19:05:04 +0000156 pid_list[i]=pid;
157 }
158 if( maxbytes > 1024*1024*1024 )
159 alloc_bytes=1024*1024*1024;
160 else
161 alloc_bytes=(unsigned long)maxbytes;
robbiewf5505642003-05-21 16:55:45 +0000162#elif __WORDSIZE==64
163 while( (pid!=0) && (maxbytes > (unsigned long long)3*1024*1024*1024) )
164 {
165 i++;
robbiew94fb20d2003-05-22 22:06:44 +0000166 maxbytes=maxbytes-(unsigned long long)3*1024*1024*1024;
robbiewf5505642003-05-21 16:55:45 +0000167 pid=fork();
168 if (pid != 0)
robbiewb56c5d42003-06-11 15:37:22 +0000169 pid_cntr++;
robbiewf5505642003-05-21 16:55:45 +0000170 pid_list[i]=pid;
171 }
172 if( maxbytes > (unsigned long long)3*1024*1024*1024 )
173 alloc_bytes=(unsigned long long)3*1024*1024*1024;
174 else
175 alloc_bytes=(unsigned long)maxbytes;
176#endif
robbiew94a8bf12003-05-13 19:05:04 +0000177
178 if ( pid == 0) /** CHILD **/
179 {
180 bytecount=chunksize;
181 while(1) {
182 if((mem = (char*)malloc(chunksize)) == NULL) {
183 printf("stopped at %lu bytes\n",bytecount);
184 exit(1);
185 }
186 if(dowrite)
187 for(j=0; j<chunksize; j++)
188 *(mem+j)='a';
189 if(verbose) printf("allocated %lu bytes chunksize is %d\n",bytecount,chunksize);
190 bytecount+=chunksize;
191 if(alloc_bytes && (bytecount >= alloc_bytes))
192 break;
plars865695b2001-08-27 22:15:12 +0000193 }
robbiew94a8bf12003-05-13 19:05:04 +0000194 if (dowrite)
195 printf("... %lu bytes allocated and used.\n",bytecount);
196 else
197 printf("... %lu bytes allocated only.\n",bytecount);
robbiewb56c5d42003-06-11 15:37:22 +0000198 kill(getppid(),SIGUSR1);
robbiew94a8bf12003-05-13 19:05:04 +0000199 while(1)
200 sleep(1);
plars865695b2001-08-27 22:15:12 +0000201 }
robbiew94a8bf12003-05-13 19:05:04 +0000202 else /** PARENT **/
203 {
robbiewb56c5d42003-06-11 15:37:22 +0000204 struct sigaction act;
205
206 act.sa_handler = handler;
207 act.sa_flags = 0;
208 sigemptyset(&act.sa_mask);
209 sigaction(SIGUSR1, &act, 0);
210
robbiew94a8bf12003-05-13 19:05:04 +0000211 i=0;
212 sysinfo(&sstats);
213
214 if (dowrite)
215 {
216 /* Total Free Post-Test RAM */
robbiewd920f602003-05-27 20:44:17 +0000217 post_mem = (unsigned long long)sstats.mem_unit*sstats.freeram;
218 post_mem = post_mem+((unsigned long long)sstats.mem_unit*sstats.freeswap);
robbiewb56c5d42003-06-11 15:37:22 +0000219
220 while ( (((unsigned long long)pre_mem - post_mem) < (unsigned long long)original_maxbytes) &&
221 (pid_count < pid_cntr) )
robbiew94a8bf12003-05-13 19:05:04 +0000222 {
223 sleep(1);
224 sysinfo(&sstats);
robbiewd920f602003-05-27 20:44:17 +0000225 post_mem = (unsigned long long)sstats.mem_unit*sstats.freeram;
226 post_mem = post_mem+((unsigned long long)sstats.mem_unit*sstats.freeswap);
robbiew94a8bf12003-05-13 19:05:04 +0000227 }
228 }
229 sleep(10);
230 while (pid_list[i]!=0)
231 {
232 kill(pid_list[i],SIGTERM);
233 i++;
234 }
235 if (dowrite)
236 printf("PASS .. %llu kbytes allocated and used.\n",original_maxbytes/1024);
237 else
238 printf("PASS .. %llu kbytes allocated only.\n",original_maxbytes/1024);
239 }
plars865695b2001-08-27 22:15:12 +0000240 exit(0);
241}