async.h revision 1.1.1.4 1 1.1.1.4 mrg /* Copyright (C) 2018-2024 Free Software Foundation, Inc.
2 1.1 mrg Contributed by Nicolas Koenig
3 1.1 mrg
4 1.1 mrg This file is part of the GNU Fortran runtime library (libgfortran).
5 1.1 mrg
6 1.1 mrg Libgfortran is free software; you can redistribute it and/or modify
7 1.1 mrg it under the terms of the GNU General Public License as published by
8 1.1 mrg the Free Software Foundation; either version 3, or (at your option)
9 1.1 mrg any later version.
10 1.1 mrg
11 1.1 mrg Libgfortran is distributed in the hope that it will be useful,
12 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 mrg GNU General Public License for more details.
15 1.1 mrg
16 1.1 mrg Under Section 7 of GPL version 3, you are granted additional
17 1.1 mrg permissions described in the GCC Runtime Library Exception, version
18 1.1 mrg 3.1, as published by the Free Software Foundation.
19 1.1 mrg
20 1.1 mrg You should have received a copy of the GNU General Public License and
21 1.1 mrg a copy of the GCC Runtime Library Exception along with this program;
22 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 1.1 mrg <http://www.gnu.org/licenses/>. */
24 1.1 mrg
25 1.1 mrg #ifndef ASYNC_H
26 1.1 mrg #define ASYNC_H
27 1.1 mrg
28 1.1 mrg /* Async I/O will not work on targets which do not support
29 1.1 mrg __gthread_cond_t and __gthread_equal / __gthread_self. Check
30 1.1 mrg this. */
31 1.1 mrg
32 1.1 mrg #if defined(__GTHREAD_HAS_COND) && defined(__GTHREADS_CXX0X)
33 1.1 mrg #define ASYNC_IO 1
34 1.1 mrg #else
35 1.1 mrg #define ASYNC_IO 0
36 1.1 mrg #endif
37 1.1 mrg
38 1.1 mrg /* Defining DEBUG_ASYNC will enable somewhat verbose debugging
39 1.1 mrg output for async I/O. */
40 1.1 mrg
41 1.1 mrg #define DEBUG_ASYNC
42 1.1 mrg #undef DEBUG_ASYNC
43 1.1 mrg
44 1.1 mrg #ifdef DEBUG_ASYNC
45 1.1 mrg
46 1.1 mrg /* Define this if you want to use ANSI color escape sequences in your
47 1.1 mrg debugging output. */
48 1.1 mrg
49 1.1 mrg #define DEBUG_COLOR
50 1.1 mrg
51 1.1 mrg #ifdef DEBUG_COLOR
52 1.1 mrg #define MPREFIX "\033[30;46mM:\033[0m "
53 1.1 mrg #define TPREFIX "\033[37;44mT:\033[0m "
54 1.1 mrg #define RPREFIX "\033[37;41mR:\033[0m "
55 1.1 mrg #define DEBUG_RED "\033[31m"
56 1.1 mrg #define DEBUG_ORANGE "\033[33m"
57 1.1 mrg #define DEBUG_GREEN "\033[32m"
58 1.1 mrg #define DEBUG_DARKRED "\033[31;2m"
59 1.1 mrg #define DEBUG_PURPLE "\033[35m"
60 1.1 mrg #define DEBUG_NORM "\033[0m"
61 1.1 mrg #define DEBUG_REVERSE_RED "\033[41;37m"
62 1.1 mrg #define DEBUG_BLUE "\033[34m"
63 1.1 mrg
64 1.1 mrg #else
65 1.1 mrg
66 1.1 mrg #define MPREFIX "M: "
67 1.1 mrg #define TPREFIX "T: "
68 1.1 mrg #define RPREFIX ""
69 1.1 mrg #define DEBUG_RED ""
70 1.1 mrg #define DEBUG_ORANGE ""
71 1.1 mrg #define DEBUG_GREEN ""
72 1.1 mrg #define DEBUG_DARKRED ""
73 1.1 mrg #define DEBUG_PURPLE ""
74 1.1 mrg #define DEBUG_NORM ""
75 1.1 mrg #define DEBUG_REVERSE_RED ""
76 1.1 mrg #define DEBUG_BLUE ""
77 1.1 mrg
78 1.1 mrg #endif
79 1.1 mrg
80 1.1 mrg #define DEBUG_PRINTF(...) fprintf (stderr,__VA_ARGS__)
81 1.1 mrg
82 1.1 mrg #define IN_DEBUG_QUEUE(mutex) ({ \
83 1.1 mrg __label__ end; \
84 1.1 mrg aio_lock_debug *curr = aio_debug_head; \
85 1.1 mrg while (curr) { \
86 1.1 mrg if (curr->m == mutex) { \
87 1.1 mrg goto end; \
88 1.1 mrg } \
89 1.1 mrg curr = curr->next; \
90 1.1 mrg } \
91 1.1 mrg end:; \
92 1.1 mrg curr; \
93 1.1 mrg })
94 1.1 mrg
95 1.1 mrg #define TAIL_DEBUG_QUEUE ({ \
96 1.1 mrg aio_lock_debug *curr = aio_debug_head; \
97 1.1 mrg while (curr && curr->next) { \
98 1.1 mrg curr = curr->next; \
99 1.1 mrg } \
100 1.1 mrg curr; \
101 1.1 mrg })
102 1.1 mrg
103 1.1 mrg #define CHECK_LOCK(mutex, status) do { \
104 1.1 mrg aio_lock_debug *curr; \
105 1.1 mrg INTERN_LOCK (&debug_queue_lock); \
106 1.1 mrg if (__gthread_mutex_trylock (mutex)) { \
107 1.1 mrg if ((curr = IN_DEBUG_QUEUE (mutex))) { \
108 1.1 mrg sprintf (status, DEBUG_RED "%s():%d" DEBUG_NORM, curr->func, curr->line); \
109 1.1 mrg } else \
110 1.1 mrg sprintf (status, DEBUG_RED "unknown" DEBUG_NORM); \
111 1.1 mrg } \
112 1.1 mrg else { \
113 1.1 mrg __gthread_mutex_unlock (mutex); \
114 1.1 mrg sprintf (status, DEBUG_GREEN "unlocked" DEBUG_NORM); \
115 1.1 mrg } \
116 1.1 mrg INTERN_UNLOCK (&debug_queue_lock); \
117 1.1 mrg }while (0)
118 1.1 mrg
119 1.1 mrg #define T_ERROR(func, ...) do { \
120 1.1 mrg int t_error_temp; \
121 1.1 mrg t_error_temp = func(__VA_ARGS__); \
122 1.1 mrg if (t_error_temp) \
123 1.1 mrg ERROR (t_error_temp, "args: " #__VA_ARGS__ "\n"); \
124 1.1 mrg } while (0)
125 1.1 mrg
126 1.1 mrg #define NOTE(str, ...) do{ \
127 1.1 mrg char note_str[200]; \
128 1.1 mrg sprintf (note_str, "%s" DEBUG_PURPLE "NOTE: " DEBUG_NORM str, aio_prefix, ##__VA_ARGS__); \
129 1.1 mrg DEBUG_PRINTF ("%-90s %20s():%-5d\n", note_str, __FUNCTION__, __LINE__); \
130 1.1 mrg }while (0);
131 1.1 mrg
132 1.1 mrg #define ERROR(errnum, str, ...) do{ \
133 1.1 mrg char note_str[200]; \
134 1.1 mrg sprintf (note_str, "%s" DEBUG_REVERSE_RED "ERROR:" DEBUG_NORM " [%d] " str, aio_prefix, \
135 1.1 mrg errnum, ##__VA_ARGS__); \
136 1.1 mrg DEBUG_PRINTF ("%-68s %s():%-5d\n", note_str, __FUNCTION__, __LINE__); \
137 1.1 mrg }while (0)
138 1.1 mrg
139 1.1 mrg #define MUTEX_DEBUG_ADD(mutex) do { \
140 1.1 mrg aio_lock_debug *n; \
141 1.1 mrg n = malloc (sizeof(aio_lock_debug)); \
142 1.1 mrg n->prev = TAIL_DEBUG_QUEUE; \
143 1.1 mrg if (n->prev) \
144 1.1 mrg n->prev->next = n; \
145 1.1 mrg n->next = NULL; \
146 1.1 mrg n->line = __LINE__; \
147 1.1 mrg n->func = __FUNCTION__; \
148 1.1 mrg n->m = mutex; \
149 1.1 mrg if (!aio_debug_head) { \
150 1.1 mrg aio_debug_head = n; \
151 1.1 mrg } \
152 1.1 mrg } while (0)
153 1.1 mrg
154 1.1 mrg #define UNLOCK(mutex) do { \
155 1.1 mrg aio_lock_debug *curr; \
156 1.1 mrg DEBUG_PRINTF ("%s%-75s %20s():%-5d %18p\n", aio_prefix, DEBUG_GREEN "UNLOCK: " DEBUG_NORM #mutex, \
157 1.1 mrg __FUNCTION__, __LINE__, (void *) mutex); \
158 1.1 mrg INTERN_LOCK (&debug_queue_lock); \
159 1.1 mrg curr = IN_DEBUG_QUEUE (mutex); \
160 1.1 mrg if (curr) \
161 1.1 mrg { \
162 1.1 mrg if (curr->prev) \
163 1.1 mrg curr->prev->next = curr->next; \
164 1.1 mrg if (curr->next) { \
165 1.1 mrg curr->next->prev = curr->prev; \
166 1.1 mrg if (curr == aio_debug_head) \
167 1.1 mrg aio_debug_head = curr->next; \
168 1.1 mrg } else { \
169 1.1 mrg if (curr == aio_debug_head) \
170 1.1 mrg aio_debug_head = NULL; \
171 1.1 mrg } \
172 1.1 mrg free (curr); \
173 1.1 mrg } \
174 1.1 mrg INTERN_UNLOCK (&debug_queue_lock); \
175 1.1 mrg INTERN_UNLOCK (mutex); \
176 1.1 mrg }while (0)
177 1.1 mrg
178 1.1 mrg #define TRYLOCK(mutex) ({ \
179 1.1 mrg char status[200]; \
180 1.1 mrg int res; \
181 1.1 mrg aio_lock_debug *curr; \
182 1.1 mrg res = __gthread_mutex_trylock (mutex); \
183 1.1 mrg INTERN_LOCK (&debug_queue_lock); \
184 1.1 mrg if (res) { \
185 1.1 mrg if ((curr = IN_DEBUG_QUEUE (mutex))) { \
186 1.1 mrg sprintf (status, DEBUG_RED "%s():%d" DEBUG_NORM, curr->func, curr->line); \
187 1.1 mrg } else \
188 1.1 mrg sprintf (status, DEBUG_RED "unknown" DEBUG_NORM); \
189 1.1 mrg } \
190 1.1 mrg else { \
191 1.1 mrg sprintf (status, DEBUG_GREEN "unlocked" DEBUG_NORM); \
192 1.1 mrg MUTEX_DEBUG_ADD (mutex); \
193 1.1 mrg } \
194 1.1 mrg DEBUG_PRINTF ("%s%-44s prev: %-35s %20s():%-5d %18p\n", aio_prefix, \
195 1.1 mrg DEBUG_DARKRED "TRYLOCK: " DEBUG_NORM #mutex, status, __FUNCTION__, __LINE__, \
196 1.1 mrg (void *) mutex); \
197 1.1 mrg INTERN_UNLOCK (&debug_queue_lock); \
198 1.1 mrg res; \
199 1.1 mrg })
200 1.1 mrg
201 1.1 mrg #define LOCK(mutex) do { \
202 1.1 mrg char status[200]; \
203 1.1 mrg CHECK_LOCK (mutex, status); \
204 1.1 mrg DEBUG_PRINTF ("%s%-42s prev: %-35s %20s():%-5d %18p\n", aio_prefix, \
205 1.1 mrg DEBUG_RED "LOCK: " DEBUG_NORM #mutex, status, __FUNCTION__, __LINE__, (void *) mutex); \
206 1.1 mrg INTERN_LOCK (mutex); \
207 1.1 mrg INTERN_LOCK (&debug_queue_lock); \
208 1.1 mrg MUTEX_DEBUG_ADD (mutex); \
209 1.1 mrg INTERN_UNLOCK (&debug_queue_lock); \
210 1.1 mrg DEBUG_PRINTF ("%s" DEBUG_RED "ACQ:" DEBUG_NORM " %-30s %78p\n", aio_prefix, #mutex, mutex); \
211 1.1 mrg } while (0)
212 1.1 mrg
213 1.1.1.4 mrg #ifdef __GTHREAD_RWLOCK_INIT
214 1.1.1.4 mrg #define RWLOCK_DEBUG_ADD(rwlock) do { \
215 1.1.1.4 mrg aio_rwlock_debug *n; \
216 1.1.1.4 mrg n = xmalloc (sizeof (aio_rwlock_debug)); \
217 1.1.1.4 mrg n->prev = TAIL_RWLOCK_DEBUG_QUEUE; \
218 1.1.1.4 mrg if (n->prev) \
219 1.1.1.4 mrg n->prev->next = n; \
220 1.1.1.4 mrg n->next = NULL; \
221 1.1.1.4 mrg n->line = __LINE__; \
222 1.1.1.4 mrg n->func = __FUNCTION__; \
223 1.1.1.4 mrg n->rw = rwlock; \
224 1.1.1.4 mrg if (!aio_rwlock_debug_head) { \
225 1.1.1.4 mrg aio_rwlock_debug_head = n; \
226 1.1.1.4 mrg } \
227 1.1.1.4 mrg } while (0)
228 1.1.1.4 mrg
229 1.1.1.4 mrg #define CHECK_RDLOCK(rwlock, status) do { \
230 1.1.1.4 mrg aio_rwlock_debug *curr; \
231 1.1.1.4 mrg INTERN_WRLOCK (&debug_queue_rwlock); \
232 1.1.1.4 mrg if (__gthread_rwlock_tryrdlock (rwlock)) { \
233 1.1.1.4 mrg if ((curr = IN_RWLOCK_DEBUG_QUEUE (rwlock))) { \
234 1.1.1.4 mrg sprintf (status, DEBUG_RED "%s():%d" DEBUG_NORM, curr->func, curr->line); \
235 1.1.1.4 mrg } else \
236 1.1.1.4 mrg sprintf (status, DEBUG_RED "unknown" DEBUG_NORM); \
237 1.1.1.4 mrg } \
238 1.1.1.4 mrg else { \
239 1.1.1.4 mrg __gthread_rwlock_unlock (rwlock); \
240 1.1.1.4 mrg sprintf (status, DEBUG_GREEN "rwunlocked" DEBUG_NORM); \
241 1.1.1.4 mrg } \
242 1.1.1.4 mrg INTERN_RWUNLOCK (&debug_queue_rwlock); \
243 1.1.1.4 mrg }while (0)
244 1.1.1.4 mrg
245 1.1.1.4 mrg #define CHECK_WRLOCK(rwlock, status) do { \
246 1.1.1.4 mrg aio_rwlock_debug *curr; \
247 1.1.1.4 mrg INTERN_WRLOCK (&debug_queue_rwlock); \
248 1.1.1.4 mrg if (__gthread_rwlock_trywrlock (rwlock)) { \
249 1.1.1.4 mrg if ((curr = IN_RWLOCK_DEBUG_QUEUE (rwlock))) { \
250 1.1.1.4 mrg sprintf (status, DEBUG_RED "%s():%d" DEBUG_NORM, curr->func, curr->line); \
251 1.1.1.4 mrg } else \
252 1.1.1.4 mrg sprintf (status, DEBUG_RED "unknown" DEBUG_NORM); \
253 1.1.1.4 mrg } \
254 1.1.1.4 mrg else { \
255 1.1.1.4 mrg __gthread_rwlock_unlock (rwlock); \
256 1.1.1.4 mrg sprintf (status, DEBUG_GREEN "rwunlocked" DEBUG_NORM); \
257 1.1.1.4 mrg } \
258 1.1.1.4 mrg INTERN_RWUNLOCK (&debug_queue_rwlock); \
259 1.1.1.4 mrg }while (0)
260 1.1.1.4 mrg
261 1.1.1.4 mrg #define TAIL_RWLOCK_DEBUG_QUEUE ({ \
262 1.1.1.4 mrg aio_rwlock_debug *curr = aio_rwlock_debug_head; \
263 1.1.1.4 mrg while (curr && curr->next) { \
264 1.1.1.4 mrg curr = curr->next; \
265 1.1.1.4 mrg } \
266 1.1.1.4 mrg curr; \
267 1.1.1.4 mrg })
268 1.1.1.4 mrg
269 1.1.1.4 mrg #define IN_RWLOCK_DEBUG_QUEUE(rwlock) ({ \
270 1.1.1.4 mrg __label__ end; \
271 1.1.1.4 mrg aio_rwlock_debug *curr = aio_rwlock_debug_head; \
272 1.1.1.4 mrg while (curr) { \
273 1.1.1.4 mrg if (curr->rw == rwlock) { \
274 1.1.1.4 mrg goto end; \
275 1.1.1.4 mrg } \
276 1.1.1.4 mrg curr = curr->next; \
277 1.1.1.4 mrg } \
278 1.1.1.4 mrg end:; \
279 1.1.1.4 mrg curr; \
280 1.1.1.4 mrg })
281 1.1.1.4 mrg
282 1.1.1.4 mrg #define RDLOCK(rwlock) do { \
283 1.1.1.4 mrg char status[200]; \
284 1.1.1.4 mrg CHECK_RDLOCK (rwlock, status); \
285 1.1.1.4 mrg DEBUG_PRINTF ("%s%-42s prev: %-35s %20s():%-5d %18p\n", aio_prefix, \
286 1.1.1.4 mrg DEBUG_RED "RDLOCK: " DEBUG_NORM #rwlock, status, __FUNCTION__, __LINE__, (void *) rwlock); \
287 1.1.1.4 mrg INTERN_RDLOCK (rwlock); \
288 1.1.1.4 mrg INTERN_WRLOCK (&debug_queue_rwlock); \
289 1.1.1.4 mrg RWLOCK_DEBUG_ADD (rwlock); \
290 1.1.1.4 mrg INTERN_RWUNLOCK (&debug_queue_rwlock); \
291 1.1.1.4 mrg DEBUG_PRINTF ("%s" DEBUG_RED "ACQ:" DEBUG_NORM " %-30s %78p\n", aio_prefix, #rwlock, rwlock); \
292 1.1.1.4 mrg } while (0)
293 1.1.1.4 mrg
294 1.1.1.4 mrg #define WRLOCK(rwlock) do { \
295 1.1.1.4 mrg char status[200]; \
296 1.1.1.4 mrg CHECK_WRLOCK (rwlock, status); \
297 1.1.1.4 mrg DEBUG_PRINTF ("%s%-42s prev: %-35s %20s():%-5d %18p\n", aio_prefix, \
298 1.1.1.4 mrg DEBUG_RED "WRLOCK: " DEBUG_NORM #rwlock, status, __FUNCTION__, __LINE__, (void *) rwlock); \
299 1.1.1.4 mrg INTERN_WRLOCK (rwlock); \
300 1.1.1.4 mrg INTERN_WRLOCK (&debug_queue_rwlock); \
301 1.1.1.4 mrg RWLOCK_DEBUG_ADD (rwlock); \
302 1.1.1.4 mrg INTERN_RWUNLOCK (&debug_queue_rwlock); \
303 1.1.1.4 mrg DEBUG_PRINTF ("%s" DEBUG_RED "ACQ:" DEBUG_NORM " %-30s %78p\n", aio_prefix, #rwlock, rwlock); \
304 1.1.1.4 mrg } while (0)
305 1.1.1.4 mrg
306 1.1.1.4 mrg #define RWUNLOCK(rwlock) do { \
307 1.1.1.4 mrg aio_rwlock_debug *curr; \
308 1.1.1.4 mrg DEBUG_PRINTF ("%s%-75s %20s():%-5d %18p\n", aio_prefix, DEBUG_GREEN "RWUNLOCK: " DEBUG_NORM #rwlock, \
309 1.1.1.4 mrg __FUNCTION__, __LINE__, (void *) rwlock); \
310 1.1.1.4 mrg INTERN_WRLOCK (&debug_queue_rwlock); \
311 1.1.1.4 mrg curr = IN_RWLOCK_DEBUG_QUEUE (rwlock); \
312 1.1.1.4 mrg if (curr) \
313 1.1.1.4 mrg { \
314 1.1.1.4 mrg if (curr->prev) \
315 1.1.1.4 mrg curr->prev->next = curr->next; \
316 1.1.1.4 mrg if (curr->next) { \
317 1.1.1.4 mrg curr->next->prev = curr->prev; \
318 1.1.1.4 mrg if (curr == aio_rwlock_debug_head) \
319 1.1.1.4 mrg aio_rwlock_debug_head = curr->next; \
320 1.1.1.4 mrg } else { \
321 1.1.1.4 mrg if (curr == aio_rwlock_debug_head) \
322 1.1.1.4 mrg aio_rwlock_debug_head = NULL; \
323 1.1.1.4 mrg } \
324 1.1.1.4 mrg free (curr); \
325 1.1.1.4 mrg } \
326 1.1.1.4 mrg INTERN_RWUNLOCK (&debug_queue_rwlock); \
327 1.1.1.4 mrg INTERN_RWUNLOCK (rwlock); \
328 1.1.1.4 mrg } while (0)
329 1.1.1.4 mrg
330 1.1.1.4 mrg #define RD_TO_WRLOCK(rwlock) \
331 1.1.1.4 mrg RWUNLOCK (rwlock); \
332 1.1.1.4 mrg WRLOCK (rwlock);
333 1.1.1.4 mrg #endif
334 1.1.1.4 mrg
335 1.1 mrg #define DEBUG_LINE(...) __VA_ARGS__
336 1.1 mrg
337 1.1 mrg #else
338 1.1 mrg #define DEBUG_PRINTF(...) {}
339 1.1 mrg #define CHECK_LOCK(au, mutex, status) {}
340 1.1 mrg #define NOTE(str, ...) {}
341 1.1 mrg #define DEBUG_LINE(...)
342 1.1 mrg #define T_ERROR(func, ...) func(__VA_ARGS__)
343 1.1 mrg #define LOCK(mutex) INTERN_LOCK (mutex)
344 1.1 mrg #define UNLOCK(mutex) INTERN_UNLOCK (mutex)
345 1.1 mrg #define TRYLOCK(mutex) (__gthread_mutex_trylock (mutex))
346 1.1.1.4 mrg #ifdef __GTHREAD_RWLOCK_INIT
347 1.1.1.4 mrg #define RDLOCK(rwlock) INTERN_RDLOCK (rwlock)
348 1.1.1.4 mrg #define WRLOCK(rwlock) INTERN_WRLOCK (rwlock)
349 1.1.1.4 mrg #define RWUNLOCK(rwlock) INTERN_RWUNLOCK (rwlock)
350 1.1.1.4 mrg #define RD_TO_WRLOCK(rwlock) \
351 1.1.1.4 mrg RWUNLOCK (rwlock); \
352 1.1.1.4 mrg WRLOCK (rwlock);
353 1.1.1.4 mrg #endif
354 1.1.1.4 mrg #endif
355 1.1.1.4 mrg
356 1.1.1.4 mrg #ifndef __GTHREAD_RWLOCK_INIT
357 1.1.1.4 mrg #define RDLOCK(rwlock) LOCK (rwlock)
358 1.1.1.4 mrg #define WRLOCK(rwlock) LOCK (rwlock)
359 1.1.1.4 mrg #define RWUNLOCK(rwlock) UNLOCK (rwlock)
360 1.1.1.4 mrg #define RD_TO_WRLOCK(rwlock) do {} while (0)
361 1.1 mrg #endif
362 1.1 mrg
363 1.1 mrg #define INTERN_LOCK(mutex) T_ERROR (__gthread_mutex_lock, mutex);
364 1.1 mrg
365 1.1 mrg #define INTERN_UNLOCK(mutex) T_ERROR (__gthread_mutex_unlock, mutex);
366 1.1 mrg
367 1.1.1.4 mrg #define INTERN_RDLOCK(rwlock) T_ERROR (__gthread_rwlock_rdlock, rwlock)
368 1.1.1.4 mrg #define INTERN_WRLOCK(rwlock) T_ERROR (__gthread_rwlock_wrlock, rwlock)
369 1.1.1.4 mrg #define INTERN_RWUNLOCK(rwlock) T_ERROR (__gthread_rwlock_unlock, rwlock)
370 1.1.1.4 mrg
371 1.1 mrg #if ASYNC_IO
372 1.1 mrg
373 1.1 mrg /* au->lock has to be held when calling this macro. */
374 1.1 mrg
375 1.1 mrg #define SIGNAL(advcond) do{ \
376 1.1 mrg (advcond)->pending = 1; \
377 1.1 mrg DEBUG_PRINTF ("%s%-75s %20s():%-5d %18p\n", aio_prefix, DEBUG_ORANGE "SIGNAL: " DEBUG_NORM \
378 1.1 mrg #advcond, __FUNCTION__, __LINE__, (void *) advcond); \
379 1.1 mrg T_ERROR (__gthread_cond_broadcast, &(advcond)->signal); \
380 1.1 mrg } while (0)
381 1.1 mrg
382 1.1 mrg /* Has to be entered with mutex locked. */
383 1.1 mrg
384 1.1 mrg #define WAIT_SIGNAL_MUTEX(advcond, condition, mutex) do{ \
385 1.1 mrg __label__ finish; \
386 1.1 mrg DEBUG_PRINTF ("%s%-75s %20s():%-5d %18p\n", aio_prefix, DEBUG_BLUE "WAITING: " DEBUG_NORM \
387 1.1 mrg #advcond, __FUNCTION__, __LINE__, (void *) advcond); \
388 1.1 mrg if ((advcond)->pending || (condition)) \
389 1.1 mrg goto finish; \
390 1.1 mrg while (1) \
391 1.1 mrg { \
392 1.1 mrg int err_ret = __gthread_cond_wait(&(advcond)->signal, mutex); \
393 1.1 mrg if (err_ret) internal_error (NULL, "WAIT_SIGNAL_MUTEX failed"); \
394 1.1 mrg if (condition) \
395 1.1 mrg { \
396 1.1 mrg DEBUG_PRINTF ("%s%-75s %20s():%-5d %18p\n", aio_prefix, DEBUG_ORANGE \
397 1.1 mrg "REC: " DEBUG_NORM \
398 1.1 mrg #advcond, __FUNCTION__, __LINE__, (void *)advcond); \
399 1.1 mrg break; \
400 1.1 mrg } \
401 1.1 mrg } \
402 1.1 mrg finish: \
403 1.1 mrg (advcond)->pending = 0; \
404 1.1 mrg UNLOCK (mutex); \
405 1.1 mrg } while (0)
406 1.1 mrg
407 1.1 mrg /* au->lock has to be held when calling this macro. */
408 1.1 mrg
409 1.1 mrg #define REVOKE_SIGNAL(advcond) do{ \
410 1.1 mrg (advcond)->pending = 0; \
411 1.1 mrg } while (0)
412 1.1 mrg
413 1.1 mrg #else
414 1.1 mrg
415 1.1 mrg #define SIGNAL(advcond) do{} while(0)
416 1.1 mrg #define WAIT_SIGNAL_MUTEX(advcond, condition, mutex) do{} while(0)
417 1.1 mrg #define REVOKE_SIGNAL(advcond) do{} while(0)
418 1.1 mrg
419 1.1 mrg #endif
420 1.1 mrg
421 1.1 mrg #if ASYNC_IO
422 1.1 mrg DEBUG_LINE (extern __thread const char *aio_prefix);
423 1.1 mrg
424 1.1 mrg DEBUG_LINE (typedef struct aio_lock_debug{
425 1.1 mrg __gthread_mutex_t *m;
426 1.1 mrg int line;
427 1.1 mrg const char *func;
428 1.1 mrg struct aio_lock_debug *next;
429 1.1 mrg struct aio_lock_debug *prev;
430 1.1 mrg } aio_lock_debug;)
431 1.1 mrg
432 1.1.1.4 mrg DEBUG_LINE (typedef struct aio_rwlock_debug{
433 1.1.1.4 mrg __gthread_rwlock_t *rw;
434 1.1.1.4 mrg int line;
435 1.1.1.4 mrg const char *func;
436 1.1.1.4 mrg struct aio_rwlock_debug *next;
437 1.1.1.4 mrg struct aio_rwlock_debug *prev;
438 1.1.1.4 mrg } aio_rwlock_debug;)
439 1.1.1.4 mrg
440 1.1 mrg DEBUG_LINE (extern aio_lock_debug *aio_debug_head;)
441 1.1 mrg DEBUG_LINE (extern __gthread_mutex_t debug_queue_lock;)
442 1.1.1.4 mrg DEBUG_LINE (extern aio_rwlock_debug *aio_rwlock_debug_head;)
443 1.1.1.4 mrg DEBUG_LINE (extern __gthread_rwlock_t debug_queue_rwlock;)
444 1.1 mrg
445 1.1 mrg /* Thread - local storage of the current unit we are looking at. Needed for
446 1.1 mrg error reporting. */
447 1.1 mrg
448 1.1 mrg extern __thread gfc_unit *thread_unit;
449 1.1 mrg #endif
450 1.1 mrg
451 1.1 mrg enum aio_do {
452 1.1 mrg AIO_INVALID = 0,
453 1.1 mrg AIO_DATA_TRANSFER_INIT,
454 1.1 mrg AIO_TRANSFER_SCALAR,
455 1.1 mrg AIO_TRANSFER_ARRAY,
456 1.1 mrg AIO_WRITE_DONE,
457 1.1 mrg AIO_READ_DONE,
458 1.1 mrg AIO_CLOSE
459 1.1 mrg };
460 1.1 mrg
461 1.1 mrg typedef union transfer_args
462 1.1 mrg {
463 1.1 mrg struct
464 1.1 mrg {
465 1.1 mrg void (*transfer) (struct st_parameter_dt *, bt, void *, int, size_t, size_t);
466 1.1 mrg bt arg_bt;
467 1.1 mrg void *data;
468 1.1 mrg int i;
469 1.1 mrg size_t s1;
470 1.1 mrg size_t s2;
471 1.1 mrg } scalar;
472 1.1 mrg struct
473 1.1 mrg {
474 1.1 mrg gfc_array_char *desc;
475 1.1 mrg int kind;
476 1.1 mrg gfc_charlen_type charlen;
477 1.1 mrg } array;
478 1.1 mrg } transfer_args;
479 1.1 mrg
480 1.1 mrg struct adv_cond
481 1.1 mrg {
482 1.1 mrg #if ASYNC_IO
483 1.1 mrg int pending;
484 1.1 mrg __gthread_cond_t signal;
485 1.1 mrg #endif
486 1.1 mrg };
487 1.1 mrg
488 1.1 mrg typedef struct async_unit
489 1.1 mrg {
490 1.1 mrg __gthread_mutex_t io_lock; /* Lock for doing actual I/O. */
491 1.1 mrg __gthread_mutex_t lock; /* Lock for manipulating the queue structure. */
492 1.1 mrg bool empty;
493 1.1 mrg struct
494 1.1 mrg {
495 1.1 mrg int waiting;
496 1.1 mrg int low;
497 1.1 mrg int high;
498 1.1 mrg struct adv_cond done;
499 1.1 mrg } id;
500 1.1 mrg
501 1.1 mrg #if ASYNC_IO
502 1.1 mrg struct adv_cond work;
503 1.1 mrg struct adv_cond emptysignal;
504 1.1 mrg struct st_parameter_dt *pdt;
505 1.1.1.4 mrg __gthread_t thread;
506 1.1 mrg struct transfer_queue *head;
507 1.1 mrg struct transfer_queue *tail;
508 1.1 mrg
509 1.1 mrg struct {
510 1.1 mrg const char *message;
511 1.1 mrg st_parameter_common *cmp;
512 1.1 mrg bool has_error;
513 1.1 mrg int last_good_id;
514 1.1 mrg int family;
515 1.1 mrg bool fatal_error;
516 1.1 mrg } error;
517 1.1 mrg #endif
518 1.1 mrg } async_unit;
519 1.1 mrg
520 1.1 mrg void init_async_unit (gfc_unit *);
521 1.1 mrg internal_proto (init_async_unit);
522 1.1 mrg
523 1.1 mrg bool async_wait (st_parameter_common *, async_unit *);
524 1.1 mrg internal_proto (async_wait);
525 1.1 mrg
526 1.1 mrg bool async_wait_id (st_parameter_common *, async_unit *, int);
527 1.1 mrg internal_proto (async_wait_id);
528 1.1 mrg
529 1.1 mrg bool collect_async_errors (st_parameter_common *, async_unit *);
530 1.1 mrg internal_proto (collect_async_errors);
531 1.1 mrg
532 1.1 mrg void async_close (async_unit *);
533 1.1 mrg internal_proto (async_close);
534 1.1 mrg
535 1.1 mrg void enqueue_transfer (async_unit * au, transfer_args * arg, enum aio_do);
536 1.1 mrg internal_proto (enqueue_transfer);
537 1.1 mrg
538 1.1 mrg void enqueue_done (async_unit *, enum aio_do type);
539 1.1 mrg internal_proto (enqueue_done);
540 1.1 mrg
541 1.1 mrg int enqueue_done_id (async_unit *, enum aio_do type);
542 1.1 mrg internal_proto (enqueue_done_id);
543 1.1 mrg
544 1.1 mrg void enqueue_init (async_unit *);
545 1.1 mrg internal_proto (enqueue_init);
546 1.1 mrg
547 1.1 mrg void enqueue_data_transfer_init (async_unit *, st_parameter_dt *, int);
548 1.1 mrg internal_proto (enqueue_data_transfer_init);
549 1.1 mrg
550 1.1 mrg void enqueue_close (async_unit *);
551 1.1 mrg internal_proto (enqueue_close);
552 1.1 mrg
553 1.1 mrg #endif
554