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

glibc/2.7/resolv/gai_notify.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 <netdb.h>
   21: #include <pthread.h>
   22: #include <stdlib.h>
   23: #include <gai_misc.h>
   24: 
   25: 
   26: struct notify_func
   27:   {
   28:     void (*func) (sigval_t);
   29:     sigval_t value;
   30:   };
   31: 
   32: static void *
   33: notify_func_wrapper (void *arg)
   34: {
   35:   gai_start_notify_thread ();
   36:   struct notify_func *const n = arg;
   37:   void (*func) (sigval_t) = n->func;
   38:   sigval_t value = n->value;
   39:   free (n);
   40:   (*func) (value);
   41:   return NULL;
   42: }
   43: 
   44: 
   45: int
   46: internal_function
   47: __gai_notify_only (struct sigevent *sigev, pid_t caller_pid)
   48: {
   49:   int result = 0;
   50: 
   51:   /* Send the signal to notify about finished processing of the request.  */
   52:   if (sigev->sigev_notify == SIGEV_THREAD)
   53:     {
   54:       /* We have to start a thread.  */
   55:       pthread_t tid;
   56:       pthread_attr_t attr, *pattr;
   57: 
   58:       pattr = (pthread_attr_t *) sigev->sigev_notify_attributes;
   59:       if (pattr == NULL)
   60:         {
   61:           pthread_attr_init (&attr);
   62:           pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
   63:           pattr = &attr;
   64:         }
   65: 
   66:       /* SIGEV may be freed as soon as we return, so we cannot let the
   67:          notification thread use that pointer.  Even though a sigval_t is
   68:          only one word and the same size as a void *, we cannot just pass
   69:          the value through pthread_create as the argument and have the new
   70:          thread run the user's function directly, because on some machines
   71:          the calling convention for a union like sigval_t is different from
   72:          that for a pointer type like void *.  */
   73:       struct notify_func *nf = malloc (sizeof *nf);
   74:       if (nf == NULL)
   75:         result = -1;
   76:       else
   77:         {
   78:           nf->func = sigev->sigev_notify_function;
   79:           nf->value = sigev->sigev_value;
   80:           if (pthread_create (&tid, pattr, notify_func_wrapper, nf) < 0)
   81:             {
   82:               free (nf);
   83:               result = -1;
   84:             }
   85:         }
   86:     }
   87:   else if (sigev->sigev_notify == SIGEV_SIGNAL)
   88:     /* We have to send a signal.  */
   89:     if (__gai_sigqueue (sigev->sigev_signo, sigev->sigev_value, caller_pid)
   90:         < 0)
   91:       result = -1;
   92: 
   93:   return result;
   94: }
   95: 
   96: 
   97: void
   98: internal_function
   99: __gai_notify (struct requestlist *req)
  100: {
  101:   struct waitlist *waitlist;
  102: 
  103:   /* Now also notify possibly waiting threads.  */
  104:   waitlist = req->waiting;
  105:   while (waitlist != NULL)
  106:     {
  107:       struct waitlist *next = waitlist->next;
  108: 
  109:       if (waitlist->sigevp == NULL)
  110:         {
  111: #ifdef DONT_NEED_GAI_MISC_COND
  112:           GAI_MISC_NOTIFY (waitlist);
  113: #else
  114:           /* Decrement the counter.  */
  115:           --*waitlist->counterp;
  116: 
  117:           pthread_cond_signal (waitlist->cond);
  118: #endif
  119:         }
  120:       else
  121:         /* This is part of a asynchronous `getaddrinfo_a' operation.  If
  122:            this request is the last one, send the signal.  */
  123:         if (--*waitlist->counterp == 0)
  124:           {
  125:             __gai_notify_only (waitlist->sigevp, waitlist->caller_pid);
  126:             /* This is tricky.  See getaddrinfo_a.c for the reason why
  127:                this works.  */
  128:             free ((void *) waitlist->counterp);
  129:           }
  130: 
  131:       waitlist = next;
  132:     }
  133: }
Syntax (Markdown)