diff options
-rw-r--r-- | tests/Makefile | 3 | ||||
-rwxr-xr-x | tests/run_tests.py | 3 | ||||
-rw-r--r-- | tests/shm-perms.c | 130 |
3 files changed, 135 insertions, 1 deletions
diff --git a/tests/Makefile b/tests/Makefile index 3e0a832..f7e9b26 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -9,7 +9,8 @@ LIB_TESTS = gethugepagesize test_root find_path unlinked_fd misalign \ misaligned_offset brk_near_huge task-size-overrun stack_grow_into_huge \ counters quota heap-overflow get_huge_pages get_hugepage_region \ shmoverride_linked gethugepagesizes \ - madvise_reserve fadvise_reserve readahead_reserve + madvise_reserve fadvise_reserve readahead_reserve \ + shm-perms LIB_TESTS_64 = straddle_4GB huge_at_4GB_normal_below \ huge_below_4GB_normal_above NOLIB_TESTS = malloc malloc_manysmall dummy heapshrink shmoverride_unlinked diff --git a/tests/run_tests.py b/tests/run_tests.py index 871ae7c..a0357ee 100755 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -482,6 +482,9 @@ def functional_tests(): do_test("readahead_reserve.sh") do_test("madvise_reserve.sh") do_test("fadvise_reserve.sh") + sysctls = setup_shm_sysctl(64*1048576) + do_test("shm-perms") + restore_shm_sysctl(sysctls) # Tests requiring an active mount and hugepage COW do_test("private") diff --git a/tests/shm-perms.c b/tests/shm-perms.c new file mode 100644 index 0000000..47d4d6b --- /dev/null +++ b/tests/shm-perms.c @@ -0,0 +1,130 @@ +/* + * libhugetlbfs - Easy use of Linux hugepages + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <errno.h> +#include <memory.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/shm.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <hugetlbfs.h> +#include "hugetests.h" + +#define P "shm-perms" +#define DESC \ + "* Test shared memory behavior when multiple threads are attached *\n"\ + "* to a segment with different permissions. A segment is created *\n"\ + "* and children attach read-only to check reservation accounting. *" + +#define SEGMENT_SIZE ((size_t)0x4000000) +#define SEGMENT_KEY 0x82ba15ff +#define SEGMENT_ADDR ((void *)0x40000000) + +#define STRIDE 0x200000 + +static int global_shmid = -1; + +void cleanup(void) +{ + remove_shmid(global_shmid); +} + +int attach_segment(size_t segsize, int shmflags, int shmperms) +{ + int shmid; + + /* Create/get large segment */ + shmid = shmget(SEGMENT_KEY, segsize, shmflags); + if (shmid == -1) { + perror("shmget(SEGMENT)"); + exit(EXIT_FAILURE); + } + + /* Attach large segment */ + if (shmat(shmid, SEGMENT_ADDR, shmperms) == (void *)-1) { + perror("shmat(SEGMENT)"); + exit(EXIT_FAILURE); + } + + global_shmid = shmid; + return shmid; +} + +int main(int argc, char **argv) +{ + char *p; + pid_t *wait_list; + int i, iterations; + long hpage_size = check_hugepagesize(); + long total_hpages = get_huge_page_counter(hpage_size, HUGEPAGES_TOTAL); + + /* Setup */ + test_init(argc, argv); + check_hugetlb_shm_group(); + if (hpage_size > SEGMENT_SIZE) + CONFIG("Page size is too large for configured SEGMENT_SIZE\n"); + check_free_huge_pages(SEGMENT_SIZE / hpage_size); + + iterations = (total_hpages * hpage_size) / SEGMENT_SIZE + 1; + verbose_printf("iterations = %d\n", iterations); + + wait_list = malloc(sizeof(pid_t) * iterations); + if (wait_list == NULL) + FAIL("Failed to allocate wait_list"); + + /* Create, attach and part init segment */ + attach_segment(SEGMENT_SIZE, IPC_CREAT|SHM_HUGETLB|0640, 0); + p = (char *)SEGMENT_ADDR; + for (i = 0; i < 4; i++, p += STRIDE) + memset(p, 0x55, STRIDE); + + /* Detach segment */ + if (shmdt(SEGMENT_ADDR) != 0) + FAIL("shmdt(SEGMENT)"); + + /* Create children to reattach read-only */ + for (i = 0; i < iterations; i++) { + pid_t pid; + pid = fork(); + if (pid == -1) + FAIL("fork"); + + if (pid) { + wait_list[i] = pid; + } else { + attach_segment(0, 0, SHM_RDONLY); + if (shmdt(SEGMENT_ADDR) != 0) { + perror("shmdt(SEGMENT)"); + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); + } + } + + /* Wait for all children to exit */ + for (i = 0; i < iterations; i++) { + int status; + if (waitpid(wait_list[i], &status, 0) == -1) + FAIL("waitpid"); + if (status != EXIT_SUCCESS) + FAIL("Child exited with failure"); + } + + PASS(); +} |