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