Update.
authorUlrich Drepper <drepper@redhat.com>
Sat, 3 Mar 2001 18:21:04 +0000 (18:21 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sat, 3 Mar 2001 18:21:04 +0000 (18:21 +0000)
* Versions.def: Add libanl definition.
* shlig-versions: Add entry for libanl.
* resolv/Makefile (distribute): Add gai_misc.h and ga_test.c.
(routines): Add gai_sigqueue.
(extra-libs): Add libanl.
(libanl-routines): New variable.
Add rules to build libanl and ga_test.
* resolv/Versions [libc] (GLIBC_2.2.3): Add __gai_sigqueue.
[libanl]: New library.
* resolv/netdb.h: Add definitions for libanl.
* resolv/getaddrinfo_a.c: New file.
* resolv/gai_cancel.c: New file.
* resolv/gai_error.c: New file.
* resolv/gai_misc.c: New file.
* resolv/gai_misc.h: New file.
* resolv/gai_notify.c: New file.
* resolv/gai_suspend.c: New file.
* resolv/ga_test.c: New file.
* sysdeps/generic/gai_sigqueue.c: New file.
* sysdeps/unix/sysv/linux/gai_sigqueue.c: New file.
* sysdeps/generic/bits/siginfo.h: Allow __need_sigevent_t being defined
and provide only that definition.
* sysdeps/unix/sysv/linux/alpha/bits/siginfo.h: Likewise.
* sysdeps/unix/sysv/linux/bits/siginfo.h: Likewise.
* sysdeps/unix/sysv/linux/ia64/bits/siginfo.h: Likewise.
* sysdeps/unix/sysv/linux/mips/bits/siginfo.h: Likewise.
* sysdeps/unix/sysv/linux/sparc/bits/siginfo.h: Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc64/bits/siginfo.h: Likewise.

* rt/aio_misc.c: Fix typos in comments.
* rt/lio_listio.c: Pretty printing.  Little optimization in request
list handling.

* elf/rtld.c: Remove commented out code.

28 files changed:
ChangeLog
NEWS
Versions.def
bits/siginfo.h
elf/rtld.c
resolv/Makefile
resolv/Versions
resolv/ga_test.c [new file with mode: 0644]
resolv/gai_cancel.c [new file with mode: 0644]
resolv/gai_error.c [new file with mode: 0644]
resolv/gai_misc.c [new file with mode: 0644]
resolv/gai_misc.h [new file with mode: 0644]
resolv/gai_notify.c [new file with mode: 0644]
resolv/gai_suspend.c [new file with mode: 0644]
resolv/getaddrinfo_a.c [new file with mode: 0644]
resolv/netdb.h
rt/aio_misc.c
rt/lio_listio.c
shlib-versions
sysdeps/generic/bits/siginfo.h
sysdeps/generic/gai_sigqueue.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/alpha/bits/siginfo.h
sysdeps/unix/sysv/linux/bits/siginfo.h
sysdeps/unix/sysv/linux/gai_sigqueue.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/ia64/bits/siginfo.h
sysdeps/unix/sysv/linux/mips/bits/siginfo.h
sysdeps/unix/sysv/linux/sparc/bits/siginfo.h
sysdeps/unix/sysv/linux/sparc/sparc64/bits/siginfo.h

index da30764..80e81fd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,40 @@
 2001-03-03  Ulrich Drepper  <drepper@redhat.com>
 
+       * Versions.def: Add libanl definition.
+       * shlig-versions: Add entry for libanl.
+       * resolv/Makefile (distribute): Add gai_misc.h and ga_test.c.
+       (routines): Add gai_sigqueue.
+       (extra-libs): Add libanl.
+       (libanl-routines): New variable.
+       Add rules to build libanl and ga_test.
+       * resolv/Versions [libc] (GLIBC_2.2.3): Add __gai_sigqueue.
+       [libanl]: New library.
+       * resolv/netdb.h: Add definitions for libanl.
+       * resolv/getaddrinfo_a.c: New file.
+       * resolv/gai_cancel.c: New file.
+       * resolv/gai_error.c: New file.
+       * resolv/gai_misc.c: New file.
+       * resolv/gai_misc.h: New file.
+       * resolv/gai_notify.c: New file.
+       * resolv/gai_suspend.c: New file.
+       * resolv/ga_test.c: New file.
+       * sysdeps/generic/gai_sigqueue.c: New file.
+       * sysdeps/unix/sysv/linux/gai_sigqueue.c: New file.
+       * sysdeps/generic/bits/siginfo.h: Allow __need_sigevent_t being defined
+       and provide only that definition.
+       * sysdeps/unix/sysv/linux/alpha/bits/siginfo.h: Likewise.
+       * sysdeps/unix/sysv/linux/bits/siginfo.h: Likewise.
+       * sysdeps/unix/sysv/linux/ia64/bits/siginfo.h: Likewise.
+       * sysdeps/unix/sysv/linux/mips/bits/siginfo.h: Likewise.
+       * sysdeps/unix/sysv/linux/sparc/bits/siginfo.h: Likewise.
+       * sysdeps/unix/sysv/linux/sparc/sparc64/bits/siginfo.h: Likewise.
+
+       * rt/aio_misc.c: Fix typos in comments.
+       * rt/lio_listio.c: Pretty printing.  Little optimization in request
+       list handling.
+
+       * elf/rtld.c: Remove commented out code.
+
        * sysdeps/unix/sysv/linux/linux_fsinfo.h (SHMFS_SUPER_MAGIC):
        Update for real 2.4 kernels.
 
diff --git a/NEWS b/NEWS
index b69b94e..34f43c1 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU C Library NEWS -- history of user-visible changes.  2001-2-9
+GNU C Library NEWS -- history of user-visible changes.  2001-3-3
 
 Copyright (C) 1992-1999, 2000, 2001 Free Software Foundation, Inc.
 See the end for copying conditions.
@@ -7,6 +7,16 @@ Please send GNU C library bug reports using the `glibcbug' script to
 <bugs@gnu.org>.  Questions and suggestions should be send to
 <bug-glibc@gnu.org>.
 \f
+Version 2.2.3
+
+* Intel's IA-64 math library is large integrated.  It provides fast and
+  accurate implementatations for most basic and standard math functions
+  in float, double, and long double format.
+
+* An asynchronous name lookup library was added.  The interface is designed
+  after POSIX AIO.  The proposal was circulated beforehand to get comments.
+  No negative ones came in.  Implemented by Ulrich Drepper.
+\f
 Version 2.2.2
 
 * Lots of headers were cleaned up.  Using the tool in the conform/ subdir
index 857e6a0..dc41136 100644 (file)
@@ -95,3 +95,6 @@ ld {
 libthread_db {
   GLIBC_2.1.3
 }
+libanl {
+  GLIBC_2.2.3
+}
index 31b0dde..77a314b 100644 (file)
@@ -1,5 +1,5 @@
 /* siginfo_t, sigevent and constants.  Stub version.
-   Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#if !defined _SIGNAL_H && !defined __need_siginfo_t
+#if !defined _SIGNAL_H && !defined __need_siginfo_t \
+    && !defined __need_sigevent_t
 # error "Never include this file directly.  Use <signal.h> instead"
 #endif
 
-#if (!defined __have_siginfo_t \
-     && (defined _SIGNAL_H || defined __need_siginfo_t))
-# define __have_siginfo_t      1
+#if (!defined __have_sigval_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t \
+        || defined __need_sigevent_t))
+# define __have_sigval_t 1
 
 /* Type for data associated with a signal.  */
 typedef union sigval
@@ -31,6 +33,11 @@ typedef union sigval
     int sival_int;
     void *sival_ptr;
   } sigval_t;
+#endif
+
+#if (!defined __have_siginfo_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t))
+# define __have_siginfo_t      1
 
 typedef struct siginfo
   {
@@ -173,7 +180,8 @@ enum
 #endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t).  */
 
 
-#if defined _SIGNAL_H && !defined __have_sigevent_t
+#if (defined _SIGNAL_H || defined __need_sigevent_t) \
+    && !defined __have_sigevent_t
 # define __have_sigevent_t     1
 
 /* Structure to transport application-defined values with signals.  */
index 7063492..9142d0b 100644 (file)
@@ -251,8 +251,7 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
     }
 #endif
 
-  if (//__builtin_expect (_dl_debug_statistics, 0))
-      __builtin_expect (_dl_debug_mask & DL_DEBUG_STATISTICS, 0))
+  if (__builtin_expect (_dl_debug_mask & DL_DEBUG_STATISTICS, 0))
     print_statistics ();
 
   return *start_addr;
index 64afbcb..fd056d0 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 1994,95,96,97,98,99,2000 Free Software Foundation, Inc.
+# Copyright (C) 1994,95,96,97,98,99,2000,2001 Free Software Foundation, Inc.
 # This file is part of the GNU C Library.
 
 # The GNU C Library is free software; you can redistribute it and/or
@@ -26,16 +26,16 @@ headers     := resolv.h \
           arpa/nameser.h arpa/nameser_compat.h \
           sys/bitypes.h
 distribute := ../conf/portability.h mapv4v6addr.h mapv4v6hostent.h \
-             Banner res_hconf.h res_debug.h README
+             Banner res_hconf.h res_debug.h README gai_misc.h ga_test.c
 
 routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \
-           res_hconf res_libc
+           res_hconf res_libc gai_sigqueue
 
 tests = tst-aton
 
 include ../Makeconfig
 
-extra-libs := libresolv libnss_dns
+extra-libs := libresolv libanl libnss_dns
 extra-libs-others = $(extra-libs)
 libresolv-routines := gethnamaddr res_comp res_debug   \
                      res_data res_mkquery res_query res_send           \
@@ -43,6 +43,9 @@ libresolv-routines := gethnamaddr res_comp res_debug  \
                      ns_parse ns_name ns_netint ns_ttl ns_print        \
                      ns_samedomain
 
+libanl-routines := gai_cancel gai_error gai_misc gai_notify gai_suspend \
+                  getaddrinfo_a
+
 subdir-dirs = nss_dns
 vpath %.c nss_dns
 
@@ -51,6 +54,10 @@ ifneq ($(build-static-nss),yes)
 libnss_dns-inhibit-o   = $(filter-out .os,$(object-suffixes))
 endif
 
+ifeq (yes,$(build-shared))
+tests: $(objpfx)ga_test
+endif
+
 include ../Rules
 
 CPPFLAGS += -Dgethostbyname=res_gethostbyname \
@@ -69,3 +76,8 @@ $(objpfx)libresolv.so: $(common-objpfx)libc.so
 
 # The DNS NSS modules needs the resolver.
 $(objpfx)libnss_dns.so: $(objpfx)libresolv.so $(common-objpfx)libc.so
+
+# The asynchronous name lookup code needs the thread library.
+$(objpfx)libanl.so: $(common-objpfx)libc.so $(shared-thread-library)
+
+$(objpfx)ga_test: $(objpfx)libanl.so $(shared-thread-library)
index 8131f1d..b76b112 100644 (file)
@@ -22,6 +22,9 @@ libc {
     # r*
     __res_state; __res_init; __res_nclose; __res_ninit; _res_hconf;
   }
+  GLIBC_2.2.3 {
+    __gai_sigqueue;
+  }
 }
 
 libresolv {
@@ -66,3 +69,9 @@ libnss_dns {
     _nss_dns_getnetbyname_r;
   }
 }
+
+libanl {
+  GLIBC_2.2.3 {
+    getaddrinfo_a; gai_cancel; gai_error; gai_suspend;
+  }
+}
diff --git a/resolv/ga_test.c b/resolv/ga_test.c
new file mode 100644 (file)
index 0000000..673162f
--- /dev/null
@@ -0,0 +1,99 @@
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int
+main (void)
+{
+#define N 10
+  struct gaicb reqmem[N];
+  struct gaicb *req[N];
+  int n;
+
+  for (n = 0; n < N; ++n)
+    {
+      asprintf (&reqmem[n].ar_name, "test%d.test.redhat.com", 140 + n);
+      reqmem[n].ar_service = NULL;
+      reqmem[n].ar_request = NULL;
+      reqmem[n].ar_result = NULL;
+      req[n] = &reqmem[n];
+    }
+
+  if (getaddrinfo_a (GAI_NOWAIT, req, N, NULL) != 0)
+    {
+      puts ("queue call failed");
+      exit (1);
+    }
+  else
+    puts ("queue call successful");
+
+  while (1)
+    {
+      int any = 0;
+
+      for (n = 0; n < N; ++n)
+       if (req[n] != NULL && gai_error (req[n]) != EAI_INPROGRESS)
+         {
+           if (gai_error (req[n]) == 0)
+             {
+               struct addrinfo *runp = req[n]->ar_result;
+
+               while (runp != NULL)
+                 {
+                   switch (runp->ai_family)
+                     {
+                     case PF_INET:
+                       {
+                         struct sockaddr_in *sinp;
+
+                         sinp = (struct sockaddr_in *) runp->ai_addr;
+                         printf ("%2d: %s = %s\n", n,
+                                 req[n]->ar_name, inet_ntoa (sinp->sin_addr));
+                       }
+                       break;
+                     default:
+                       printf ("%2d: family %d\n", n, runp->ai_family);
+                       break;
+                     }
+                   runp = runp->ai_next;
+                 }
+             }
+           else
+             printf ("error for %d: %s\n", n,
+                     gai_strerror (gai_error (req[n])));
+           req[n] = NULL;
+           break;
+         }
+       else if (req[n] != NULL)
+         any = 1;
+
+      if (n == N)
+       {
+         if (any)
+           gai_suspend (req, N, NULL);
+         else
+           break;
+       }
+    }
+
+  __libc_write(1,"got all\n", 8);
+
+  for (n = 0; n < N; ++n)
+    if (gai_error (&reqmem[n]) == 0)
+      {
+       struct addrinfo *runp = reqmem[n].ar_result;
+
+       while (runp != NULL)
+         {
+           struct addrinfo *oldp = runp;
+           runp = runp->ai_next;
+           freeaddrinfo (oldp);
+         }
+      }
+
+  return 0;
+}
diff --git a/resolv/gai_cancel.c b/resolv/gai_cancel.c
new file mode 100644 (file)
index 0000000..13c6488
--- /dev/null
@@ -0,0 +1,48 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <netdb.h>
+#include <pthread.h>
+
+#include "gai_misc.h"
+
+
+int
+gai_cancel (struct gaicb *gaicbp)
+{
+  int result = 0;
+  int status;
+
+  /* Request the mutex.  */
+  pthread_mutex_lock (&__gai_requests_mutex);
+
+  /* Find the request among those queued but not yet running.  */
+  status = __gai_remove_request (gaicbp);
+  if (status == 0)
+    result = EAI_CANCELED;
+  else if (status > 0)
+    result = EAI_NOTCANCELED;
+  else
+    result = EAI_ALLDONE;
+
+  /* Release the mutex.  */
+  pthread_mutex_unlock (&__gai_requests_mutex);
+
+  return result;
+}
diff --git a/resolv/gai_error.c b/resolv/gai_error.c
new file mode 100644 (file)
index 0000000..f3d36c5
--- /dev/null
@@ -0,0 +1,28 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <netdb.h>
+
+#include "gai_misc.h"
+
+int
+gai_error (struct gaicb *req)
+{
+  return req->__return;
+}
diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c
new file mode 100644 (file)
index 0000000..b69a8f6
--- /dev/null
@@ -0,0 +1,423 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "gai_misc.h"
+
+
+
+/* Pool of request list entries.  */
+static struct requestlist **pool;
+
+/* Number of total and allocated pool entries.  */
+static size_t pool_max_size;
+static size_t pool_size;
+
+/* We implement a two dimensional array but allocate each row separately.
+   The macro below determines how many entries should be used per row.
+   It should better be a power of two.  */
+#define ENTRIES_PER_ROW        32
+
+/* How many rows we allocate at once.  */
+#define ROWS_STEP      8
+
+/* List of available entries.  */
+static struct requestlist *freelist;
+
+/* Structure list of all currently processed requests.  */
+static struct requestlist *requests;
+static struct requestlist *requests_tail;
+
+/* Number of threads currently running.  */
+static int nthreads;
+
+/* Number of threads waiting for work to arrive. */
+static int idle_thread_count;
+
+
+/* These are the values used for optimization.  We will probably
+   create a funcion to set these values.  */
+static struct gaiinit optim =
+{
+  20,  /* int gai_threads;     Maximal number of threads.  */
+  64,  /* int gai_num;         Number of expected simultanious requests. */
+  0,
+  0,
+  0,
+  0,
+  1,
+  0
+};
+
+
+/* Since the list is global we need a mutex protecting it.  */
+pthread_mutex_t __gai_requests_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+
+/* When you add a request to the list and there are idle threads present,
+   you signal this condition variable. When a thread finishes work, it waits
+   on this condition variable for a time before it actually exits. */
+pthread_cond_t __gai_new_request_notification = PTHREAD_COND_INITIALIZER;
+
+
+/* Functions to handle request list pool.  */
+static struct requestlist *
+get_elem (void)
+{
+  struct requestlist *result;
+
+  if (freelist == NULL)
+    {
+      struct requestlist *new_row;
+      int cnt;
+
+      if (pool_size + 1 >= pool_max_size)
+       {
+         size_t new_max_size = pool_max_size + ROWS_STEP;
+         struct requestlist **new_tab;
+
+         new_tab = (struct requestlist **)
+           realloc (pool, new_max_size * sizeof (struct requestlist *));
+
+         if (new_tab == NULL)
+           return NULL;
+
+         pool_max_size = new_max_size;
+         pool = new_tab;
+       }
+
+      /* Allocate the new row.  */
+      cnt = pool_size == 0 ? optim.gai_num : ENTRIES_PER_ROW;
+      new_row = (struct requestlist *) calloc (cnt,
+                                              sizeof (struct requestlist));
+      if (new_row == NULL)
+       return NULL;
+
+      pool[pool_size++] = new_row;
+
+      /* Put all the new entries in the freelist.  */
+      do
+       {
+         new_row->next = freelist;
+         freelist = new_row++;
+       }
+      while (--cnt > 0);
+    }
+
+  result = freelist;
+  freelist = freelist->next;
+
+  return result;
+}
+
+
+struct requestlist *
+internal_function
+__gai_find_request (const struct gaicb *gaicbp)
+{
+  struct requestlist *runp;
+
+  runp = requests;
+  while (runp != NULL)
+    if (runp->gaicbp == gaicbp)
+      return runp;
+    else
+      runp = runp->next;
+
+  return NULL;
+}
+
+
+int
+internal_function
+__gai_remove_request (struct gaicb *gaicbp)
+{
+  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;
+}
+
+
+/* The thread handler.  */
+static void *handle_requests (void *arg);
+
+
+/* The main function of the async I/O handling.  It enqueues requests
+   and if necessary starts and handles threads.  */
+struct requestlist *
+internal_function
+__gai_enqueue_request (struct gaicb *gaicbp)
+{
+  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;
+      pthread_attr_t attr;
+
+      newp->running = 1;
+
+      /* Make sure the thread is created detached.  */
+      pthread_attr_init (&attr);
+      pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+
+      /* Now try to start a thread.  */
+      if (pthread_create (&thid, &attr, 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;
+}
+
+
+static void *
+handle_requests (void *arg)
+{
+  struct requestlist *runp = (struct requestlist *) arg;
+
+  do
+    {
+      /* If runp is NULL, then we were created to service the work queue
+        in general, not to handle any particular request. In that case we
+        skip the "do work" stuff on the first pass, and go directly to the
+        "get work off the work queue" part of this loop, which is near the
+        end. */
+      if (runp == NULL)
+       pthread_mutex_lock (&__gai_requests_mutex);
+      else
+       {
+         /* Make the request.  */
+         struct gaicb *req = runp->gaicbp;
+         struct requestlist *srchp;
+         struct requestlist *lastp;
+
+         req->__return = getaddrinfo (req->ar_name, req->ar_service,
+                                      req->ar_request, &req->ar_result);
+
+         /* Get the mutex.  */
+         pthread_mutex_lock (&__gai_requests_mutex);
+
+         /* Send the signal to notify about finished processing of the
+            request.  */
+         __gai_notify (runp);
+
+         /* Now dequeue the current request.  */
+         lastp = NULL;
+         srchp = requests;
+         while (srchp != runp)
+           {
+             lastp = srchp;
+             srchp = srchp->next;
+           }
+         assert (runp->running == 1);
+
+         if (requests_tail == runp)
+           requests_tail = lastp;
+         if (lastp == NULL)
+           requests = requests->next;
+         else
+           lastp->next = runp->next;
+
+         /* Free the old element.  */
+         runp->next = freelist;
+         freelist = runp;
+       }
+
+      runp = requests;
+      while (runp != NULL && runp->running != 0)
+       runp = runp->next;
+
+      /* If the runlist is empty, then we sleep for a while, waiting for
+        something to arrive in it. */
+      if (runp == NULL && optim.gai_idle_time >= 0)
+       {
+         struct timeval now;
+         struct timespec wakeup_time;
+
+         ++idle_thread_count;
+         gettimeofday (&now, NULL);
+         wakeup_time.tv_sec = now.tv_sec + optim.gai_idle_time;
+         wakeup_time.tv_nsec = now.tv_usec * 1000;
+         if (wakeup_time.tv_nsec > 1000000000)
+           {
+             wakeup_time.tv_nsec -= 1000000000;
+             ++wakeup_time.tv_sec;
+           }
+         pthread_cond_timedwait (&__gai_new_request_notification,
+                                 &__gai_requests_mutex, &wakeup_time);
+         --idle_thread_count;
+         runp = requests;
+         while (runp != NULL && runp->running != 0)
+           runp = runp->next;
+       }
+
+      if (runp == NULL)
+       --nthreads;
+      else
+       {
+         /* Mark the request as being worked on.  */
+         assert (runp->running == 0);
+         runp->running = 1;
+
+         /* If we have a request to process, and there's still another in
+            the run list, then we need to either wake up or create a new
+            thread to service the request that is still in the run list. */
+         if (requests != NULL)
+           {
+             /* There are at least two items in the work queue to work on.
+                If there are other idle threads, then we should wake them
+                up for these other work elements; otherwise, we should try
+                to create a new thread. */
+             if (idle_thread_count > 0)
+               pthread_cond_signal (&__gai_new_request_notification);
+             else if (nthreads < optim.gai_threads)
+               {
+                 pthread_t thid;
+                 pthread_attr_t attr;
+
+                 /* Make sure the thread is created detached.  */
+                 pthread_attr_init (&attr);
+                 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+
+                 /* Now try to start a thread. If we fail, no big deal,
+                    because we know that there is at least one thread (us)
+                    that is working on lookup operations. */
+                 if (pthread_create (&thid, &attr, handle_requests, NULL)
+                     == 0)
+                   ++nthreads;
+               }
+           }
+       }
+
+      /* Release the mutex.  */
+      pthread_mutex_unlock (&__gai_requests_mutex);
+    }
+  while (runp != NULL);
+
+  pthread_exit (NULL);
+}
+
+
+/* Free allocated resources.  */
+static void
+__attribute__ ((unused))
+free_res (void)
+{
+  size_t row;
+
+  for (row = 0; row < pool_max_size; ++row)
+    free (pool[row]);
+
+  free (pool);
+}
+text_set_element (__libc_subfreeres, free_res);
diff --git a/resolv/gai_misc.h b/resolv/gai_misc.h
new file mode 100644 (file)
index 0000000..a37264e
--- /dev/null
@@ -0,0 +1,100 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _GAI_MISC_H
+#define _GAI_MISC_H    1
+
+#include <netdb.h>
+#include <signal.h>
+
+
+/* Used to synchronize.  */
+struct waitlist
+  {
+    struct waitlist *next;
+
+    pthread_cond_t *cond;
+    volatile int *counterp;
+    /* The next field is used in asynchronous `lio_listio' operations.  */
+    struct sigevent *sigevp;
+    /* XXX See requestlist, it's used to work around the broken signal
+       handling in Linux.  */
+    pid_t caller_pid;
+  };
+
+
+/* Used to queue requests..  */
+struct requestlist
+  {
+    int running;
+
+    struct requestlist *next;
+
+    /* Pointer to the actual data.  */
+    struct gaicb *gaicbp;
+
+    /* List of waiting processes.  */
+    struct waitlist *waiting;
+  };
+
+/* To customize the implementation one can use the following struct.
+   This implementation follows the one in Irix.  */
+struct gaiinit
+  {
+    int gai_threads;           /* Maximal number of threads.  */
+    int gai_num;               /* Number of expected simultanious requests. */
+    int gai_locks;             /* Not used.  */
+    int gai_usedba;            /* Not used.  */
+    int gai_debug;             /* Not used.  */
+    int gai_numusers;          /* Not used.  */
+    int gai_idle_time;         /* Number of seconds before idle thread
+                                  terminates.  */
+    int gai_reserved;
+  };
+
+
+/* Lock for global I/O list of requests.  */
+extern pthread_mutex_t __gai_requests_mutex;
+
+
+/* Enqueue request.  */
+extern struct requestlist *__gai_enqueue_request (struct gaicb *gaicbp)
+     internal_function;
+
+/* Find request on wait list.  */
+extern struct requestlist *__gai_find_request (const struct gaicb *gaicbp)
+     internal_function;
+
+/* Remove request from waitlist.  */
+extern int __gai_remove_request (struct gaicb *gaicbp)
+     internal_function;
+
+/* Notify initiator of request and tell this everybody listening.  */
+extern void __gai_notify (struct requestlist *req)
+     internal_function;
+
+/* Notify initiator of request.  */
+extern int __gai_notify_only (struct sigevent *sigev, pid_t caller_pid)
+     internal_function;
+
+/* Send the signal.  */
+extern int __gai_sigqueue (int sig, const union sigval val, pid_t caller_pid)
+     internal_function;
+
+#endif /* gai_misc.h */
diff --git a/resolv/gai_notify.c b/resolv/gai_notify.c
new file mode 100644 (file)
index 0000000..b3e623a
--- /dev/null
@@ -0,0 +1,100 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <netdb.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+#include "gai_misc.h"
+
+
+static void *
+notify_func_wrapper (void *arg)
+{
+  struct sigevent *sigev = arg;
+  sigev->sigev_notify_function (sigev->sigev_value);
+  return NULL;
+}
+
+
+int
+internal_function
+__gai_notify_only (struct sigevent *sigev, pid_t caller_pid)
+{
+  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;
+       }
+
+      if (pthread_create (&tid, pattr, notify_func_wrapper, sigev) < 0)
+       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;
+}
+
+
+void
+internal_function
+__gai_notify (struct requestlist *req)
+{
+  struct waitlist *waitlist;
+
+  /* Now also notify possibly waiting threads.  */
+  waitlist = req->waiting;
+  while (waitlist != NULL)
+    {
+      struct waitlist *next = waitlist->next;
+
+      /* Decrement the counter.  This is used in both cases.  */
+      --*waitlist->counterp;
+
+      if (waitlist->sigevp == NULL)
+       pthread_cond_signal (waitlist->cond);
+      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;
+    }
+}
diff --git a/resolv/gai_suspend.c b/resolv/gai_suspend.c
new file mode 100644 (file)
index 0000000..b82acb4
--- /dev/null
@@ -0,0 +1,147 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "gai_misc.h"
+
+
+int
+gai_suspend (const struct gaicb *const list[], int ent,
+            const struct timespec *timeout)
+{
+  struct waitlist waitlist[ent];
+  struct requestlist *requestlist[ent];
+  pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+  int cnt;
+  int dummy;
+  int none = 1;
+  int result;
+
+  /* Request the mutex.  */
+  pthread_mutex_lock (&__gai_requests_mutex);
+
+  /* There is not yet a finished request.  Signal the request that
+     we are working for it.  */
+  for (cnt = 0; cnt < ent; ++cnt)
+    if (list[cnt] != NULL && list[cnt]->__return == EAI_INPROGRESS)
+      {
+       requestlist[cnt] = __gai_find_request (list[cnt]);
+
+       if (requestlist[cnt] != NULL)
+         {
+           waitlist[cnt].cond = &cond;
+           waitlist[cnt].next = requestlist[cnt]->waiting;
+           waitlist[cnt].counterp = &dummy;
+           waitlist[cnt].sigevp = NULL;
+           waitlist[cnt].caller_pid = 0;       /* Not needed.  */
+           requestlist[cnt]->waiting = &waitlist[cnt];
+           none = 0;
+         }
+      }
+
+  if (none)
+    {
+      if (cnt < ent)
+       /* There is an entry which is finished.  */
+       result = 0;
+      else
+       result = EAI_ALLDONE;
+    }
+  else
+    {
+      /* There is no request done but some are still being worked on.  */
+      int oldstate;
+
+      /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation
+        points we must be careful.  We added entries to the waiting lists
+        which we must remove.  So defer cancelation for now.  */
+      pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate);
+
+      if (timeout == NULL)
+       result = pthread_cond_wait (&cond, &__gai_requests_mutex);
+      else
+       {
+         /* We have to convert the relative timeout value into an
+            absolute time value with pthread_cond_timedwait expects.  */
+         struct timeval now;
+         struct timespec abstime;
+
+         __gettimeofday (&now, NULL);
+         abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000;
+         abstime.tv_sec = timeout->tv_sec + now.tv_sec;
+         if (abstime.tv_nsec >= 1000000000)
+           {
+             abstime.tv_nsec -= 1000000000;
+             abstime.tv_sec += 1;
+           }
+
+         result = pthread_cond_timedwait (&cond, &__gai_requests_mutex,
+                                          &abstime);
+       }
+
+      /* Now remove the entry in the waiting list for all requests
+        which didn't terminate.  */
+      for (cnt = 0; cnt < ent; ++cnt)
+       if (list[cnt] != NULL && list[cnt]->__return == EAI_INPROGRESS
+           && requestlist[cnt] != NULL)
+         {
+           struct waitlist **listp = &requestlist[cnt]->waiting;
+
+           /* There is the chance that we cannot find our entry anymore.
+              This could happen if the request terminated and restarted
+              again.  */
+           while (*listp != NULL && *listp != &waitlist[cnt])
+             listp = &(*listp)->next;
+
+           if (*listp != NULL)
+             *listp = (*listp)->next;
+         }
+
+      /* Now it's time to restore the cancelation state.  */
+      pthread_setcancelstate (oldstate, NULL);
+
+      /* Release the conditional variable.  */
+      if (pthread_cond_destroy (&cond) != 0)
+       /* This must never happen.  */
+       abort ();
+
+      if (result != 0)
+       {
+         /* An error occurred.  Possibly it's EINTR.  We have to translate
+            the timeout error report of `pthread_cond_timedwait' to the
+            form expected from `gai_suspend'.  */
+         if (__builtin_expect (result, ETIMEDOUT) == ETIMEDOUT)
+           result = EAI_AGAIN;
+         else if (result == EINTR)
+           result = EAI_INTR;
+         else
+           result = EAI_SYSTEM;
+       }
+    }
+
+  /* Release the mutex.  */
+  pthread_mutex_unlock (&__gai_requests_mutex);
+
+  return result;
+}
diff --git a/resolv/getaddrinfo_a.c b/resolv/getaddrinfo_a.c
new file mode 100644 (file)
index 0000000..1a077d1
--- /dev/null
@@ -0,0 +1,168 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "gai_misc.h"
+
+
+/* We need this special structure to handle asynchronous I/O.  */
+struct async_waitlist
+  {
+    int counter;
+    struct sigevent sigev;
+    struct waitlist list[0];
+  };
+
+
+int
+getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig)
+{
+  struct sigevent defsigev;
+  struct requestlist *requests[ent];
+  int cnt;
+  volatile int total = 0;
+  int result = 0;
+
+  /* Check arguments.  */
+  if (mode != GAI_WAIT && mode != GAI_NOWAIT)
+    {
+      __set_errno (EINVAL);
+      return EAI_SYSTEM;
+    }
+
+  if (sig == NULL)
+    {
+      defsigev.sigev_notify = SIGEV_NONE;
+      sig = &defsigev;
+    }
+
+  /* Request the mutex.  */
+  pthread_mutex_lock (&__gai_requests_mutex);
+
+  /* Now we can enqueue all requests.  Since we already acquired the
+     mutex the enqueue function need not do this.  */
+  for (cnt = 0; cnt < ent; ++cnt)
+    if (list[cnt] != NULL)
+      {
+       requests[cnt] = __gai_enqueue_request (list[cnt]);
+
+       if (requests[cnt] != NULL)
+         /* Successfully enqueued.  */
+         ++total;
+       else
+         /* Signal that we've seen an error.  `errno' and the error code
+            of the gaicb will tell more.  */
+         result = EAI_SYSTEM;
+      }
+    else
+      requests[cnt] = NULL;
+
+  if (total == 0)
+    {
+      /* We don't have anything to do except signalling if we work
+        asynchronously.  */
+
+      /* Release the mutex.  We do this before raising a signal since the
+        signal handler might do a `siglongjmp' and then the mutex is
+        locked forever.  */
+      pthread_mutex_unlock (&__gai_requests_mutex);
+
+      if (mode == GAI_NOWAIT)
+       __gai_notify_only (sig,
+                          sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0);
+
+      return result;
+    }
+  else if (mode == GAI_WAIT)
+    {
+      pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+      struct waitlist waitlist[ent];
+      int oldstate;
+
+      total = 0;
+      for (cnt = 0; cnt < ent; ++cnt)
+       if (requests[cnt] != NULL)
+         {
+           waitlist[cnt].cond = &cond;
+           waitlist[cnt].next = requests[cnt]->waiting;
+           waitlist[cnt].counterp = &total;
+           waitlist[cnt].sigevp = NULL;
+           waitlist[cnt].caller_pid = 0;       /* Not needed.  */
+           requests[cnt]->waiting = &waitlist[cnt];
+           ++total;
+         }
+
+      /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation
+        points we must be careful.  We added entries to the waiting lists
+        which we must remove.  So defer cancelation for now.  */
+      pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate);
+
+      while (total > 0)
+       pthread_cond_wait (&cond, &__gai_requests_mutex);
+
+      /* Now it's time to restore the cancelation state.  */
+      pthread_setcancelstate (oldstate, NULL);
+
+      /* Release the conditional variable.  */
+      if (pthread_cond_destroy (&cond) != 0)
+       /* This must never happen.  */
+       abort ();
+    }
+  else
+    {
+      struct async_waitlist *waitlist;
+
+      waitlist = (struct async_waitlist *)
+       malloc (sizeof (struct async_waitlist)
+               + (ent * sizeof (struct waitlist)));
+
+      if (waitlist == NULL)
+       result = EAI_AGAIN;
+      else
+       {
+         pid_t caller_pid = sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0;
+         total = 0;
+
+         for (cnt = 0; cnt < ent; ++cnt)
+           if (requests[cnt] != NULL)
+             {
+               waitlist->list[cnt].cond = NULL;
+               waitlist->list[cnt].next = requests[cnt]->waiting;
+               waitlist->list[cnt].counterp = &waitlist->counter;
+               waitlist->list[cnt].sigevp = &waitlist->sigev;
+               waitlist->list[cnt].caller_pid = caller_pid;
+               requests[cnt]->waiting = &waitlist->list[cnt];
+               ++total;
+             }
+
+         waitlist->counter = total;
+         waitlist->sigev = *sig;
+       }
+    }
+
+  /* Release the mutex.  */
+  pthread_mutex_unlock (&__gai_requests_mutex);
+
+  return result;
+}
index ae3f95a..79c147e 100644 (file)
 # include <rpc/netdb.h>
 #endif
 
