xref: /freebsd/tools/test/stress2/misc/tmpfs26.sh (revision 347dd0539f3a75fdf2128dd4620ca99e96f311e9)
1#!/bin/sh
2
3# Bug 272678 - VFS: Incorrect data in read from concurrent write
4
5# Test scenario by: Kristian Nielsen <knielsen@knielsen-hq.org>
6
7. ../default.cfg
8
9prog=$(basename "$0" .sh)
10cat > /tmp/$prog.c <<EOF
11#include <stdio.h>
12#include <pthread.h>
13#include <sys/select.h>
14#include <unistd.h>
15#include <stdlib.h>
16#include <string.h>
17
18#define MAGIC 0x42
19
20const char *filename = "testfile.bin";
21
22static FILE *write_file;
23static FILE *read_file;
24static pthread_mutex_t write_mutex;
25static pthread_cond_t write_cond;
26static pthread_mutex_t read_mutex;
27static pthread_cond_t read_cond;
28static pthread_mutex_t state_mutex;
29static pthread_cond_t state_cond;
30static int write_state;
31static int read_state;
32
33void *
34writer_routine(void *arg __unused)
35{
36	unsigned char data[44];
37
38	memset(data, MAGIC, sizeof(data));
39	pthread_mutex_lock(&write_mutex);
40
41	for (;;) {
42
43		while (write_state != 1)
44			pthread_cond_wait(&write_cond, &write_mutex);
45
46		fwrite(data, 1, sizeof(data), write_file);
47		fflush(write_file);
48
49		pthread_mutex_lock(&state_mutex);
50		write_state = 2;
51		pthread_cond_signal(&state_cond);
52		pthread_mutex_unlock(&state_mutex);
53	}
54}
55
56void *
57reader_routine(void *arg __unused)
58{
59
60	for (;;) {
61		unsigned char buf[387];
62		int len;
63
64		while (read_state != 1)
65			pthread_cond_wait(&read_cond, &read_mutex);
66
67		len = fread(buf, 1, sizeof(buf), read_file);
68		if (len < (int)sizeof(buf) && ferror(read_file)) {
69			perror(" read file");
70			exit(1);
71		}
72		for (int i = 0; i < len; ++i) {
73			if (buf[i] != MAGIC) {
74				fprintf(stderr, "ERROR! invalid value read 0x%2x at %d of %d, pos %ld\n",
75						buf[i], i, len, ftell(read_file));
76				exit(126);
77			}
78		}
79
80		pthread_mutex_lock(&state_mutex);
81		read_state = 2;
82		pthread_cond_signal(&state_cond);
83		pthread_mutex_unlock(&state_mutex);
84	}
85}
86
87void
88create_threads(void)
89{
90	pthread_t write_thread_id, read_thread_id;
91	pthread_attr_t attr;
92
93	pthread_mutex_init(&write_mutex, NULL);
94	pthread_mutex_init(&read_mutex, NULL);
95	pthread_mutex_init(&state_mutex, NULL);
96	pthread_cond_init(&write_cond, NULL);
97	pthread_cond_init(&read_cond, NULL);
98	pthread_cond_init(&state_cond, NULL);
99
100	pthread_attr_init(&attr);
101	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
102	pthread_create(&write_thread_id, &attr, writer_routine, NULL);
103	pthread_create(&read_thread_id, &attr, reader_routine, NULL);
104}
105
106int
107main(int argc, char *argv[])
108{
109	int num_iter = 1000;
110	int i;
111	unsigned char buf[343];
112
113	if (argc >= 2)
114		num_iter = atoi(argv[1]);
115
116	write_state = 0;
117	read_state = 0;
118
119	create_threads();
120	memset(buf, MAGIC, sizeof(buf));
121
122	for (i = 0; i < num_iter; ++i) {
123		/* Write the first part of the file. */
124		pthread_mutex_lock(&write_mutex);
125		write_file = fopen(filename, "wb");
126		if (!write_file) {
127			perror(" open file");
128			exit(1);
129		}
130		fwrite(buf, 1, sizeof(buf), write_file);
131		fflush(write_file);
132
133		/* Open a read handle on the file. */
134		pthread_mutex_lock(&read_mutex);
135		read_file = fopen(filename, "rb");
136		if (!read_file) {
137			perror(" open read file");
138			exit(1);
139		}
140
141		write_state = 1;
142		read_state = 1;
143		pthread_cond_signal(&write_cond);
144		pthread_mutex_unlock(&write_mutex);
145		pthread_cond_signal(&read_cond);
146		pthread_mutex_unlock(&read_mutex);
147
148		pthread_mutex_lock(&state_mutex);
149		while (write_state != 2 || read_state != 2)
150			pthread_cond_wait(&state_cond, &state_mutex);
151		pthread_mutex_unlock(&state_mutex);
152
153		/* Close and remove the file, ready for another iteration. */
154		pthread_mutex_lock(&write_mutex);
155		fclose(write_file);
156		write_state = 0;
157		pthread_mutex_unlock(&write_mutex);
158
159		pthread_mutex_lock(&read_mutex);
160		fclose(read_file);
161		read_state = 0;
162		pthread_mutex_unlock(&read_mutex);
163
164		unlink(filename);
165	}
166
167	return (0);
168}
169EOF
170mycc -o /tmp/$prog -Wall -Wextra -O2 /tmp/$prog.c -lpthread || exit 1
171
172mount -t tmpfs dummy $mntpoint
173cd $mntpoint
174/tmp/$prog; s=$?
175cd -
176umount $mntpoint
177
178rm /tmp/$prog /tmp/$prog.c
179exit $s
180