cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

futex_wait.c (3911B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright Collabora Ltd., 2021
      4 *
      5 * futex cmp requeue test by André Almeida <andrealmeid@collabora.com>
      6 */
      7
      8#include <pthread.h>
      9#include <sys/shm.h>
     10#include <sys/mman.h>
     11#include <fcntl.h>
     12#include "logging.h"
     13#include "futextest.h"
     14
     15#define TEST_NAME "futex-wait"
     16#define timeout_ns  30000000
     17#define WAKE_WAIT_US 10000
     18#define SHM_PATH "futex_shm_file"
     19
     20void *futex;
     21
     22void usage(char *prog)
     23{
     24	printf("Usage: %s\n", prog);
     25	printf("  -c	Use color\n");
     26	printf("  -h	Display this help message\n");
     27	printf("  -v L	Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n",
     28	       VQUIET, VCRITICAL, VINFO);
     29}
     30
     31static void *waiterfn(void *arg)
     32{
     33	struct timespec to;
     34	unsigned int flags = 0;
     35
     36	if (arg)
     37		flags = *((unsigned int *) arg);
     38
     39	to.tv_sec = 0;
     40	to.tv_nsec = timeout_ns;
     41
     42	if (futex_wait(futex, 0, &to, flags))
     43		printf("waiter failed errno %d\n", errno);
     44
     45	return NULL;
     46}
     47
     48int main(int argc, char *argv[])
     49{
     50	int res, ret = RET_PASS, fd, c, shm_id;
     51	u_int32_t f_private = 0, *shared_data;
     52	unsigned int flags = FUTEX_PRIVATE_FLAG;
     53	pthread_t waiter;
     54	void *shm;
     55
     56	futex = &f_private;
     57
     58	while ((c = getopt(argc, argv, "cht:v:")) != -1) {
     59		switch (c) {
     60		case 'c':
     61			log_color(1);
     62			break;
     63		case 'h':
     64			usage(basename(argv[0]));
     65			exit(0);
     66		case 'v':
     67			log_verbosity(atoi(optarg));
     68			break;
     69		default:
     70			usage(basename(argv[0]));
     71			exit(1);
     72		}
     73	}
     74
     75	ksft_print_header();
     76	ksft_set_plan(3);
     77	ksft_print_msg("%s: Test futex_wait\n", basename(argv[0]));
     78
     79	/* Testing a private futex */
     80	info("Calling private futex_wait on futex: %p\n", futex);
     81	if (pthread_create(&waiter, NULL, waiterfn, (void *) &flags))
     82		error("pthread_create failed\n", errno);
     83
     84	usleep(WAKE_WAIT_US);
     85
     86	info("Calling private futex_wake on futex: %p\n", futex);
     87	res = futex_wake(futex, 1, FUTEX_PRIVATE_FLAG);
     88	if (res != 1) {
     89		ksft_test_result_fail("futex_wake private returned: %d %s\n",
     90				      errno, strerror(errno));
     91		ret = RET_FAIL;
     92	} else {
     93		ksft_test_result_pass("futex_wake private succeeds\n");
     94	}
     95
     96	/* Testing an anon page shared memory */
     97	shm_id = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666);
     98	if (shm_id < 0) {
     99		perror("shmget");
    100		exit(1);
    101	}
    102
    103	shared_data = shmat(shm_id, NULL, 0);
    104
    105	*shared_data = 0;
    106	futex = shared_data;
    107
    108	info("Calling shared (page anon) futex_wait on futex: %p\n", futex);
    109	if (pthread_create(&waiter, NULL, waiterfn, NULL))
    110		error("pthread_create failed\n", errno);
    111
    112	usleep(WAKE_WAIT_US);
    113
    114	info("Calling shared (page anon) futex_wake on futex: %p\n", futex);
    115	res = futex_wake(futex, 1, 0);
    116	if (res != 1) {
    117		ksft_test_result_fail("futex_wake shared (page anon) returned: %d %s\n",
    118				      errno, strerror(errno));
    119		ret = RET_FAIL;
    120	} else {
    121		ksft_test_result_pass("futex_wake shared (page anon) succeeds\n");
    122	}
    123
    124
    125	/* Testing a file backed shared memory */
    126	fd = open(SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
    127	if (fd < 0) {
    128		perror("open");
    129		exit(1);
    130	}
    131
    132	if (ftruncate(fd, sizeof(f_private))) {
    133		perror("ftruncate");
    134		exit(1);
    135	}
    136
    137	shm = mmap(NULL, sizeof(f_private), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    138	if (shm == MAP_FAILED) {
    139		perror("mmap");
    140		exit(1);
    141	}
    142
    143	memcpy(shm, &f_private, sizeof(f_private));
    144
    145	futex = shm;
    146
    147	info("Calling shared (file backed) futex_wait on futex: %p\n", futex);
    148	if (pthread_create(&waiter, NULL, waiterfn, NULL))
    149		error("pthread_create failed\n", errno);
    150
    151	usleep(WAKE_WAIT_US);
    152
    153	info("Calling shared (file backed) futex_wake on futex: %p\n", futex);
    154	res = futex_wake(shm, 1, 0);
    155	if (res != 1) {
    156		ksft_test_result_fail("futex_wake shared (file backed) returned: %d %s\n",
    157				      errno, strerror(errno));
    158		ret = RET_FAIL;
    159	} else {
    160		ksft_test_result_pass("futex_wake shared (file backed) succeeds\n");
    161	}
    162
    163	/* Freeing resources */
    164	shmdt(shared_data);
    165	munmap(shm, sizeof(f_private));
    166	remove(SHM_PATH);
    167	close(fd);
    168
    169	ksft_print_cnts();
    170	return ret;
    171}