xref: /linux/tools/testing/selftests/mm/hugetlb-shm.c (revision 3d5e48944e824bddc20d7b874e784f7b279636fe)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * hugetlb-shm:
4  *
5  * Example of using huge page memory in a user application using Sys V shared
6  * memory system calls.  In this example the app is requesting 256MB of
7  * memory that is backed by huge pages.  The application uses the flag
8  * SHM_HUGETLB in the shmget system call to inform the kernel that it is
9  * requesting huge pages.
10  *
11  * Note: The default shared memory limit is quite low on many kernels,
12  * you may need to increase it via:
13  *
14  * echo 268435456 > /proc/sys/kernel/shmmax
15  *
16  * This will increase the maximum size per shared memory segment to 256MB.
17  * The other limit that you will hit eventually is shmall which is the
18  * total amount of shared memory in pages. To set it to 16GB on a system
19  * with a 4kB pagesize do:
20  *
21  * echo 4194304 > /proc/sys/kernel/shmall
22  */
23 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <sys/ipc.h>
28 #include <sys/shm.h>
29 #include <sys/mman.h>
30 
31 #include "vm_util.h"
32 #include "hugepage_settings.h"
33 
34 #define LENGTH (256UL*1024*1024)
35 
36 static void prepare(void)
37 {
38 	unsigned long length, hugepage_size, nr;
39 
40 	hugepage_size = default_huge_page_size();
41 	if (!hugepage_size)
42 		ksft_exit_skip("Unable to determine huge page size\n");
43 
44 	length = (LENGTH + hugepage_size - 1) & ~(hugepage_size - 1);
45 	nr = length / hugepage_size;
46 
47 	if (!hugetlb_setup_default(nr))
48 		ksft_exit_skip("Not enough free huge pages\n");
49 
50 	shm_limits_prepare(length);
51 }
52 
53 int main(void)
54 {
55 	int shmid;
56 	unsigned long i;
57 	char *shmaddr;
58 
59 	ksft_print_header();
60 	ksft_set_plan(1);
61 
62 	prepare();
63 
64 	shmid = shmget(2, LENGTH, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
65 	if (shmid < 0)
66 		ksft_exit_fail_perror("shmget");
67 
68 	ksft_print_msg("shmid: 0x%x\n", shmid);
69 
70 	shmaddr = shmat(shmid, NULL, 0);
71 	if (shmaddr == (char *)-1) {
72 		ksft_perror("Shared memory attach failure");
73 		shmctl(shmid, IPC_RMID, NULL);
74 		ksft_exit_fail();
75 	}
76 	ksft_print_msg("shmaddr: %p\n", shmaddr);
77 
78 	ksft_print_msg("Starting the writes:\n");
79 	for (i = 0; i < LENGTH; i++)
80 		shmaddr[i] = (char)(i);
81 
82 	ksft_print_msg("Starting the Check...");
83 	for (i = 0; i < LENGTH; i++)
84 		if (shmaddr[i] != (char)i)
85 			ksft_exit_fail_msg("Data mismatch at index %lu\n", i);
86 	ksft_print_msg("Done.\n");
87 
88 	if (shmdt((const void *)shmaddr) != 0) {
89 		ksft_perror("Detach failure");
90 		shmctl(shmid, IPC_RMID, NULL);
91 		ksft_exit_fail();
92 	}
93 
94 	shmctl(shmid, IPC_RMID, NULL);
95 
96 	ksft_test_result_pass("hugepage using SysV shmget/shmat\n");
97 	ksft_finished();
98 }
99 
100 SHM_LIMITS_RESTORE()
101