gai_misc.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* Copyright (C) 2006-2019 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library 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 GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <http://www.gnu.org/licenses/>. */
  14. /* We define a special synchronization primitive for AIO. POSIX
  15. conditional variables would be ideal but the pthread_cond_*wait
  16. operations do not return on EINTR. This is a requirement for
  17. correct aio_suspend and lio_listio implementations. */
  18. #include <assert.h>
  19. #include <signal.h>
  20. #include <nptl/pthreadP.h>
  21. #include <futex-internal.h>
  22. #define DONT_NEED_GAI_MISC_COND 1
  23. #define GAI_MISC_NOTIFY(waitlist) \
  24. do { \
  25. if (*waitlist->counterp > 0 && --*waitlist->counterp == 0) \
  26. futex_wake ((unsigned int *) waitlist->counterp, 1, FUTEX_PRIVATE); \
  27. } while (0)
  28. #define GAI_MISC_WAIT(result, futex, timeout, cancel) \
  29. do { \
  30. volatile unsigned int *futexaddr = &futex; \
  31. unsigned int oldval = futex; \
  32. \
  33. if (oldval != 0) \
  34. { \
  35. pthread_mutex_unlock (&__gai_requests_mutex); \
  36. \
  37. int status; \
  38. do \
  39. { \
  40. if (cancel) \
  41. status = futex_reltimed_wait_cancelable ( \
  42. (unsigned int *) futexaddr, oldval, timeout, FUTEX_PRIVATE); \
  43. else \
  44. status = futex_reltimed_wait ((unsigned int *) futexaddr, \
  45. oldval, timeout, FUTEX_PRIVATE); \
  46. if (status != EAGAIN) \
  47. break; \
  48. \
  49. oldval = *futexaddr; \
  50. } \
  51. while (oldval != 0); \
  52. \
  53. if (status == EINTR) \
  54. result = EINTR; \
  55. else if (status == ETIMEDOUT) \
  56. result = EAGAIN; \
  57. else \
  58. assert (status == 0 || status == EAGAIN); \
  59. \
  60. pthread_mutex_lock (&__gai_requests_mutex); \
  61. } \
  62. } while (0)
  63. #define gai_start_notify_thread __gai_start_notify_thread
  64. #define gai_create_helper_thread __gai_create_helper_thread
  65. extern inline void
  66. __gai_start_notify_thread (void)
  67. {
  68. sigset_t ss;
  69. sigemptyset (&ss);
  70. int sigerr __attribute__ ((unused));
  71. sigerr = pthread_sigmask (SIG_SETMASK, &ss, NULL);
  72. assert_perror (sigerr);
  73. }
  74. extern inline int
  75. __gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *),
  76. void *arg)
  77. {
  78. pthread_attr_t attr;
  79. /* Make sure the thread is created detached. */
  80. pthread_attr_init (&attr);
  81. pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
  82. /* The helper thread needs only very little resources. */
  83. (void) pthread_attr_setstacksize (&attr,
  84. __pthread_get_minstack (&attr)
  85. + 4 * PTHREAD_STACK_MIN);
  86. /* Block all signals in the helper thread. To do this thoroughly we
  87. temporarily have to block all signals here. */
  88. sigset_t ss;
  89. sigset_t oss;
  90. sigfillset (&ss);
  91. int sigerr __attribute__ ((unused));
  92. sigerr = pthread_sigmask (SIG_SETMASK, &ss, &oss);
  93. assert_perror (sigerr);
  94. int ret = pthread_create (threadp, &attr, tf, arg);
  95. /* Restore the signal mask. */
  96. sigerr = pthread_sigmask (SIG_SETMASK, &oss, NULL);
  97. assert_perror (sigerr);
  98. (void) pthread_attr_destroy (&attr);
  99. return ret;
  100. }
  101. #include_next <gai_misc.h>