From 4aa28d8ae279329f2b46c92e05b0bf457f07b9af Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 30 May 2012 08:58:42 +0000 Subject: [PATCH] * libc/stdio/local.h (_newlib_flockfile_start): New macro to secure stream related critical section against thread cancellation. (_newlib_flockfile_exit): Ditto. (_newlib_sfp_lock_end): Ditto. (_newlib_sfp_lock_start): Ditto for the list of streams. (_newlib_sfp_lock_exit): Ditto. (_newlib_sfp_lock_end): Ditto. Use aforementioned macros in place of _flockfile/_funlockfile and __sfp_lock_acquire/__sfp_lock_release throughout the code. * libc/stdio/fclose.c: Explicitely disable and re-enable thread cancellation. Explain why. * libc/stdio/freopen.c: Ditto. * libc/stdio64/freopen64.c: Ditto. --- newlib/ChangeLog | 16 +++++++ newlib/libc/stdio/clearerr.c | 4 +- newlib/libc/stdio/fclose.c | 12 +++++ newlib/libc/stdio/fdopen.c | 4 +- newlib/libc/stdio/feof.c | 4 +- newlib/libc/stdio/ferror.c | 4 +- newlib/libc/stdio/fflush.c | 4 +- newlib/libc/stdio/fgetc.c | 8 ++-- newlib/libc/stdio/fgets.c | 12 ++--- newlib/libc/stdio/fgetwc.c | 4 +- newlib/libc/stdio/fgetws.c | 6 +-- newlib/libc/stdio/fileno.c | 4 +- newlib/libc/stdio/findfp.c | 6 +-- newlib/libc/stdio/fmemopen.c | 8 ++-- newlib/libc/stdio/fopen.c | 8 ++-- newlib/libc/stdio/fopencookie.c | 8 ++-- newlib/libc/stdio/fpurge.c | 6 +-- newlib/libc/stdio/fputc.c | 8 ++-- newlib/libc/stdio/fputs.c | 4 +- newlib/libc/stdio/fputwc.c | 4 +- newlib/libc/stdio/fputws.c | 6 +-- newlib/libc/stdio/fread.c | 14 +++--- newlib/libc/stdio/freopen.c | 15 ++++++ newlib/libc/stdio/fseek.c | 18 +++---- newlib/libc/stdio/ftell.c | 8 ++-- newlib/libc/stdio/funopen.c | 8 ++-- newlib/libc/stdio/fwide.c | 4 +- newlib/libc/stdio/fwrite.c | 6 +-- newlib/libc/stdio/getc.c | 8 ++-- newlib/libc/stdio/getdelim.c | 4 +- newlib/libc/stdio/gets.c | 7 +-- newlib/libc/stdio/local.h | 77 ++++++++++++++++++++++++++++++ newlib/libc/stdio/open_memstream.c | 12 ++--- newlib/libc/stdio/putc.c | 8 ++-- newlib/libc/stdio/setvbuf.c | 8 ++-- newlib/libc/stdio/ungetc.c | 14 +++--- newlib/libc/stdio/ungetwc.c | 4 +- newlib/libc/stdio/vfprintf.c | 8 ++-- newlib/libc/stdio/vfscanf.c | 18 +++---- newlib/libc/stdio/vfwprintf.c | 8 ++-- newlib/libc/stdio/vfwscanf.c | 18 +++---- newlib/libc/stdio64/fdopen64.c | 4 +- newlib/libc/stdio64/fopen64.c | 8 ++-- newlib/libc/stdio64/freopen64.c | 23 +++++++-- newlib/libc/stdio64/fseeko64.c | 12 ++--- newlib/libc/stdio64/ftello64.c | 8 ++-- 46 files changed, 301 insertions(+), 161 deletions(-) diff --git a/newlib/ChangeLog b/newlib/ChangeLog index d51b87f01..b40d62abb 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,19 @@ +2012-05-30 Corinna Vinschen + + * libc/stdio/local.h (_newlib_flockfile_start): New macro to + secure stream related critical section against thread cancellation. + (_newlib_flockfile_exit): Ditto. + (_newlib_sfp_lock_end): Ditto. + (_newlib_sfp_lock_start): Ditto for the list of streams. + (_newlib_sfp_lock_exit): Ditto. + (_newlib_sfp_lock_end): Ditto. + Use aforementioned macros in place of _flockfile/_funlockfile + and __sfp_lock_acquire/__sfp_lock_release throughout the code. + * libc/stdio/fclose.c: Explicitely disable and re-enable thread + cancellation. Explain why. + * libc/stdio/freopen.c: Ditto. + * libc/stdio64/freopen64.c: Ditto. + 2012-05-21 Sandeep Kumar Singh * libc/machine/cr16/asm.h: Added some missing instructions diff --git a/newlib/libc/stdio/clearerr.c b/newlib/libc/stdio/clearerr.c index d3b620bed..ed4603ba2 100644 --- a/newlib/libc/stdio/clearerr.c +++ b/newlib/libc/stdio/clearerr.c @@ -65,7 +65,7 @@ _DEFUN(clearerr, (fp), FILE * fp) { CHECK_INIT(_REENT, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); __sclearerr (fp); - _funlockfile (fp); + _newlib_flockfile_end (fp); } diff --git a/newlib/libc/stdio/fclose.c b/newlib/libc/stdio/fclose.c index 3c8868a51..790496413 100644 --- a/newlib/libc/stdio/fclose.c +++ b/newlib/libc/stdio/fclose.c @@ -76,11 +76,20 @@ _DEFUN(_fclose_r, (rptr, fp), CHECK_INIT (rptr, fp); + /* We can't use the _newlib_flockfile_XXX macros here due to the + interlocked locking with the sfp_lock. */ +#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) + int __oldcancel; + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldcancel); +#endif _flockfile (fp); if (fp->_flags == 0) /* not open! */ { _funlockfile (fp); +#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) + pthread_setcancelstate (__oldcancel, &__oldcancel); +#endif return (0); } /* Unconditionally flush to allow special handling for seekable read @@ -103,6 +112,9 @@ _DEFUN(_fclose_r, (rptr, fp), #endif __sfp_lock_release (); +#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) + pthread_setcancelstate (__oldcancel, &__oldcancel); +#endif return (r); } diff --git a/newlib/libc/stdio/fdopen.c b/newlib/libc/stdio/fdopen.c index aa764c372..77f599b65 100644 --- a/newlib/libc/stdio/fdopen.c +++ b/newlib/libc/stdio/fdopen.c @@ -93,7 +93,7 @@ _DEFUN(_fdopen_r, (ptr, fd, mode), if ((fp = __sfp (ptr)) == 0) return 0; - _flockfile (fp); + _newlib_flockfile_start (fp); fp->_flags = flags; /* POSIX recommends setting the O_APPEND bit on fd to match append @@ -127,7 +127,7 @@ _DEFUN(_fdopen_r, (ptr, fd, mode), fp->_flags |= __SCLE; #endif - _funlockfile (fp); + _newlib_flockfile_end (fp); return fp; } diff --git a/newlib/libc/stdio/feof.c b/newlib/libc/stdio/feof.c index e8db65b86..c0216ffed 100644 --- a/newlib/libc/stdio/feof.c +++ b/newlib/libc/stdio/feof.c @@ -58,8 +58,8 @@ _DEFUN(feof, (fp), { int result; CHECK_INIT(_REENT, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); result = __sfeof (fp); - _funlockfile (fp); + _newlib_flockfile_end (fp); return result; } diff --git a/newlib/libc/stdio/ferror.c b/newlib/libc/stdio/ferror.c index 72b7ce2c5..0cd3c3089 100644 --- a/newlib/libc/stdio/ferror.c +++ b/newlib/libc/stdio/ferror.c @@ -67,8 +67,8 @@ _DEFUN(ferror, (fp), { int result; CHECK_INIT(_REENT, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); result = __sferror (fp); - _funlockfile (fp); + _newlib_flockfile_end (fp); return result; } diff --git a/newlib/libc/stdio/fflush.c b/newlib/libc/stdio/fflush.c index 130c148c9..b2bde7af5 100644 --- a/newlib/libc/stdio/fflush.c +++ b/newlib/libc/stdio/fflush.c @@ -226,9 +226,9 @@ _DEFUN(_fflush_r, (ptr, fp), if (!fp->_flags) return 0; - _flockfile (fp); + _newlib_flockfile_start (fp); ret = __sflush_r (ptr, fp); - _funlockfile (fp); + _newlib_flockfile_end (fp); return ret; } diff --git a/newlib/libc/stdio/fgetc.c b/newlib/libc/stdio/fgetc.c index e275cfeeb..99d8330fe 100644 --- a/newlib/libc/stdio/fgetc.c +++ b/newlib/libc/stdio/fgetc.c @@ -78,9 +78,9 @@ _DEFUN(_fgetc_r, (ptr, fp), { int result; CHECK_INIT(ptr, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); result = __sgetc_r (ptr, fp); - _funlockfile (fp); + _newlib_flockfile_end (fp); return result; } @@ -93,9 +93,9 @@ _DEFUN(fgetc, (fp), #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) int result; CHECK_INIT(_REENT, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); result = __sgetc_r (_REENT, fp); - _funlockfile (fp); + _newlib_flockfile_end (fp); return result; #else return _fgetc_r (_REENT, fp); diff --git a/newlib/libc/stdio/fgets.c b/newlib/libc/stdio/fgets.c index 7f02e3fcb..1644fba6a 100644 --- a/newlib/libc/stdio/fgets.c +++ b/newlib/libc/stdio/fgets.c @@ -98,7 +98,7 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp), CHECK_INIT(ptr, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); #ifdef __SCLE if (fp->_flags & __SCLE) { @@ -112,11 +112,11 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp), } if (c == EOF && s == buf) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return NULL; } *s = 0; - _funlockfile (fp); + _newlib_flockfile_exit (fp); return buf; } #endif @@ -134,7 +134,7 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp), /* EOF: stop with partial or no line */ if (s == buf) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return 0; } break; @@ -159,7 +159,7 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp), fp->_p = t; _CAST_VOID memcpy ((_PTR) s, (_PTR) p, len); s[len] = 0; - _funlockfile (fp); + _newlib_flockfile_exit (fp); return (buf); } fp->_r -= len; @@ -169,7 +169,7 @@ _DEFUN(_fgets_r, (ptr, buf, n, fp), } while ((n -= len) != 0); *s = 0; - _funlockfile (fp); + _newlib_flockfile_end (fp); return buf; } diff --git a/newlib/libc/stdio/fgetwc.c b/newlib/libc/stdio/fgetwc.c index 38a79bc7c..0eaaecb2f 100644 --- a/newlib/libc/stdio/fgetwc.c +++ b/newlib/libc/stdio/fgetwc.c @@ -164,10 +164,10 @@ _DEFUN(_fgetwc_r, (ptr, fp), { wint_t r; - _flockfile (fp); + _newlib_flockfile_start (fp); ORIENT(fp, 1); r = __fgetwc (ptr, fp); - _funlockfile (fp); + _newlib_flockfile_end (fp); return r; } diff --git a/newlib/libc/stdio/fgetws.c b/newlib/libc/stdio/fgetws.c index 2784f1513..cbfd84eb2 100644 --- a/newlib/libc/stdio/fgetws.c +++ b/newlib/libc/stdio/fgetws.c @@ -93,7 +93,7 @@ _DEFUN(_fgetws_r, (ptr, ws, n, fp), const char *src; unsigned char *nl; - _flockfile (fp); + _newlib_flockfile_start (fp); ORIENT (fp, 1); if (n <= 0) @@ -142,11 +142,11 @@ _DEFUN(_fgetws_r, (ptr, ws, n, fp), /* Incomplete character */ goto error; *wsp++ = L'\0'; - _funlockfile (fp); + _newlib_flockfile_exit (fp); return ws; error: - _funlockfile (fp); + _newlib_flockfile_end (fp); return NULL; } diff --git a/newlib/libc/stdio/fileno.c b/newlib/libc/stdio/fileno.c index db399eb12..818f1a1ca 100644 --- a/newlib/libc/stdio/fileno.c +++ b/newlib/libc/stdio/fileno.c @@ -55,8 +55,8 @@ _DEFUN(fileno, (f), { int result; CHECK_INIT (_REENT, f); - _flockfile (f); + _newlib_flockfile_start (f); result = __sfileno (f); - _funlockfile (f); + _newlib_flockfile_end (f); return result; } diff --git a/newlib/libc/stdio/findfp.c b/newlib/libc/stdio/findfp.c index d81241434..e39660cd4 100644 --- a/newlib/libc/stdio/findfp.c +++ b/newlib/libc/stdio/findfp.c @@ -108,7 +108,7 @@ _DEFUN(__sfp, (d), int n; struct _glue *g; - __sfp_lock_acquire (); + _newlib_sfp_lock_start (); if (!_GLOBAL_REENT->__sdidinit) __sinit (_GLOBAL_REENT); @@ -121,7 +121,7 @@ _DEFUN(__sfp, (d), (g->_next = __sfmoreglue (d, NDYNAMIC)) == NULL) break; } - __sfp_lock_release (); + _newlib_sfp_lock_exit (); d->_errno = ENOMEM; return NULL; @@ -132,7 +132,7 @@ found: #ifndef __SINGLE_THREAD__ __lock_init_recursive (fp->_lock); #endif - __sfp_lock_release (); + _newlib_sfp_lock_end (); fp->_p = NULL; /* no current pointer */ fp->_w = 0; /* nothing to read or write */ diff --git a/newlib/libc/stdio/fmemopen.c b/newlib/libc/stdio/fmemopen.c index 5218e8a98..acfb23c1b 100644 --- a/newlib/libc/stdio/fmemopen.c +++ b/newlib/libc/stdio/fmemopen.c @@ -291,12 +291,12 @@ _DEFUN(_fmemopen_r, (ptr, buf, size, mode), if ((c = (fmemcookie *) _malloc_r (ptr, sizeof *c + (buf ? 0 : size))) == NULL) { - __sfp_lock_acquire (); + _newlib_sfp_lock_start (); fp->_flags = 0; /* release */ #ifndef __SINGLE_THREAD__ __lock_close_recursive (fp->_lock); #endif - __sfp_lock_release (); + _newlib_sfp_lock_end (); return NULL; } @@ -343,7 +343,7 @@ _DEFUN(_fmemopen_r, (ptr, buf, size, mode), } } - _flockfile (fp); + _newlib_flockfile_start (fp); fp->_file = -1; fp->_flags = flags; fp->_cookie = c; @@ -355,7 +355,7 @@ _DEFUN(_fmemopen_r, (ptr, buf, size, mode), fp->_flags |= __SL64; #endif fp->_close = fmemcloser; - _funlockfile (fp); + _newlib_flockfile_end (fp); return fp; } diff --git a/newlib/libc/stdio/fopen.c b/newlib/libc/stdio/fopen.c index 64c24e7ef..27d4bc810 100644 --- a/newlib/libc/stdio/fopen.c +++ b/newlib/libc/stdio/fopen.c @@ -140,16 +140,16 @@ _DEFUN(_fopen_r, (ptr, file, mode), if ((f = _open_r (ptr, file, oflags, 0666)) < 0) { - __sfp_lock_acquire (); + _newlib_sfp_lock_start (); fp->_flags = 0; /* release */ #ifndef __SINGLE_THREAD__ __lock_close_recursive (fp->_lock); #endif - __sfp_lock_release (); + _newlib_sfp_lock_end (); return NULL; } - _flockfile (fp); + _newlib_flockfile_start (fp); fp->_file = f; fp->_flags = flags; @@ -167,7 +167,7 @@ _DEFUN(_fopen_r, (ptr, file, mode), fp->_flags |= __SCLE; #endif - _funlockfile (fp); + _newlib_flockfile_end (fp); return fp; } diff --git a/newlib/libc/stdio/fopencookie.c b/newlib/libc/stdio/fopencookie.c index 5148c8a1a..f08d13289 100644 --- a/newlib/libc/stdio/fopencookie.c +++ b/newlib/libc/stdio/fopencookie.c @@ -219,16 +219,16 @@ _DEFUN(_fopencookie_r, (ptr, cookie, mode, functions), return NULL; if ((c = (fccookie *) _malloc_r (ptr, sizeof *c)) == NULL) { - __sfp_lock_acquire (); + _newlib_sfp_lock_start (); fp->_flags = 0; /* release */ #ifndef __SINGLE_THREAD__ __lock_close_recursive (fp->_lock); #endif - __sfp_lock_release (); + _newlib_sfp_lock_end (); return NULL; } - _flockfile (fp); + _newlib_flockfile_start (fp); fp->_file = -1; fp->_flags = flags; c->cookie = cookie; @@ -246,7 +246,7 @@ _DEFUN(_fopencookie_r, (ptr, cookie, mode, functions), #endif c->closefn = functions.close; fp->_close = fccloser; - _funlockfile (fp); + _newlib_flockfile_end (fp); return fp; } diff --git a/newlib/libc/stdio/fpurge.c b/newlib/libc/stdio/fpurge.c index 7e23bb7fd..dc052e85b 100644 --- a/newlib/libc/stdio/fpurge.c +++ b/newlib/libc/stdio/fpurge.c @@ -68,13 +68,13 @@ _DEFUN(_fpurge_r, (ptr, fp), CHECK_INIT (ptr, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); t = fp->_flags; if (!t) { ptr->_errno = EBADF; - _funlockfile (fp); + _newlib_flockfile_exit (fp); return EOF; } fp->_p = fp->_bf._base; @@ -86,7 +86,7 @@ _DEFUN(_fpurge_r, (ptr, fp), } else fp->_w = t & (__SLBF | __SNBF) ? 0 : fp->_bf._size; - _funlockfile (fp); + _newlib_flockfile_end (fp); return 0; } diff --git a/newlib/libc/stdio/fputc.c b/newlib/libc/stdio/fputc.c index 777a34242..6af79d470 100644 --- a/newlib/libc/stdio/fputc.c +++ b/newlib/libc/stdio/fputc.c @@ -83,9 +83,9 @@ _DEFUN(_fputc_r, (ptr, ch, file), { int result; CHECK_INIT(ptr, file); - _flockfile (file); + _newlib_flockfile_start (file); result = _putc_r (ptr, ch, file); - _funlockfile (file); + _newlib_flockfile_end (file); return result; } @@ -98,9 +98,9 @@ _DEFUN(fputc, (ch, file), #if !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED) int result; CHECK_INIT(_REENT, file); - _flockfile (file); + _newlib_flockfile_start (file); result = _putc_r (_REENT, ch, file); - _funlockfile (file); + _newlib_flockfile_end (file); return result; #else return _fputc_r (_REENT, ch, file); diff --git a/newlib/libc/stdio/fputs.c b/newlib/libc/stdio/fputs.c index a32dea4e2..6e623a530 100644 --- a/newlib/libc/stdio/fputs.c +++ b/newlib/libc/stdio/fputs.c @@ -88,10 +88,10 @@ _DEFUN(_fputs_r, (ptr, s, fp), CHECK_INIT(ptr, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); ORIENT (fp, -1); result = __sfvwrite_r (ptr, fp, &uio); - _funlockfile (fp); + _newlib_flockfile_end (fp); return result; } diff --git a/newlib/libc/stdio/fputwc.c b/newlib/libc/stdio/fputwc.c index f32d56675..74e7a452c 100644 --- a/newlib/libc/stdio/fputwc.c +++ b/newlib/libc/stdio/fputwc.c @@ -160,10 +160,10 @@ _DEFUN(_fputwc_r, (ptr, wc, fp), { wint_t r; - _flockfile (fp); + _newlib_flockfile_start (fp); ORIENT(fp, 1); r = __fputwc(ptr, wc, fp); - _funlockfile (fp); + _newlib_flockfile_end (fp); return r; } diff --git a/newlib/libc/stdio/fputws.c b/newlib/libc/stdio/fputws.c index b8e5d1e0b..c88111cb0 100644 --- a/newlib/libc/stdio/fputws.c +++ b/newlib/libc/stdio/fputws.c @@ -87,7 +87,7 @@ _DEFUN(_fputws_r, (ptr, ws, fp), struct __suio uio; struct __siov iov; - _flockfile (fp); + _newlib_flockfile_start (fp); ORIENT (fp, 1); if (cantwrite (ptr, fp) != 0) goto error; @@ -104,11 +104,11 @@ _DEFUN(_fputws_r, (ptr, ws, fp), goto error; } while (ws != NULL); - _funlockfile (fp); + _newlib_flockfile_exit (fp); return (0); error: - _funlockfile(fp); + _newlib_flockfile_end(fp); return (-1); } diff --git a/newlib/libc/stdio/fread.c b/newlib/libc/stdio/fread.c index a39e9d85f..07fe0af5c 100644 --- a/newlib/libc/stdio/fread.c +++ b/newlib/libc/stdio/fread.c @@ -146,7 +146,7 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp), CHECK_INIT(ptr, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); ORIENT (fp, -1); if (fp->_r < 0) fp->_r = 0; @@ -195,11 +195,11 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp), #ifdef __SCLE if (fp->_flags & __SCLE) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return crlf_r (ptr, fp, buf, total-resid, 1) / size; } #endif - _funlockfile (fp); + _newlib_flockfile_exit (fp); return (total - resid) / size; } } @@ -220,11 +220,11 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp), #ifdef __SCLE if (fp->_flags & __SCLE) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return crlf_r (ptr, fp, buf, total-resid, 1) / size; } #endif - _funlockfile (fp); + _newlib_flockfile_exit (fp); return (total - resid) / size; } } @@ -237,11 +237,11 @@ _DEFUN(_fread_r, (ptr, buf, size, count, fp), #ifdef __SCLE if (fp->_flags & __SCLE) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return crlf_r(ptr, fp, buf, total, 0) / size; } #endif - _funlockfile (fp); + _newlib_flockfile_end (fp); return count; } diff --git a/newlib/libc/stdio/freopen.c b/newlib/libc/stdio/freopen.c index 172006259..6483655bf 100644 --- a/newlib/libc/stdio/freopen.c +++ b/newlib/libc/stdio/freopen.c @@ -100,11 +100,20 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp), CHECK_INIT (ptr, fp); + /* We can't use the _newlib_flockfile_XXX macros here due to the + interlocked locking with the sfp_lock. */ +#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) + int __oldcancel; + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldcancel); +#endif _flockfile (fp); if ((flags = __sflags (ptr, mode, &oflags)) == 0) { _funlockfile (fp); +#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) + pthread_setcancelstate (__oldcancel, &__oldcancel); +#endif _fclose_r (ptr, fp); return NULL; } @@ -213,6 +222,9 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp), __lock_close_recursive (fp->_lock); #endif __sfp_lock_release (); +#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) + pthread_setcancelstate (__oldcancel, &__oldcancel); +#endif return NULL; } @@ -230,6 +242,9 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp), #endif _funlockfile (fp); +#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) + pthread_setcancelstate (__oldcancel, &__oldcancel); +#endif return fp; } diff --git a/newlib/libc/stdio/fseek.c b/newlib/libc/stdio/fseek.c index c78d2b26c..099a95892 100644 --- a/newlib/libc/stdio/fseek.c +++ b/newlib/libc/stdio/fseek.c @@ -138,7 +138,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), CHECK_INIT (ptr, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); /* If we've been doing some writing, and we're in append mode then we don't really know where the filepos is. */ @@ -154,7 +154,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), if ((seekfn = fp->_seek) == NULL) { ptr->_errno = ESPIPE; /* ??? */ - _funlockfile (fp); + _newlib_flockfile_exit (fp); return EOF; } @@ -179,7 +179,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), curoff = seekfn (ptr, fp->_cookie, (_fpos_t) 0, SEEK_CUR); if (curoff == -1L) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return EOF; } } @@ -204,7 +204,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), default: ptr->_errno = EINVAL; - _funlockfile (fp); + _newlib_flockfile_exit (fp); return (EOF); } @@ -263,7 +263,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), if ((long)target != target) { ptr->_errno = EOVERFLOW; - _funlockfile (fp); + _newlib_flockfile_exit (fp); return EOF; } @@ -319,7 +319,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), FREEUB (ptr, fp); fp->_flags &= ~__SEOF; memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); - _funlockfile (fp); + _newlib_flockfile_exit (fp); return 0; } @@ -349,7 +349,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence), fp->_r -= n; } memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); - _funlockfile (fp); + _newlib_flockfile_exit (fp); return 0; /* @@ -361,7 +361,7 @@ dumb: if (_fflush_r (ptr, fp) || seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return EOF; } /* success: clear EOF indicator and discard ungetc() data */ @@ -379,7 +379,7 @@ dumb: is performed. */ fp->_flags &= ~__SNPT; memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); - _funlockfile (fp); + _newlib_flockfile_end (fp); return 0; } diff --git a/newlib/libc/stdio/ftell.c b/newlib/libc/stdio/ftell.c index 816cafa76..54a656c09 100644 --- a/newlib/libc/stdio/ftell.c +++ b/newlib/libc/stdio/ftell.c @@ -109,12 +109,12 @@ _DEFUN(_ftell_r, (ptr, fp), CHECK_INIT (ptr, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); if (fp->_seek == NULL) { ptr->_errno = ESPIPE; - _funlockfile (fp); + _newlib_flockfile_exit (fp); return -1L; } @@ -131,7 +131,7 @@ _DEFUN(_ftell_r, (ptr, fp), pos = fp->_seek (ptr, fp->_cookie, (_fpos_t) 0, SEEK_CUR); if (pos == -1L) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return pos; } } @@ -156,7 +156,7 @@ _DEFUN(_ftell_r, (ptr, fp), pos += fp->_p - fp->_bf._base; } - _funlockfile (fp); + _newlib_flockfile_end (fp); if ((long)pos != pos) { pos = -1; diff --git a/newlib/libc/stdio/funopen.c b/newlib/libc/stdio/funopen.c index 35a274f7b..065ed93d7 100644 --- a/newlib/libc/stdio/funopen.c +++ b/newlib/libc/stdio/funopen.c @@ -214,16 +214,16 @@ _DEFUN(_funopen_r, (ptr, cookie, readfn, writefn, seekfn, closefn), return NULL; if ((c = (funcookie *) _malloc_r (ptr, sizeof *c)) == NULL) { - __sfp_lock_acquire (); + _newlib_sfp_lock_start (); fp->_flags = 0; /* release */ #ifndef __SINGLE_THREAD__ __lock_close_recursive (fp->_lock); #endif - __sfp_lock_release (); + _newlib_sfp_lock_end (); return NULL; } - _flockfile (fp); + _newlib_flockfile_start (fp); fp->_file = -1; c->cookie = (void *) cookie; /* cast away const */ fp->_cookie = c; @@ -260,7 +260,7 @@ _DEFUN(_funopen_r, (ptr, cookie, readfn, writefn, seekfn, closefn), #endif c->closefn = closefn; fp->_close = funcloser; - _funlockfile (fp); + _newlib_flockfile_end (fp); return fp; } diff --git a/newlib/libc/stdio/fwide.c b/newlib/libc/stdio/fwide.c index e298f911a..a060d8f65 100644 --- a/newlib/libc/stdio/fwide.c +++ b/newlib/libc/stdio/fwide.c @@ -68,7 +68,7 @@ _DEFUN(_fwide_r, (ptr, fp, mode), CHECK_INIT(ptr, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); if (mode != 0) { ORIENT (fp, mode); } @@ -76,7 +76,7 @@ _DEFUN(_fwide_r, (ptr, fp, mode), ret = 0; else ret = (fp->_flags2 & __SWID) ? 1 : -1; - _funlockfile (fp); + _newlib_flockfile_end (fp); return ret; } diff --git a/newlib/libc/stdio/fwrite.c b/newlib/libc/stdio/fwrite.c index ce77c8dc1..dc218050e 100644 --- a/newlib/libc/stdio/fwrite.c +++ b/newlib/libc/stdio/fwrite.c @@ -119,14 +119,14 @@ _DEFUN(_fwrite_r, (ptr, buf, size, count, fp), CHECK_INIT(ptr, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); ORIENT (fp, -1); if (__sfvwrite_r (ptr, fp, &uio) == 0) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return count; } - _funlockfile (fp); + _newlib_flockfile_end (fp); return (n - uio.uio_resid) / size; } diff --git a/newlib/libc/stdio/getc.c b/newlib/libc/stdio/getc.c index 5b1fa888a..355b19131 100644 --- a/newlib/libc/stdio/getc.c +++ b/newlib/libc/stdio/getc.c @@ -92,9 +92,9 @@ _DEFUN(_getc_r, (ptr, fp), { int result; CHECK_INIT (ptr, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); result = __sgetc_r (ptr, fp); - _funlockfile (fp); + _newlib_flockfile_end (fp); return result; } @@ -106,9 +106,9 @@ _DEFUN(getc, (fp), { int result; CHECK_INIT (_REENT, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); result = __sgetc_r (_REENT, fp); - _funlockfile (fp); + _newlib_flockfile_end (fp); return result; } diff --git a/newlib/libc/stdio/getdelim.c b/newlib/libc/stdio/getdelim.c index 23fc50218..63a579a79 100644 --- a/newlib/libc/stdio/getdelim.c +++ b/newlib/libc/stdio/getdelim.c @@ -81,7 +81,7 @@ _DEFUN(__getdelim, (bufptr, n, delim, fp), CHECK_INIT (_REENT, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); numbytes = *n; ptr = buf; @@ -129,7 +129,7 @@ _DEFUN(__getdelim, (bufptr, n, delim, fp), } } - _funlockfile (fp); + _newlib_flockfile_end (fp); /* if no input data, return failure */ if (ptr == buf) diff --git a/newlib/libc/stdio/gets.c b/newlib/libc/stdio/gets.c index 17d144316..f51d46196 100644 --- a/newlib/libc/stdio/gets.c +++ b/newlib/libc/stdio/gets.c @@ -70,6 +70,7 @@ Supporting OS subroutines required: <>, <>, <>, #include <_ansi.h> #include #include +#include "local.h" char * _DEFUN(_gets_r, (ptr, buf), @@ -79,12 +80,12 @@ _DEFUN(_gets_r, (ptr, buf), register int c; register char *s = buf; - _flockfile (stdin); + _newlib_flockfile_start (stdin); while ((c = __sgetc_r (ptr, stdin)) != '\n') if (c == EOF) if (s == buf) { - _funlockfile (stdin); + _newlib_flockfile_exit (stdin); return NULL; } else @@ -92,7 +93,7 @@ _DEFUN(_gets_r, (ptr, buf), else *s++ = c; *s = 0; - _funlockfile (stdin); + _newlib_flockfile_end (stdin); return buf; } diff --git a/newlib/libc/stdio/local.h b/newlib/libc/stdio/local.h index 187f7d858..aeeb0e8ee 100644 --- a/newlib/libc/stdio/local.h +++ b/newlib/libc/stdio/local.h @@ -32,6 +32,83 @@ # include #endif +/* The following macros are supposed to replace calls to _flockfile/_funlockfile + and __sfp_lock_acquire/__sfp_lock_release. In case of multi-threaded + environments using pthreads, it's not sufficient to lock the stdio functions + against concurrent threads accessing the same data, the locking must also be + secured against thread cancellation. + + The below macros have to be used in pairs. The _newlib_XXX_start macro + starts with a opening curly brace, the _newlib_XXX_end macro ends with a + closing curly brace, so the start macro and the end macro mark the code + start and end of a critical section. In case the code leaves the critical + section before reaching the end of the critical section's code end, use + the appropriate _newlib_XXX_exit macro. */ + +#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) +#include + +/* Start a stream oriented critical section: */ +# define _newlib_flockfile_start(_fp) \ + { \ + int __oldfpcancel; \ + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldfpcancel); \ + _flockfile (_fp) + +/* Exit from a stream oriented critical section prematurely: */ +# define _newlib_flockfile_exit(_fp) \ + _funlockfile (_fp); \ + pthread_setcancelstate (__oldfpcancel, &__oldfpcancel); + +/* End a stream oriented critical section: */ +# define _newlib_flockfile_end(_fp) \ + _funlockfile (_fp); \ + pthread_setcancelstate (__oldfpcancel, &__oldfpcancel); \ + } + +/* Start a stream list oriented critical section: */ +# define _newlib_sfp_lock_start() \ + { \ + int __oldsfpcancel; \ + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldsfpcancel); \ + __sfp_lock_acquire () + +/* Exit from a stream list oriented critical section prematurely: */ +# define _newlib_sfp_lock_exit() \ + __sfp_lock_release (); \ + pthread_setcancelstate (__oldsfpcancel, &__oldsfpcancel); + +/* End a stream list oriented critical section: */ +# define _newlib_sfp_lock_end() \ + __sfp_lock_release (); \ + pthread_setcancelstate (__oldsfpcancel, &__oldsfpcancel); \ + } + +#else /* __SINGLE_THREAD__ || !_POSIX_THREADS */ + +# define _newlib_flockfile_start(_fp) \ + { \ + _flockfile(_fp) + +# define _newlib_flockfile_exit(_fp) \ + _funlockfile(_fp); \ + +# define _newlib_flockfile_end(_fp) \ + _funlockfile(_fp); \ + } + +# define _newlib_sfp_lock_start() \ + { \ + __sfp_lock_acquire () + +# define _newlib_sfp_lock_end() \ + __sfp_lock_release (); + +# define _newlib_sfp_lock_end() \ + __sfp_lock_release (); \ + } + +#endif /* !__SINGLE_THREAD__ && _POSIX_THREADS */ extern u_char *_EXFUN(__sccl, (char *, u_char *fmt)); extern int _EXFUN(__svfscanf_r,(struct _reent *,FILE *, _CONST char *,va_list)); diff --git a/newlib/libc/stdio/open_memstream.c b/newlib/libc/stdio/open_memstream.c index a53bdef2f..0b58720a1 100644 --- a/newlib/libc/stdio/open_memstream.c +++ b/newlib/libc/stdio/open_memstream.c @@ -313,12 +313,12 @@ _DEFUN(internal_open_memstream_r, (ptr, buf, size, wide), return NULL; if ((c = (memstream *) _malloc_r (ptr, sizeof *c)) == NULL) { - __sfp_lock_acquire (); + _newlib_sfp_lock_start (); fp->_flags = 0; /* release */ #ifndef __SINGLE_THREAD__ __lock_close_recursive (fp->_lock); #endif - __sfp_lock_release (); + _newlib_sfp_lock_end (); return NULL; } /* Use *size as a hint for initial sizing, but bound the initial @@ -338,12 +338,12 @@ _DEFUN(internal_open_memstream_r, (ptr, buf, size, wide), *buf = _malloc_r (ptr, c->max); if (!*buf) { - __sfp_lock_acquire (); + _newlib_sfp_lock_start (); fp->_flags = 0; /* release */ #ifndef __SINGLE_THREAD__ __lock_close_recursive (fp->_lock); #endif - __sfp_lock_release (); + _newlib_sfp_lock_end (); _free_r (ptr, c); return NULL; } @@ -359,7 +359,7 @@ _DEFUN(internal_open_memstream_r, (ptr, buf, size, wide), c->saved.w = L'\0'; c->wide = (int8_t) wide; - _flockfile (fp); + _newlib_flockfile_start (fp); fp->_file = -1; fp->_flags = __SWR; fp->_cookie = c; @@ -372,7 +372,7 @@ _DEFUN(internal_open_memstream_r, (ptr, buf, size, wide), #endif fp->_close = memcloser; ORIENT (fp, wide); - _funlockfile (fp); + _newlib_flockfile_end (fp); return fp; } diff --git a/newlib/libc/stdio/putc.c b/newlib/libc/stdio/putc.c index 667324d9d..1115bf40d 100644 --- a/newlib/libc/stdio/putc.c +++ b/newlib/libc/stdio/putc.c @@ -97,9 +97,9 @@ _DEFUN(_putc_r, (ptr, c, fp), { int result; CHECK_INIT (ptr, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); result = __sputc_r (ptr, c, fp); - _funlockfile (fp); + _newlib_flockfile_end (fp); return result; } @@ -112,9 +112,9 @@ _DEFUN(putc, (c, fp), #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) int result; CHECK_INIT (_REENT, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); result = __sputc_r (_REENT, c, fp); - _funlockfile (fp); + _newlib_flockfile_end (fp); return result; #else return _putc_r (_REENT, c, fp); diff --git a/newlib/libc/stdio/setvbuf.c b/newlib/libc/stdio/setvbuf.c index 583a081f4..63f1f80db 100644 --- a/newlib/libc/stdio/setvbuf.c +++ b/newlib/libc/stdio/setvbuf.c @@ -106,7 +106,7 @@ _DEFUN(setvbuf, (fp, buf, mode, size), CHECK_INIT (_REENT, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); /* * Verify arguments. The `int' limit on `size' is due to this @@ -115,7 +115,7 @@ _DEFUN(setvbuf, (fp, buf, mode, size), if ((mode != _IOFBF && mode != _IOLBF && mode != _IONBF) || (int)(_POINTER_INT) size < 0) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return (EOF); } @@ -158,7 +158,7 @@ nbf: fp->_w = 0; fp->_bf._base = fp->_p = fp->_nbuf; fp->_bf._size = 1; - _funlockfile (fp); + _newlib_flockfile_exit (fp); return (ret); } fp->_flags |= __SMBF; @@ -193,6 +193,6 @@ nbf: if (fp->_flags & __SWR) fp->_w = fp->_flags & (__SLBF | __SNBF) ? 0 : size; - _funlockfile (fp); + _newlib_flockfile_end (fp); return 0; } diff --git a/newlib/libc/stdio/ungetc.c b/newlib/libc/stdio/ungetc.c index 0339a3d0c..e385ce8fb 100644 --- a/newlib/libc/stdio/ungetc.c +++ b/newlib/libc/stdio/ungetc.c @@ -125,7 +125,7 @@ _DEFUN(_ungetc_r, (rptr, c, fp), CHECK_INIT (rptr, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); ORIENT (fp, -1); @@ -140,14 +140,14 @@ _DEFUN(_ungetc_r, (rptr, c, fp), */ if ((fp->_flags & __SRW) == 0) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return EOF; } if (fp->_flags & __SWR) { if (_fflush_r (rptr, fp)) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return EOF; } fp->_flags &= ~__SWR; @@ -167,12 +167,12 @@ _DEFUN(_ungetc_r, (rptr, c, fp), { if (fp->_r >= fp->_ub._size && __submore (rptr, fp)) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return EOF; } *--fp->_p = c; fp->_r++; - _funlockfile (fp); + _newlib_flockfile_exit (fp); return c; } @@ -186,7 +186,7 @@ _DEFUN(_ungetc_r, (rptr, c, fp), { fp->_p--; fp->_r++; - _funlockfile (fp); + _newlib_flockfile_exit (fp); return c; } @@ -202,7 +202,7 @@ _DEFUN(_ungetc_r, (rptr, c, fp), fp->_ubuf[sizeof (fp->_ubuf) - 1] = c; fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1]; fp->_r = 1; - _funlockfile (fp); + _newlib_flockfile_end (fp); return c; } diff --git a/newlib/libc/stdio/ungetwc.c b/newlib/libc/stdio/ungetwc.c index 234d2f7ef..ee0d7fc75 100644 --- a/newlib/libc/stdio/ungetwc.c +++ b/newlib/libc/stdio/ungetwc.c @@ -82,7 +82,7 @@ _DEFUN(_ungetwc_r, (ptr, wc, fp), char buf[MB_LEN_MAX]; size_t len; - _flockfile (fp); + _newlib_flockfile_start (fp); ORIENT (fp, 1); if (wc == WEOF) wc = WEOF; @@ -98,7 +98,7 @@ _DEFUN(_ungetwc_r, (ptr, wc, fp), wc = WEOF; break; } - _funlockfile (fp); + _newlib_flockfile_end (fp); return wc; } diff --git a/newlib/libc/stdio/vfprintf.c b/newlib/libc/stdio/vfprintf.c index e3fc099d3..559899107 100644 --- a/newlib/libc/stdio/vfprintf.c +++ b/newlib/libc/stdio/vfprintf.c @@ -708,20 +708,20 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap), #ifndef STRING_ONLY /* Initialize std streams if not dealing with sprintf family. */ CHECK_INIT (data, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); ORIENT(fp, -1); /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ if (cantwrite (data, fp)) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return (EOF); } /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return (__sbprintf (data, fp, fmt0, ap)); } #else /* STRING_ONLY */ @@ -1633,7 +1633,7 @@ error: if (malloc_buf != NULL) _free_r (data, malloc_buf); #ifndef STRING_ONLY - _funlockfile (fp); + _newlib_flockfile_end (fp); #endif return (__sferror (fp) ? EOF : ret); /* NOTREACHED */ diff --git a/newlib/libc/stdio/vfscanf.c b/newlib/libc/stdio/vfscanf.c index 32a132a93..e05082db7 100644 --- a/newlib/libc/stdio/vfscanf.c +++ b/newlib/libc/stdio/vfscanf.c @@ -148,10 +148,12 @@ Supporting OS subroutines required: #endif #ifdef STRING_ONLY -#undef _flockfile -#undef _funlockfile -#define _flockfile(x) {} -#define _funlockfile(x) {} +#undef _newlib_flockfile_start +#undef _newlib_flockfile_exit +#undef _newlib_flockfile_end +#define _newlib_flockfile_start(x) {} +#define _newlib_flockfile_exit(x) {} +#define _newlib_flockfile_end(x) {} #define _ungetc_r _sungetc_r #define __srefill_r __ssrefill_r #define _fread_r _sfread_r @@ -496,7 +498,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), # define GET_ARG(n, ap, type) (va_arg (ap, type)) #endif - _flockfile (fp); + _newlib_flockfile_start (fp); ORIENT (fp, -1); @@ -795,7 +797,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap), * Disgusting backwards compatibility hacks. XXX */ case '\0': /* compat */ - _funlockfile (fp); + _newlib_flockfile_exit (fp); return EOF; default: /* compat */ @@ -1595,12 +1597,12 @@ input_failure: should have been set prior to here. On EOF failure (including invalid format string), return EOF if no matches yet, else number of matches made prior to failure. */ - _funlockfile (fp); + _newlib_flockfile_exit (fp); return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF; match_failure: all_done: /* Return number of matches, which can be 0 on match failure. */ - _funlockfile (fp); + _newlib_flockfile_end (fp); return nassigned; } diff --git a/newlib/libc/stdio/vfwprintf.c b/newlib/libc/stdio/vfwprintf.c index d76fff0d6..029f1d08c 100644 --- a/newlib/libc/stdio/vfwprintf.c +++ b/newlib/libc/stdio/vfwprintf.c @@ -553,20 +553,20 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap), #ifndef STRING_ONLY /* Initialize std streams if not dealing with sprintf family. */ CHECK_INIT (data, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); ORIENT(fp, 1); /* sorry, fwprintf(read_only_file, "") returns EOF, not 0 */ if (cantwrite (data, fp)) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return (EOF); } /* optimise fwprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) { - _funlockfile (fp); + _newlib_flockfile_exit (fp); return (__sbwprintf (data, fp, fmt0, ap)); } #else /* STRING_ONLY */ @@ -1465,7 +1465,7 @@ error: if (malloc_buf != NULL) _free_r (data, malloc_buf); #ifndef STRING_ONLY - _funlockfile (fp); + _newlib_flockfile_end (fp); #endif return (__sferror (fp) ? EOF : ret); /* NOTREACHED */ diff --git a/newlib/libc/stdio/vfwscanf.c b/newlib/libc/stdio/vfwscanf.c index 49ccf2f4b..5d2388df8 100644 --- a/newlib/libc/stdio/vfwscanf.c +++ b/newlib/libc/stdio/vfwscanf.c @@ -145,10 +145,12 @@ C99, POSIX-1.2008 #endif #ifdef STRING_ONLY -#undef _flockfile -#undef _funlockfile -#define _flockfile(x) {} -#define _funlockfile(x) {} +#undef _newlib_flockfile_start +#undef _newlib_flockfile_exit +#undef _newlib_flockfile_end +#define _newlib_flockfile_start(x) {} +#define _newlib_flockfile_exit(x) {} +#define _newlib_flockfile_end(x) {} #define _ungetwc_r _sungetwc_r #define __srefill_r __ssrefill_r #define _fgetwc_r _sfgetwc_r @@ -434,7 +436,7 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap), # define GET_ARG(n, ap, type) (va_arg (ap, type)) #endif - _flockfile (fp); + _newlib_flockfile_start (fp); ORIENT (fp, 1); @@ -712,7 +714,7 @@ _DEFUN(__SVFWSCANF_R, (rptr, fp, fmt0, ap), * Disgusting backwards compatibility hacks. XXX */ case L'\0': /* compat */ - _funlockfile (fp); + _newlib_flockfile_exit (fp); return EOF; default: /* compat */ @@ -1440,12 +1442,12 @@ input_failure: should have been set prior to here. On EOF failure (including invalid format string), return EOF if no matches yet, else number of matches made prior to failure. */ - _funlockfile (fp); + _newlib_flockfile_exit (fp); return nassigned && !(fp->_flags & __SERR) ? nassigned : EOF; match_failure: all_done: /* Return number of matches, which can be 0 on match failure. */ - _funlockfile (fp); + _newlib_flockfile_end (fp); return nassigned; } diff --git a/newlib/libc/stdio64/fdopen64.c b/newlib/libc/stdio64/fdopen64.c index 49d1f03aa..659d343e5 100644 --- a/newlib/libc/stdio64/fdopen64.c +++ b/newlib/libc/stdio64/fdopen64.c @@ -64,7 +64,7 @@ _DEFUN (_fdopen64_r, (ptr, fd, mode), if ((fp = __sfp (ptr)) == 0) return 0; - _flockfile(fp); + _newlib_flockfile_start(fp); fp->_flags = flags; /* POSIX recommends setting the O_APPEND bit on fd to match append @@ -101,7 +101,7 @@ _DEFUN (_fdopen64_r, (ptr, fd, mode), fp->_flags |= __SL64; - _funlockfile(fp); + _newlib_flockfile_end(fp); return fp; } diff --git a/newlib/libc/stdio64/fopen64.c b/newlib/libc/stdio64/fopen64.c index aa6775116..84f7b6e49 100644 --- a/newlib/libc/stdio64/fopen64.c +++ b/newlib/libc/stdio64/fopen64.c @@ -91,16 +91,16 @@ _DEFUN (_fopen64_r, (ptr, file, mode), if ((f = _open64_r (ptr, file, oflags, 0666)) < 0) { - __sfp_lock_acquire (); + _newlib_sfp_lock_start (); fp->_flags = 0; /* release */ #ifndef __SINGLE_THREAD__ __lock_close_recursive (fp->_lock); #endif - __sfp_lock_release (); + _newlib_sfp_lock_end (); return NULL; } - _flockfile(fp); + _newlib_flockfile_start (fp); fp->_file = f; fp->_flags = flags; @@ -121,7 +121,7 @@ _DEFUN (_fopen64_r, (ptr, file, mode), fp->_flags |= __SL64; - _funlockfile(fp); + _newlib_flockfile_end (fp); return fp; } diff --git a/newlib/libc/stdio64/freopen64.c b/newlib/libc/stdio64/freopen64.c index 1e2ec7827..db0e1ee0f 100644 --- a/newlib/libc/stdio64/freopen64.c +++ b/newlib/libc/stdio64/freopen64.c @@ -100,11 +100,20 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp), CHECK_INIT (ptr, fp); - _flockfile(fp); + /* We can't use the _newlib_flockfile_XXX macros here due to the + interlocked locking with the sfp_lock. */ +#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) + int __oldcancel; + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldcancel); +#endif + _flockfile (fp); if ((flags = __sflags (ptr, mode, &oflags)) == 0) { - _funlockfile(fp); + _funlockfile (fp); +#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) + pthread_setcancelstate (__oldcancel, &__oldcancel); +#endif _fclose_r (ptr, fp); return NULL; } @@ -205,11 +214,14 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp), __sfp_lock_acquire (); fp->_flags = 0; /* set it free */ ptr->_errno = e; /* restore in case _close clobbered */ - _funlockfile(fp); + _funlockfile (fp); #ifndef __SINGLE_THREAD__ __lock_close_recursive (fp->_lock); #endif __sfp_lock_release (); +#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) + pthread_setcancelstate (__oldcancel, &__oldcancel); +#endif return NULL; } @@ -229,7 +241,10 @@ _DEFUN (_freopen64_r, (ptr, file, mode, fp), fp->_flags |= __SL64; - _funlockfile(fp); + _funlockfile (fp); +#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS) + pthread_setcancelstate (__oldcancel, &__oldcancel); +#endif return fp; } diff --git a/newlib/libc/stdio64/fseeko64.c b/newlib/libc/stdio64/fseeko64.c index 301d6f54f..b323f97d8 100644 --- a/newlib/libc/stdio64/fseeko64.c +++ b/newlib/libc/stdio64/fseeko64.c @@ -126,7 +126,7 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, whence), CHECK_INIT (ptr, fp); - _flockfile (fp); + _newlib_flockfile_start (fp); curoff = fp->_offset; @@ -144,7 +144,7 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, whence), if ((seekfn = fp->_seek64) == NULL) { ptr->_errno = ESPIPE; /* ??? */ - _funlockfile(fp); + _newlib_flockfile_exit(fp); return EOF; } @@ -169,7 +169,7 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, whence), curoff = seekfn (ptr, fp->_cookie, (_fpos64_t) 0, SEEK_CUR); if (curoff == -1L) { - _funlockfile(fp); + _newlib_flockfile_exit(fp); return EOF; } } @@ -194,7 +194,7 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, whence), default: ptr->_errno = EINVAL; - _funlockfile(fp); + _newlib_flockfile_exit(fp); return (EOF); } @@ -294,7 +294,7 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, whence), if (HASUB (fp)) FREEUB (ptr, fp); fp->_flags &= ~__SEOF; - _funlockfile(fp); + _newlib_flockfile_exit(fp); return 0; } @@ -323,7 +323,7 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, whence), fp->_p += n; fp->_r -= n; } - _funlockfile(fp); + _newlib_flockfile_end(fp); return 0; /* diff --git a/newlib/libc/stdio64/ftello64.c b/newlib/libc/stdio64/ftello64.c index 51dcd2796..c4d6da24b 100644 --- a/newlib/libc/stdio64/ftello64.c +++ b/newlib/libc/stdio64/ftello64.c @@ -99,12 +99,12 @@ _DEFUN (_ftello64_r, (ptr, fp), CHECK_INIT (ptr, fp); - _flockfile(fp); + _newlib_flockfile_start(fp); if (fp->_seek64 == NULL) { ptr->_errno = ESPIPE; - _funlockfile(fp); + _newlib_flockfile_exit(fp); return -1L; } @@ -121,7 +121,7 @@ _DEFUN (_ftello64_r, (ptr, fp), pos = fp->_seek64 (ptr, fp->_cookie, (_fpos64_t) 0, SEEK_CUR); if (pos == -1L) { - _funlockfile(fp); + _newlib_flockfile_exit(fp); return pos; } } @@ -146,7 +146,7 @@ _DEFUN (_ftello64_r, (ptr, fp), pos += fp->_p - fp->_bf._base; } - _funlockfile(fp); + _newlib_flockfile_end(fp); return pos; }