mbtowc-lock.h 3.2 KB

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