+#ifdef __USE_GNU
+# define __need_sigevent_t
+# include <bits/siginfo.h>
+#endif
+
 #include <bits/netdb.h>
 
 /* Absolute file name for network data base files.  */
@@ -412,23 +417,48 @@ struct addrinfo
   struct addrinfo *ai_next;    /* Pointer to next in list.  */
 };
 
+# ifdef __USE_GNU
+/* Structure used as control block for asynchronous lookup.  */
+struct gaicb
+{
+  const char *ar_name;         /* Name to look up.  */
+  const char *ar_service;      /* Service name.  */
+  const struct addrinfo *ar_request; /* Additional request specification.  */
+  struct addrinfo *ar_result;  /* Pointer to result.  */
+  /* The following are internal elements.  */
+  int __return;
+  int __unused[5];
+};
+
+/* Lookup mode.  */
+#  define GAI_WAIT     0
+#  define GAI_NOWAIT   1
+# endif
+
 /* Possible values for `ai_flags' field in `addrinfo' structure.  */
 # define AI_PASSIVE    0x0001  /* Socket address is intended for `bind'.  */
 # define AI_CANONNAME  0x0002  /* Request for canonical name.  */
 # define AI_NUMERICHOST        0x0004  /* Don't use name resolution.  */
 
 /* Error values for `getaddrinfo' function.  */
