1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz> 4 * 5 * Block on a futex and wait for wakeup. 6 * 7 * This tests uses shared memory page to store the mutex variable. 8 */ 9 10#include <sys/mman.h> 11#include <sys/wait.h> 12 13#include "futextest.h" 14#include "futex_utils.h" 15 16static futex_t *futex; 17 18static struct futex_test_variants variants[] = { 19#if (__NR_futex != __LTP__NR_INVALID_SYSCALL) 20 { .fntype = FUTEX_FN_FUTEX, .desc = "syscall with old kernel spec"}, 21#endif 22 23#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL) 24 { .fntype = FUTEX_FN_FUTEX64, .desc = "syscall time64 with kernel spec"}, 25#endif 26}; 27 28static void do_child(void) 29{ 30 struct futex_test_variants *tv = &variants[tst_variant]; 31 int ret; 32 33 TST_PROCESS_STATE_WAIT(getppid(), 'S', 1000); 34 35 ret = futex_wake(tv->fntype, futex, 1, 0); 36 37 if (ret != 1) 38 tst_res(TFAIL | TERRNO, "futex_wake() failed"); 39 40 exit(0); 41} 42 43static void run(void) 44{ 45 struct futex_test_variants *tv = &variants[tst_variant]; 46 int res, pid; 47 48 pid = SAFE_FORK(); 49 if (!pid) 50 do_child(); 51 52 res = futex_wait(tv->fntype, futex, *futex, NULL, 0); 53 if (res) { 54 tst_res(TFAIL | TERRNO, "futex_wait() failed"); 55 return; 56 } 57 58 SAFE_WAIT(NULL); 59 tst_res(TPASS, "futex_wait() woken up"); 60} 61 62static void setup(void) 63{ 64 struct futex_test_variants *tv = &variants[tst_variant]; 65 66 tst_res(TINFO, "Testing variant: %s", tv->desc); 67 futex_supported_by_kernel(tv->fntype); 68 69 futex = SAFE_MMAP(NULL, sizeof(*futex), PROT_READ | PROT_WRITE, 70 MAP_ANONYMOUS | MAP_SHARED, -1, 0); 71 72 *futex = FUTEX_INITIALIZER; 73} 74 75static struct tst_test test = { 76 .setup = setup, 77 .test_all = run, 78 .test_variants = ARRAY_SIZE(variants), 79 .forks_child = 1, 80}; 81