* libc/stdio/fclose.c: Only use sfp lock to guard non-atomic
changes of flags and fp lock. * libc/stdio/freopen.c: Ditto. * libc/stdio/freopen64.c: Ditto. * libc/stdio/fgetc.c: Revert change from 2009-04-24, remove sfp locks which guard entire function to avoid potential deadlocks when using stdio functions in multiple thraeds. * libc/stdio/fgets.c: Ditto. * libc/stdio/fgetwc.c: Ditto. * libc/stdio/fgetws.c: Ditto. * libc/stdio/fread.c: Ditto. * libc/stdio/fseek.c: Ditto. * libc/stdio/getc.c: Ditto. * libc/stdio/getdelim.c: Ditto. * libc/stdio/gets.c: Ditto. * libc/stdio/vfscanf.c: Ditto. * libc/stdio/vfwscanf.c: Ditto. * libc/stdio/fflush.c (_fflush_r): Split out core functionality into new function __sflush_r. Just lock file and call __sflush_r from here. * libc/stdio/fwalk.c (_fwalk): Remove static helper function and move functionality back into main function. Don't walk a file with flags value of 1. Add comment. (_fwalk_reent): Ditto. * libc/stdio/local.h (__sflush_r): Declare. * libc/stdio/refill.c (__srefill): Before calling fwalk, set flags value to 1 so this file pointer isn't walked. Revert flags afterwards and call __sflush_r for this fp if necessary. Add comments.
This commit is contained in:
		
							parent
							
								
									b5ca0d7271
								
							
						
					
					
						commit
						656df313e0
					
				|  | @ -1,3 +1,34 @@ | |||
| 2011-01-28  Corinna Vinschen  <vinschen@redhat.com> | ||||
| 
 | ||||
| 	* libc/stdio/fclose.c: Only use sfp lock to guard non-atomic | ||||
| 	changes of flags and fp lock. | ||||
| 	* libc/stdio/freopen.c: Ditto. | ||||
| 	* libc/stdio/freopen64.c: Ditto. | ||||
| 	* libc/stdio/fgetc.c: Revert change from 2009-04-24, remove sfp locks | ||||
| 	which guard entire function to avoid potential deadlocks when using | ||||
| 	stdio functions in multiple thraeds. | ||||
| 	* libc/stdio/fgets.c: Ditto. | ||||
| 	* libc/stdio/fgetwc.c: Ditto. | ||||
| 	* libc/stdio/fgetws.c: Ditto. | ||||
| 	* libc/stdio/fread.c: Ditto. | ||||
| 	* libc/stdio/fseek.c: Ditto. | ||||
| 	* libc/stdio/getc.c: Ditto. | ||||
| 	* libc/stdio/getdelim.c: Ditto. | ||||
| 	* libc/stdio/gets.c: Ditto. | ||||
| 	* libc/stdio/vfscanf.c: Ditto. | ||||
| 	* libc/stdio/vfwscanf.c: Ditto. | ||||
| 
 | ||||
| 	* libc/stdio/fflush.c (_fflush_r): Split out core functionality into | ||||
| 	new function __sflush_r.  Just lock file and call __sflush_r from here. | ||||
| 	* libc/stdio/fwalk.c (_fwalk): Remove static helper function and move | ||||
| 	functionality back into main function. Don't walk a file with flags | ||||
| 	value of 1.  Add comment. | ||||
| 	(_fwalk_reent): Ditto. | ||||
| 	* libc/stdio/local.h (__sflush_r): Declare. | ||||
| 	* libc/stdio/refill.c (__srefill): Before calling fwalk, set flags | ||||
| 	value to 1 so this file pointer isn't walked.  Revert flags afterwards | ||||
| 	and call __sflush_r for this fp if necessary.  Add comments. | ||||
| 
 | ||||
| 2011-01-27  Corinna Vinschen  <vinschen@redhat.com> | ||||
| 
 | ||||