-# define EAI_BADFLAGS  -1      /* Invalid value for `ai_flags' field.  */
-# define EAI_NONAME    -2      /* NAME or SERVICE is unknown.  */
-# define EAI_AGAIN     -3      /* Temporary failure in name resolution.  */
-# define EAI_FAIL      -4      /* Non-recoverable failure in name res.  */
-# define EAI_NODATA    -5      /* No address associated with NAME.  */
-# define EAI_FAMILY    -6      /* `ai_family' not supported.  */
-# define EAI_SOCKTYPE  -7      /* `ai_socktype' not supported.  */
-# define EAI_SERVICE   -8      /* SERVICE not supported for `ai_socktype'.  */
-# define EAI_ADDRFAMILY        -9      /* Address family for NAME not supported.  */
-# define EAI_MEMORY    -10     /* Memory allocation failure.  */
-# define EAI_SYSTEM    -11     /* System error returned in `errno'.  */
+# define EAI_BADFLAGS    -1    /* Invalid value for `ai_flags' field.  */
+# define EAI_NONAME      -2    /* NAME or SERVICE is unknown.  */
+# define EAI_AGAIN       -3    /* Temporary failure in name resolution.  */
+# define EAI_FAIL        -4    /* Non-recoverable failure in name res.  */
+# define EAI_NODATA      -5    /* No address associated with NAME.  */
+# define EAI_FAMILY      -6    /* `ai_family' not supported.  */
+# define EAI_SOCKTYPE    -7    /* `ai_socktype' not supported.  */
+# define EAI_SERVICE     -8    /* SERVICE not supported for `ai_socktype'.  */
+# define EAI_ADDRFAMILY          -9    /* Address family for NAME not supported.  */
+# define EAI_MEMORY      -10   /* Memory allocation failure.  */
+# define EAI_SYSTEM      -11   /* System error returned in `errno'.  */
+# ifdef __USE_GNU
+#  define EAI_INPROGRESS  -100 /* Processing request in progress.  */
+#  define EAI_CANCELED   -101  /* Request canceled.  */
+#  define EAI_NOTCANCELED -102 /* Request not canceled.  */
+#  define EAI_ALLDONE    -103  /* All requests done.  */
+#  define EAI_INTR       -104  /* Interrupted by a signal.  */
+# endif
 
 # define NI_MAXHOST      1025
 # define NI_MAXSERV      32
