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