xref: /aosp_15_r20/external/ltp/testcases/kernel/mem/mtest07/mallocstress.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) International Business Machines Corp., 2001
4*49cdfc7eSAndroid Build Coastguard Worker  * Author: Manoj Iyer, IBM Austin TX <[email protected]>, 2001
5*49cdfc7eSAndroid Build Coastguard Worker  *
6*49cdfc7eSAndroid Build Coastguard Worker  * Stress the VMM and C library by spawning N threads which malloc
7*49cdfc7eSAndroid Build Coastguard Worker  * blocks of increasing size until malloc returns NULL.
8*49cdfc7eSAndroid Build Coastguard Worker  */
9*49cdfc7eSAndroid Build Coastguard Worker 
10*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
11*49cdfc7eSAndroid Build Coastguard Worker #include <pthread.h>
12*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
13*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
14*49cdfc7eSAndroid Build Coastguard Worker #include <math.h>
15*49cdfc7eSAndroid Build Coastguard Worker #include <assert.h>
16*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
17*49cdfc7eSAndroid Build Coastguard Worker #include <stdint.h>
18*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
19*49cdfc7eSAndroid Build Coastguard Worker 
20*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
21*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_pthread.h"
22*49cdfc7eSAndroid Build Coastguard Worker 
23*49cdfc7eSAndroid Build Coastguard Worker /* Number of loops per-thread */
24*49cdfc7eSAndroid Build Coastguard Worker #define NUM_LOOPS	100
25*49cdfc7eSAndroid Build Coastguard Worker 
26*49cdfc7eSAndroid Build Coastguard Worker /* Number of threads to create */
27*49cdfc7eSAndroid Build Coastguard Worker #define NUM_THREADS     60
28*49cdfc7eSAndroid Build Coastguard Worker 
29*49cdfc7eSAndroid Build Coastguard Worker /* Define SPEW_SIGNALS to tickle thread_create bug (it fails if interrupted). */
30*49cdfc7eSAndroid Build Coastguard Worker #define SPEW_SIGNALS
31*49cdfc7eSAndroid Build Coastguard Worker 
32*49cdfc7eSAndroid Build Coastguard Worker static pthread_t *thread_id;	/* Spawned thread */
33*49cdfc7eSAndroid Build Coastguard Worker 
my_yield(void)34*49cdfc7eSAndroid Build Coastguard Worker static void my_yield(void)
35*49cdfc7eSAndroid Build Coastguard Worker {
36*49cdfc7eSAndroid Build Coastguard Worker #ifdef SPEW_SIGNALS
37*49cdfc7eSAndroid Build Coastguard Worker 	/* usleep just happens to use signals in glibc at moment.
38*49cdfc7eSAndroid Build Coastguard Worker 	 * This is good because it allows us to test whether pthread_create
39*49cdfc7eSAndroid Build Coastguard Worker 	 * improperly returns EINTR (which would violate SUSv3)
40*49cdfc7eSAndroid Build Coastguard Worker 	 */
41*49cdfc7eSAndroid Build Coastguard Worker 	usleep(0);
42*49cdfc7eSAndroid Build Coastguard Worker #else
43*49cdfc7eSAndroid Build Coastguard Worker 	/* If you want this test to pass, don't define SPEW_SIGNALS,
44*49cdfc7eSAndroid Build Coastguard Worker 	 * as pthread_create is broken at moment, and fails if interrupted
45*49cdfc7eSAndroid Build Coastguard Worker 	 */
46*49cdfc7eSAndroid Build Coastguard Worker 	static const struct timespec t0 = { 0, 0 };
47*49cdfc7eSAndroid Build Coastguard Worker 	nanosleep(&t0, NULL);
48*49cdfc7eSAndroid Build Coastguard Worker #endif
49*49cdfc7eSAndroid Build Coastguard Worker }
50*49cdfc7eSAndroid Build Coastguard Worker 
51*49cdfc7eSAndroid Build Coastguard Worker /*
52*49cdfc7eSAndroid Build Coastguard Worker  * allocate_free() - Allocate and free test called per-thread
53*49cdfc7eSAndroid Build Coastguard Worker  *
54*49cdfc7eSAndroid Build Coastguard Worker  * @scheme: 0-3; selects how fast memory size grows
55*49cdfc7eSAndroid Build Coastguard Worker  *
56*49cdfc7eSAndroid Build Coastguard Worker  * This function does the allocation and free by calling malloc
57*49cdfc7eSAndroid Build Coastguard Worker  * and free functions. The size of the memory to be malloced is
58*49cdfc7eSAndroid Build Coastguard Worker  * determined by the caller of this function. The size can be
59*49cdfc7eSAndroid Build Coastguard Worker  * a number from the fibannoaci series, power of 2 or 3 or 5
60*49cdfc7eSAndroid Build Coastguard Worker  *
61*49cdfc7eSAndroid Build Coastguard Worker  * Return:
62*49cdfc7eSAndroid Build Coastguard Worker  *  0: success
63*49cdfc7eSAndroid Build Coastguard Worker  *  1: failure
64*49cdfc7eSAndroid Build Coastguard Worker  */
allocate_free(int scheme,int threadnum)65*49cdfc7eSAndroid Build Coastguard Worker int allocate_free(int scheme, int threadnum)
66*49cdfc7eSAndroid Build Coastguard Worker {
67*49cdfc7eSAndroid Build Coastguard Worker 	int loop;
68*49cdfc7eSAndroid Build Coastguard Worker 	const int MAXPTRS = 50;	/* only 42 or so get used on 32 bit machine */
69*49cdfc7eSAndroid Build Coastguard Worker 
70*49cdfc7eSAndroid Build Coastguard Worker 	for (loop = 0; loop < NUM_LOOPS; loop++) {
71*49cdfc7eSAndroid Build Coastguard Worker 		size_t oldsize = 5;
72*49cdfc7eSAndroid Build Coastguard Worker 		size_t size = sizeof(long);
73*49cdfc7eSAndroid Build Coastguard Worker 		long *ptrs[MAXPTRS];
74*49cdfc7eSAndroid Build Coastguard Worker 		int num_alloc;
75*49cdfc7eSAndroid Build Coastguard Worker 		int i;
76*49cdfc7eSAndroid Build Coastguard Worker 
77*49cdfc7eSAndroid Build Coastguard Worker 		/* loop terminates in one of three ways:
78*49cdfc7eSAndroid Build Coastguard Worker 		 * 1. after MAXPTRS iterations
79*49cdfc7eSAndroid Build Coastguard Worker 		 * 2. if malloc fails
80*49cdfc7eSAndroid Build Coastguard Worker 		 * 3. if new size overflows
81*49cdfc7eSAndroid Build Coastguard Worker 		 */
82*49cdfc7eSAndroid Build Coastguard Worker 		for (num_alloc = 0; num_alloc < MAXPTRS; num_alloc++) {
83*49cdfc7eSAndroid Build Coastguard Worker 			size_t newsize = 0;
84*49cdfc7eSAndroid Build Coastguard Worker 
85*49cdfc7eSAndroid Build Coastguard Worker 			/* Malloc the next block */
86*49cdfc7eSAndroid Build Coastguard Worker 			ptrs[num_alloc] = malloc(size);
87*49cdfc7eSAndroid Build Coastguard Worker 			/* terminate loop if malloc fails */
88*49cdfc7eSAndroid Build Coastguard Worker 			if (!ptrs[num_alloc])
89*49cdfc7eSAndroid Build Coastguard Worker 				break;
90*49cdfc7eSAndroid Build Coastguard Worker 			ptrs[num_alloc][0] = num_alloc;
91*49cdfc7eSAndroid Build Coastguard Worker 
92*49cdfc7eSAndroid Build Coastguard Worker 			/* Increase size according to one of four schedules. */
93*49cdfc7eSAndroid Build Coastguard Worker 			switch (scheme) {
94*49cdfc7eSAndroid Build Coastguard Worker 			case 0:
95*49cdfc7eSAndroid Build Coastguard Worker 				newsize = size + oldsize;
96*49cdfc7eSAndroid Build Coastguard Worker 				oldsize = size;
97*49cdfc7eSAndroid Build Coastguard Worker 				break;
98*49cdfc7eSAndroid Build Coastguard Worker 			case 1:
99*49cdfc7eSAndroid Build Coastguard Worker 				newsize = size * 2;
100*49cdfc7eSAndroid Build Coastguard Worker 				break;
101*49cdfc7eSAndroid Build Coastguard Worker 			case 2:
102*49cdfc7eSAndroid Build Coastguard Worker 				newsize = size * 3;
103*49cdfc7eSAndroid Build Coastguard Worker 				break;
104*49cdfc7eSAndroid Build Coastguard Worker 			case 3:
105*49cdfc7eSAndroid Build Coastguard Worker 				newsize = size * 5;
106*49cdfc7eSAndroid Build Coastguard Worker 				break;
107*49cdfc7eSAndroid Build Coastguard Worker 			default:
108*49cdfc7eSAndroid Build Coastguard Worker 				assert(0);
109*49cdfc7eSAndroid Build Coastguard Worker 			}
110*49cdfc7eSAndroid Build Coastguard Worker 			/* terminate loop on overflow */
111*49cdfc7eSAndroid Build Coastguard Worker 			if (newsize < size)
112*49cdfc7eSAndroid Build Coastguard Worker 				break;
113*49cdfc7eSAndroid Build Coastguard Worker 			size = newsize;
114*49cdfc7eSAndroid Build Coastguard Worker 
115*49cdfc7eSAndroid Build Coastguard Worker 			my_yield();
116*49cdfc7eSAndroid Build Coastguard Worker 		}
117*49cdfc7eSAndroid Build Coastguard Worker 
118*49cdfc7eSAndroid Build Coastguard Worker 		for (i = 0; i < num_alloc; i++) {
119*49cdfc7eSAndroid Build Coastguard Worker 			if (ptrs[i][0] != i) {
120*49cdfc7eSAndroid Build Coastguard Worker 				tst_res(TFAIL,
121*49cdfc7eSAndroid Build Coastguard Worker 					"pid[%d]: fail: bad sentinel value\n",
122*49cdfc7eSAndroid Build Coastguard Worker 					getpid());
123*49cdfc7eSAndroid Build Coastguard Worker 				return 1;
124*49cdfc7eSAndroid Build Coastguard Worker 			}
125*49cdfc7eSAndroid Build Coastguard Worker 			free(ptrs[i]);
126*49cdfc7eSAndroid Build Coastguard Worker 			my_yield();
127*49cdfc7eSAndroid Build Coastguard Worker 		}
128*49cdfc7eSAndroid Build Coastguard Worker 
129*49cdfc7eSAndroid Build Coastguard Worker 		my_yield();
130*49cdfc7eSAndroid Build Coastguard Worker 
131*49cdfc7eSAndroid Build Coastguard Worker 		if (!tst_remaining_runtime()) {
132*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TINFO, "Thread [%d]: Test runtime is over, exiting", threadnum);
133*49cdfc7eSAndroid Build Coastguard Worker 			break;
134*49cdfc7eSAndroid Build Coastguard Worker 		}
135*49cdfc7eSAndroid Build Coastguard Worker 	}
136*49cdfc7eSAndroid Build Coastguard Worker 
137*49cdfc7eSAndroid Build Coastguard Worker 	/* Success! */
138*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
139*49cdfc7eSAndroid Build Coastguard Worker }
140*49cdfc7eSAndroid Build Coastguard Worker 
alloc_mem(void * threadnum)141*49cdfc7eSAndroid Build Coastguard Worker void *alloc_mem(void *threadnum)
142*49cdfc7eSAndroid Build Coastguard Worker {
143*49cdfc7eSAndroid Build Coastguard Worker 	int err;
144*49cdfc7eSAndroid Build Coastguard Worker 
145*49cdfc7eSAndroid Build Coastguard Worker 	/* waiting for other threads starting */
146*49cdfc7eSAndroid Build Coastguard Worker 	TST_CHECKPOINT_WAIT(0);
147*49cdfc7eSAndroid Build Coastguard Worker 
148*49cdfc7eSAndroid Build Coastguard Worker 	/* thread N will use growth scheme N mod 4 */
149*49cdfc7eSAndroid Build Coastguard Worker 	err = allocate_free(((uintptr_t)threadnum) % 4, (uintptr_t)threadnum);
150*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TINFO,
151*49cdfc7eSAndroid Build Coastguard Worker 		"Thread [%d]: allocate_free() returned %d, %s.  Thread exiting.\n",
152*49cdfc7eSAndroid Build Coastguard Worker 		(int)(uintptr_t)threadnum, err,
153*49cdfc7eSAndroid Build Coastguard Worker 		(err ? "failed" : "succeeded"));
154*49cdfc7eSAndroid Build Coastguard Worker 	return (void *)(uintptr_t) (err ? -1 : 0);
155*49cdfc7eSAndroid Build Coastguard Worker }
156*49cdfc7eSAndroid Build Coastguard Worker 
stress_malloc(void)157*49cdfc7eSAndroid Build Coastguard Worker static void stress_malloc(void)
158*49cdfc7eSAndroid Build Coastguard Worker {
159*49cdfc7eSAndroid Build Coastguard Worker 	int thread_index;
160*49cdfc7eSAndroid Build Coastguard Worker 
161*49cdfc7eSAndroid Build Coastguard Worker 	for (thread_index = 0; thread_index < NUM_THREADS; thread_index++) {
162*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_PTHREAD_CREATE(&thread_id[thread_index], NULL, alloc_mem,
163*49cdfc7eSAndroid Build Coastguard Worker 				    (void *)(uintptr_t)thread_index);
164*49cdfc7eSAndroid Build Coastguard Worker 	}
165*49cdfc7eSAndroid Build Coastguard Worker 
166*49cdfc7eSAndroid Build Coastguard Worker 	/* Wake up all threads */
167*49cdfc7eSAndroid Build Coastguard Worker 	TST_CHECKPOINT_WAKE2(0, NUM_THREADS);
168*49cdfc7eSAndroid Build Coastguard Worker 
169*49cdfc7eSAndroid Build Coastguard Worker 	/* wait for all threads to finish */
170*49cdfc7eSAndroid Build Coastguard Worker 	for (thread_index = 0; thread_index < NUM_THREADS; thread_index++) {
171*49cdfc7eSAndroid Build Coastguard Worker 		void *status;
172*49cdfc7eSAndroid Build Coastguard Worker 
173*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_PTHREAD_JOIN(thread_id[thread_index], &status);
174*49cdfc7eSAndroid Build Coastguard Worker 		if ((intptr_t)status != 0) {
175*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL, "thread [%d] - exited with errors",
176*49cdfc7eSAndroid Build Coastguard Worker 				thread_index);
177*49cdfc7eSAndroid Build Coastguard Worker 		}
178*49cdfc7eSAndroid Build Coastguard Worker 	}
179*49cdfc7eSAndroid Build Coastguard Worker 
180*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TPASS, "malloc stress test finished successfully");
181*49cdfc7eSAndroid Build Coastguard Worker }
182*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)183*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
184*49cdfc7eSAndroid Build Coastguard Worker {
185*49cdfc7eSAndroid Build Coastguard Worker 	thread_id = SAFE_MALLOC(sizeof(pthread_t) * NUM_THREADS);
186*49cdfc7eSAndroid Build Coastguard Worker }
187*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)188*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
189*49cdfc7eSAndroid Build Coastguard Worker {
190*49cdfc7eSAndroid Build Coastguard Worker 	if (thread_id) {
191*49cdfc7eSAndroid Build Coastguard Worker 		free(thread_id);
192*49cdfc7eSAndroid Build Coastguard Worker 		thread_id = NULL;
193*49cdfc7eSAndroid Build Coastguard Worker 	}
194*49cdfc7eSAndroid Build Coastguard Worker }
195*49cdfc7eSAndroid Build Coastguard Worker 
196*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
197*49cdfc7eSAndroid Build Coastguard Worker 	.max_runtime = 600,
198*49cdfc7eSAndroid Build Coastguard Worker 	.needs_checkpoints = 1,
199*49cdfc7eSAndroid Build Coastguard Worker 	.setup = setup,
200*49cdfc7eSAndroid Build Coastguard Worker 	.cleanup = cleanup,
201*49cdfc7eSAndroid Build Coastguard Worker 	.test_all = stress_malloc,
202*49cdfc7eSAndroid Build Coastguard Worker };
203