1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz> 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * 1. Block on a bitset futex and wait for timeout, the difference between 6f08c3bdfSopenharmony_ci * normal futex and bitset futex is that that the later have absolute timeout. 7f08c3bdfSopenharmony_ci * 2. Check that the futex waited for expected time. 8f08c3bdfSopenharmony_ci */ 9f08c3bdfSopenharmony_ci 10f08c3bdfSopenharmony_ci#include "tst_test.h" 11f08c3bdfSopenharmony_ci#include "tst_timer.h" 12f08c3bdfSopenharmony_ci#include "futextest.h" 13f08c3bdfSopenharmony_ci 14f08c3bdfSopenharmony_ci#define THRESHOLD_US 100000 15f08c3bdfSopenharmony_ci#define DEFAULT_TIMEOUT_US 100010 16f08c3bdfSopenharmony_ci 17f08c3bdfSopenharmony_cistatic struct test_case_t { 18f08c3bdfSopenharmony_ci clockid_t clk_id; 19f08c3bdfSopenharmony_ci} tcases[] = { 20f08c3bdfSopenharmony_ci { CLOCK_MONOTONIC }, 21f08c3bdfSopenharmony_ci { CLOCK_REALTIME } 22f08c3bdfSopenharmony_ci}; 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_cistatic struct futex_test_variants variants[] = { 25f08c3bdfSopenharmony_ci#if (__NR_futex != __LTP__NR_INVALID_SYSCALL) 26f08c3bdfSopenharmony_ci { .fntype = FUTEX_FN_FUTEX, .tstype = TST_KERN_OLD_TIMESPEC, .gettime = sys_clock_gettime, .desc = "syscall with old kernel spec"}, 27f08c3bdfSopenharmony_ci#endif 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_ci#if (__NR_futex_time64 != __LTP__NR_INVALID_SYSCALL) 30f08c3bdfSopenharmony_ci { .fntype = FUTEX_FN_FUTEX64, .tstype = TST_KERN_TIMESPEC, .gettime = sys_clock_gettime64, .desc = "syscall time64 with kernel spec"}, 31f08c3bdfSopenharmony_ci#endif 32f08c3bdfSopenharmony_ci}; 33f08c3bdfSopenharmony_ci 34f08c3bdfSopenharmony_cistatic void verify_futex_wait_bitset(long long wait_us, clock_t clk_id) 35f08c3bdfSopenharmony_ci{ 36f08c3bdfSopenharmony_ci struct futex_test_variants *tv = &variants[tst_variant]; 37f08c3bdfSopenharmony_ci struct tst_ts start, to, end; 38f08c3bdfSopenharmony_ci futex_t futex = FUTEX_INITIALIZER; 39f08c3bdfSopenharmony_ci u_int32_t bitset = 0xffffffff; 40f08c3bdfSopenharmony_ci int flags = clk_id == CLOCK_REALTIME ? FUTEX_CLOCK_REALTIME : 0; 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_ci start.type = end.type = to.type = tv->tstype; 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_ci tst_res(TINFO, "testing futex_wait_bitset() timeout with %s", 45f08c3bdfSopenharmony_ci clk_id == CLOCK_REALTIME ? "CLOCK_REALTIME" : "CLOCK_MONOTONIC"); 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci tv->gettime(clk_id, tst_ts_get(&start)); 48f08c3bdfSopenharmony_ci to = tst_ts_add_us(start, wait_us); 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_ci TEST(futex_wait_bitset(tv->fntype, &futex, futex, &to, bitset, flags)); 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci tv->gettime(clk_id, tst_ts_get(&end)); 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_ci if (TST_RET != -1) { 55f08c3bdfSopenharmony_ci tst_res(TFAIL, "futex_wait_bitset() returned %li, expected -1", 56f08c3bdfSopenharmony_ci TST_RET); 57f08c3bdfSopenharmony_ci return; 58f08c3bdfSopenharmony_ci } 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci if (TST_ERR == ENOSYS) { 61f08c3bdfSopenharmony_ci tst_res(TCONF, 62f08c3bdfSopenharmony_ci "In this kernel, futex() does not support FUTEX_WAIT_BITSET operation"); 63f08c3bdfSopenharmony_ci return; 64f08c3bdfSopenharmony_ci } 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_ci if (TST_ERR != ETIMEDOUT) { 67f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "expected %s", 68f08c3bdfSopenharmony_ci tst_strerrno(ETIMEDOUT)); 69f08c3bdfSopenharmony_ci return; 70f08c3bdfSopenharmony_ci } 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci if (tst_ts_lt(end, to)) { 73f08c3bdfSopenharmony_ci tst_res(TFAIL, 74f08c3bdfSopenharmony_ci "futex_wait_bitset() woken up prematurely %llius, expected %llius", 75f08c3bdfSopenharmony_ci tst_ts_diff_us(end, start), wait_us); 76f08c3bdfSopenharmony_ci return; 77f08c3bdfSopenharmony_ci } 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci if (tst_ts_diff_us(end, to) > THRESHOLD_US) { 80f08c3bdfSopenharmony_ci tst_res(TFAIL, 81f08c3bdfSopenharmony_ci "futex_wait_bitset() waited too long %llius, expected %llius", 82f08c3bdfSopenharmony_ci tst_ts_diff_us(end, start), wait_us); 83f08c3bdfSopenharmony_ci return; 84f08c3bdfSopenharmony_ci } 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_ci tst_res(TPASS, "futex_wait_bitset() waited %llius, expected %llius", 87f08c3bdfSopenharmony_ci tst_ts_diff_us(end, start), wait_us); 88f08c3bdfSopenharmony_ci} 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_cistatic void run(unsigned int n) 91f08c3bdfSopenharmony_ci{ 92f08c3bdfSopenharmony_ci verify_futex_wait_bitset(DEFAULT_TIMEOUT_US, tcases[n].clk_id); 93f08c3bdfSopenharmony_ci} 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_cistatic void setup(void) 96f08c3bdfSopenharmony_ci{ 97f08c3bdfSopenharmony_ci struct futex_test_variants *tv = &variants[tst_variant]; 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_ci tst_res(TINFO, "Testing variant: %s", tv->desc); 100f08c3bdfSopenharmony_ci futex_supported_by_kernel(tv->fntype); 101f08c3bdfSopenharmony_ci} 102f08c3bdfSopenharmony_ci 103f08c3bdfSopenharmony_cistatic struct tst_test test = { 104f08c3bdfSopenharmony_ci .setup = setup, 105f08c3bdfSopenharmony_ci .test = run, 106f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 107f08c3bdfSopenharmony_ci .test_variants = ARRAY_SIZE(variants), 108f08c3bdfSopenharmony_ci}; 109