| 	* libc/include/sys/features.h: Define __STDC_ISO_10646__ for Cygwin. | ||||
|  |  | |||
|  | @ -74,8 +74,6 @@ _DEFUN(_fclose_r, (rptr, fp), | |||
|   if (fp == NULL) | ||||
|     return (0);			/* on NULL */ | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
| 
 | ||||
|   CHECK_INIT (rptr, fp); | ||||
| 
 | ||||
|   _flockfile (fp); | ||||
|  | @ -83,7 +81,6 @@ _DEFUN(_fclose_r, (rptr, fp), | |||
|   if (fp->_flags == 0)		/* not open! */ | ||||
|     { | ||||
|       _funlockfile (fp); | ||||
|       __sfp_lock_release (); | ||||
|       return (0); | ||||
|     } | ||||
|   /* Unconditionally flush to allow special handling for seekable read
 | ||||
|  | @ -98,6 +95,7 @@ _DEFUN(_fclose_r, (rptr, fp), | |||
|     FREEUB (rptr, fp); | ||||
|   if (HASLB (fp)) | ||||
|     FREELB (rptr, fp); | ||||
|   __sfp_lock_acquire (); | ||||
|   fp->_flags = 0;		/* release this FILE for reuse */ | ||||
|   _funlockfile (fp); | ||||
| #ifndef __SINGLE_THREAD__ | ||||
|  |  | |||
|  | @ -67,37 +67,16 @@ No supporting OS subroutines are required. | |||
| 
 | ||||
| /* Flush a single file, or (if fp is NULL) all files.  */ | ||||
| 
 | ||||
| /* Core function which does not lock file pointer.  This gets called
 | ||||
|    directly from __srefill. */ | ||||
| int | ||||
| _DEFUN(_fflush_r, (ptr, fp), | ||||
| _DEFUN(__sflush_r, (ptr, fp), | ||||
|        struct _reent *ptr _AND | ||||
|        register FILE * fp) | ||||
| { | ||||
|   register unsigned char *p; | ||||
|   register int n, t; | ||||
| 
 | ||||
| #ifdef _REENT_SMALL | ||||
|   /* For REENT_SMALL platforms, it is possible we are being
 | ||||
|      called for the first time on a std stream.  This std | ||||
|      stream can belong to a reentrant struct that is not | ||||
|      _REENT.  If CHECK_INIT gets called below based on _REENT, | ||||
|      we will end up changing said file pointers to the equivalent | ||||
|      std stream off of _REENT.  This causes unexpected behavior if | ||||
|      there is any data to flush on the _REENT std stream.  There | ||||
|      are two alternatives to fix this:  1) make a reentrant fflush | ||||
|      or 2) simply recognize that this file has nothing to flush | ||||
|      and return immediately before performing a CHECK_INIT.  Choice | ||||
|      2 is implemented here due to its simplicity.  */ | ||||
|   if (fp->_bf._base == NULL) | ||||
|     return 0; | ||||
| #endif /* _REENT_SMALL  */ | ||||
| 
 | ||||
|   CHECK_INIT (ptr, fp); | ||||
| 
 | ||||
|   if (!fp->_flags) | ||||
|     return 0; | ||||
| 
 | ||||
|   _flockfile (fp); | ||||
| 
 | ||||
|   t = fp->_flags; | ||||
|   if ((t & __SWR) == 0) | ||||
|     { | ||||
|  | @ -150,7 +129,6 @@ _DEFUN(_fflush_r, (ptr, fp), | |||
| 		    } | ||||
| 		  else | ||||
| 		    fp->_flags |= __SERR; | ||||
| 		  _funlockfile (fp); | ||||
| 		  return result; | ||||
| 		} | ||||
|             } | ||||
|  | @ -186,17 +164,14 @@ _DEFUN(_fflush_r, (ptr, fp), | |||
| 	  else | ||||
| 	    { | ||||
| 	      fp->_flags |= __SERR; | ||||
| 	      _funlockfile (fp); | ||||
| 	      return EOF; | ||||
| 	    } | ||||
| 	} | ||||
|       _funlockfile (fp); | ||||
|       return 0; | ||||
|     } | ||||
|   if ((p = fp->_bf._base) == NULL) | ||||
|     { | ||||
|       /* Nothing to flush.  */ | ||||
|       _funlockfile (fp); | ||||
|       return 0; | ||||
|     } | ||||
|   n = fp->_p - p;		/* write this much */ | ||||
|  | @ -215,16 +190,48 @@ _DEFUN(_fflush_r, (ptr, fp), | |||
|       if (t <= 0) | ||||
| 	{ | ||||
|           fp->_flags |= __SERR; | ||||
|           _funlockfile (fp); | ||||
|           return EOF; | ||||
| 	} | ||||
|       p += t; | ||||
|       n -= t; | ||||
|     } | ||||
|   _funlockfile (fp); | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| _DEFUN(_fflush_r, (ptr, fp), | ||||
|        struct _reent *ptr _AND | ||||
|        register FILE * fp) | ||||
| { | ||||
|   int ret; | ||||
| 
 | ||||
| #ifdef _REENT_SMALL | ||||
|   /* For REENT_SMALL platforms, it is possible we are being
 | ||||
|      called for the first time on a std stream.  This std | ||||
|      stream can belong to a reentrant struct that is not | ||||
|      _REENT.  If CHECK_INIT gets called below based on _REENT, | ||||
|      we will end up changing said file pointers to the equivalent | ||||
|      std stream off of _REENT.  This causes unexpected behavior if | ||||
|      there is any data to flush on the _REENT std stream.  There | ||||
|      are two alternatives to fix this:  1) make a reentrant fflush | ||||
|      or 2) simply recognize that this file has nothing to flush | ||||
|      and return immediately before performing a CHECK_INIT.  Choice | ||||
|      2 is implemented here due to its simplicity.  */ | ||||
|   if (fp->_bf._base == NULL) | ||||
|     return 0; | ||||
| #endif /* _REENT_SMALL  */ | ||||
| 
 | ||||
|   CHECK_INIT (ptr, fp); | ||||
| 
 | ||||
|   if (!fp->_flags) | ||||
|     return 0; | ||||
| 
 | ||||
|   _flockfile (fp); | ||||
|   ret = __sflush_r (ptr, fp); | ||||
|   _funlockfile (fp); | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| #ifndef _REENT_ONLY | ||||
| 
 | ||||
| int | ||||
|  |  | |||
|  | @ -93,11 +93,9 @@ _DEFUN(fgetc, (fp), | |||
| #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) | ||||
|   int result; | ||||
|   CHECK_INIT(_REENT, fp); | ||||
|   __sfp_lock_acquire (); | ||||
|   _flockfile (fp); | ||||
|   result = __sgetc_r (_REENT, fp); | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return result; | ||||
| #else | ||||
|   return _fgetc_r (_REENT, fp); | ||||
|  |  | |||
|  | @ -98,7 +98,6 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp), | |||
| 
 | ||||
|   CHECK_INIT(ptr, fp); | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
|   _flockfile (fp); | ||||
| #ifdef __SCLE | ||||
|   if (fp->_flags & __SCLE) | ||||
|  | @ -114,12 +113,10 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp), | |||
|       if (c == EOF && s == buf) | ||||
|         { | ||||
|           _funlockfile (fp); | ||||
| 	  __sfp_lock_release (); | ||||
|           return NULL; | ||||
|         } | ||||
|       *s = 0; | ||||
|       _funlockfile (fp); | ||||
|       __sfp_lock_release (); | ||||
|       return buf; | ||||
|     } | ||||
| #endif | ||||
|  | @ -138,7 +135,6 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp), | |||
| 	      if (s == buf) | ||||
|                 { | ||||
|                   _funlockfile (fp); | ||||
| 		  __sfp_lock_release (); | ||||
|                   return 0; | ||||
|                 } | ||||
| 	      break; | ||||
|  | @ -164,7 +160,6 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp), | |||
| 	  _CAST_VOID memcpy ((_PTR) s, (_PTR) p, len); | ||||
| 	  s[len] = 0; | ||||
|           _funlockfile (fp); | ||||
| 	  __sfp_lock_release (); | ||||
| 	  return (buf); | ||||
| 	} | ||||
|       fp->_r -= len; | ||||
|  | @ -175,7 +170,6 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp), | |||
|   while ((n -= len) != 0); | ||||
|   *s = 0; | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return buf; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -164,12 +164,10 @@ _DEFUN(_fgetwc_r, (ptr, fp), | |||
| { | ||||
|   wint_t r; | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
|   _flockfile (fp); | ||||
|   ORIENT(fp, 1); | ||||
|   r = __fgetwc (ptr, fp); | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return r; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -93,7 +93,6 @@ _DEFUN(_fgetws_r, (ptr, ws, n, fp), | |||
|   const char *src; | ||||
|   unsigned char *nl; | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
|   _flockfile (fp); | ||||
|   ORIENT (fp, 1); | ||||
| 
 | ||||
|  | @ -144,12 +143,10 @@ _DEFUN(_fgetws_r, (ptr, ws, n, fp), | |||
|     goto error; | ||||
|   *wsp++ = L'\0'; | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return ws; | ||||
| 
 | ||||
| error: | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return NULL; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -146,7 +146,6 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp), | |||
| 
 | ||||
|   CHECK_INIT(ptr, fp); | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
|   _flockfile (fp); | ||||
|   ORIENT (fp, -1); | ||||
|   if (fp->_r < 0) | ||||
|  | @ -197,12 +196,10 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp), | |||
|               if (fp->_flags & __SCLE) | ||||
| 	        { | ||||
| 	          _funlockfile (fp); | ||||
| 		  __sfp_lock_release (); | ||||
| 	          return crlf_r (ptr, fp, buf, total-resid, 1) / size; | ||||
| 	        } | ||||
| #endif | ||||
| 	      _funlockfile (fp); | ||||
| 	      __sfp_lock_release (); | ||||
| 	      return (total - resid) / size; | ||||
| 	    } | ||||
| 	} | ||||
|  | @ -224,12 +221,10 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp), | |||
| 	      if (fp->_flags & __SCLE) | ||||
| 		{ | ||||
| 		  _funlockfile (fp); | ||||
| 		  __sfp_lock_release (); | ||||
| 		  return crlf_r (ptr, fp, buf, total-resid, 1) / size; | ||||
| 		} | ||||
| #endif | ||||
| 	      _funlockfile (fp); | ||||
| 	      __sfp_lock_release (); | ||||
| 	      return (total - resid) / size; | ||||
| 	    } | ||||
| 	} | ||||
|  | @ -243,12 +238,10 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp), | |||
|   if (fp->_flags & __SCLE) | ||||
|     { | ||||
|       _funlockfile (fp); | ||||
|       __sfp_lock_release (); | ||||
|       return crlf_r(ptr, fp, buf, total, 0) / size; | ||||
|     } | ||||
| #endif | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return count; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -98,8 +98,6 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp), | |||
|   int flags, oflags; | ||||
|   int e = 0; | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
| 
 | ||||