@@ -458,6 +488,26 @@ extern int getnameinfo (__const struct sockaddr *__restrict __sa,
                        socklen_t __hostlen, char *__restrict __serv,
                        socklen_t __servlen, unsigned int __flags) __THROW;
 
+# ifdef __USE_GNU
+/* Enqueue ENT requests from the LIST.  If MODE is GAI_WAIT wait until all
+   requests are handled.  If WAIT is GAI_NOWAIT return immediately after
+   queueing the requests and signal completion according to SIG.  */
+extern int getaddrinfo_a (int __mode, struct gaicb *__list[__restrict_arr],
+                         int __ent, struct sigevent *__restrict __sig)
+     __THROW;
+
+/* Suspend execution of the thread until at least one of the ENT requests
+   in LIST is handled.  If TIMEOUT is not a null pointer it specifies the
+   longest time the function keeps waiting before returning with an error.  */
+extern int gai_suspend (__const struct gaicb *__const __list[], int __ent,
+                       const struct timespec *__timeout) __THROW;
+
+/* Get the error status of the request REQ.  */
+extern int gai_error (struct gaicb *__req) __THROW;
+
+/* Cancel the requests associated with GAICBP.  */
+extern int gai_cancel (struct gaicb *__gaicbp) __THROW;
+# endif        /* GNU */
 #endif /* POSIX */
 
 __END_DECLS
