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

glibc/2.7/resolv/getaddrinfo_a.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 <unistd.h>
   25: 
   26: #include <gai_misc.h>
   27: 
   28: 
   29: /* We need this special structure to handle asynchronous I/O.  */
   30: struct async_waitlist
   31:   {
   32:     int counter;
   33:     struct sigevent sigev;
   34:     struct waitlist list[0];
   35:   };
   36: 
   37: 
   38: int
   39: getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig)
   40: {
   41:   struct sigevent defsigev;
   42:   struct requestlist *requests[ent];
   43:   int cnt;
   44:   volatile int total = 0;
   45:   int result = 0;
   46: 
   47:   /* Check arguments.  */
   48:   if (mode != GAI_WAIT && mode != GAI_NOWAIT)
   49:     {
   50:       __set_errno (EINVAL);
   51:       return EAI_SYSTEM;
   52:     }
   53: 
   54:   if (sig == NULL)
   55:     {
   56:       defsigev.sigev_notify = SIGEV_NONE;
   57:       sig = &defsigev;
   58:     }
   59: 
   60:   /* Request the mutex.  */
   61:   pthread_mutex_lock (&__gai_requests_mutex);
   62: 
   63:   /* Now we can enqueue all requests.  Since we already acquired the
   64:      mutex the enqueue function need not do this.  */
   65:   for (cnt = 0; cnt < ent; ++cnt)
   66:     if (list[cnt] != NULL)
   67:       {
   68:         requests[cnt] = __gai_enqueue_request (list[cnt]);
   69: 
   70:         if (requests[cnt] != NULL)
   71:           /* Successfully enqueued.  */
   72:           ++total;
   73:         else
   74:           /* Signal that we've seen an error.  `errno' and the error code
   75:              of the gaicb will tell more.  */
   76:           result = EAI_SYSTEM;
   77:       }
   78:     else
   79:       requests[cnt] = NULL;
   80: 
   81:   if (total == 0)
   82:     {
   83:       /* We don't have anything to do except signalling if we work
   84:          asynchronously.  */
   85: 
   86:       /* Release the mutex.  We do this before raising a signal since the
   87:          signal handler might do a `siglongjmp' and then the mutex is
   88:          locked forever.  */
   89:       pthread_mutex_unlock (&__gai_requests_mutex);
   90: 
   91:       if (mode == GAI_NOWAIT)
   92:         __gai_notify_only (sig,
   93:                            sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0);
   94: 
   95:       return result;
   96:     }
   97:   else if (mode == GAI_WAIT)
   98:     {
   99: #ifndef DONT_NEED_GAI_MISC_COND
  100:       pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  101: #endif
  102:       struct waitlist waitlist[ent];
  103:       int oldstate;
  104: 
  105:       total = 0;
  106:       for (cnt = 0; cnt < ent; ++cnt)
  107:         if (requests[cnt] != NULL)
  108:           {
  109: #ifndef DONT_NEED_GAI_MISC_COND
  110:             waitlist[cnt].cond = &cond;
  111: #endif
  112:             waitlist[cnt].next = requests[cnt]->waiting;
  113:             waitlist[cnt].counterp = &total;
  114:             waitlist[cnt].sigevp = NULL;
  115:             waitlist[cnt].caller_pid = 0;      /* Not needed.  */
  116:             requests[cnt]->waiting = &waitlist[cnt];
  117:             ++total;
  118:           }
  119: 
  120:       /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation
  121:          points we must be careful.  We added entries to the waiting lists
  122:          which we must remove.  So defer cancelation for now.  */
  123:       pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate);
  124: 
  125:       while (total > 0)
  126:         {
  127: #ifdef DONT_NEED_GAI_MISC_COND
  128:           int result;
  129:           GAI_MISC_WAIT (result, total, NULL, 1);
  130: #else
  131:           pthread_cond_wait (&cond, &__gai_requests_mutex);
  132: #endif
  133:         }
  134: 
  135:       /* Now it's time to restore the cancelation state.  */
  136:       pthread_setcancelstate (oldstate, NULL);
  137: 
  138: #ifndef DONT_NEED_GAI_MISC_COND
  139:       /* Release the conditional variable.  */
  140:       if (pthread_cond_destroy (&cond) != 0)
  141:         /* This must never happen.  */
  142:         abort ();
  143: #endif
  144:     }
  145:   else
  146:     {
  147:       struct async_waitlist *waitlist;
  148: 
  149:       waitlist = (struct async_waitlist *)
  150:         malloc (sizeof (struct async_waitlist)
  151:                 + (ent * sizeof (struct waitlist)));
  152: 
  153:       if (waitlist == NULL)
  154:         result = EAI_AGAIN;
  155:       else
  156:         {
  157:           pid_t caller_pid = sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0;
  158:           total = 0;
  159: 
  160:           for (cnt = 0; cnt < ent; ++cnt)
  161:             if (requests[cnt] != NULL)
  162:               {
  163: #ifndef DONT_NEED_GAI_MISC_COND
  164:                 waitlist->list[cnt].cond = NULL;
  165: #endif
  166:                 waitlist->list[cnt].next = requests[cnt]->waiting;
  167:                 waitlist->list[cnt].counterp = &waitlist->counter;
  168:                 waitlist->list[cnt].sigevp = &waitlist->sigev;
  169:                 waitlist->list[cnt].caller_pid = caller_pid;
  170:                 requests[cnt]->waiting = &waitlist->list[cnt];
  171:                 ++total;
  172:               }
  173: 
  174:           waitlist->counter = total;
  175:           waitlist->sigev = *sig;
  176:         }
  177:     }
  178: 
  179:   /* Release the mutex.  */
  180:   pthread_mutex_unlock (&__gai_requests_mutex);
  181: 
  182:   return result;
  183: }
Syntax (Markdown)