From 4aa28d8ae279329f2b46c92e05b0bf457f07b9af Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 30 May 2012 08:58:42 +0000 Subject: * 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/libc/stdio/local.h | 77 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'newlib/libc/stdio/local.h') 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)); -- cgit v1.2.3