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