Back to index

glibc  2.9
gai_misc.h
Go to the documentation of this file.
00001 /* Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 /* We define a special synchronization primitive for AIO.  POSIX
00020    conditional variables would be ideal but the pthread_cond_*wait
00021    operations do not return on EINTR.  This is a requirement for
00022    correct aio_suspend and lio_listio implementations.  */
00023 
00024 #include <assert.h>
00025 #include <signal.h>
00026 #include <pthreadP.h>
00027 #include <lowlevellock.h>
00028 
00029 #define DONT_NEED_GAI_MISC_COND    1
00030 
00031 #define GAI_MISC_NOTIFY(waitlist) \
00032   do {                                                               \
00033     if (*waitlist->counterp > 0 && --*waitlist->counterp == 0)              \
00034       lll_futex_wake (waitlist->counterp, 1, LLL_PRIVATE);                  \
00035   } while (0)
00036 
00037 #define GAI_MISC_WAIT(result, futex, timeout, cancel) \
00038   do {                                                               \
00039     volatile int *futexaddr = &futex;                                       \
00040     int oldval = futex;                                                     \
00041                                                                      \
00042     if (oldval != 0)                                                 \
00043       {                                                                     \
00044        pthread_mutex_unlock (&__gai_requests_mutex);                        \
00045                                                                      \
00046        int oldtype;                                                  \
00047        if (cancel)                                                   \
00048          oldtype = LIBC_CANCEL_ASYNC ();                             \
00049                                                                      \
00050        int status;                                                   \
00051        do                                                            \
00052          {                                                           \
00053            status = lll_futex_timed_wait (futexaddr, oldval, timeout,       \
00054                                       LLL_PRIVATE);                  \
00055            if (status != -EWOULDBLOCK)                                      \
00056              break;                                                  \
00057                                                                      \
00058            oldval = *futexaddr;                                      \
00059          }                                                           \
00060        while (oldval != 0);                                          \
00061                                                                      \
00062        if (cancel)                                                   \
00063          LIBC_CANCEL_RESET (oldtype);                                       \
00064                                                                      \
00065        if (status == -EINTR)                                                \
00066          result = EINTR;                                             \
00067        else if (status == -ETIMEDOUT)                                       \
00068          result = EAGAIN;                                            \
00069        else                                                          \
00070          assert (status == 0 || status == -EWOULDBLOCK);                    \
00071                                                                      \
00072        pthread_mutex_lock (&__gai_requests_mutex);                          \
00073       }                                                                     \
00074   } while (0)
00075 
00076 
00077 #define gai_start_notify_thread __gai_start_notify_thread
00078 #define gai_create_helper_thread __gai_create_helper_thread
00079 
00080 extern inline void
00081 __gai_start_notify_thread (void)
00082 {
00083   sigset_t ss;
00084   sigemptyset (&ss);
00085   INTERNAL_SYSCALL_DECL (err);
00086   INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8);
00087 }
00088 
00089 extern inline int
00090 __gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *),
00091                          void *arg)
00092 {
00093   pthread_attr_t attr;
00094 
00095   /* Make sure the thread is created detached.  */
00096   pthread_attr_init (&attr);
00097   pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
00098 
00099   /* The helper thread needs only very little resources.  */
00100   (void) pthread_attr_setstacksize (&attr, 4 * PTHREAD_STACK_MIN);
00101 
00102   /* Block all signals in the helper thread.  To do this thoroughly we
00103      temporarily have to block all signals here.  */
00104   sigset_t ss;
00105   sigset_t oss;
00106   sigfillset (&ss);
00107   INTERNAL_SYSCALL_DECL (err);
00108   INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8);
00109 
00110   int ret = pthread_create (threadp, &attr, tf, arg);
00111 
00112   /* Restore the signal mask.  */
00113   INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL,
00114                   _NSIG / 8);
00115 
00116   (void) pthread_attr_destroy (&attr);
00117   return ret;
00118 }
00119 
00120 #include_next <gai_misc.h>