linux/tools/testing/selftests/futex/functional/futex_wait.c
<<
>>
Prefs
   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}
 172