From 10dcf7e718e250e222f00bc648c9cb43100edf88 Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Thu, 25 Mar 2004 22:29:18 +0000 Subject: [PATCH] 2004-03-25 Thomas Pfaff * libc/stdio/fclose.c (fclose): Protect file pointer list when releasing a file. * libc/stdio/fcloseall.c (_fcloseall_r): Close all files via fwalk. * libc/stdio/fdopen.c (_fdopen_r): Add calls to _flockfile/_funlockfile. * libc/stdio/findfp.c: Move __sfp_lock. Change __sfp_lock type to recursive. Change __lock_acquire/__lock_release calls for __sfp_lock to __sfp_lock_acquire/__sfp_lock_release throughout. (std): Make sure that file lock is only initialized once. (__sfp): Move _file initialization. Initialize file lock. (__sfp_lock_acquire): New function. (__sfp_lock_release): Ditto. (__fp_lock_all): Remove __sfp_lock_acquire call. (__fp_unlock_all): Remove __sfp_lock_release call. * libc/stdio/fopen.c (_fopen_r): Protect file pointer list. Add calls to _flockfile/_funlockfile. Remove __lock_init_recursive call. * libc/stdio/freopen.c (_freopen_r): Protect file pointer list. * libc/stdio/fwalk.c (__fwalk): New static function. (_fwalk): Protect file pointer list. Use __fwalk to walk through file pointers. * libc/stdio/local.h: Add defines for __sfp_lock_acquire/__sfp_lock_release when single threaded. Add function prototypes otherwise. * libc/stdio64/fdopen64.c (_fdopen64_r): Add calls to _flockfile/_funlockfile. * libc/stdio/fopen64.c (_fopen64_r): Protect file pointer list. Add calls to _flockfile/_funlockfile. Remove __lock_init_recursive call. * libc/stdio/freopen64.c (_freopen64_r): Protect file pointer list. --- newlib/ChangeLog | 36 +++++++++++++++++++++++++++ newlib/libc/stdio/fclose.c | 7 +++++- newlib/libc/stdio/fcloseall.c | 10 +------- newlib/libc/stdio/fdopen.c | 4 +++ newlib/libc/stdio/findfp.c | 42 ++++++++++++++++++------------- newlib/libc/stdio/fopen.c | 12 ++++++--- newlib/libc/stdio/freopen.c | 9 +++++-- newlib/libc/stdio/fwalk.c | 44 ++++++++++++++++++++++----------- newlib/libc/stdio/local.h | 8 ++++++ newlib/libc/stdio64/fdopen64.c | 8 +++--- newlib/libc/stdio64/fopen64.c | 12 ++++++--- newlib/libc/stdio64/freopen64.c | 11 ++++++++- 12 files changed, 147 insertions(+), 56 deletions(-) diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 1c7363ec4..9f2f066e2 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,39 @@ +2004-03-25 Thomas Pfaff + + * libc/stdio/fclose.c (fclose): Protect file pointer list when + releasing a file. + * libc/stdio/fcloseall.c (_fcloseall_r): Close all files via + fwalk. + * libc/stdio/fdopen.c (_fdopen_r): Add calls to + _flockfile/_funlockfile. + * libc/stdio/findfp.c: Move __sfp_lock. Change __sfp_lock type + to recursive. + Change __lock_acquire/__lock_release calls for __sfp_lock to + __sfp_lock_acquire/__sfp_lock_release throughout. + (std): Make sure that file lock is only initialized once. + (__sfp): Move _file initialization. Initialize file lock. + (__sfp_lock_acquire): New function. + (__sfp_lock_release): Ditto. + (__fp_lock_all): Remove __sfp_lock_acquire call. + (__fp_unlock_all): Remove __sfp_lock_release call. + * libc/stdio/fopen.c (_fopen_r): Protect file pointer list. + Add calls to _flockfile/_funlockfile. Remove + __lock_init_recursive call. + * libc/stdio/freopen.c (_freopen_r): Protect file pointer list. + * libc/stdio/fwalk.c (__fwalk): New static function. + (_fwalk): Protect file pointer list. Use __fwalk to walk through + file pointers. + * libc/stdio/local.h: Add defines for + __sfp_lock_acquire/__sfp_lock_release when + single threaded. Add function prototypes otherwise. + * libc/stdio64/fdopen64.c (_fdopen64_r): Add calls to + _flockfile/_funlockfile. + * libc/stdio/fopen64.c (_fopen64_r): Protect file pointer list. + Add calls to _flockfile/_funlockfile. Remove + __lock_init_recursive call. + * libc/stdio/freopen64.c (_freopen64_r): Protect file pointer + list. + 2004-03-25 Jeff Johnston * libc/sys/linux/sys/lock.h: Turn on __USE_GNU flag if not already diff --git a/newlib/libc/stdio/fclose.c b/newlib/libc/stdio/fclose.c index 1caeb4cde..a125f16ef 100644 --- a/newlib/libc/stdio/fclose.c +++ b/newlib/libc/stdio/fclose.c @@ -65,6 +65,8 @@ _DEFUN (fclose, (fp), if (fp == NULL) return (0); /* on NULL */ + __sfp_lock_acquire (); + _flockfile(fp); CHECK_INIT (fp); @@ -72,6 +74,7 @@ _DEFUN (fclose, (fp), if (fp->_flags == 0) /* not open! */ { _funlockfile(fp); + __sfp_lock_release (); return (0); } r = fp->_flags & __SWR ? fflush (fp) : 0; @@ -83,11 +86,13 @@ _DEFUN (fclose, (fp), FREEUB (fp); if (HASLB (fp)) FREELB (fp); + fp->_flags = 0; /* release this FILE for reuse */ _funlockfile(fp); #ifndef __SINGLE_THREAD__ __lock_close_recursive (*(_LOCK_RECURSIVE_T *)&fp->_lock); #endif - fp->_flags = 0; /* release this FILE for reuse */ + + __sfp_lock_release (); return (r); } diff --git a/newlib/libc/stdio/fcloseall.c b/newlib/libc/stdio/fcloseall.c index d51c6fe34..e5a3af277 100644 --- a/newlib/libc/stdio/fcloseall.c +++ b/newlib/libc/stdio/fcloseall.c @@ -66,15 +66,7 @@ int _fcloseall_r (ptr) struct _reent *ptr; { - register FILE *fp; - register int n, ret = 0; - register struct _glue *g; - - for (g = &ptr->__sglue; g != NULL; g = g->_next) - for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++) - if (fp->_flags != 0) - ret |= fclose (fp); - return ret; + return _fwalk (ptr, fclose); } #ifndef _REENT_ONLY diff --git a/newlib/libc/stdio/fdopen.c b/newlib/libc/stdio/fdopen.c index 0db6062dd..8c1555d34 100644 --- a/newlib/libc/stdio/fdopen.c +++ b/newlib/libc/stdio/fdopen.c @@ -76,6 +76,9 @@ _DEFUN (_fdopen_r, (ptr, fd, mode), if ((fp = __sfp (ptr)) == 0) return 0; + + _flockfile(fp); + fp->_flags = flags; /* * If opened for appending, but underlying descriptor @@ -111,6 +114,7 @@ _DEFUN (_fdopen_r, (ptr, fd, mode), fp->_flags |= __SCLE; #endif + _funlockfile(fp); return fp; } diff --git a/newlib/libc/stdio/findfp.c b/newlib/libc/stdio/findfp.c index 0ddbf9403..10f01b271 100644 --- a/newlib/libc/stdio/findfp.c +++ b/newlib/libc/stdio/findfp.c @@ -25,10 +25,6 @@ #include #include "local.h" -#ifndef __SINGLE_THREAD__ -__LOCK_INIT(static, __sfp_lock); -#endif - static void std (ptr, flags, file, data) FILE *ptr; @@ -49,8 +45,12 @@ std (ptr, flags, file, data) ptr->_write = __swrite; ptr->_seek = __sseek; ptr->_close = __sclose; -#ifndef __SINGLE_THREAD__ +#if !defined(__SINGLE_THREAD__) && !defined(_REENT_SMALL) __lock_init_recursive (*(_LOCK_RECURSIVE_T *)&ptr->_lock); + /* + * #else + * lock is already initialized in __sfp + */ #endif #ifdef __SCLE @@ -90,9 +90,7 @@ __sfp (d) int n; struct _glue *g; -#ifndef __SINGLE_THREAD__ - __lock_acquire(__sfp_lock); -#endif + __sfp_lock_acquire (); if (!_GLOBAL_REENT->__sdidinit) __sinit (_GLOBAL_REENT); @@ -105,24 +103,24 @@ __sfp (d) (g->_next = __sfmoreglue (d, NDYNAMIC)) == NULL) break; } -#ifndef __SINGLE_THREAD__ - __lock_release(__sfp_lock); -#endif + __sfp_lock_release (); d->_errno = ENOMEM; return NULL; found: + fp->_file = -1; /* no file */ fp->_flags = 1; /* reserve this slot; caller sets real flags */ #ifndef __SINGLE_THREAD__ - __lock_release(__sfp_lock); + __lock_init_recursive (*(_LOCK_RECURSIVE_T *)&fp->_lock); #endif + __sfp_lock_release (); + fp->_p = NULL; /* no current pointer */ fp->_w = 0; /* nothing to read or write */ fp->_r = 0; fp->_bf._base = NULL; /* no buffer */ fp->_bf._size = 0; fp->_lbfsize = 0; /* not line buffered */ - fp->_file = -1; /* no file */ /* fp->_cookie = ; */ /* caller sets cookie, _read/_write etc */ fp->_ub._base = NULL; /* no ungetc buffer */ fp->_ub._size = 0; @@ -197,6 +195,20 @@ __sinit (s) #ifndef __SINGLE_THREAD__ +__LOCK_INIT_RECURSIVE(static, __sfp_lock); + +void +__sfp_lock_acquire () +{ + __lock_acquire(__sfp_lock); +} + +void +__sfp_lock_release () +{ + __lock_release(__sfp_lock); +} + /* Walkable file locking routine. */ static int __fp_lock (ptr) @@ -220,8 +232,6 @@ __fp_unlock (ptr) void __fp_lock_all () { - __lock_acquire(__sfp_lock); - (void) _fwalk (_REENT, __fp_lock); } @@ -229,7 +239,5 @@ void __fp_unlock_all () { (void) _fwalk (_REENT, __fp_unlock); - - __lock_release(__sfp_lock); } #endif diff --git a/newlib/libc/stdio/fopen.c b/newlib/libc/stdio/fopen.c index bcd2287c5..844e6dc05 100644 --- a/newlib/libc/stdio/fopen.c +++ b/newlib/libc/stdio/fopen.c @@ -138,10 +138,17 @@ _DEFUN (_fopen_r, (ptr, file, mode), if ((f = _open_r (ptr, file, oflags, 0666)) < 0) { + __sfp_lock_acquire (); fp->_flags = 0; /* release */ +#ifndef __SINGLE_THREAD__ + __lock_close_recursive (*(_LOCK_RECURSIVE_T *)&fp->_lock); +#endif + __sfp_lock_release (); return NULL; } + _flockfile(fp); + fp->_file = f; fp->_flags = flags; fp->_cookie = (_PTR) fp; @@ -158,10 +165,7 @@ _DEFUN (_fopen_r, (ptr, file, mode), fp->_flags |= __SCLE; #endif -#ifndef __SINGLE_THREAD__ - __lock_init_recursive (*(_LOCK_RECURSIVE_T *)&fp->_lock); -#endif - + _funlockfile(fp); return fp; } diff --git a/newlib/libc/stdio/freopen.c b/newlib/libc/stdio/freopen.c index ba83dd215..dd42aaae1 100644 --- a/newlib/libc/stdio/freopen.c +++ b/newlib/libc/stdio/freopen.c @@ -87,14 +87,17 @@ _DEFUN (_freopen_r, (ptr, file, mode, fp), register int f; int flags, oflags, e; + __sfp_lock_acquire (); + _flockfile(fp); CHECK_INIT (fp); if ((flags = __sflags (ptr, mode, &oflags)) == 0) { - (void) fclose (fp); _funlockfile(fp); + (void) fclose (fp); + __sfp_lock_release (); return NULL; } @@ -148,12 +151,13 @@ _DEFUN (_freopen_r, (ptr, file, mode, fp), if (f < 0) { /* did not get it after all */ + fp->_flags = 0; /* set it free */ ptr->_errno = e; /* restore in case _close clobbered */ _funlockfile(fp); #ifndef __SINGLE_THREAD__ __lock_close_recursive (*(_LOCK_RECURSIVE_T *)&fp->_lock); #endif - fp->_flags = 0; /* set it free */ + __sfp_lock_release (); return NULL; } @@ -171,6 +175,7 @@ _DEFUN (_freopen_r, (ptr, file, mode, fp), #endif _funlockfile(fp); + __sfp_lock_release (); return fp; } diff --git a/newlib/libc/stdio/fwalk.c b/newlib/libc/stdio/fwalk.c index b147da3af..566fa4af8 100644 --- a/newlib/libc/stdio/fwalk.c +++ b/newlib/libc/stdio/fwalk.c @@ -26,8 +26,8 @@ static char sccsid[] = "%W% (Berkeley) %G%"; #include #include "local.h" -int -_fwalk (ptr, function) +static int +__fwalk (ptr, function) struct _reent *ptr; register int (*function) (); { @@ -35,20 +35,36 @@ _fwalk (ptr, function) register int n, ret = 0; register struct _glue *g; - /* Must traverse given list for std streams. */ - if (ptr != _GLOBAL_REENT) - { - for (g = &ptr->__sglue; g != NULL; g = g->_next) - for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++) - if (fp->_flags != 0) - ret |= (*function) (fp); - } - - /* Must traverse global list for all other streams. */ - for (g = &_GLOBAL_REENT->__sglue; g != NULL; g = g->_next) + for (g = &ptr->__sglue; g != NULL; g = g->_next) for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++) if (fp->_flags != 0) - ret |= (*function) (fp); + { + _flockfile (fp); + if (fp->_flags != 0 && fp->_file != -1) + ret |= (*function) (fp); + _funlockfile (fp); + } + + return ret; +} + +int +_fwalk (ptr, function) + struct _reent *ptr; + register int (*function) (); +{ + register int ret = 0; + + __sfp_lock_acquire (); + + /* Must traverse given list for std streams. */ + if (ptr != _GLOBAL_REENT) + ret |= __fwalk (ptr, function); + + /* Must traverse global list for all other streams. */ + ret |= __fwalk (_GLOBAL_REENT, function); + + __sfp_lock_release (); return ret; } diff --git a/newlib/libc/stdio/local.h b/newlib/libc/stdio/local.h index b4f4457fc..d97a03e9a 100644 --- a/newlib/libc/stdio/local.h +++ b/newlib/libc/stdio/local.h @@ -87,3 +87,11 @@ char *_EXFUN(_llicvt,(char *, long long, char)); #define CVT_BUF_SIZE 128 #define NDYNAMIC 4 /* add four more whenever necessary */ + +#ifdef __SINGLE_THREAD__ +#define __sfp_lock_acquire() +#define __sfp_lock_release() +#else +void _EXFUN(__sfp_lock_acquire,(void)); +void _EXFUN(__sfp_lock_release,(void)); +#endif diff --git a/newlib/libc/stdio64/fdopen64.c b/newlib/libc/stdio64/fdopen64.c index d0fd0d584..aa5a9ce56 100644 --- a/newlib/libc/stdio64/fdopen64.c +++ b/newlib/libc/stdio64/fdopen64.c @@ -63,6 +63,9 @@ _DEFUN (_fdopen64_r, (ptr, fd, mode), if ((fp = __sfp (ptr)) == 0) return 0; + + _flockfile(fp); + fp->_flags = flags; /* * If opened for appending, but underlying descriptor @@ -99,12 +102,9 @@ _DEFUN (_fdopen64_r, (ptr, fd, mode), fp->_flags |= __SCLE; #endif -#ifndef __SINGLE_THREAD__ - __lock_init_recursive (*(_LOCK_RECURSIVE_T *)&fp->_lock); -#endif - fp->_flags |= __SL64; + _funlockfile(fp); return fp; } diff --git a/newlib/libc/stdio64/fopen64.c b/newlib/libc/stdio64/fopen64.c index 3c69820ee..1feffd1db 100644 --- a/newlib/libc/stdio64/fopen64.c +++ b/newlib/libc/stdio64/fopen64.c @@ -91,10 +91,17 @@ _DEFUN (_fopen64_r, (ptr, file, mode), if ((f = _open64_r (ptr, file, oflags, 0666)) < 0) { + __sfp_lock_acquire (); fp->_flags = 0; /* release */ +#ifndef __SINGLE_THREAD__ + __lock_close_recursive (*(_LOCK_RECURSIVE_T *)&fp->_lock); +#endif + __sfp_lock_release (); return NULL; } + _flockfile(fp); + fp->_file = f; fp->_flags = flags; fp->_cookie = (_PTR) fp; @@ -114,10 +121,7 @@ _DEFUN (_fopen64_r, (ptr, file, mode), fp->_flags |= __SL64; -#ifndef __SINGLE_THREAD__ - __lock_init_recursive (*(_LOCK_RECURSIVE_T *)&fp->_lock); -#endif - + _funlockfile(fp); return fp; } diff --git a/newlib/libc/stdio64/freopen64.c b/newlib/libc/stdio64/freopen64.c index 6e4586cd9..c28cbeee2 100644 --- a/newlib/libc/stdio64/freopen64.c +++ b/newlib/libc/stdio64/freopen64.c @@ -70,6 +70,7 @@ Supporting OS subroutines required: <>, <>, <>, #include #include #include +#include #include "local64.h" /* @@ -88,14 +89,17 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp), register int f; int flags, oflags, e; + __sfp_lock_acquire (); + _flockfile(fp); CHECK_INIT (fp); if ((flags = __sflags (ptr, mode, &oflags)) == 0) { - (void) fclose (fp); _funlockfile(fp); + (void) fclose (fp); + __sfp_lock_release (); return NULL; } @@ -152,6 +156,10 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp), fp->_flags = 0; /* set it free */ ptr->_errno = e; /* restore in case _close clobbered */ _funlockfile(fp); +#ifndef __SINGLE_THREAD__ + __lock_close_recursive (*(_LOCK_RECURSIVE_T *)&fp->_lock); +#endif + __sfp_lock_release (); return NULL; } @@ -172,6 +180,7 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp), fp->_flags |= __SL64; _funlockfile(fp); + __sfp_lock_release (); return fp; }