1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> 4 */ 5 6/*\ 7 * [Description] 8 * 9 * This test verifies futex_waitv syscall using private data. 10 */ 11 12#define _GNU_SOURCE 13#include <unistd.h> 14#include <time.h> 15#include "tst_test.h" 16#include "lapi/futex.h" 17#include "lapi/syscalls.h" 18#include "futex2test.h" 19#include "futex_utils.h" 20#include "tst_safe_pthread.h" 21#include "tst_safe_clocks.h" 22 23static char *str_numfutex; 24static int numfutex = 30; 25 26static uint32_t *futexes; 27static struct futex_waitv *waitv; 28 29static void setup(void) 30{ 31 struct futex_test_variants tv = futex_variant(); 32 int i; 33 34 tst_res(TINFO, "Testing variant: %s", tv.desc); 35 futex_supported_by_kernel(tv.fntype); 36 37 if (tst_parse_int(str_numfutex, &numfutex, 1, FUTEX_WAITV_MAX)) 38 tst_brk(TBROK, "Invalid number of futexes '%s'", str_numfutex); 39 40 futexes = tst_alloc(sizeof(uint32_t) * numfutex); 41 memset(futexes, FUTEX_INITIALIZER, sizeof(uint32_t) * numfutex); 42 43 waitv = tst_alloc(sizeof(struct futex_waitv) * numfutex); 44 memset(waitv, 0, sizeof(struct futex_waitv) * numfutex); 45 46 for (i = 0; i < numfutex; i++) { 47 waitv[i].uaddr = (uintptr_t)&futexes[i]; 48 waitv[i].flags = FUTEX_32 | FUTEX_PRIVATE_FLAG; 49 waitv[i].val = 0; 50 } 51} 52 53static void *threaded(LTP_ATTRIBUTE_UNUSED void *arg) 54{ 55 struct futex_test_variants tv = futex_variant(); 56 57 TST_RETRY_FUNC(futex_wake(tv.fntype, 58 (void *)(uintptr_t)waitv[numfutex - 1].uaddr, 59 1, FUTEX_PRIVATE_FLAG), futex_waked_someone); 60 61 return NULL; 62} 63 64static void run(void) 65{ 66 struct timespec to; 67 pthread_t t; 68 69 SAFE_PTHREAD_CREATE(&t, NULL, threaded, NULL); 70 71 /* setting absolute timeout for futex2 */ 72 SAFE_CLOCK_GETTIME(CLOCK_MONOTONIC, &to); 73 to.tv_sec += 5; 74 75 TEST(futex_waitv(waitv, numfutex, 0, &to, CLOCK_MONOTONIC)); 76 if (TST_RET < 0) { 77 tst_brk(TBROK | TTERRNO, "futex_waitv returned: %ld", TST_RET); 78 } else if (TST_RET != numfutex - 1) { 79 tst_res(TFAIL, "futex_waitv returned: %ld, expecting %d", 80 TST_RET, numfutex - 1); 81 } 82 83 SAFE_PTHREAD_JOIN(t, NULL); 84 tst_res(TPASS, "futex_waitv returned correctly"); 85} 86 87static struct tst_test test = { 88 .test_all = run, 89 .setup = setup, 90 .min_kver = "5.16", 91 .test_variants = FUTEX_VARIANTS, 92 .options = 93 (struct tst_option[]){ 94 { "n:", &str_numfutex, "Number of futex (default 30)" }, 95 {}, 96 }, 97}; 98