• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2020 SUSE LLC <mdoucha@suse.cz>
4  */
5 
6 #include <unistd.h>
7 #include <limits.h>
8 #include <sys/sysinfo.h>
9 #include <stdlib.h>
10 
11 #define TST_NO_DEFAULT_MAIN
12 #include "tst_test.h"
13 
14 #define BLOCKSIZE (16 * 1024 * 1024)
15 
tst_pollute_memory(size_t maxsize,int fillchar)16 void tst_pollute_memory(size_t maxsize, int fillchar)
17 {
18 	size_t i, map_count = 0, safety = 0, blocksize = BLOCKSIZE;
19 	void **map_blocks;
20 	struct sysinfo info;
21 
22 	SAFE_SYSINFO(&info);
23 	safety = MAX(4096 * SAFE_SYSCONF(_SC_PAGESIZE), 128 * 1024 * 1024);
24 	safety /= info.mem_unit;
25 
26 	if (info.freeswap > safety)
27 		safety = 0;
28 
29 	/* Not enough free memory to avoid invoking OOM killer */
30 	if (info.freeram <= safety)
31 		return;
32 
33 	if (!maxsize)
34 		maxsize = SIZE_MAX;
35 
36 	if (info.freeram - safety < maxsize / info.mem_unit)
37 		maxsize = (info.freeram - safety) * info.mem_unit;
38 
39 	blocksize = MIN(maxsize, blocksize);
40 	map_count = maxsize / blocksize;
41 	map_blocks = SAFE_MALLOC(map_count * sizeof(void *));
42 
43 	/*
44 	 * Keep allocating until the first failure. The address space may be
45 	 * too fragmented or just smaller than maxsize.
46 	 */
47 	for (i = 0; i < map_count; i++) {
48 		map_blocks[i] = mmap(NULL, blocksize, PROT_READ | PROT_WRITE,
49 			MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
50 
51 		if (map_blocks[i] == MAP_FAILED) {
52 			map_count = i;
53 			break;
54 		}
55 
56 		memset(map_blocks[i], fillchar, blocksize);
57 	}
58 
59 	for (i = 0; i < map_count; i++)
60 		SAFE_MUNMAP(map_blocks[i], blocksize);
61 
62 	free(map_blocks);
63 }
64