1 /* The writer part of a test program for non-blocking communication.
2
3 Copyright (C) 2011-2021 Free Software Foundation, Inc.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17
18 /* This program implements 4 tests:
19
20 test == 0:
21 Test blocking write() with blocking read().
22
23 Timeline Main process Child process
24 0 s Start Start, read(10000)
25 1 s write(20000) Return from read(10000)
26 2 s Next read(10000)
27 2 s Return from write(20000) Return from read(10000)
28
29 test == 1:
30 Test non-blocking write() with blocking read().
31
32 Timeline Main process Child process
33 0 s Start Start, read(10000)
34 1 s write(20000) Return from read(10000)
35 Return with at least 10000,
36 Repeatedly continue
37 write() of the rest
38 2 s Next read(10000)
39 2 s Return from write(10000) Return from read(10000)
40
41 test == 2:
42 Test blocking write() with non-blocking read().
43
44 Timeline Main process Child process
45 0 s Start Start, read(10000)
46 repeatedly polling
47 1 s write(20000) Return from read(10000)
48 2 s Next read(10000)
49 2 s Return from write(20000) Return from read(10000)
50
51 test == 3:
52 Test non-blocking write() with non-blocking read().
53 */
54
55 #include "test-nonblocking-misc.h"
56
57 /* Execute the writer loop.
58 Returns 0 if successful, 1 if data_block_size is too small. */
59 static int
60 main_writer_loop (int test, size_t data_block_size, int fd,
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
61 bool has_large_buffer)
62 {
63 int too_small = 0;
64 unsigned char *data;
65
66 /* Set up the data to transfer. */
67 data = init_data (data_block_size);
68
69 switch (test)
70 {
71 TIMING_DECLS
72 ssize_t ret;
73
74 case 0: /* Test blocking write() with blocking read(). */
75 case 2: /* Test blocking write() with non-blocking read(). */
76 {
77 int saved_errno;
78
79 usleep (1000000);
80
81 dbgfprintf (stderr, "%s:1: >> write (%lu)\n", PROG_ROLE,
82 (unsigned long) (2 * data_block_size));
83 START_TIMING
84 ret = write (fd, data, 2 * data_block_size);
85 saved_errno = errno;
86 END_TIMING
87 dbgfprintf (stderr, "%s:1: << write -> %ld%s\n", PROG_ROLE,
88 (long) ret, dbgstrerror (ret < 0, saved_errno));
89 ASSERT (ret == 2 * data_block_size);
90 if (!has_large_buffer)
91 {
92 /* This assertion fails if data_block_size is too small. */
93 if (!(spent_time > 0.5))
94 {
95 fprintf (stderr,
96 "%s:1: spent_time = %g, data_block_size too small\n",
97 PROG_ROLE, spent_time);
98 too_small = 1;
99 }
100 }
101 ASSERT (spent_time < 1.5);
102 }
103 break;
104
105 case 1: /* Test non-blocking write() with blocking read(). */
106 case 3: /* Test non-blocking write() with non-blocking read(). */
107 {
108 size_t bytes_written;
109 int saved_errno;
110
111 usleep (1000000);
112
113 bytes_written = 0;
114 while (bytes_written < 2 * data_block_size)
115 {
116 dbgfprintf (stderr, "%s:2: >> write (%lu)\n", PROG_ROLE,
117 (unsigned long) (2 * data_block_size - bytes_written));
118 START_TIMING
119 ret = write (fd, data + bytes_written,
120 2 * data_block_size - bytes_written);
121 saved_errno = errno;
122 END_TIMING
123 dbgfprintf (stderr, "%s:2: << write -> %ld%s\n", PROG_ROLE,
124 (long) ret, dbgstrerror (ret < 0, saved_errno));
125 if (ret < 0 && bytes_written >= data_block_size)
126 {
127 ASSERT (saved_errno == EAGAIN || saved_errno == EWOULDBLOCK);
128 ASSERT (spent_time < 0.5);
129 break;
130 }
131 /* This assertion fails if the non-blocking flag is effectively not
132 set on fd. */
133 ASSERT (spent_time < 0.5);
134 if (ret < 0)
135 {
136 ASSERT (saved_errno == EAGAIN || saved_errno == EWOULDBLOCK);
137 usleep (SMALL_DELAY);
138 }
139 else
140 {
141 /* This assertion fails if data_block_size is too small. */
142 if (!(ret > 0))
143 {
144 fprintf (stderr,
145 "%s:1: spent_time = %g, data_block_size too small\n",
146 PROG_ROLE, spent_time);
147 too_small = 1;
148 }
149 bytes_written += ret;
150 }
151 }
152 ASSERT (bytes_written >= data_block_size);
153
154 while (bytes_written < 2 * data_block_size)
155 {
156 dbgfprintf (stderr, "%s:3: >> write (%lu)\n", PROG_ROLE,
157 (unsigned long) (2 * data_block_size - bytes_written));
158 START_TIMING
159 ret = write (fd, data + bytes_written,
160 2 * data_block_size - bytes_written);
161 saved_errno = errno;
162 END_TIMING
163 dbgfprintf (stderr, "%s:3: << write -> %ld%s\n", PROG_ROLE,
164 (long) ret, dbgstrerror (ret < 0, saved_errno));
165 ASSERT (spent_time < 0.5);
166 if (ret < 0)
167 {
168 ASSERT (saved_errno == EAGAIN || saved_errno == EWOULDBLOCK);
169 usleep (SMALL_DELAY);
170 }
171 else
172 {
173 ASSERT (ret > 0);
174 bytes_written += ret;
175 }
176 }
177 }
178 break;
179
180 default:
181 abort ();
182 }
183
184 free (data);
185 return too_small;
186 }