index b26558a..46f77b2 100644 (file)
@@ -1,5 +1,5 @@
 /* Handle general operations.
-   Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -115,7 +115,7 @@ get_elem (void)
          pool = new_tab;
        }
 
-      /* Allocat the new row.  */
+      /* Allocate the new row.  */
       cnt = pool_size == 0 ? optim.aio_num : ENTRIES_PER_ROW;
       new_row = (struct requestlist *) calloc (cnt,
                                               sizeof (struct requestlist));
@@ -414,7 +414,7 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
            ++nthreads;
          else
            {
-             /* Reset the running flat.  The new request is not running.  */
+             /* Reset the running flag.  The new request is not running.  */
              running = newp->running = yes;
 
              if (nthreads == 0)
index 37ddb84..aa267a8 100644 (file)
@@ -1,5 +1,5 @@
 /* Enqueue and list of read or write requests.
-   Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -70,8 +70,8 @@ lio_listio (mode, list, nent, sig)
     if (list[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP)
       {
        list[cnt]->aio_sigevent.sigev_notify = SIGEV_NONE;
-       requests[cnt] =  __aio_enqueue_request ((aiocb_union *) list[cnt],
-                                               list[cnt]->aio_lio_opcode);
+       requests[cnt] = __aio_enqueue_request ((aiocb_union *) list[cnt],
+                                              list[cnt]->aio_lio_opcode);
 
        if (requests[cnt] != NULL)
          /* Successfully enqueued.  */
@@ -81,6 +81,8 @@ lio_listio (mode, list, nent, sig)
             of the aiocb will tell more.  */
          result = -1;
       }
