brintos

brintos / linux-shallow public Read only

0
0
Text · 5.7 KiB · a94337f Raw
238 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * futex_waitv() test by André Almeida <andrealmeid@collabora.com>4 *5 * Copyright 2021 Collabora Ltd.6 */7 8#include <errno.h>9#include <error.h>10#include <getopt.h>11#include <stdio.h>12#include <stdlib.h>13#include <string.h>14#include <time.h>15#include <pthread.h>16#include <stdint.h>17#include <sys/shm.h>18#include "futextest.h"19#include "futex2test.h"20#include "logging.h"21 22#define TEST_NAME "futex-wait"23#define WAKE_WAIT_US 1000024#define NR_FUTEXES 3025static struct futex_waitv waitv[NR_FUTEXES];26u_int32_t futexes[NR_FUTEXES] = {0};27 28void usage(char *prog)29{30	printf("Usage: %s\n", prog);31	printf("  -c	Use color\n");32	printf("  -h	Display this help message\n");33	printf("  -v L	Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n",34	       VQUIET, VCRITICAL, VINFO);35}36 37void *waiterfn(void *arg)38{39	struct timespec to;40	int res;41 42	/* setting absolute timeout for futex2 */43	if (clock_gettime(CLOCK_MONOTONIC, &to))44		error("gettime64 failed\n", errno);45 46	to.tv_sec++;47 48	res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);49	if (res < 0) {50		ksft_test_result_fail("futex_waitv returned: %d %s\n",51				      errno, strerror(errno));52	} else if (res != NR_FUTEXES - 1) {53		ksft_test_result_fail("futex_waitv returned: %d, expecting %d\n",54				      res, NR_FUTEXES - 1);55	}56 57	return NULL;58}59 60int main(int argc, char *argv[])61{62	pthread_t waiter;63	int res, ret = RET_PASS;64	struct timespec to;65	int c, i;66 67	while ((c = getopt(argc, argv, "cht:v:")) != -1) {68		switch (c) {69		case 'c':70			log_color(1);71			break;72		case 'h':73			usage(basename(argv[0]));74			exit(0);75		case 'v':76			log_verbosity(atoi(optarg));77			break;78		default:79			usage(basename(argv[0]));80			exit(1);81		}82	}83 84	ksft_print_header();85	ksft_set_plan(7);86	ksft_print_msg("%s: Test FUTEX_WAITV\n",87		       basename(argv[0]));88 89	for (i = 0; i < NR_FUTEXES; i++) {90		waitv[i].uaddr = (uintptr_t)&futexes[i];91		waitv[i].flags = FUTEX_32 | FUTEX_PRIVATE_FLAG;92		waitv[i].val = 0;93		waitv[i].__reserved = 0;94	}95 96	/* Private waitv */97	if (pthread_create(&waiter, NULL, waiterfn, NULL))98		error("pthread_create failed\n", errno);99 100	usleep(WAKE_WAIT_US);101 102	res = futex_wake(u64_to_ptr(waitv[NR_FUTEXES - 1].uaddr), 1, FUTEX_PRIVATE_FLAG);103	if (res != 1) {104		ksft_test_result_fail("futex_wake private returned: %d %s\n",105				      res ? errno : res,106				      res ? strerror(errno) : "");107		ret = RET_FAIL;108	} else {109		ksft_test_result_pass("futex_waitv private\n");110	}111 112	/* Shared waitv */113	for (i = 0; i < NR_FUTEXES; i++) {114		int shm_id = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666);115 116		if (shm_id < 0) {117			perror("shmget");118			exit(1);119		}120 121		unsigned int *shared_data = shmat(shm_id, NULL, 0);122 123		*shared_data = 0;124		waitv[i].uaddr = (uintptr_t)shared_data;125		waitv[i].flags = FUTEX_32;126		waitv[i].val = 0;127		waitv[i].__reserved = 0;128	}129 130	if (pthread_create(&waiter, NULL, waiterfn, NULL))131		error("pthread_create failed\n", errno);132 133	usleep(WAKE_WAIT_US);134 135	res = futex_wake(u64_to_ptr(waitv[NR_FUTEXES - 1].uaddr), 1, 0);136	if (res != 1) {137		ksft_test_result_fail("futex_wake shared returned: %d %s\n",138				      res ? errno : res,139				      res ? strerror(errno) : "");140		ret = RET_FAIL;141	} else {142		ksft_test_result_pass("futex_waitv shared\n");143	}144 145	for (i = 0; i < NR_FUTEXES; i++)146		shmdt(u64_to_ptr(waitv[i].uaddr));147 148	/* Testing a waiter without FUTEX_32 flag */149	waitv[0].flags = FUTEX_PRIVATE_FLAG;150 151	if (clock_gettime(CLOCK_MONOTONIC, &to))152		error("gettime64 failed\n", errno);153 154	to.tv_sec++;155 156	res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);157	if (res == EINVAL) {158		ksft_test_result_fail("futex_waitv private returned: %d %s\n",159				      res ? errno : res,160				      res ? strerror(errno) : "");161		ret = RET_FAIL;162	} else {163		ksft_test_result_pass("futex_waitv without FUTEX_32\n");164	}165 166	/* Testing a waiter with an unaligned address */167	waitv[0].flags = FUTEX_PRIVATE_FLAG | FUTEX_32;168	waitv[0].uaddr = 1;169 170	if (clock_gettime(CLOCK_MONOTONIC, &to))171		error("gettime64 failed\n", errno);172 173	to.tv_sec++;174 175	res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);176	if (res == EINVAL) {177		ksft_test_result_fail("futex_wake private returned: %d %s\n",178				      res ? errno : res,179				      res ? strerror(errno) : "");180		ret = RET_FAIL;181	} else {182		ksft_test_result_pass("futex_waitv with an unaligned address\n");183	}184 185	/* Testing a NULL address for waiters.uaddr */186	waitv[0].uaddr = 0x00000000;187 188	if (clock_gettime(CLOCK_MONOTONIC, &to))189		error("gettime64 failed\n", errno);190 191	to.tv_sec++;192 193	res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);194	if (res == EINVAL) {195		ksft_test_result_fail("futex_waitv private returned: %d %s\n",196				      res ? errno : res,197				      res ? strerror(errno) : "");198		ret = RET_FAIL;199	} else {200		ksft_test_result_pass("futex_waitv NULL address in waitv.uaddr\n");201	}202 203	/* Testing a NULL address for *waiters */204	if (clock_gettime(CLOCK_MONOTONIC, &to))205		error("gettime64 failed\n", errno);206 207	to.tv_sec++;208 209	res = futex_waitv(NULL, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);210	if (res == EINVAL) {211		ksft_test_result_fail("futex_waitv private returned: %d %s\n",212				      res ? errno : res,213				      res ? strerror(errno) : "");214		ret = RET_FAIL;215	} else {216		ksft_test_result_pass("futex_waitv NULL address in *waiters\n");217	}218 219	/* Testing an invalid clockid */220	if (clock_gettime(CLOCK_MONOTONIC, &to))221		error("gettime64 failed\n", errno);222 223	to.tv_sec++;224 225	res = futex_waitv(NULL, NR_FUTEXES, 0, &to, CLOCK_TAI);226	if (res == EINVAL) {227		ksft_test_result_fail("futex_waitv private returned: %d %s\n",228				      res ? errno : res,229				      res ? strerror(errno) : "");230		ret = RET_FAIL;231	} else {232		ksft_test_result_pass("futex_waitv invalid clockid\n");233	}234 235	ksft_print_cnts();236	return ret;237}238