Back to index

glibc  2.9
Classes | Functions | Variables
gai_misc.h File Reference
#include <netdb.h>
#include <signal.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  waitlist
struct  requestlist
struct  gaiinit

Functions

struct requestlist__gai_enqueue_request (struct gaicb *gaicbp) internal_function
struct requestlist__gai_find_request (const struct gaicb *gaicbp) internal_function
int __gai_remove_request (struct gaicb *gaicbp) internal_function
void __gai_notify (struct requestlist *req) internal_function
int __gai_notify_only (struct sigevent *sigev, pid_t caller_pid) internal_function
int __gai_sigqueue (int sig, const union sigval val, pid_t caller_pid) internal_function

Variables

pthread_mutex_t __gai_requests_mutex

Class Documentation

struct waitlist

Definition at line 28 of file gai_misc.h.

Collaboration diagram for waitlist:
Class Members
pid_t caller_pid
pthread_cond_t * cond
volatile int * counterp
struct waitlist * next
int * result
struct sigevent * sigevp
struct requestlist

Definition at line 45 of file gai_misc.h.

Collaboration diagram for requestlist:
Class Members
aiocb_union * aiocbp
struct gaicb * gaicbp
struct requestlist * last_fd
struct requestlist * next
struct requestlist * next_fd
struct requestlist * next_prio
struct requestlist * next_run
int running
struct waitlist * waiting
struct gaiinit

Definition at line 60 of file gai_misc.h.

Class Members
int gai_debug
int gai_idle_time
int gai_locks
int gai_num
int gai_numusers
int gai_reserved
int gai_threads
int gai_usedba

Function Documentation

struct requestlist* __gai_enqueue_request ( struct gaicb *  gaicbp) [read]

Definition at line 217 of file gai_misc.c.

{
  struct requestlist *newp;
  struct requestlist *lastp;

  /* Get the mutex.  */
  pthread_mutex_lock (&__gai_requests_mutex);

  /* Get a new element for the waiting list.  */
  newp = get_elem ();
  if (newp == NULL)
    {
      pthread_mutex_unlock (&__gai_requests_mutex);
      __set_errno (EAGAIN);
      return NULL;
    }
  newp->running = 0;
  newp->gaicbp = gaicbp;
  newp->waiting = NULL;
  newp->next = NULL;

  lastp = requests_tail;
  if (requests_tail == NULL)
    requests = requests_tail = newp;
  else
    {
      requests_tail->next = newp;
      requests_tail = newp;
    }

  gaicbp->__return = EAI_INPROGRESS;

  /* See if we need to and are able to create a thread.  */
  if (nthreads < optim.gai_threads && idle_thread_count == 0)
    {
      pthread_t thid;

      newp->running = 1;

      /* Now try to start a thread.  */
      if (gai_create_helper_thread (&thid, handle_requests, newp) == 0)
       /* We managed to enqueue the request.  All errors which can
          happen now can be recognized by calls to `gai_error'.  */
       ++nthreads;
      else
       {
         if (nthreads == 0)
           {
             /* We cannot create a thread in the moment and there is
               also no thread running.  This is a problem.  `errno' is
               set to EAGAIN if this is only a temporary problem.  */
             assert (lastp->next == newp);
             lastp->next = NULL;
             requests_tail = lastp;

             newp->next = freelist;
             freelist = newp;

             newp = NULL;
           }
         else
           /* We are not handling the request after all.  */
           newp->running = 0;
       }
    }

  /* Enqueue the request in the request queue.  */
  if (newp != NULL)
    {
      /* If there is a thread waiting for work, then let it know that we
        have just given it something to do. */
      if (idle_thread_count > 0)
       pthread_cond_signal (&__gai_new_request_notification);
    }

  /* Release the mutex.  */
  pthread_mutex_unlock (&__gai_requests_mutex);

  return newp;
}

Here is the call graph for this function:

Here is the caller graph for this function:

struct requestlist* __gai_find_request ( const struct gaicb *  gaicbp) [read]