+    else
+      requests[cnt] = NULL;
 
   if (total == 0)
     {
@@ -106,8 +108,7 @@ lio_listio (mode, list, nent, sig)
 
       total = 0;
       for (cnt = 0; cnt < nent; ++cnt)
-       if (list[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP
-           && requests[cnt] != NULL)
+       if (requests[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP)
          {
            waitlist[cnt].cond = &cond;
            waitlist[cnt].next = requests[cnt]->waiting;
@@ -153,8 +154,7 @@ lio_listio (mode, list, nent, sig)
          total = 0;
 
          for (cnt = 0; cnt < nent; ++cnt)
-           if (list[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP
-               && requests[cnt] != NULL)
+           if (requests[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP)
              {
                waitlist->list[cnt].cond = NULL;
                waitlist->list[cnt].next = requests[cnt]->waiting;
index 24e934d..892950a 100644 (file)
@@ -116,3 +116,6 @@ hppa-.*-.*          libBrokenLocale=1       GLIBC_2.2
 # The real-time library from POSIX.1b.
 mips.*-.*-linux.*      librt=1                 GLIBC_2.0 GLIBC_2.2
 .*-.*-.*               librt=1
+
+# The asynchronous name lookup library.
+.*-.*-.*               libanl=1
index 31b0dde..77a314b 100644 (file)
@@ -1,5 +1,5 @@
 /* siginfo_t, sigevent and constants.  Stub version.
-   Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#if !defined _SIGNAL_H && !defined __need_siginfo_t
+#if !defined _SIGNAL_H && !defined __need_siginfo_t \
+    && !defined __need_sigevent_t
 # error "Never include this file directly.  Use <signal.h> instead"
 #endif
 
-#if (!defined __have_siginfo_t \
-     && (defined _SIGNAL_H || defined __need_siginfo_t))
-# define __have_siginfo_t      1
+#if (!defined __have_sigval_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t \
+        || defined __need_sigevent_t))
+# define __have_sigval_t 1
 
 /* Type for data associated with a signal.  */
 typedef union sigval
@@ -31,6 +33,11 @@ typedef union sigval
     int sival_int;
     void *sival_ptr;
   } sigval_t;
+#endif
+
+#if (!defined __have_siginfo_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t))
+# define __have_siginfo_t      1
 
 typedef struct siginfo
   {
@@ -173,7 +180,8 @@ enum
 #endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t).  */
 
 
-#if defined _SIGNAL_H && !defined __have_sigevent_t
+#if (defined _SIGNAL_H || defined __need_sigevent_t) \
+    && !defined __have_sigevent_t
 # define __have_sigevent_t     1
 
 /* Structure to transport application-defined values with signals.  */
diff --git a/sysdeps/generic/gai_sigqueue.c b/sysdeps/generic/gai_sigqueue.c
new file mode 100644 (file)
index 0000000..856547c
--- /dev/null
@@ -0,0 +1,36 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <aio.h>
+#include <errno.h>
+#include <signal.h>
+
+#include "gai_misc.h"
+
+int
+__gai_sigqueue (sig, val, caller_pid)
+     int sig;
+     const union sigval val;
+     pid_t caller_pid;
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__gai_sigqueue)
+#include <stub-tag.h>
index ca0a4fc..25360a1 100644 (file)
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#if !defined _SIGNAL_H && !defined __need_siginfo_t
+#if !defined _SIGNAL_H && !defined __need_siginfo_t \
+    && !defined __need_sigevent_t
 # error "Never include this file directly.  Use <signal.h> instead"
 #endif
 
 #include <bits/wordsize.h>
 
-#if (!defined __have_siginfo_t \
-     && (defined _SIGNAL_H || defined __need_siginfo_t))
-# define __have_siginfo_t      1
+#if (!defined __have_sigval_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t \
+        || defined __need_sigevent_t))
+# define __have_sigval_t       1
 
 /* Type for data associated with a signal.  */
 typedef union sigval
@@ -33,6 +35,11 @@ typedef union sigval
     int sival_int;
     void *sival_ptr;
   } sigval_t;
+#endif
+
+#if (!defined __have_siginfo_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t))
+# define __have_siginfo_t      1
 
 # define __SI_MAX_SIZE     128
 # if __WORDSIZE == 64
@@ -246,7 +253,8 @@ enum
 #endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t).  */
 
 
-#if defined _SIGNAL_H && !defined __have_sigevent_t
+#if (defined _SIGNAL_H || defined __need_sigevent_t) \
+    && !defined __have_sigevent_t
 # define __have_sigevent_t     1
 
 /* Structure to transport application-defined values with signals.  */
index 2f7dc19..1b5328d 100644 (file)
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#if !defined _SIGNAL_H && !defined __need_siginfo_t
+#if !defined _SIGNAL_H && !defined __need_siginfo_t \
+    && !defined __need_sigevent_t
 # error "Never include this file directly.  Use <signal.h> instead"
 #endif
 
 #include <bits/wordsize.h>
 
-#if (!defined __have_siginfo_t \
-     && (defined _SIGNAL_H || defined __need_siginfo_t))
-# define __have_siginfo_t      1
+#if (!defined __have_sigval_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t \
+        || defined __need_sigevent_t))
+# define __have_sigval_t       1
 
 /* Type for data associated with a signal.  */
 typedef union sigval
