linux/tools/testing/selftests/membarrier/membarrier_test_impl.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#define _GNU_SOURCE
   3#include <linux/membarrier.h>
   4#include <syscall.h>
   5#include <stdio.h>
   6#include <errno.h>
   7#include <string.h>
   8#include <pthread.h>
   9
  10#include "../kselftest.h"
  11
  12static int sys_membarrier(int cmd, int flags)
  13{
  14        return syscall(__NR_membarrier, cmd, flags);
  15}
  16
  17static int test_membarrier_cmd_fail(void)
  18{
  19        int cmd = -1, flags = 0;
  20        const char *test_name = "sys membarrier invalid command";
  21
  22        if (sys_membarrier(cmd, flags) != -1) {
  23                ksft_exit_fail_msg(
  24                        "%s test: command = %d, flags = %d. Should fail, but passed\n",
  25                        test_name, cmd, flags);
  26        }
  27        if (errno != EINVAL) {
  28                ksft_exit_fail_msg(
  29                        "%s test: flags = %d. Should return (%d: \"%s\"), but returned (%d: \"%s\").\n",
  30                        test_name, flags, EINVAL, strerror(EINVAL),
  31                        errno, strerror(errno));
  32        }
  33
  34        ksft_test_result_pass(
  35                "%s test: command = %d, flags = %d, errno = %d. Failed as expected\n",
  36                test_name, cmd, flags, errno);
  37        return 0;
  38}
  39
  40static int test_membarrier_flags_fail(void)
  41{
  42        int cmd = MEMBARRIER_CMD_QUERY, flags = 1;
  43        const char *test_name = "sys membarrier MEMBARRIER_CMD_QUERY invalid flags";
  44
  45        if (sys_membarrier(cmd, flags) != -1) {
  46                ksft_exit_fail_msg(
  47                        "%s test: flags = %d. Should fail, but passed\n",
  48                        test_name, flags);
  49        }
  50        if (errno != EINVAL) {
  51                ksft_exit_fail_msg(
  52                        "%s test: flags = %d. Should return (%d: \"%s\"), but returned (%d: \"%s\").\n",
  53                        test_name, flags, EINVAL, strerror(EINVAL),
  54                        errno, strerror(errno));
  55        }
  56
  57        ksft_test_result_pass(
  58                "%s test: flags = %d, errno = %d. Failed as expected\n",
  59                test_name, flags, errno);
  60        return 0;
  61}
  62
  63static int test_membarrier_global_success(void)
  64{
  65        int cmd = MEMBARRIER_CMD_GLOBAL, flags = 0;
  66        const char *test_name = "sys membarrier MEMBARRIER_CMD_GLOBAL";
  67
  68        if (sys_membarrier(cmd, flags) != 0) {
  69                ksft_exit_fail_msg(
  70                        "%s test: flags = %d, errno = %d\n",
  71                        test_name, flags, errno);
  72        }
  73
  74        ksft_test_result_pass(
  75                "%s test: flags = %d\n", test_name, flags);
  76        return 0;
  77}
  78
  79static int test_membarrier_private_expedited_fail(void)
  80{
  81        int cmd = MEMBARRIER_CMD_PRIVATE_EXPEDITED, flags = 0;
  82        const char *test_name = "sys membarrier MEMBARRIER_CMD_PRIVATE_EXPEDITED not registered failure";
  83
  84        if (sys_membarrier(cmd, flags) != -1) {
  85                ksft_exit_fail_msg(
  86                        "%s test: flags = %d. Should fail, but passed\n",
  87                        test_name, flags);
  88        }
  89        if (errno != EPERM) {
  90                ksft_exit_fail_msg(
  91                        "%s test: flags = %d. Should return (%d: \"%s\"), but returned (%d: \"%s\").\n",
  92                        test_name, flags, EPERM, strerror(EPERM),
  93                        errno, strerror(errno));
  94        }
  95
  96        ksft_test_result_pass(
  97                "%s test: flags = %d, errno = %d\n",
  98                test_name, flags, errno);
  99        return 0;
 100}
 101
 102static int test_membarrier_register_private_expedited_success(void)
 103{
 104        int cmd = MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, flags = 0;
 105        const char *test_name = "sys membarrier MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED";
 106
 107        if (sys_membarrier(cmd, flags) != 0) {
 108                ksft_exit_fail_msg(
 109                        "%s test: flags = %d, errno = %d\n",
 110                        test_name, flags, errno);
 111        }
 112
 113        ksft_test_result_pass(
 114                "%s test: flags = %d\n",
 115                test_name, flags);
 116        return 0;
 117}
 118
 119static int test_membarrier_private_expedited_success(void)
 120{
 121        int cmd = MEMBARRIER_CMD_PRIVATE_EXPEDITED, flags = 0;
 122        const char *test_name = "sys membarrier MEMBARRIER_CMD_PRIVATE_EXPEDITED";
 123
 124        if (sys_membarrier(cmd, flags) != 0) {
 125                ksft_exit_fail_msg(
 126                        "%s test: flags = %d, errno = %d\n",
 127                        test_name, flags, errno);
 128        }
 129
 130        ksft_test_result_pass(
 131                "%s test: flags = %d\n",
 132                test_name, flags);
 133        return 0;
 134}
 135
 136static int test_membarrier_private_expedited_sync_core_fail(void)
 137{
 138        int cmd = MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE, flags = 0;
 139        const char *test_name = "sys membarrier MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE not registered failure";
 140
 141        if (sys_membarrier(cmd, flags) != -1) {
 142                ksft_exit_fail_msg(
 143                        "%s test: flags = %d. Should fail, but passed\n",
 144                        test_name, flags);
 145        }
 146        if (errno != EPERM) {
 147                ksft_exit_fail_msg(
 148                        "%s test: flags = %d. Should return (%d: \"%s\"), but returned (%d: \"%s\").\n",
 149                        test_name, flags, EPERM, strerror(EPERM),
 150                        errno, strerror(errno));
 151        }
 152
 153        ksft_test_result_pass(
 154                "%s test: flags = %d, errno = %d\n",
 155                test_name, flags, errno);
 156        return 0;
 157}
 158
 159static int test_membarrier_register_private_expedited_sync_core_success(void)
 160{
 161        int cmd = MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE, flags = 0;
 162        const char *test_name = "sys membarrier MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE";
 163
 164        if (sys_membarrier(cmd, flags) != 0) {
 165                ksft_exit_fail_msg(
 166                        "%s test: flags = %d, errno = %d\n",
 167                        test_name, flags, errno);
 168        }
 169
 170        ksft_test_result_pass(
 171                "%s test: flags = %d\n",
 172                test_name, flags);
 173        return 0;
 174}
 175
 176static int test_membarrier_private_expedited_sync_core_success(void)
 177{
 178        int cmd = MEMBARRIER_CMD_PRIVATE_EXPEDITED, flags = 0;
 179        const char *test_name = "sys membarrier MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE";
 180
 181        if (sys_membarrier(cmd, flags) != 0) {
 182                ksft_exit_fail_msg(
 183                        "%s test: flags = %d, errno = %d\n",
 184                        test_name, flags, errno);
 185        }
 186
 187        ksft_test_result_pass(
 188                "%s test: flags = %d\n",
 189                test_name, flags);
 190        return 0;
 191}
 192
 193static int test_membarrier_register_global_expedited_success(void)
 194{
 195        int cmd = MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED, flags = 0;
 196        const char *test_name = "sys membarrier MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED";
 197
 198        if (sys_membarrier(cmd, flags) != 0) {
 199                ksft_exit_fail_msg(
 200                        "%s test: flags = %d, errno = %d\n",
 201                        test_name, flags, errno);
 202        }
 203
 204        ksft_test_result_pass(
 205                "%s test: flags = %d\n",
 206                test_name, flags);
 207        return 0;
 208}
 209
 210static int test_membarrier_global_expedited_success(void)
 211{
 212        int cmd = MEMBARRIER_CMD_GLOBAL_EXPEDITED, flags = 0;
 213        const char *test_name = "sys membarrier MEMBARRIER_CMD_GLOBAL_EXPEDITED";
 214
 215        if (sys_membarrier(cmd, flags) != 0) {
 216                ksft_exit_fail_msg(
 217                        "%s test: flags = %d, errno = %d\n",
 218                        test_name, flags, errno);
 219        }
 220
 221        ksft_test_result_pass(
 222                "%s test: flags = %d\n",
 223                test_name, flags);
 224        return 0;
 225}
 226
 227static int test_membarrier_fail(void)
 228{
 229        int status;
 230
 231        status = test_membarrier_cmd_fail();
 232        if (status)
 233                return status;
 234        status = test_membarrier_flags_fail();
 235        if (status)
 236                return status;
 237        status = test_membarrier_private_expedited_fail();
 238        if (status)
 239                return status;
 240        status = sys_membarrier(MEMBARRIER_CMD_QUERY, 0);
 241        if (status < 0) {
 242                ksft_test_result_fail("sys_membarrier() failed\n");
 243                return status;
 244        }
 245        if (status & MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE) {
 246                status = test_membarrier_private_expedited_sync_core_fail();
 247                if (status)
 248                        return status;
 249        }
 250        return 0;
 251}
 252
 253static int test_membarrier_success(void)
 254{
 255        int status;
 256
 257        status = test_membarrier_global_success();
 258        if (status)
 259                return status;
 260        status = test_membarrier_register_private_expedited_success();
 261        if (status)
 262                return status;
 263        status = test_membarrier_private_expedited_success();
 264        if (status)
 265                return status;
 266        status = sys_membarrier(MEMBARRIER_CMD_QUERY, 0);
 267        if (status < 0) {
 268                ksft_test_result_fail("sys_membarrier() failed\n");
 269                return status;
 270        }
 271        if (status & MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE) {
 272                status = test_membarrier_register_private_expedited_sync_core_success();
 273                if (status)
 274                        return status;
 275                status = test_membarrier_private_expedited_sync_core_success();
 276                if (status)
 277                        return status;
 278        }
 279        /*
 280         * It is valid to send a global membarrier from a non-registered
 281         * process.
 282         */
 283        status = test_membarrier_global_expedited_success();
 284        if (status)
 285                return status;
 286        status = test_membarrier_register_global_expedited_success();
 287        if (status)
 288                return status;
 289        status = test_membarrier_global_expedited_success();
 290        if (status)
 291                return status;
 292        return 0;
 293}
 294
 295static int test_membarrier_query(void)
 296{
 297        int flags = 0, ret;
 298
 299        ret = sys_membarrier(MEMBARRIER_CMD_QUERY, flags);
 300        if (ret < 0) {
 301                if (errno == ENOSYS) {
 302                        /*
 303                         * It is valid to build a kernel with
 304                         * CONFIG_MEMBARRIER=n. However, this skips the tests.
 305                         */
 306                        ksft_exit_skip(
 307                                "sys membarrier (CONFIG_MEMBARRIER) is disabled.\n");
 308                }
 309                ksft_exit_fail_msg("sys_membarrier() failed\n");
 310        }
 311        if (!(ret & MEMBARRIER_CMD_GLOBAL))
 312                ksft_exit_skip(
 313                        "sys_membarrier unsupported: CMD_GLOBAL not found.\n");
 314
 315        ksft_test_result_pass("sys_membarrier available\n");
 316        return 0;
 317}
 318