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