@@ -33,6 +35,11 @@ typedef union sigval
     int sival_int;
     void *sival_ptr;
   } sigval_t;
+#endif
+
+#if (!defined __have_siginfo_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t))
+# define __have_siginfo_t      1
 
 # define __SI_MAX_SIZE     128
 # if __WORDSIZE == 64
@@ -120,7 +127,9 @@ typedef struct siginfo
    signals.  */
 enum
 {
-  SI_SIGIO = -5,               /* Sent by queued SIGIO. */
+  SI_ASYNCNL = -6,             /* Sent by asynch name lookup completion.  */
+# define SI_ASYNCNL    SI_ASYNCNL
+  SI_SIGIO,                    /* Sent by queued SIGIO. */
 # define SI_SIGIO      SI_SIGIO
   SI_ASYNCIO,                  /* Sent by AIO completion.  */
 # define SI_ASYNCIO    SI_ASYNCIO
@@ -246,7 +255,8 @@ enum
 #endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t).  */
 
 
-#if defined _SIGNAL_H && !defined __have_sigevent_t
+#if (defined _SIGNAL_H || defined __need_sigevent_t) \
+    && !defined __have_sigevent_t
 # define __have_sigevent_t     1
 
 /* Structure to transport application-defined values with signals.  */
diff --git a/sysdeps/unix/sysv/linux/gai_sigqueue.c b/sysdeps/unix/sysv/linux/gai_sigqueue.c
new file mode 100644 (file)
index 0000000..c9d686f
--- /dev/null
@@ -0,0 +1,58 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <netdb.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sysdep.h>
+#include <sys/syscall.h>
+
+#include "gai_misc.h"
+
+#ifdef __NR_rt_sigqueueinfo
+extern int __syscall_rt_sigqueueinfo (int, int, siginfo_t *__unbounded);
+
+
+/* Return any pending signal or wait for one for the given time.  */
+int
+__gai_sigqueue (sig, val, caller_pid)
+     int sig;
+     const union sigval val;
+     pid_t caller_pid;
+{
+  siginfo_t info;
+
+  /* First, clear the siginfo_t structure, so that we don't pass our
+     stack content to other tasks.  */
+  memset (&info, 0, sizeof (siginfo_t));
+  /* We must pass the information about the data in a siginfo_t value.  */
+  info.si_signo = sig;
+  info.si_code = SI_ASYNCNL;
+  info.si_pid = caller_pid;
+  info.si_uid = getuid ();
+  info.si_value = val;
+
+  return INLINE_SYSCALL (rt_sigqueueinfo, 3, info.si_pid,
+                        sig, __ptrvalue (&info));
+}
+#else
+# include <sysdeps/generic/gai_sigqueue.c>
+#endif
index 0113257..5f5ee00 100644 (file)
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#if !defined _SIGNAL_H && !defined __need_siginfo_t
+#if !defined _SIGNAL_H && !defined __need_siginfo_t \
+    && !defined __need_sigevent_t
 # error "Never include this file directly.  Use <signal.h> instead"
 #endif
 
-#if (!defined __have_siginfo_t \
-     && (defined _SIGNAL_H || defined __need_siginfo_t))
-# define __have_siginfo_t      1
+#if (!defined __have_sigval_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t \
+        || defined __need_sigval_t))
+# define __have_sigval_t       1
 
 /* Type for data associated with a signal.  */
 typedef union sigval