|   CHECK_INIT (ptr, fp); | ||||
| 
 | ||||
|   _flockfile (fp); | ||||
|  | @ -108,7 +106,6 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp), | |||
|     { | ||||
|       _funlockfile (fp); | ||||
|       _fclose_r (ptr, fp); | ||||
|       __sfp_lock_release (); | ||||
|       return NULL; | ||||
|     } | ||||
| 
 | ||||
|  | @ -208,6 +205,7 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp), | |||
| 
 | ||||
|   if (f < 0) | ||||
|     {				/* did not get it after all */ | ||||
|       __sfp_lock_acquire (); | ||||
|       fp->_flags = 0;		/* set it free */ | ||||
|       ptr->_errno = e;		/* restore in case _close clobbered */ | ||||
|       _funlockfile (fp); | ||||
|  | @ -232,7 +230,6 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp), | |||
| #endif | ||||
| 
 | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return fp; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -138,7 +138,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), | |||
| 
 | ||||
|   CHECK_INIT (ptr, fp); | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
|   _flockfile (fp); | ||||
| 
 | ||||
|   /* If we've been doing some writing, and we're in append mode
 | ||||
|  | @ -156,7 +155,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), | |||
|     { | ||||
|       ptr->_errno = ESPIPE;	/* ??? */ | ||||
|       _funlockfile (fp); | ||||
|       __sfp_lock_release (); | ||||
|       return EOF; | ||||
|     } | ||||
| 
 | ||||
