xref: /Universal-ctags/gnulib/mbtowc-lock.h (revision 820c1a8d46849a90376d8eb15b319ac05439f656)
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