X-Git-Url: https://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fmsvc-inval.c;h=ef2b8609446ec45000d5f08731400111e4f28d16;hb=84d1749c4b5ad026522be96537320556ec6f7a57;hp=4e6fd3401e6ca50bff4b2b1401641edbb188ec07;hpb=0b3a22be69e9afb311ae8b64e141155b3d948f14;p=gnulib.git diff --git a/lib/msvc-inval.c b/lib/msvc-inval.c index 4e6fd3401..ef2b86094 100644 --- a/lib/msvc-inval.c +++ b/lib/msvc-inval.c @@ -1,5 +1,5 @@ /* Invalid parameter handler for MSVC runtime libraries. - Copyright (C) 2011 Free Software Foundation, Inc. + Copyright (C) 2011-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -12,22 +12,39 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + with this program; if not, see . */ #include /* Specification. */ #include "msvc-inval.h" -#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER \ + && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING) -# ifdef STATUS_GNULIB_INVALID_PARAMETER +/* Get _invalid_parameter_handler type and _set_invalid_parameter_handler + declaration. */ +# include -/* Get declarations of the Win32 API functions. */ +# if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING + +static void cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ +} + +# else + +/* Get declarations of the native Windows API functions. */ # define WIN32_LEAN_AND_MEAN # include +# if defined _MSC_VER + static void cdecl gl_msvc_invalid_parameter_handler (const wchar_t *expression, const wchar_t *function, @@ -38,32 +55,75 @@ gl_msvc_invalid_parameter_handler (const wchar_t *expression, RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); } -static int gl_msvc_inval_initialized /* = 0 */; +# else -void -gl_msvc_inval_ensure_handler (void) +/* An index to thread-local storage. */ +static DWORD tls_index; +static int tls_initialized /* = 0 */; + +/* Used as a fallback only. */ +static struct gl_msvc_inval_per_thread not_per_thread; + +struct gl_msvc_inval_per_thread * +gl_msvc_inval_current (void) { - if (gl_msvc_inval_initialized == 0) + if (!tls_initialized) { - _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler); - gl_msvc_inval_initialized = 1; + tls_index = TlsAlloc (); + tls_initialized = 1; + } + if (tls_index == TLS_OUT_OF_INDEXES) + /* TlsAlloc had failed. */ + return ¬_per_thread; + else + { + struct gl_msvc_inval_per_thread *pointer = + (struct gl_msvc_inval_per_thread *) TlsGetValue (tls_index); + if (pointer == NULL) + { + /* First call. Allocate a new 'struct gl_msvc_inval_per_thread'. */ + pointer = + (struct gl_msvc_inval_per_thread *) + malloc (sizeof (struct gl_msvc_inval_per_thread)); + if (pointer == NULL) + /* Could not allocate memory. Use the global storage. */ + pointer = ¬_per_thread; + TlsSetValue (tls_index, pointer); + } + return pointer; } } -# else - -jmp_buf gl_msvc_inval_restart; - -void cdecl +static void cdecl gl_msvc_invalid_parameter_handler (const wchar_t *expression, const wchar_t *function, const wchar_t *file, unsigned int line, uintptr_t dummy) { - longjmp (gl_msvc_inval_restart, 1); + struct gl_msvc_inval_per_thread *current = gl_msvc_inval_current (); + if (current->restart_valid) + longjmp (current->restart, 1); + else + /* An invalid parameter notification from outside the gnulib code. + Give the caller a chance to intervene. */ + RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); } +# endif + # endif +static int gl_msvc_inval_initialized /* = 0 */; + +void +gl_msvc_inval_ensure_handler (void) +{ + if (gl_msvc_inval_initialized == 0) + { + _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler); + gl_msvc_inval_initialized = 1; + } +} + #endif