|  | @ -182,7 +180,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), | |||
| 	  if (curoff == -1L) | ||||
| 	    { | ||||
| 	      _funlockfile (fp); | ||||
| 	      __sfp_lock_release (); | ||||
| 	      return EOF; | ||||
| 	    } | ||||
| 	} | ||||
|  | @ -208,7 +205,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), | |||
|     default: | ||||
|       ptr->_errno = EINVAL; | ||||
|       _funlockfile (fp); | ||||
|       __sfp_lock_release (); | ||||
|       return (EOF); | ||||
|     } | ||||
| 
 | ||||
|  | @ -268,7 +264,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), | |||
|     { | ||||
|       ptr->_errno = EOVERFLOW; | ||||
|       _funlockfile (fp); | ||||
|       __sfp_lock_release (); | ||||
|       return EOF; | ||||
|     } | ||||
| 
 | ||||
|  | @ -325,7 +320,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), | |||
|       fp->_flags &= ~__SEOF; | ||||
|       memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); | ||||
|       _funlockfile (fp); | ||||
|       __sfp_lock_release (); | ||||
|       return 0; | ||||
|     } | ||||
| 
 | ||||
|  | @ -356,7 +350,6 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), | |||
|     } | ||||
|   memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return 0; | ||||
| 
 | ||||
