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