Path: blob/master/tools/testing/selftests/futex/functional/futex_waitv.c
29271 views
// SPDX-License-Identifier: GPL-2.0-or-later1/*2* futex_waitv() test by André Almeida <[email protected]>3*4* Copyright 2021 Collabora Ltd.5*/67#include <errno.h>8#include <error.h>9#include <getopt.h>10#include <stdio.h>11#include <stdlib.h>12#include <string.h>13#include <time.h>14#include <pthread.h>15#include <stdint.h>16#include <sys/shm.h>1718#include "futextest.h"19#include "futex2test.h"20#include "../../kselftest_harness.h"2122#define WAKE_WAIT_US 1000023#define NR_FUTEXES 3024static struct futex_waitv waitv[NR_FUTEXES];25u_int32_t futexes[NR_FUTEXES] = {0};2627void *waiterfn(void *arg)28{29struct timespec to;30int res;3132/* setting absolute timeout for futex2 */33if (clock_gettime(CLOCK_MONOTONIC, &to))34ksft_exit_fail_msg("gettime64 failed\n");3536to.tv_sec++;3738res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);39if (res < 0) {40ksft_test_result_fail("futex_waitv returned: %d %s\n",41errno, strerror(errno));42} else if (res != NR_FUTEXES - 1) {43ksft_test_result_fail("futex_waitv returned: %d, expecting %d\n",44res, NR_FUTEXES - 1);45}4647return NULL;48}4950TEST(private_waitv)51{52pthread_t waiter;53int res, i;5455for (i = 0; i < NR_FUTEXES; i++) {56waitv[i].uaddr = (uintptr_t)&futexes[i];57waitv[i].flags = FUTEX_32 | FUTEX_PRIVATE_FLAG;58waitv[i].val = 0;59waitv[i].__reserved = 0;60}6162/* Private waitv */63if (pthread_create(&waiter, NULL, waiterfn, NULL))64ksft_exit_fail_msg("pthread_create failed\n");6566usleep(WAKE_WAIT_US);6768res = futex_wake(u64_to_ptr(waitv[NR_FUTEXES - 1].uaddr), 1, FUTEX_PRIVATE_FLAG);69if (res != 1) {70ksft_test_result_fail("futex_wake private returned: %d %s\n",71res ? errno : res,72res ? strerror(errno) : "");73} else {74ksft_test_result_pass("futex_waitv private\n");75}76}7778TEST(shared_waitv)79{80pthread_t waiter;81int res, i;8283/* Shared waitv */84for (i = 0; i < NR_FUTEXES; i++) {85int shm_id = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666);8687if (shm_id < 0) {88perror("shmget");89exit(1);90}9192unsigned int *shared_data = shmat(shm_id, NULL, 0);9394*shared_data = 0;95waitv[i].uaddr = (uintptr_t)shared_data;96waitv[i].flags = FUTEX_32;97waitv[i].val = 0;98waitv[i].__reserved = 0;99}100101if (pthread_create(&waiter, NULL, waiterfn, NULL))102ksft_exit_fail_msg("pthread_create failed\n");103104usleep(WAKE_WAIT_US);105106res = futex_wake(u64_to_ptr(waitv[NR_FUTEXES - 1].uaddr), 1, 0);107if (res != 1) {108ksft_test_result_fail("futex_wake shared returned: %d %s\n",109res ? errno : res,110res ? strerror(errno) : "");111} else {112ksft_test_result_pass("futex_waitv shared\n");113}114115for (i = 0; i < NR_FUTEXES; i++)116shmdt(u64_to_ptr(waitv[i].uaddr));117}118119TEST(invalid_flag)120{121struct timespec to;122int res;123124/* Testing a waiter without FUTEX_32 flag */125waitv[0].flags = FUTEX_PRIVATE_FLAG;126127if (clock_gettime(CLOCK_MONOTONIC, &to))128ksft_exit_fail_msg("gettime64 failed\n");129130to.tv_sec++;131132res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);133if (res == EINVAL) {134ksft_test_result_fail("futex_waitv private returned: %d %s\n",135res ? errno : res,136res ? strerror(errno) : "");137} else {138ksft_test_result_pass("futex_waitv without FUTEX_32\n");139}140}141142TEST(unaligned_address)143{144struct timespec to;145int res;146147/* Testing a waiter with an unaligned address */148waitv[0].flags = FUTEX_PRIVATE_FLAG | FUTEX_32;149waitv[0].uaddr = 1;150151if (clock_gettime(CLOCK_MONOTONIC, &to))152ksft_exit_fail_msg("gettime64 failed\n");153154to.tv_sec++;155156res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);157if (res == EINVAL) {158ksft_test_result_fail("futex_wake private returned: %d %s\n",159res ? errno : res,160res ? strerror(errno) : "");161} else {162ksft_test_result_pass("futex_waitv with an unaligned address\n");163}164}165166TEST(null_address)167{168struct timespec to;169int res;170171/* Testing a NULL address for waiters.uaddr */172waitv[0].uaddr = 0x00000000;173174if (clock_gettime(CLOCK_MONOTONIC, &to))175ksft_exit_fail_msg("gettime64 failed\n");176177to.tv_sec++;178179res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);180if (res == EINVAL) {181ksft_test_result_fail("futex_waitv private returned: %d %s\n",182res ? errno : res,183res ? strerror(errno) : "");184} else {185ksft_test_result_pass("futex_waitv NULL address in waitv.uaddr\n");186}187188/* Testing a NULL address for *waiters */189if (clock_gettime(CLOCK_MONOTONIC, &to))190ksft_exit_fail_msg("gettime64 failed\n");191192to.tv_sec++;193194res = futex_waitv(NULL, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);195if (res == EINVAL) {196ksft_test_result_fail("futex_waitv private returned: %d %s\n",197res ? errno : res,198res ? strerror(errno) : "");199} else {200ksft_test_result_pass("futex_waitv NULL address in *waiters\n");201}202}203204TEST(invalid_clockid)205{206struct timespec to;207int res;208209/* Testing an invalid clockid */210if (clock_gettime(CLOCK_MONOTONIC, &to))211ksft_exit_fail_msg("gettime64 failed\n");212213to.tv_sec++;214215res = futex_waitv(NULL, NR_FUTEXES, 0, &to, CLOCK_TAI);216if (res == EINVAL) {217ksft_test_result_fail("futex_waitv private returned: %d %s\n",218res ? errno : res,219res ? strerror(errno) : "");220} else {221ksft_test_result_pass("futex_waitv invalid clockid\n");222}223}224225TEST_HARNESS_MAIN226227228