1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * hugepage-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 | * For the ia64 architecture, the Linux kernel reserves Region number 4 for |
12 | * huge pages. That means that if one requires a fixed address, a huge page |
13 | * aligned address starting with 0x800000... will be required. If a fixed |
14 | * address is not required, the kernel will select an address in the proper |
15 | * range. |
16 | * Other architectures, such as ppc64, i386 or x86_64 are not so constrained. |
17 | * |
18 | * Note: The default shared memory limit is quite low on many kernels, |
19 | * you may need to increase it via: |
20 | * |
21 | * echo 268435456 > /proc/sys/kernel/shmmax |
22 | * |
23 | * This will increase the maximum size per shared memory segment to 256MB. |
24 | * The other limit that you will hit eventually is shmall which is the |
25 | * total amount of shared memory in pages. To set it to 16GB on a system |
26 | * with a 4kB pagesize do: |
27 | * |
28 | * echo 4194304 > /proc/sys/kernel/shmall |
29 | */ |
30 | |
31 | #include <stdlib.h> |
32 | #include <stdio.h> |
33 | #include <sys/types.h> |
34 | #include <sys/ipc.h> |
35 | #include <sys/shm.h> |
36 | #include <sys/mman.h> |
37 | |
38 | #define LENGTH (256UL*1024*1024) |
39 | |
40 | #define dprintf(x) printf(x) |
41 | |
42 | /* Only ia64 requires this */ |
43 | #ifdef __ia64__ |
44 | #define ADDR (void *)(0x8000000000000000UL) |
45 | #define SHMAT_FLAGS (SHM_RND) |
46 | #else |
47 | #define ADDR (void *)(0x0UL) |
48 | #define SHMAT_FLAGS (0) |
49 | #endif |
50 | |
51 | int main(void) |
52 | { |
53 | int shmid; |
54 | unsigned long i; |
55 | char *shmaddr; |
56 | |
57 | shmid = shmget(2, LENGTH, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W); |
58 | if (shmid < 0) { |
59 | perror("shmget" ); |
60 | exit(1); |
61 | } |
62 | printf("shmid: 0x%x\n" , shmid); |
63 | |
64 | shmaddr = shmat(shmid, ADDR, SHMAT_FLAGS); |
65 | if (shmaddr == (char *)-1) { |
66 | perror("Shared memory attach failure" ); |
67 | shmctl(shmid, IPC_RMID, NULL); |
68 | exit(2); |
69 | } |
70 | printf("shmaddr: %p\n" , shmaddr); |
71 | |
72 | dprintf("Starting the writes:\n" ); |
73 | for (i = 0; i < LENGTH; i++) { |
74 | shmaddr[i] = (char)(i); |
75 | if (!(i % (1024 * 1024))) |
76 | dprintf("." ); |
77 | } |
78 | dprintf("\n" ); |
79 | |
80 | dprintf("Starting the Check..." ); |
81 | for (i = 0; i < LENGTH; i++) |
82 | if (shmaddr[i] != (char)i) { |
83 | printf("\nIndex %lu mismatched\n" , i); |
84 | exit(3); |
85 | } |
86 | dprintf("Done.\n" ); |
87 | |
88 | if (shmdt((const void *)shmaddr) != 0) { |
89 | perror("Detach failure" ); |
90 | shmctl(shmid, IPC_RMID, NULL); |
91 | exit(4); |
92 | } |
93 | |
94 | shmctl(shmid, IPC_RMID, NULL); |
95 | |
96 | return 0; |
97 | } |
98 | |