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