|   /*
 | ||||
|  | @ -369,7 +362,6 @@ dumb: | |||
|       || seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR) | ||||
|     { | ||||
|       _funlockfile (fp); | ||||
|       __sfp_lock_release (); | ||||
|       return EOF; | ||||
|     } | ||||
|   /* success: clear EOF indicator and discard ungetc() data */ | ||||
|  | @ -388,7 +380,6 @@ dumb: | |||
|   fp->_flags &= ~__SNPT; | ||||
|   memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,8 +27,8 @@ static char sccsid[] = "%W% (Berkeley) %G%"; | |||
| #include <errno.h> | ||||
| #include "local.h" | ||||
| 
 | ||||
| static int | ||||
| _DEFUN(__fwalk, (ptr, function), | ||||
| int | ||||
| _DEFUN(_fwalk, (ptr, function), | ||||
|        struct _reent *ptr _AND | ||||
|        register int (*function) (FILE *)) | ||||
| { | ||||
|  | @ -36,11 +36,19 @@ _DEFUN(__fwalk, (ptr, function), | |||
|   register int n, ret = 0; | ||||
|   register struct _glue *g; | ||||
| 
 | ||||
|   /*
 | ||||
|    * It should be safe to walk the list without locking it; | ||||
|    * new nodes are only added to the end and none are ever | ||||
|    * removed. | ||||
|    * | ||||
|    * Avoid locking this list while walking it or else you will | ||||
|    * introduce a potential deadlock in [at least] refill.c. | ||||
|    */ | ||||
|   for (g = &ptr->__sglue; g != NULL; g = g->_next) | ||||
|     for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++) | ||||
|       if (fp->_flags != 0) | ||||
|         { | ||||
|           if (fp->_flags != 0 && fp->_file != -1) | ||||
|           if (fp->_flags != 0 && fp->_flags != 1 && fp->_file != -1) | ||||
|             ret |= (*function) (fp); | ||||
|         } | ||||
| 
 | ||||
|  | @ -49,8 +57,8 @@ _DEFUN(__fwalk, (ptr, function), | |||
| 
 | ||||
| /* Special version of __fwalk where the function pointer is a reentrant
 | ||||
|    I/O function (e.g. _fclose_r).  */ | ||||
| static int | ||||
| _DEFUN(__fwalk_reent, (ptr, reent_function), | ||||
| int | ||||
| _DEFUN(_fwalk_reent, (ptr, reent_function), | ||||
|        struct _reent *ptr _AND | ||||
|        register int (*reent_function) (struct _reent *, FILE *)) | ||||
| { | ||||
|  | @ -58,51 +66,21 @@ _DEFUN(__fwalk_reent, (ptr, reent_function), | |||
|   register int n, ret = 0; | ||||
|   register struct _glue *g; | ||||
| 
 | ||||
|   /*
 | ||||
|    * It should be safe to walk the list without locking it; | ||||
|    * new nodes are only added to the end and none are ever | ||||
|    * removed. | ||||
|    * | ||||
|    * Avoid locking this list while walking it or else you will | ||||
|    * introduce a potential deadlock in [at least] refill.c. | ||||
|    */ | ||||
|   for (g = &ptr->__sglue; g != NULL; g = g->_next) | ||||
|     for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++) | ||||
|       if (fp->_flags != 0) | ||||
|         { | ||||
|           if (fp->_flags != 0 && fp->_file != -1) | ||||
|           if (fp->_flags != 0 && fp->_flags != 1 && fp->_file != -1) | ||||
|             ret |= (*reent_function) (ptr, fp); | ||||
|         } | ||||
| 
 | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| _DEFUN(_fwalk, (ptr, function), | ||||
|        struct _reent *ptr _AND | ||||
|        register int (*function)(FILE *)) | ||||
| { | ||||
|   register int ret = 0; | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
| 
 | ||||
|   /* Must traverse given list for streams.  Note that _GLOBAL_REENT
 | ||||
|      only walked once in exit().  */ | ||||
|   ret |= __fwalk (ptr, function); | ||||
| 
 | ||||
|   __sfp_lock_release (); | ||||
| 
 | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| /* Special version of _fwalk which handles a function pointer to a
 | ||||
|    reentrant I/O function (e.g. _fclose_r).  */ | ||||
| int | ||||
| _DEFUN(_fwalk_reent, (ptr, reent_function), | ||||
|        struct _reent *ptr _AND | ||||
|        register int (*reent_function) (struct _reent *, FILE *)) | ||||
| { | ||||
|   register int ret = 0; | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
| 
 | ||||
|   /* Must traverse given list for streams.  Note that _GLOBAL_REENT
 | ||||
|      only walked once in exit().  */ | ||||
|   ret |= __fwalk_reent (ptr, reent_function); | ||||
| 
 | ||||
|   __sfp_lock_release (); | ||||
| 
 | ||||
|   return ret; | ||||
| } | ||||
|  |  | |||
|  | @ -92,11 +92,9 @@ _DEFUN(_getc_r, (ptr, fp), | |||
| { | ||||
|   int result; | ||||
|   CHECK_INIT (ptr, fp); | ||||
|   __sfp_lock_acquire (); | ||||
|   _flockfile (fp); | ||||
|   result = __sgetc_r (ptr, fp); | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
|  | @ -108,11 +106,9 @@ _DEFUN(getc, (fp), | |||
| { | ||||
|   int result; | ||||
|   CHECK_INIT (_REENT, fp); | ||||
|   __sfp_lock_acquire (); | ||||
|   _flockfile (fp); | ||||
|   result = __sgetc_r (_REENT, fp); | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -81,7 +81,6 @@ _DEFUN(__getdelim, (bufptr, n, delim, fp), | |||
| 
 | ||||
|   CHECK_INIT (_REENT, fp); | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
|   _flockfile (fp); | ||||
| 
 | ||||
|   numbytes = *n; | ||||
|  | @ -131,7 +130,6 @@ _DEFUN(__getdelim, (bufptr, n, delim, fp), | |||
|     } | ||||
| 
 | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
| 
 | ||||
|   /* if no input data, return failure */ | ||||
|   if (ptr == buf) | ||||
|  |  | |||
|  | @ -79,14 +79,12 @@ _DEFUN(_gets_r, (ptr, buf), | |||
|   register int c; | ||||
|   register char *s = buf; | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
|   _flockfile (stdin); | ||||
|   while ((c = __sgetc_r (ptr, stdin)) != '\n') | ||||
|     if (c == EOF) | ||||
|       if (s == buf) | ||||
| 	{ | ||||
| 	  _funlockfile (stdin); | ||||
| 	  __sfp_lock_release (); | ||||
| 	  return NULL; | ||||
| 	} | ||||
|       else | ||||
|  | @ -95,7 +93,6 @@ _DEFUN(_gets_r, (ptr, buf), | |||
|       *s++ = c; | ||||
|   *s = 0; | ||||
|   _funlockfile (stdin); | ||||
|   __sfp_lock_release (); | ||||
|   return buf; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -54,6 +54,7 @@ int	      _EXFUN(_svfiwprintf_r,(struct _reent *, FILE *, const wchar_t *, | |||
| 				  va_list)); | ||||
| extern FILE  *_EXFUN(__sfp,(struct _reent *)); | ||||
| extern int    _EXFUN(__sflags,(struct _reent *,_CONST char*, int*)); | ||||
| extern int    _EXFUN(__sflush_r,(struct _reent *,FILE *)); | ||||
| extern int    _EXFUN(__srefill_r,(struct _reent *,FILE *)); | ||||
| extern _READ_WRITE_RETURN_TYPE _EXFUN(__sread,(struct _reent *, void *, char *, | ||||
| 					       int)); | ||||
|  |  | |||
|  | @ -102,9 +102,19 @@ _DEFUN(__srefill_r, (ptr, fp), | |||
|    * flush all line buffered output files, per the ANSI C | ||||
|    * standard. | ||||
|    */ | ||||
| 
 | ||||
|   if (fp->_flags & (__SLBF | __SNBF)) | ||||
|     _CAST_VOID _fwalk (_GLOBAL_REENT, lflush); | ||||
|     { | ||||
|       /* Ignore this file in _fwalk to avoid potential deadlock. */ | ||||
|       short orig_flags = fp->_flags; | ||||
|       fp->_flags = 1; | ||||
|       _CAST_VOID _fwalk (_GLOBAL_REENT, lflush); | ||||
|       fp->_flags = orig_flags; | ||||
| 
 | ||||
|       /* Now flush this file without locking it. */ | ||||
|       if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) | ||||
| 	__sflush_r (ptr, fp); | ||||
|     } | ||||
| 
 | ||||
|   fp->_p = fp->_bf._base; | ||||
|   fp->_r = fp->_read (ptr, fp->_cookie, (char *) fp->_p, fp->_bf._size); | ||||
| #ifndef __CYGWIN__ | ||||
|  |  | |||
|  | @ -494,7 +494,6 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), | |||
| # define GET_ARG(n, ap, type) (va_arg (ap, type)) | ||||
| #endif | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
|   _flockfile (fp); | ||||
| 
 | ||||
|   ORIENT (fp, -1); | ||||
|  | @ -795,7 +794,6 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), | |||
| 	   */ | ||||
| 	case '\0':		/* compat */ | ||||
| 	  _funlockfile (fp); | ||||
| 	  __sfp_lock_release (); | ||||
| 	  return EOF; | ||||
| 
 | ||||
| 	default:		/* compat */ | ||||
|  | @ -1596,13 +1594,11 @@ input_failure: | |||
|      invalid format string), return EOF if no matches yet, else number | ||||
|      of matches made prior to failure.  */ | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF; | ||||
| match_failure: | ||||
| all_done: | ||||
|   /* Return number of matches, which can be 0 on match failure.  */ | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return nassigned; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -434,7 +434,6 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap), | |||
| # define GET_ARG(n, ap, type) (va_arg (ap, type)) | ||||
| #endif | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
|   _flockfile (fp); | ||||
| 
 | ||||
|   ORIENT (fp, 1); | ||||
|  | @ -714,7 +713,6 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap), | |||
| 	   */ | ||||
| 	case L'\0':		/* compat */ | ||||
| 	  _funlockfile (fp); | ||||
| 	  __sfp_lock_release (); | ||||
| 	  return EOF; | ||||
| 
 | ||||
| 	default:		/* compat */ | ||||
|  | @ -1443,13 +1441,11 @@ input_failure: | |||
|      invalid format string), return EOF if no matches yet, else number | ||||
|      of matches made prior to failure.  */ | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF; | ||||
| match_failure: | ||||
| all_done: | ||||
|   /* Return number of matches, which can be 0 on match failure.  */ | ||||
|   _funlockfile (fp); | ||||
|   __sfp_lock_release (); | ||||
|   return nassigned; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -97,7 +97,6 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp), | |||
|   int flags, oflags; | ||||
|   int e = 0; | ||||
| 
 | ||||
|   __sfp_lock_acquire (); | ||||
| 
 | ||||
|   CHECK_INIT (ptr, fp); | ||||
| 
 | ||||
|  | @ -107,7 +106,6 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp), | |||
|     { | ||||
|       _funlockfile(fp); | ||||
|       _fclose_r (ptr, fp); | ||||
|       __sfp_lock_release (); | ||||
|       return NULL; | ||||
|     } | ||||
| 
 | ||||
|  | @ -204,6 +202,7 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp), | |||
| 
 | ||||
|   if (f < 0) | ||||
|     {				/* did not get it after all */ | ||||
|       __sfp_lock_acquire (); | ||||
|       fp->_flags = 0;		/* set it free */ | ||||
|       ptr->_errno = e;		/* restore in case _close clobbered */ | ||||
|       _funlockfile(fp); | ||||
|  | @ -231,7 +230,6 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp), | |||
|   fp->_flags |= __SL64; | ||||
| 
 | ||||
|   _funlockfile(fp); | ||||
|   __sfp_lock_release (); | ||||
|   return fp; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue