Home | History | Annotate | Line # | Download | only in io
      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