1#define _GNU_SOURCE 2#include <linux/membarrier.h> 3#include <syscall.h> 4#include <stdio.h> 5#include <errno.h> 6#include <string.h> 7 8#include "../kselftest.h" 9 10enum test_membarrier_status { 11 TEST_MEMBARRIER_PASS = 0, 12 TEST_MEMBARRIER_FAIL, 13 TEST_MEMBARRIER_SKIP, 14}; 15 16static int sys_membarrier(int cmd, int flags) 17{ 18 return syscall(__NR_membarrier, cmd, flags); 19} 20 21static enum test_membarrier_status test_membarrier_cmd_fail(void) 22{ 23 int cmd = -1, flags = 0; 24 25 if (sys_membarrier(cmd, flags) != -1) { 26 printf("membarrier: Wrong command should fail but passed.\n"); 27 return TEST_MEMBARRIER_FAIL; 28 } 29 return TEST_MEMBARRIER_PASS; 30} 31 32static enum test_membarrier_status test_membarrier_flags_fail(void) 33{ 34 int cmd = MEMBARRIER_CMD_QUERY, flags = 1; 35 36 if (sys_membarrier(cmd, flags) != -1) { 37 printf("membarrier: Wrong flags should fail but passed.\n"); 38 return TEST_MEMBARRIER_FAIL; 39 } 40 return TEST_MEMBARRIER_PASS; 41} 42 43static enum test_membarrier_status test_membarrier_success(void) 44{ 45 int cmd = MEMBARRIER_CMD_SHARED, flags = 0; 46 47 if (sys_membarrier(cmd, flags) != 0) { 48 printf("membarrier: Executing MEMBARRIER_CMD_SHARED failed. %s.\n", 49 strerror(errno)); 50 return TEST_MEMBARRIER_FAIL; 51 } 52 53 printf("membarrier: MEMBARRIER_CMD_SHARED success.\n"); 54 return TEST_MEMBARRIER_PASS; 55} 56 57static enum test_membarrier_status test_membarrier(void) 58{ 59 enum test_membarrier_status status; 60 61 status = test_membarrier_cmd_fail(); 62 if (status) 63 return status; 64 status = test_membarrier_flags_fail(); 65 if (status) 66 return status; 67 status = test_membarrier_success(); 68 if (status) 69 return status; 70 return TEST_MEMBARRIER_PASS; 71} 72 73static enum test_membarrier_status test_membarrier_query(void) 74{ 75 int flags = 0, ret; 76 77 printf("membarrier MEMBARRIER_CMD_QUERY "); 78 ret = sys_membarrier(MEMBARRIER_CMD_QUERY, flags); 79 if (ret < 0) { 80 printf("failed. %s.\n", strerror(errno)); 81 switch (errno) { 82 case ENOSYS: 83 /* 84 * It is valid to build a kernel with 85 * CONFIG_MEMBARRIER=n. However, this skips the tests. 86 */ 87 return TEST_MEMBARRIER_SKIP; 88 case EINVAL: 89 default: 90 return TEST_MEMBARRIER_FAIL; 91 } 92 } 93 if (!(ret & MEMBARRIER_CMD_SHARED)) { 94 printf("command MEMBARRIER_CMD_SHARED is not supported.\n"); 95 return TEST_MEMBARRIER_FAIL; 96 } 97 printf("syscall available.\n"); 98 return TEST_MEMBARRIER_PASS; 99} 100 101int main(int argc, char **argv) 102{ 103 switch (test_membarrier_query()) { 104 case TEST_MEMBARRIER_FAIL: 105 return ksft_exit_fail(); 106 case TEST_MEMBARRIER_SKIP: 107 return ksft_exit_skip(); 108 } 109 switch (test_membarrier()) { 110 case TEST_MEMBARRIER_FAIL: 111 return ksft_exit_fail(); 112 case TEST_MEMBARRIER_SKIP: 113 return ksft_exit_skip(); 114 } 115 116 printf("membarrier: tests done!\n"); 117 return ksft_exit_pass(); 118} 119