1*820c1a8dSHiroo HAYASHI /* Use the internal lock used by mbrtowc and mbrtoc32.
2*820c1a8dSHiroo HAYASHI Copyright (C) 2019-2021 Free Software Foundation, Inc.
3*820c1a8dSHiroo HAYASHI
4*820c1a8dSHiroo HAYASHI This file is free software: you can redistribute it and/or modify
5*820c1a8dSHiroo HAYASHI it under the terms of the GNU Lesser General Public License as
6*820c1a8dSHiroo HAYASHI published by the Free Software Foundation; either version 2.1 of the
7*820c1a8dSHiroo HAYASHI License, or (at your option) any later version.
8*820c1a8dSHiroo HAYASHI
9*820c1a8dSHiroo HAYASHI This file is distributed in the hope that it will be useful,
10*820c1a8dSHiroo HAYASHI but WITHOUT ANY WARRANTY; without even the implied warranty of
11*820c1a8dSHiroo HAYASHI MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*820c1a8dSHiroo HAYASHI GNU Lesser General Public License for more details.
13*820c1a8dSHiroo HAYASHI
14*820c1a8dSHiroo HAYASHI You should have received a copy of the GNU Lesser General Public License
15*820c1a8dSHiroo HAYASHI along with this program. If not, see <https://www.gnu.org/licenses/>. */
16*820c1a8dSHiroo HAYASHI
17*820c1a8dSHiroo HAYASHI /* Written by Bruno Haible <bruno@clisp.org>, 2019-2020. */
18*820c1a8dSHiroo HAYASHI
19*820c1a8dSHiroo HAYASHI /* Use a lock, so that no two threads can invoke mbtowc at the same time. */
20*820c1a8dSHiroo HAYASHI
21*820c1a8dSHiroo HAYASHI static inline int
mbtowc_unlocked(wchar_t * pwc,const char * p,size_t m)22*820c1a8dSHiroo HAYASHI mbtowc_unlocked (wchar_t *pwc, const char *p, size_t m)
23*820c1a8dSHiroo HAYASHI {
24*820c1a8dSHiroo HAYASHI /* Put the hidden internal state of mbtowc into its initial state.
25*820c1a8dSHiroo HAYASHI This is needed at least with glibc, uClibc, and MSVC CRT.
26*820c1a8dSHiroo HAYASHI See <https://sourceware.org/bugzilla/show_bug.cgi?id=9674>. */
27*820c1a8dSHiroo HAYASHI mbtowc (NULL, NULL, 0);
28*820c1a8dSHiroo HAYASHI
29*820c1a8dSHiroo HAYASHI return mbtowc (pwc, p, m);
30*820c1a8dSHiroo HAYASHI }
31*820c1a8dSHiroo HAYASHI
32*820c1a8dSHiroo HAYASHI /* Prohibit renaming this symbol. */
33*820c1a8dSHiroo HAYASHI #undef gl_get_mbtowc_lock
34*820c1a8dSHiroo HAYASHI
35*820c1a8dSHiroo HAYASHI #if GNULIB_MBRTOWC_SINGLE_THREAD
36*820c1a8dSHiroo HAYASHI
37*820c1a8dSHiroo HAYASHI /* All uses of this function are in a single thread. No locking needed. */
38*820c1a8dSHiroo HAYASHI
39*820c1a8dSHiroo HAYASHI static int
mbtowc_with_lock(wchar_t * pwc,const char * p,size_t m)40*820c1a8dSHiroo HAYASHI mbtowc_with_lock (wchar_t *pwc, const char *p, size_t m)
41*820c1a8dSHiroo HAYASHI {
42*820c1a8dSHiroo HAYASHI return mbtowc_unlocked (pwc, p, m);
43*820c1a8dSHiroo HAYASHI }
44*820c1a8dSHiroo HAYASHI
45*820c1a8dSHiroo HAYASHI #elif defined _WIN32 && !defined __CYGWIN__
46*820c1a8dSHiroo HAYASHI
47*820c1a8dSHiroo HAYASHI extern __declspec(dllimport) CRITICAL_SECTION *gl_get_mbtowc_lock (void);
48*820c1a8dSHiroo HAYASHI
49*820c1a8dSHiroo HAYASHI static int
mbtowc_with_lock(wchar_t * pwc,const char * p,size_t m)50*820c1a8dSHiroo HAYASHI mbtowc_with_lock (wchar_t *pwc, const char *p, size_t m)
51*820c1a8dSHiroo HAYASHI {
52*820c1a8dSHiroo HAYASHI CRITICAL_SECTION *lock = gl_get_mbtowc_lock ();
53*820c1a8dSHiroo HAYASHI int ret;
54*820c1a8dSHiroo HAYASHI
55*820c1a8dSHiroo HAYASHI EnterCriticalSection (lock);
56*820c1a8dSHiroo HAYASHI ret = mbtowc_unlocked (pwc, p, m);
57*820c1a8dSHiroo HAYASHI LeaveCriticalSection (lock);
58*820c1a8dSHiroo HAYASHI
59*820c1a8dSHiroo HAYASHI return ret;
60*820c1a8dSHiroo HAYASHI }
61*820c1a8dSHiroo HAYASHI
62*820c1a8dSHiroo HAYASHI #elif HAVE_PTHREAD_API /* AIX, IRIX, Cygwin */
63*820c1a8dSHiroo HAYASHI
64*820c1a8dSHiroo HAYASHI extern
65*820c1a8dSHiroo HAYASHI # if defined _WIN32 || defined __CYGWIN__
66*820c1a8dSHiroo HAYASHI __declspec(dllimport)
67*820c1a8dSHiroo HAYASHI # endif
68*820c1a8dSHiroo HAYASHI pthread_mutex_t *gl_get_mbtowc_lock (void);
69*820c1a8dSHiroo HAYASHI
70*820c1a8dSHiroo HAYASHI # if HAVE_WEAK_SYMBOLS /* IRIX */
71*820c1a8dSHiroo HAYASHI
72*820c1a8dSHiroo HAYASHI /* Avoid the need to link with '-lpthread'. */
73*820c1a8dSHiroo HAYASHI # pragma weak pthread_mutex_lock
74*820c1a8dSHiroo HAYASHI # pragma weak pthread_mutex_unlock
75*820c1a8dSHiroo HAYASHI
76*820c1a8dSHiroo HAYASHI /* Determine whether libpthread is in use. */
77*820c1a8dSHiroo HAYASHI # pragma weak pthread_mutexattr_gettype
78*820c1a8dSHiroo HAYASHI /* See the comments in lock.h. */
79*820c1a8dSHiroo HAYASHI # define pthread_in_use() \
80*820c1a8dSHiroo HAYASHI (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
81*820c1a8dSHiroo HAYASHI
82*820c1a8dSHiroo HAYASHI # else
83*820c1a8dSHiroo HAYASHI # define pthread_in_use() 1
84*820c1a8dSHiroo HAYASHI # endif
85*820c1a8dSHiroo HAYASHI
86*820c1a8dSHiroo HAYASHI static int
mbtowc_with_lock(wchar_t * pwc,const char * p,size_t m)87*820c1a8dSHiroo HAYASHI mbtowc_with_lock (wchar_t *pwc, const char *p, size_t m)
88*820c1a8dSHiroo HAYASHI {
89*820c1a8dSHiroo HAYASHI if (pthread_in_use())
90*820c1a8dSHiroo HAYASHI {
91*820c1a8dSHiroo HAYASHI pthread_mutex_t *lock = gl_get_mbtowc_lock ();
92*820c1a8dSHiroo HAYASHI int ret;
93*820c1a8dSHiroo HAYASHI
94*820c1a8dSHiroo HAYASHI if (pthread_mutex_lock (lock))
95*820c1a8dSHiroo HAYASHI abort ();
96*820c1a8dSHiroo HAYASHI ret = mbtowc_unlocked (pwc, p, m);
97*820c1a8dSHiroo HAYASHI if (pthread_mutex_unlock (lock))
98*820c1a8dSHiroo HAYASHI abort ();
99*820c1a8dSHiroo HAYASHI
100*820c1a8dSHiroo HAYASHI return ret;
101*820c1a8dSHiroo HAYASHI }
102*820c1a8dSHiroo HAYASHI else
103*820c1a8dSHiroo HAYASHI return mbtowc_unlocked (pwc, p, m);
104*820c1a8dSHiroo HAYASHI }
105*820c1a8dSHiroo HAYASHI
106*820c1a8dSHiroo HAYASHI #elif HAVE_THREADS_H
107*820c1a8dSHiroo HAYASHI
108*820c1a8dSHiroo HAYASHI extern mtx_t *gl_get_mbtowc_lock (void);
109*820c1a8dSHiroo HAYASHI
110*820c1a8dSHiroo HAYASHI static int
mbtowc_with_lock(wchar_t * pwc,const char * p,size_t m)111*820c1a8dSHiroo HAYASHI mbtowc_with_lock (wchar_t *pwc, const char *p, size_t m)
112*820c1a8dSHiroo HAYASHI {
113*820c1a8dSHiroo HAYASHI mtx_t *lock = gl_get_mbtowc_lock ();
114*820c1a8dSHiroo HAYASHI int ret;
115*820c1a8dSHiroo HAYASHI
116*820c1a8dSHiroo HAYASHI if (mtx_lock (lock) != thrd_success)
117*820c1a8dSHiroo HAYASHI abort ();
118*820c1a8dSHiroo HAYASHI ret = mbtowc_unlocked (pwc, p, m);
119*820c1a8dSHiroo HAYASHI if (mtx_unlock (lock) != thrd_success)
120*820c1a8dSHiroo HAYASHI abort ();
121*820c1a8dSHiroo HAYASHI
122*820c1a8dSHiroo HAYASHI return ret;
123*820c1a8dSHiroo HAYASHI }
124*820c1a8dSHiroo HAYASHI
125*820c1a8dSHiroo HAYASHI #endif
126