(linenum→info "unix/slp.c:2238")

glibc/2.7/resolv/gai_suspend.c

    1: /* Copyright (C) 2001, 2006 Free Software Foundation, Inc.
    2:    This file is part of the GNU C Library.
    3:    Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <errno.h>
   21: #include <netdb.h>
   22: #include <pthread.h>
   23: #include <stdlib.h>
   24: #include <sys/time.h>
   25: 
   26: #include <gai_misc.h>
   27: 
   28: 
   29: int
   30: gai_suspend (const struct gaicb *const list[], int ent,
   31:              const struct timespec *timeout)
   32: {
   33:   struct waitlist waitlist[ent];
   34:   struct requestlist *requestlist[ent];
   35: #ifndef DONT_NEED_GAI_MISC_COND
   36:   pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
   37: #endif
   38:   int cnt;
   39:   int cntr = 1;
   40:   int none = 1;
   41:   int result;
   42: 
   43:   /* Request the mutex.  */
   44:   pthread_mutex_lock (&__gai_requests_mutex);
   45: 
   46:   /* There is not yet a finished request.  Signal the request that
   47:      we are working for it.  */
   48:   for (cnt = 0; cnt < ent; ++cnt)
   49:     if (list[cnt] != NULL && list[cnt]->__return == EAI_INPROGRESS)
   50:       {
   51:         requestlist[cnt] = __gai_find_request (list[cnt]);
   52: 
   53:         if (requestlist[cnt] != NULL)
   54:           {
   55: #ifndef DONT_NEED_GAI_MISC_COND
   56:             waitlist[cnt].cond = &cond;
   57: #endif
   58:             waitlist[cnt].next = requestlist[cnt]->waiting;
   59:             waitlist[cnt].counterp = &cntr;
   60:             waitlist[cnt].sigevp = NULL;
   61:             waitlist[cnt].caller_pid = 0;      /* Not needed.  */
   62:             requestlist[cnt]->waiting = &waitlist[cnt];
   63:             none = 0;
   64:           }
   65:       }
   66: 
   67:   if (none)
   68:     {
   69:       if (cnt < ent)
   70:         /* There is an entry which is finished.  */
   71:         result = 0;
   72:       else
   73:         result = EAI_ALLDONE;
   74:     }
   75:   else
   76:     {
   77:       /* There is no request done but some are still being worked on.  */
   78:       int oldstate;
   79: 
   80:       /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation
   81:          points we must be careful.  We added entries to the waiting lists
   82:          which we must remove.  So defer cancelation for now.  */
   83:       pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate);
   84: 
   85: #ifdef DONT_NEED_GAI_MISC_COND
   86:       result = 0;
   87:       GAI_MISC_WAIT (result, cntr, timeout, 1);
   88: #else
   89:       if (timeout == NULL)
   90:         result = pthread_cond_wait (&cond, &__gai_requests_mutex);
   91:       else
   92:         {
   93:           /* We have to convert the relative timeout value into an
   94:              absolute time value with pthread_cond_timedwait expects.  */
   95:           struct timeval now;
   96:           struct timespec abstime;
   97: 
   98:           __gettimeofday (&now, NULL);
   99:           abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000;
  100:           abstime.tv_sec = timeout->tv_sec + now.tv_sec;
  101:           if (abstime.tv_nsec >= 1000000000)
  102:             {
  103:               abstime.tv_nsec -= 1000000000;
  104:               abstime.tv_sec += 1;
  105:             }
  106: 
  107:           result = pthread_cond_timedwait (&cond, &__gai_requests_mutex,
  108:                                            &abstime);
  109:         }
  110: #endif
  111: 
  112:       /* Now remove the entry in the waiting list for all requests
  113:          which didn't terminate.  */
  114:       for (cnt = 0; cnt < ent; ++cnt)
  115:         if (list[cnt] != NULL && list[cnt]->__return == EAI_INPROGRESS
  116:             && requestlist[cnt] != NULL)
  117:           {
  118:             struct waitlist **listp = &requestlist[cnt]->waiting;
  119: 
  120:             /* There is the chance that we cannot find our entry anymore.
  121:                This could happen if the request terminated and restarted
  122:                again.  */
  123:             while (*listp != NULL && *listp != &waitlist[cnt])
  124:               listp = &(*listp)->next;
  125: 
  126:             if (*listp != NULL)
  127:               *listp = (*listp)->next;
  128:           }
  129: 
  130:       /* Now it's time to restore the cancelation state.  */
  131:       pthread_setcancelstate (oldstate, NULL);
  132: 
  133: #ifndef DONT_NEED_GAI_MISC_COND
  134:       /* Release the conditional variable.  */
  135:       if (pthread_cond_destroy (&cond) != 0)
  136:         /* This must never happen.  */
  137:         abort ();
  138: #endif
  139: 
  140:       if (result != 0)
  141:         {
  142:           /* An error occurred.  Possibly it's EINTR.  We have to translate
  143:              the timeout error report of `pthread_cond_timedwait' to the
  144:              form expected from `gai_suspend'.  */
  145:           if (__builtin_expect (result, ETIMEDOUT) == ETIMEDOUT)
  146:             result = EAI_AGAIN;
  147:           else if (result == EINTR)
  148:             result = EAI_INTR;
  149:           else
  150:             result = EAI_SYSTEM;
  151:         }
  152:     }
  153: 
  154:   /* Release the mutex.  */
  155:   pthread_mutex_unlock (&__gai_requests_mutex);
  156: 
  157:   return result;
  158: }
Syntax (Markdown)