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