@@ -32,6 +34,11 @@ typedef union sigval
     int sival_int;
     void *sival_ptr;
   } sigval_t;
+#endif
+
+#if (!defined __have_siginfo_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t))
+# define __have_siginfo_t      1
 
 # define __SI_MAX_SIZE     128
 # define __SI_PAD_SIZE     ((__SI_MAX_SIZE / sizeof (int)) - 4)
@@ -276,7 +283,8 @@ enum
 #endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t).  */
 
 
-#if defined _SIGNAL_H && !defined __have_sigevent_t
+#if (defined _SIGNAL_H || defined __need_sigevent_t) \
+    && !defined __have_sigevent_t
 # define __have_sigevent_t     1
 
 /* Structure to transport application-defined values with signals.  */
index 6bebeb2..03f5b3e 100644 (file)
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#if !defined _SIGNAL_H && !defined __need_siginfo_t
+#if !defined _SIGNAL_H && !defined __need_siginfo_t \
+    && !defined __need_sigevent_t
 # error "Never include this file directly.  Use <signal.h> instead"
 #endif
 
-#if (!defined __have_siginfo_t \
-     && (defined _SIGNAL_H || defined __need_siginfo_t))
-# define __have_siginfo_t      1
+#if (!defined __have_sigval_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t \
+        || defined __need_sigevent_t))
+# define __have_sigval_t       1
 
 /* Type for data associated with a signal.  */
 typedef union sigval
@@ -31,6 +33,11 @@ typedef union sigval
     int sival_int;
     void *sival_ptr;
   } sigval_t;
+#endif
+
+#if (!defined __have_siginfo_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t))
+# define __have_siginfo_t      1
 
 # define __SI_MAX_SIZE     128
 # define __SI_PAD_SIZE     ((__SI_MAX_SIZE / sizeof (int)) - 3)
@@ -238,7 +245,8 @@ enum
 #endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t).  */
 
 
-#if defined _SIGNAL_H && !defined __have_sigevent_t
+#if (defined _SIGNAL_H || defined __need_sigevent_t) \
+    && !defined __have_sigevent_t
 # define __have_sigevent_t     1
 
 /* Structure to transport application-defined values with signals.  */
index 0d92a84..51389bd 100644 (file)
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#if !defined _SIGNAL_H && !defined __need_siginfo_t
+#if !defined _SIGNAL_H && !defined __need_siginfo_t \
+    && !defined __need_sigevent_t
 # error "Never include this file directly.  Use <signal.h> instead"
 #endif
 
 #include <bits/wordsize.h>
 
-#if (!defined __have_siginfo_t \
-     && (defined _SIGNAL_H || defined __need_siginfo_t))
-# define __have_siginfo_t      1
+#if (!defined __have_sigval_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t \
+        || defined __need_sigevent_t))
+# define __have_sigval_t       1
 
 /* Type for data associated with a signal.  */
 typedef union sigval
@@ -33,6 +35,11 @@ typedef union sigval
     int sival_int;
     void *sival_ptr;
   } sigval_t;
+#endif
+
+#if (!defined __have_siginfo_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t))
+# define __have_siginfo_t      1
 
 # define __SI_MAX_SIZE     128
 # if __WORDSIZE == 64
@@ -255,7 +262,8 @@ enum
 #endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t).  */
 
 
-#if defined _SIGNAL_H && !defined __have_sigevent_t
+#if (defined _SIGNAL_H || defined __need_sigevent_t) \
+    && !defined __have_sigevent_t
 # define __have_sigevent_t     1
 
 /* Structure to transport application-defined values with signals.  */
index 9feb725..035f36f 100644 (file)
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#if !defined _SIGNAL_H && !defined __need_siginfo_t
+#if !defined _SIGNAL_H && !defined __need_siginfo_t \
+    && !defined __need_sigevent_t
 # error "Never include this file directly.  Use <signal.h> instead"
 #endif
 
 #include <bits/wordsize.h>
 
-#if (!defined __have_siginfo_t \
-     && (defined _SIGNAL_H || defined __need_siginfo_t))
-# define __have_siginfo_t      1
+#if (!defined __have_sigval_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t \
+        || defined __need_sigevent_t))
+# define __have_sigval_t       1
 
 /* Type for data associated with a signal.  */
 typedef union sigval
@@ -33,6 +35,11 @@ typedef union sigval
     int sival_int;
     void *sival_ptr;
   } sigval_t;
+#endif
+
+#if (!defined __have_siginfo_t \
+     && (defined _SIGNAL_H || defined __need_siginfo_t))
+# define __have_siginfo_t      1
 
 # define __SI_MAX_SIZE     128
 # if __WORDSIZE == 64
@@ -246,7 +253,8 @@ enum
 #endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t).  */
 
 
-#if defined _SIGNAL_H && !defined __have_sigevent_t
+#if (defined _SIGNAL_H || defined __need_sigevent_t) \
+    && !defined __have_sigevent_t
 # define __have_sigevent_t     1
 
 /* Structure to transport application-defined values with signals.  */