Definition at line 157 of file gai_misc.c.

{
  struct requestlist *runp;

  runp = requests;
  while (runp != NULL)
    if (runp->gaicbp == gaicbp)
      return runp;
    else
      runp = runp->next;

  return NULL;
}

Here is the caller graph for this function:

void __gai_notify ( struct requestlist req)

Definition at line 99 of file gai_notify.c.

{
  struct waitlist *waitlist;

  /* Now also notify possibly waiting threads.  */
  waitlist = req->waiting;
  while (waitlist != NULL)
    {
      struct waitlist *next = waitlist->next;

      if (waitlist->sigevp == NULL)
       {
#ifdef DONT_NEED_GAI_MISC_COND
         GAI_MISC_NOTIFY (waitlist);
#else
         /* Decrement the counter.  */
         --*waitlist->counterp;

         pthread_cond_signal (waitlist->cond);
#endif
       }
      else
       /* This is part of a asynchronous `getaddrinfo_a' operation.  If
          this request is the last one, send the signal.  */
       if (--*waitlist->counterp == 0)
         {
           __gai_notify_only (waitlist->sigevp, waitlist->caller_pid);
           /* This is tricky.  See getaddrinfo_a.c for the reason why
              this works.  */
           free ((void *) waitlist->counterp);
         }

      waitlist = next;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int __gai_notify_only ( struct sigevent *  sigev,
pid_t  caller_pid 
)

Definition at line 47 of file gai_notify.c.

{
  int result = 0;

  /* Send the signal to notify about finished processing of the request.  */
  if (sigev->sigev_notify == SIGEV_THREAD)
    {
      /* We have to start a thread.  */
      pthread_t tid;
      pthread_attr_t attr, *pattr;

      pattr = (pthread_attr_t *) sigev->sigev_notify_attributes;
      if (pattr == NULL)
       {
         pthread_attr_init (&attr);
         pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
         pattr = &attr;
       }

      /* SIGEV may be freed as soon as we return, so we cannot let the
        notification thread use that pointer.  Even though a sigval_t is
        only one word and the same size as a void *, we cannot just pass
        the value through pthread_create as the argument and have the new
        thread run the user's function directly, because on some machines
        the calling convention for a union like sigval_t is different from
        that for a pointer type like void *.  */
      struct notify_func *nf = malloc (sizeof *nf);
      if (nf == NULL)
       result = -1;
      else
       {
         nf->func = sigev->sigev_notify_function;
         nf->value = sigev->sigev_value;
         if (pthread_create (&tid, pattr, notify_func_wrapper, nf) < 0)
           {
             free (nf);
             result = -1;
           }
       }
    }
  else if (sigev->sigev_notify == SIGEV_SIGNAL)
    /* We have to send a signal.  */
    if (__gai_sigqueue (sigev->sigev_signo, sigev->sigev_value, caller_pid)
       < 0)
      result = -1;

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int __gai_remove_request ( struct gaicb *  gaicbp)

Definition at line 174 of file gai_misc.c.

{
  struct requestlist *runp;
  struct requestlist *lastp;

  runp = requests;
  lastp = NULL;
  while (runp != NULL)
    if (runp->gaicbp == gaicbp)
      break;
    else
      {
       lastp = runp;
       runp = runp->next;
      }

  if (runp == NULL)
    /* Not known.  */
    return -1;
  if (runp->running != 0)
    /* Currently handled.  */
    return 1;

  /* Dequeue the request.  */
  if (lastp == NULL)
    requests = runp->next;
  else
    lastp->next = runp->next;
  if (runp == requests_tail)
    requests_tail = lastp;

  return 0;
}

Here is the caller graph for this function:

int __gai_sigqueue ( int  sig,
const union sigval  val,
pid_t  caller_pid 
)

Definition at line 26 of file gai_sigqueue.c.

{
  __set_errno (ENOSYS);
  return -1;
}

Here is the caller graph for this function:


Variable Documentation

Definition at line 96 of file gai_misc.c.