1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2017 Red Hat Inc. All Rights Reserved. 4f08c3bdfSopenharmony_ci * Author: Xiong Zhou <xzhou@redhat.com> 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * This is testing OFD locks racing with POSIX locks: 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * OFD read lock vs OFD write lock 9f08c3bdfSopenharmony_ci * OFD read lock vs POSIX write lock 10f08c3bdfSopenharmony_ci * OFD write lock vs POSIX write lock 11f08c3bdfSopenharmony_ci * OFD write lock vs POSIX read lock 12f08c3bdfSopenharmony_ci * OFD write lock vs OFD write lock 13f08c3bdfSopenharmony_ci * 14f08c3bdfSopenharmony_ci * OFD r/w locks vs POSIX write locks 15f08c3bdfSopenharmony_ci * OFD r/w locks vs POSIX read locks 16f08c3bdfSopenharmony_ci * 17f08c3bdfSopenharmony_ci * For example: 18f08c3bdfSopenharmony_ci * 19f08c3bdfSopenharmony_ci * Init an file with preset values. 20f08c3bdfSopenharmony_ci * 21f08c3bdfSopenharmony_ci * Threads acquire OFD READ locks to read a 4k section start from 0; 22f08c3bdfSopenharmony_ci * checking data read back, there should not be any surprise 23f08c3bdfSopenharmony_ci * values and data should be consistent in a 1k block. 24f08c3bdfSopenharmony_ci * 25f08c3bdfSopenharmony_ci * Threads acquire OFD WRITE locks to write a 4k section start from 1k, 26f08c3bdfSopenharmony_ci * writing different values in different threads. 27f08c3bdfSopenharmony_ci * 28f08c3bdfSopenharmony_ci * Check file data after racing, there should not be any surprise values 29f08c3bdfSopenharmony_ci * and data should be consistent in a 1k block. 30f08c3bdfSopenharmony_ci */ 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci#include <sys/types.h> 33f08c3bdfSopenharmony_ci#include <sys/stat.h> 34f08c3bdfSopenharmony_ci#include <unistd.h> 35f08c3bdfSopenharmony_ci#include <stdio.h> 36f08c3bdfSopenharmony_ci#include <stdlib.h> 37f08c3bdfSopenharmony_ci#include <pthread.h> 38f08c3bdfSopenharmony_ci#include <sched.h> 39f08c3bdfSopenharmony_ci#include <errno.h> 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ci#include "lapi/fcntl.h" 42f08c3bdfSopenharmony_ci#include "tst_safe_pthread.h" 43f08c3bdfSopenharmony_ci#include "tst_test.h" 44f08c3bdfSopenharmony_ci#include "fcntl_common.h" 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_cistatic int thread_cnt; 47f08c3bdfSopenharmony_cistatic int fail_flag = 0; 48f08c3bdfSopenharmony_cistatic volatile int loop_flag = 1; 49f08c3bdfSopenharmony_cistatic const int max_thread_cnt = 32; 50f08c3bdfSopenharmony_cistatic const char fname[] = "tst_ofd_posix_locks"; 51f08c3bdfSopenharmony_cistatic const long write_size = 4096; 52f08c3bdfSopenharmony_cistatic pthread_barrier_t barrier; 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_cistruct param { 55f08c3bdfSopenharmony_ci long offset; 56f08c3bdfSopenharmony_ci long length; 57f08c3bdfSopenharmony_ci long cnt; 58f08c3bdfSopenharmony_ci}; 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_cistatic void setup(void) 61f08c3bdfSopenharmony_ci{ 62f08c3bdfSopenharmony_ci thread_cnt = tst_ncpus_conf() * 3; 63f08c3bdfSopenharmony_ci if (thread_cnt > max_thread_cnt) 64f08c3bdfSopenharmony_ci thread_cnt = max_thread_cnt; 65f08c3bdfSopenharmony_ci} 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci/* OFD write lock writing data*/ 68f08c3bdfSopenharmony_cistatic void *fn_ofd_w(void *arg) 69f08c3bdfSopenharmony_ci{ 70f08c3bdfSopenharmony_ci struct param *pa = arg; 71f08c3bdfSopenharmony_ci unsigned char buf[pa->length]; 72f08c3bdfSopenharmony_ci int fd = SAFE_OPEN(fname, O_RDWR); 73f08c3bdfSopenharmony_ci long wt = pa->cnt; 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci struct flock lck = { 76f08c3bdfSopenharmony_ci .l_whence = SEEK_SET, 77f08c3bdfSopenharmony_ci .l_start = pa->offset, 78f08c3bdfSopenharmony_ci .l_len = pa->length, 79f08c3bdfSopenharmony_ci .l_pid = 0, 80f08c3bdfSopenharmony_ci }; 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_ci do { 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci memset(buf, wt, pa->length); 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_ci lck.l_type = F_WRLCK; 87f08c3bdfSopenharmony_ci FCNTL_COMPAT(fd, F_OFD_SETLKW, &lck); 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci SAFE_LSEEK(fd, pa->offset, SEEK_SET); 90f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ALL, fd, buf, pa->length); 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_ci lck.l_type = F_UNLCK; 93f08c3bdfSopenharmony_ci FCNTL_COMPAT(fd, F_OFD_SETLKW, &lck); 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci wt++; 96f08c3bdfSopenharmony_ci if (wt >= 255) 97f08c3bdfSopenharmony_ci wt = pa->cnt; 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_ci sched_yield(); 100f08c3bdfSopenharmony_ci } while (loop_flag); 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci pthread_barrier_wait(&barrier); 103f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 104f08c3bdfSopenharmony_ci return NULL; 105f08c3bdfSopenharmony_ci} 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci/* POSIX write lock writing data*/ 108f08c3bdfSopenharmony_cistatic void *fn_posix_w(void *arg) 109f08c3bdfSopenharmony_ci{ 110f08c3bdfSopenharmony_ci struct param *pa = arg; 111f08c3bdfSopenharmony_ci unsigned char buf[pa->length]; 112f08c3bdfSopenharmony_ci int fd = SAFE_OPEN(fname, O_RDWR); 113f08c3bdfSopenharmony_ci long wt = pa->cnt; 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci struct flock lck = { 116f08c3bdfSopenharmony_ci .l_whence = SEEK_SET, 117f08c3bdfSopenharmony_ci .l_start = pa->offset, 118f08c3bdfSopenharmony_ci .l_len = pa->length, 119f08c3bdfSopenharmony_ci }; 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci do { 122f08c3bdfSopenharmony_ci 123f08c3bdfSopenharmony_ci memset(buf, wt, pa->length); 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci lck.l_type = F_WRLCK; 126f08c3bdfSopenharmony_ci SAFE_FCNTL(fd, F_SETLKW, &lck); 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_ci SAFE_LSEEK(fd, pa->offset, SEEK_SET); 129f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ALL, fd, buf, pa->length); 130f08c3bdfSopenharmony_ci 131f08c3bdfSopenharmony_ci lck.l_type = F_UNLCK; 132f08c3bdfSopenharmony_ci SAFE_FCNTL(fd, F_SETLKW, &lck); 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci wt++; 135f08c3bdfSopenharmony_ci if (wt >= 255) 136f08c3bdfSopenharmony_ci wt = pa->cnt; 137f08c3bdfSopenharmony_ci 138f08c3bdfSopenharmony_ci sched_yield(); 139f08c3bdfSopenharmony_ci } while (loop_flag); 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci pthread_barrier_wait(&barrier); 142f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 143f08c3bdfSopenharmony_ci return NULL; 144f08c3bdfSopenharmony_ci} 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_ci/* OFD read lock reading data*/ 147f08c3bdfSopenharmony_cistatic void *fn_ofd_r(void *arg) 148f08c3bdfSopenharmony_ci{ 149f08c3bdfSopenharmony_ci struct param *pa = arg; 150f08c3bdfSopenharmony_ci unsigned char buf[pa->length]; 151f08c3bdfSopenharmony_ci int i; 152f08c3bdfSopenharmony_ci int fd = SAFE_OPEN(fname, O_RDWR); 153f08c3bdfSopenharmony_ci 154f08c3bdfSopenharmony_ci struct flock lck = { 155f08c3bdfSopenharmony_ci .l_whence = SEEK_SET, 156f08c3bdfSopenharmony_ci .l_start = pa->offset, 157f08c3bdfSopenharmony_ci .l_len = pa->length, 158f08c3bdfSopenharmony_ci .l_pid = 0, 159f08c3bdfSopenharmony_ci }; 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci while (loop_flag) { 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ci memset(buf, 0, pa->length); 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_ci lck.l_type = F_RDLCK; 166f08c3bdfSopenharmony_ci FCNTL_COMPAT(fd, F_OFD_SETLKW, &lck); 167f08c3bdfSopenharmony_ci 168f08c3bdfSopenharmony_ci /* rlock acquired */ 169f08c3bdfSopenharmony_ci SAFE_LSEEK(fd, pa->offset, SEEK_SET); 170f08c3bdfSopenharmony_ci SAFE_READ(1, fd, buf, pa->length); 171f08c3bdfSopenharmony_ci 172f08c3bdfSopenharmony_ci /* Verifying data read */ 173f08c3bdfSopenharmony_ci for (i = 0; i < pa->length; i++) { 174f08c3bdfSopenharmony_ci 175f08c3bdfSopenharmony_ci if (buf[i] < 1 || buf[i] > 254) { 176f08c3bdfSopenharmony_ci 177f08c3bdfSopenharmony_ci tst_res(TFAIL, "Unexpected data " 178f08c3bdfSopenharmony_ci "offset %ld value %d", 179f08c3bdfSopenharmony_ci pa->offset + i, buf[i]); 180f08c3bdfSopenharmony_ci fail_flag = 1; 181f08c3bdfSopenharmony_ci break; 182f08c3bdfSopenharmony_ci } 183f08c3bdfSopenharmony_ci 184f08c3bdfSopenharmony_ci int j = (i / (pa->length/4)) * pa->length/4; 185f08c3bdfSopenharmony_ci 186f08c3bdfSopenharmony_ci if (buf[i] != buf[j]) { 187f08c3bdfSopenharmony_ci 188f08c3bdfSopenharmony_ci tst_res(TFAIL, "Unexpected data " 189f08c3bdfSopenharmony_ci "offset %ld value %d", 190f08c3bdfSopenharmony_ci pa->offset + i, buf[i]); 191f08c3bdfSopenharmony_ci fail_flag = 1; 192f08c3bdfSopenharmony_ci break; 193f08c3bdfSopenharmony_ci } 194f08c3bdfSopenharmony_ci } 195f08c3bdfSopenharmony_ci 196f08c3bdfSopenharmony_ci lck.l_type = F_UNLCK; 197f08c3bdfSopenharmony_ci FCNTL_COMPAT(fd, F_OFD_SETLK, &lck); 198f08c3bdfSopenharmony_ci 199f08c3bdfSopenharmony_ci sched_yield(); 200f08c3bdfSopenharmony_ci } 201f08c3bdfSopenharmony_ci 202f08c3bdfSopenharmony_ci pthread_barrier_wait(&barrier); 203f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 204f08c3bdfSopenharmony_ci return NULL; 205f08c3bdfSopenharmony_ci} 206f08c3bdfSopenharmony_ci 207f08c3bdfSopenharmony_ci/* POSIX read lock reading data */ 208f08c3bdfSopenharmony_cistatic void *fn_posix_r(void *arg) 209f08c3bdfSopenharmony_ci{ 210f08c3bdfSopenharmony_ci struct param *pa = arg; 211f08c3bdfSopenharmony_ci unsigned char buf[pa->length]; 212f08c3bdfSopenharmony_ci int i; 213f08c3bdfSopenharmony_ci int fd = SAFE_OPEN(fname, O_RDWR); 214f08c3bdfSopenharmony_ci 215f08c3bdfSopenharmony_ci struct flock lck = { 216f08c3bdfSopenharmony_ci .l_whence = SEEK_SET, 217f08c3bdfSopenharmony_ci .l_start = pa->offset, 218f08c3bdfSopenharmony_ci .l_len = pa->length, 219f08c3bdfSopenharmony_ci }; 220f08c3bdfSopenharmony_ci 221f08c3bdfSopenharmony_ci while (loop_flag) { 222f08c3bdfSopenharmony_ci 223f08c3bdfSopenharmony_ci memset(buf, 0, pa->length); 224f08c3bdfSopenharmony_ci 225f08c3bdfSopenharmony_ci lck.l_type = F_RDLCK; 226f08c3bdfSopenharmony_ci SAFE_FCNTL(fd, F_SETLKW, &lck); 227f08c3bdfSopenharmony_ci 228f08c3bdfSopenharmony_ci /* rlock acquired */ 229f08c3bdfSopenharmony_ci SAFE_LSEEK(fd, pa->offset, SEEK_SET); 230f08c3bdfSopenharmony_ci SAFE_READ(1, fd, buf, pa->length); 231f08c3bdfSopenharmony_ci 232f08c3bdfSopenharmony_ci /* Verifying data read */ 233f08c3bdfSopenharmony_ci for (i = 0; i < pa->length; i++) { 234f08c3bdfSopenharmony_ci 235f08c3bdfSopenharmony_ci if (buf[i] < 1 || buf[i] > 254) { 236f08c3bdfSopenharmony_ci 237f08c3bdfSopenharmony_ci tst_res(TFAIL, "Unexpected data " 238f08c3bdfSopenharmony_ci "offset %ld value %d", 239f08c3bdfSopenharmony_ci pa->offset + i, buf[i]); 240f08c3bdfSopenharmony_ci fail_flag = 1; 241f08c3bdfSopenharmony_ci break; 242f08c3bdfSopenharmony_ci } 243f08c3bdfSopenharmony_ci 244f08c3bdfSopenharmony_ci int j = (i / (pa->length/4)) * pa->length/4; 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_ci if (buf[i] != buf[j]) { 247f08c3bdfSopenharmony_ci 248f08c3bdfSopenharmony_ci tst_res(TFAIL, "Unexpected data " 249f08c3bdfSopenharmony_ci "offset %ld value %d", 250f08c3bdfSopenharmony_ci pa->offset + i, buf[i]); 251f08c3bdfSopenharmony_ci fail_flag = 1; 252f08c3bdfSopenharmony_ci break; 253f08c3bdfSopenharmony_ci } 254f08c3bdfSopenharmony_ci } 255f08c3bdfSopenharmony_ci 256f08c3bdfSopenharmony_ci lck.l_type = F_UNLCK; 257f08c3bdfSopenharmony_ci SAFE_FCNTL(fd, F_SETLK, &lck); 258f08c3bdfSopenharmony_ci 259f08c3bdfSopenharmony_ci sched_yield(); 260f08c3bdfSopenharmony_ci } 261f08c3bdfSopenharmony_ci 262f08c3bdfSopenharmony_ci pthread_barrier_wait(&barrier); 263f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 264f08c3bdfSopenharmony_ci return NULL; 265f08c3bdfSopenharmony_ci} 266f08c3bdfSopenharmony_ci 267f08c3bdfSopenharmony_cistatic void *fn_dummy(void *arg) 268f08c3bdfSopenharmony_ci{ 269f08c3bdfSopenharmony_ci arg = NULL; 270f08c3bdfSopenharmony_ci 271f08c3bdfSopenharmony_ci pthread_barrier_wait(&barrier); 272f08c3bdfSopenharmony_ci return arg; 273f08c3bdfSopenharmony_ci} 274f08c3bdfSopenharmony_ci 275f08c3bdfSopenharmony_ci/* Test different functions and verify data */ 276f08c3bdfSopenharmony_cistatic void test_fn(void *f0(void *), void *f1(void *), 277f08c3bdfSopenharmony_ci void *f2(void *), const char *msg) 278f08c3bdfSopenharmony_ci{ 279f08c3bdfSopenharmony_ci int i, k, fd; 280f08c3bdfSopenharmony_ci pthread_t id0[thread_cnt]; 281f08c3bdfSopenharmony_ci pthread_t id1[thread_cnt]; 282f08c3bdfSopenharmony_ci pthread_t id2[thread_cnt]; 283f08c3bdfSopenharmony_ci struct param p0[thread_cnt]; 284f08c3bdfSopenharmony_ci struct param p1[thread_cnt]; 285f08c3bdfSopenharmony_ci struct param p2[thread_cnt]; 286f08c3bdfSopenharmony_ci unsigned char buf[write_size]; 287f08c3bdfSopenharmony_ci 288f08c3bdfSopenharmony_ci tst_res(TINFO, "%s", msg); 289f08c3bdfSopenharmony_ci 290f08c3bdfSopenharmony_ci if (tst_fill_file(fname, 1, write_size, thread_cnt + 1)) 291f08c3bdfSopenharmony_ci tst_brk(TBROK, "Failed to create tst file"); 292f08c3bdfSopenharmony_ci 293f08c3bdfSopenharmony_ci if (pthread_barrier_init(&barrier, NULL, thread_cnt*3) != 0) 294f08c3bdfSopenharmony_ci tst_brk(TBROK, "Failed to init pthread barrier"); 295f08c3bdfSopenharmony_ci 296f08c3bdfSopenharmony_ci for (i = 0; i < thread_cnt; i++) { 297f08c3bdfSopenharmony_ci 298f08c3bdfSopenharmony_ci p0[i].offset = i * write_size; 299f08c3bdfSopenharmony_ci p0[i].length = write_size; 300f08c3bdfSopenharmony_ci p0[i].cnt = i + 2; 301f08c3bdfSopenharmony_ci 302f08c3bdfSopenharmony_ci p1[i].offset = i * write_size + write_size / 4; 303f08c3bdfSopenharmony_ci p1[i].length = write_size; 304f08c3bdfSopenharmony_ci p1[i].cnt = i + 2; 305f08c3bdfSopenharmony_ci 306f08c3bdfSopenharmony_ci p2[i].offset = i * write_size + write_size / 2; 307f08c3bdfSopenharmony_ci p2[i].length = write_size; 308f08c3bdfSopenharmony_ci p2[i].cnt = i + 2; 309f08c3bdfSopenharmony_ci } 310f08c3bdfSopenharmony_ci 311f08c3bdfSopenharmony_ci fail_flag = 0; 312f08c3bdfSopenharmony_ci loop_flag = 1; 313f08c3bdfSopenharmony_ci 314f08c3bdfSopenharmony_ci for (i = 0; i < thread_cnt; i++) { 315f08c3bdfSopenharmony_ci 316f08c3bdfSopenharmony_ci SAFE_PTHREAD_CREATE(id0 + i, NULL, f0, (void *)&p0[i]); 317f08c3bdfSopenharmony_ci SAFE_PTHREAD_CREATE(id1 + i, NULL, f1, (void *)&p1[i]); 318f08c3bdfSopenharmony_ci SAFE_PTHREAD_CREATE(id2 + i, NULL, f2, (void *)&p2[i]); 319f08c3bdfSopenharmony_ci } 320f08c3bdfSopenharmony_ci 321f08c3bdfSopenharmony_ci sleep(1); 322f08c3bdfSopenharmony_ci loop_flag = 0; 323f08c3bdfSopenharmony_ci 324f08c3bdfSopenharmony_ci for (i = 0; i < thread_cnt; i++) { 325f08c3bdfSopenharmony_ci 326f08c3bdfSopenharmony_ci SAFE_PTHREAD_JOIN(id0[i], NULL); 327f08c3bdfSopenharmony_ci SAFE_PTHREAD_JOIN(id1[i], NULL); 328f08c3bdfSopenharmony_ci SAFE_PTHREAD_JOIN(id2[i], NULL); 329f08c3bdfSopenharmony_ci } 330f08c3bdfSopenharmony_ci 331f08c3bdfSopenharmony_ci fd = SAFE_OPEN(fname, O_RDONLY); 332f08c3bdfSopenharmony_ci 333f08c3bdfSopenharmony_ci for (i = 0; i < thread_cnt * 4; i++) { 334f08c3bdfSopenharmony_ci 335f08c3bdfSopenharmony_ci SAFE_READ(1, fd, buf, write_size/4); 336f08c3bdfSopenharmony_ci 337f08c3bdfSopenharmony_ci for (k = 0; k < write_size/4; k++) { 338f08c3bdfSopenharmony_ci 339f08c3bdfSopenharmony_ci if (buf[k] < 2 || buf[k] > 254) { 340f08c3bdfSopenharmony_ci 341f08c3bdfSopenharmony_ci if (i < 3 && buf[k] == 1) 342f08c3bdfSopenharmony_ci continue; 343f08c3bdfSopenharmony_ci tst_res(TFAIL, "Unexpected data " 344f08c3bdfSopenharmony_ci "offset %ld value %d", 345f08c3bdfSopenharmony_ci i * write_size / 4 + k, buf[k]); 346f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 347f08c3bdfSopenharmony_ci return; 348f08c3bdfSopenharmony_ci } 349f08c3bdfSopenharmony_ci } 350f08c3bdfSopenharmony_ci 351f08c3bdfSopenharmony_ci for (k = 1; k < write_size/4; k++) { 352f08c3bdfSopenharmony_ci 353f08c3bdfSopenharmony_ci if (buf[k] != buf[0]) { 354f08c3bdfSopenharmony_ci tst_res(TFAIL, "Unexpected block read"); 355f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 356f08c3bdfSopenharmony_ci return; 357f08c3bdfSopenharmony_ci } 358f08c3bdfSopenharmony_ci } 359f08c3bdfSopenharmony_ci } 360f08c3bdfSopenharmony_ci 361f08c3bdfSopenharmony_ci if (pthread_barrier_destroy(&barrier) != 0) 362f08c3bdfSopenharmony_ci tst_brk(TBROK, "Failed to destroy pthread barrier"); 363f08c3bdfSopenharmony_ci 364f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 365f08c3bdfSopenharmony_ci if (fail_flag == 0) 366f08c3bdfSopenharmony_ci tst_res(TPASS, "Access between threads synchronized"); 367f08c3bdfSopenharmony_ci} 368f08c3bdfSopenharmony_ci 369f08c3bdfSopenharmony_cistatic struct tcase { 370f08c3bdfSopenharmony_ci void *(*fn0)(void *); 371f08c3bdfSopenharmony_ci void *(*fn1)(void *); 372f08c3bdfSopenharmony_ci void *(*fn2)(void *); 373f08c3bdfSopenharmony_ci const char *desc; 374f08c3bdfSopenharmony_ci} tcases[] = { 375f08c3bdfSopenharmony_ci {fn_ofd_r, fn_ofd_w, fn_dummy, "OFD read lock vs OFD write lock"}, 376f08c3bdfSopenharmony_ci {fn_ofd_w, fn_posix_w, fn_dummy, "OFD write lock vs POSIX write lock"}, 377f08c3bdfSopenharmony_ci {fn_ofd_r, fn_posix_w, fn_dummy, "OFD read lock vs POSIX write lock"}, 378f08c3bdfSopenharmony_ci {fn_ofd_w, fn_posix_r, fn_dummy, "OFD write lock vs POSIX read lock"}, 379f08c3bdfSopenharmony_ci {fn_ofd_w, fn_ofd_w, fn_dummy, "OFD write lock vs OFD write lock"}, 380f08c3bdfSopenharmony_ci {fn_ofd_r, fn_ofd_w, fn_posix_w, "OFD r/w lock vs POSIX write lock"}, 381f08c3bdfSopenharmony_ci {fn_ofd_r, fn_ofd_w, fn_posix_r, "OFD r/w lock vs POSIX read lock"}, 382f08c3bdfSopenharmony_ci}; 383f08c3bdfSopenharmony_ci 384f08c3bdfSopenharmony_cistatic void tests(unsigned int i) 385f08c3bdfSopenharmony_ci{ 386f08c3bdfSopenharmony_ci test_fn(tcases[i].fn0, tcases[i].fn1, tcases[i].fn2, tcases[i].desc); 387f08c3bdfSopenharmony_ci} 388f08c3bdfSopenharmony_ci 389f08c3bdfSopenharmony_cistatic struct tst_test test = { 390f08c3bdfSopenharmony_ci .min_kver = "3.15", 391f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 392f08c3bdfSopenharmony_ci .test = tests, 393f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 394f08c3bdfSopenharmony_ci .setup = setup 395f08c3bdfSopenharmony_ci}; 396