[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[commits] r4842 - in /fsf/trunk/libc: ./ localedata/ localedata/locales/ malloc/ nptl/ nptl/sysdeps/unix/sysv/linux/ nptl/sysdeps/unix...



Author: eglibc
Date: Fri Jan 11 00:22:59 2008
New Revision: 4842

Log:
Import glibc-mainline for 2008-01-11

Modified:
    fsf/trunk/libc/ChangeLog
    fsf/trunk/libc/localedata/ChangeLog
    fsf/trunk/libc/localedata/locales/ga_IE
    fsf/trunk/libc/malloc/malloc.c
    fsf/trunk/libc/nptl/ChangeLog
    fsf/trunk/libc/nptl/pthread-errnos.sym
    fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S
    fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/sem_post.c
    fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/structsem.sym
    fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S
    fsf/trunk/libc/posix/tst-rfc3484-2.c
    fsf/trunk/libc/posix/tst-rfc3484-3.c
    fsf/trunk/libc/posix/tst-rfc3484.c
    fsf/trunk/libc/sysdeps/posix/getaddrinfo.c

Modified: fsf/trunk/libc/ChangeLog
==============================================================================
--- fsf/trunk/libc/ChangeLog (original)
+++ fsf/trunk/libc/ChangeLog Fri Jan 11 00:22:59 2008
@@ -1,3 +1,27 @@
+2008-01-10  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* sysdeps/posix/getaddrinfo.c (rfc3484_sort): Store result of
+	native interface lookup in all the relevant places.
+
+2008-01-10  Jakub Jelinek  <jakub@xxxxxxxxxx>
+	    Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* sysdeps/posix/getaddrinfo.c (sort_results): Remove service_order
+	field.  Use sockaddr_in6 for source_addr.
+	(get_scope): Change type of parameter to sockaddr_in6.  Adjust.
+	(match_prefix): Likewise.
+	(get_label): Likewise.
+	(get_precedence): Likewise.
+	(rfc3484_sort): Change to use indirect access to results array.
+	Adjust to use of sockaddr_in6.  Replace service_order test with
+	simple index comparison.
+	(getaddrinfo): Define order array.  Initialize it.  Don't initialize
+	service_order field.  Adjust qsort_t calls.  Access sorted result
+	array indirectly through order array.
+	* posix/tst-rfc3484.c: Adjust for change of rfc3484_sort.
+	* posix/tst-rfc3484-2.c: Likewise.
+	* posix/tst-rfc3484-3.c: Likewise.
+
 2008-01-09  Ulrich Drepper  <drepper@xxxxxxxxxx>
 
 	[BZ #5541]

Modified: fsf/trunk/libc/localedata/ChangeLog
==============================================================================
--- fsf/trunk/libc/localedata/ChangeLog (original)
+++ fsf/trunk/libc/localedata/ChangeLog Fri Jan 11 00:22:59 2008
@@ -1,3 +1,8 @@
+2008-01-10  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	[BZ #5520]
+	* locales/ga_IE: Fix May, June, November and December entries in mon.
+
 2007-12-11  Ulrich Drepper  <drepper@xxxxxxxxxx>
 
 	* charmsp/HP-THAI8: New file.

Modified: fsf/trunk/libc/localedata/locales/ga_IE
==============================================================================
--- fsf/trunk/libc/localedata/locales/ga_IE (original)
+++ fsf/trunk/libc/localedata/locales/ga_IE Fri Jan 11 00:22:59 2008
@@ -101,14 +101,14 @@
             "<U0046><U0065><U0061><U0062><U0068><U0072><U0061>";/
             "<U004D><U00E1><U0072><U0074><U0061>";/
             "<U0041><U0069><U0062><U0072><U0065><U00E1><U006E>";/
-            "<U004D><U00ED><U0020><U006E><U0061><U0020><U0042><U0065><U0061><U006C><U0074><U0061><U0069><U006E><U0065>";/
-            "<U004D><U0065><U0069><U0074><U0068>";/
+            "<U0042><U0065><U0061><U006C><U0074><U0061><U0069><U006E><U0065>";/
+            "<U004D><U0065><U0069><U0074><U0068><U0065><U0061><U006d><U0068>";/
             "<U0049><U00FA><U0069><U006C>";/
             "<U004C><U00FA><U006E><U0061><U0073><U0061>";/
             "<U004D><U0065><U00E1><U006E><U0020><U0046><U00F3><U006D><U0068><U0061><U0069><U0072>";/
             "<U0044><U0065><U0069><U0072><U0065><U0061><U0064><U0068><U0020><U0046><U00F3><U006D><U0068><U0061><U0069><U0072>";/
-            "<U004D><U00ED><U0020><U006E><U0061><U0020><U0053><U0061><U006D><U0068><U006E><U0061>";/
-            "<U004D><U00ED><U0020><U006E><U0061><U0020><U004E><U006F><U006C><U006C><U0061><U0067>"
+            "<U0053><U0061><U006D><U0068><U0061><U0069><U006E>";/
+            "<U004E><U006F><U006C><U006C><U0061><U0069><U0067>"
 d_t_fmt     "<U0025><U0061><U0020><U0025><U0064><U0020><U0025><U0062><U0020><U0025><U0059><U0020><U0025><U0054><U0020><U0025><U005A>"
 d_fmt       "<U0025><U0064><U002E><U0025><U006D><U002E><U0025><U0079>"
 t_fmt       "<U0025><U0054>"

Modified: fsf/trunk/libc/malloc/malloc.c
==============================================================================
--- fsf/trunk/libc/malloc/malloc.c (original)
+++ fsf/trunk/libc/malloc/malloc.c Fri Jan 11 00:22:59 2008
@@ -3781,7 +3781,8 @@
       }
 #endif
     }
-  }
+  } else
+    (void)mutex_unlock(&ar_ptr->mutex);
   assert(!p || chunk_is_mmapped(mem2chunk(p)) ||
 	 ar_ptr == arena_for_chunk(mem2chunk(p)));
   return p;

Modified: fsf/trunk/libc/nptl/ChangeLog
==============================================================================
--- fsf/trunk/libc/nptl/ChangeLog (original)
+++ fsf/trunk/libc/nptl/ChangeLog Fri Jan 11 00:22:59 2008
@@ -1,3 +1,11 @@
+2008-01-10  Ulrich Drepper  <drepper@xxxxxxxxxx>
+
+	* pthread-errnos.sym: Add EOVERFLOW.
+	* sysdeps/unix/sysv/linux/structsem.sym: Add SEM_VALUE_MAX.
+	* sysdeps/unix/sysv/linux/sem_post.c: Don't overflow value field.
+	* sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise.
+	* sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise.
+
 2007-12-14  Ulrich Drepper  <drepper@xxxxxxxxxx>
 
 	* sysdeps/x86_64/pthreaddef.h (ARCH_RETRY_MMAP): Take additional

Modified: fsf/trunk/libc/nptl/pthread-errnos.sym
==============================================================================
--- fsf/trunk/libc/nptl/pthread-errnos.sym (original)
+++ fsf/trunk/libc/nptl/pthread-errnos.sym Fri Jan 11 00:22:59 2008
@@ -8,5 +8,6 @@
 EINTR		EINTR
 EINVAL		EINVAL
 ENOSYS		ENOSYS
+EOVERFLOW	EOVERFLOW
 ETIMEDOUT	ETIMEDOUT
 EWOULDBLOCK	EWOULDBLOCK

Modified: fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S
==============================================================================
--- fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S (original)
+++ fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S Fri Jan 11 00:22:59 2008
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 2002.
 
@@ -34,12 +34,21 @@
 
 	movl	8(%esp), %ebx
 
+#if VALUE == 0
+	movl	(%ebx), %eax
+#else
+	movl	VALUE(%ebx), %eax
+#endif
+0:	cmpl	$SEM_VALUE_MAX, %eax
+	je	3f
+	leal	1(%eax), %edx
 	LOCK
 #if VALUE == 0
-	addl	$1, (%ebx)
+	cmpxchgl %edx, (%ebx)
 #else
-	addl	$1, VALUE(%ebx)
+	cmpxchgl %edx, VALUE(%ebx)
 #endif
+	jnz	0b
 
 	cmpl	$0, NWAITERS(%ebx)
 	je	2f
@@ -77,6 +86,32 @@
 #else
 	call	__errno_location@plt
 	movl	$EINVAL, (%eax)
+#endif
+
+	orl	$-1, %eax
+	popl	%ebx
+	ret
+
+3:
+#ifdef PIC
+	call	__i686.get_pc_thunk.bx
+#else
+	movl	$5f, %ebx
+5:
+#endif
+	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
+#if USE___THREAD
+# ifdef NO_TLS_DIRECT_SEG_REFS
+	movl	errno@gotntpoff(%ebx), %edx
+	addl	%gs:0, %edx
+	movl	$EOVERFLOW, (%edx)
+# else
+	movl	errno@gotntpoff(%ebx), %edx
+	movl	$EOVERFLOW, %gs:(%edx)
+# endif
+#else
+	call	__errno_location@plt
+	movl	$EOVERFLOW, (%eax)
 #endif
 
 	orl	$-1, %eax

Modified: fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/sem_post.c
==============================================================================
--- fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/sem_post.c (original)
+++ fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/sem_post.c Fri Jan 11 00:22:59 2008
@@ -1,5 +1,5 @@
 /* sem_post -- post to a POSIX semaphore.  Generic futex-using version.
-   Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@xxxxxxxxxx>, 2003.
 
@@ -31,7 +31,18 @@
 {
   struct new_sem *isem = (struct new_sem *) sem;
 
-  int nr = atomic_increment_val (&isem->value);
+  __typeof (isem->value) cur;
+  do
+    {
+      cur = isem->value;
+      if (isem->value == SEM_VALUE_MAX)
+	{
+	  __set_errno (EOVERFLOW);
+	  return -1;
+	}
+    }
+  while (atomic_compare_and_exchange_bool_acq (&isem->value, cur + 1, cur));
+
   atomic_full_barrier ();
   if (isem->nwaiters > 0)
     {

Modified: fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/structsem.sym
==============================================================================
--- fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/structsem.sym (original)
+++ fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/structsem.sym Fri Jan 11 00:22:59 2008
@@ -1,3 +1,4 @@
+#include <limits.h>
 #include <stddef.h>
 #include <sched.h>
 #include <bits/pthreadtypes.h>
@@ -8,3 +9,4 @@
 VALUE		offsetof (struct new_sem, value)
 PRIVATE		offsetof (struct new_sem, private)
 NWAITERS	offsetof (struct new_sem, nwaiters)
+SEM_VALUE_MAX	SEM_VALUE_MAX

Modified: fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S
==============================================================================
--- fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S (original)
+++ fsf/trunk/libc/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S Fri Jan 11 00:22:59 2008
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@xxxxxxxxxx>, 2002.
 
@@ -30,12 +30,21 @@
 	.type	sem_post,@function
 	.align	16
 sem_post:
+#if VALUE == 0
+	movl	(%rdi), %eax
+#else
+	movl	VALUE(%rdi), %eax
+#endif
+0:	cmpl	$SEM_VALUE_MAX, %eax
+	je	3f
+	leal	1(%eax), %esi
 	LOCK
 #if VALUE == 0
-	addl	$1, (%rdi)
+	cmpxchgl %esi, (%rdi)
 #else
-	addl	$1, VALUE(%rdi)
+	cmpxchgl %esi, VALUE(%rdi)
 #endif
+	jnz	0b
 
 	cmpq	$0, NWAITERS(%rdi)
 	je	2f
@@ -54,13 +63,28 @@
 
 1:
 #if USE___THREAD
-	movq	errno@gottpoff(%rip), %rdx
-	movl	$EINVAL, %fs:(%rdx)
+	movl	$EINVAL, %eax
 #else
 	callq	__errno_location@plt
-	movl	$EINVAL, (%rax)
+	movl	$EINVAL, %edx
+#endif
+	jmp	4f
+
+3:
+#if USE___THREAD
+	movl	$EOVERFLOW, %eax
+#else
+	callq	__errno_location@plt
+	movl	$EOVERFLOW, %edx
 #endif
 
+4:
+#if USE___THREAD
+	movq	errno@gottpoff(%rip), %rdx
+	movl	%eax, %fs:(%rdx)
+#else
+	movl	%edx, (%rax)
+#endif
 	orl	$-1, %eax
 	retq
 	.size	sem_post,.-sem_post

Modified: fsf/trunk/libc/posix/tst-rfc3484-2.c
==============================================================================
--- fsf/trunk/libc/posix/tst-rfc3484-2.c (original)
+++ fsf/trunk/libc/posix/tst-rfc3484-2.c Fri Jan 11 00:22:59 2008
@@ -100,31 +100,32 @@
 
 
   struct sort_result results[2];
+  size_t order[2];
 
   results[0].dest_addr = &ai1;
   results[0].got_source_addr = true;
   results[0].source_addr_len = sizeof (so1);
   results[0].source_addr_flags = 0;
-  results[0].service_order = 0;
   results[0].prefixlen = 16;
   results[0].index = 0;
   memcpy (&results[0].source_addr, &so1, sizeof (so1));
+  order[0] = 0;
 
   results[1].dest_addr = &ai2;
   results[1].got_source_addr = true;
   results[1].source_addr_len = sizeof (so2);
   results[1].source_addr_flags = 0;
-  results[1].service_order = 1;
   results[1].prefixlen = 16;
   results[1].index = 0;
   memcpy (&results[1].source_addr, &so2, sizeof (so2));
+  order[1] = 1;
 
 
   struct sort_result_combo combo = { .results = results, .nresults = 2 };
-  qsort_r (results, 2, sizeof (results[0]), rfc3484_sort, &combo);
+  qsort_r (order, 2, sizeof (order[0]), rfc3484_sort, &combo);
 
   int result = 0;
-  if (results[0].dest_addr->ai_family == AF_INET6)
+  if (results[order[0]].dest_addr->ai_family == AF_INET6)
     {
       puts ("wrong order in first test");
       result |= 1;
@@ -136,24 +137,24 @@
   results[1].got_source_addr = true;
   results[1].source_addr_len = sizeof (so1);
   results[1].source_addr_flags = 0;
-  results[1].service_order = 1;
   results[1].prefixlen = 16;
   results[1].index = 0;
   memcpy (&results[1].source_addr, &so1, sizeof (so1));
+  order[1] = 1;
 
   results[0].dest_addr = &ai2;
   results[0].got_source_addr = true;
   results[0].source_addr_len = sizeof (so2);
   results[0].source_addr_flags = 0;
-  results[0].service_order = 0;
   results[0].prefixlen = 16;
   results[0].index = 0;
   memcpy (&results[0].source_addr, &so2, sizeof (so2));
+  order[0] = 0;
 
 
-  qsort_r (results, 2, sizeof (results[0]), rfc3484_sort, &combo);
+  qsort_r (order, 2, sizeof (order[0]), rfc3484_sort, &combo);
 
-  if (results[0].dest_addr->ai_family == AF_INET6)
+  if (results[order[0]].dest_addr->ai_family == AF_INET6)
     {
       puts ("wrong order in second test");
       result |= 1;

Modified: fsf/trunk/libc/posix/tst-rfc3484-3.c
==============================================================================
--- fsf/trunk/libc/posix/tst-rfc3484-3.c (original)
+++ fsf/trunk/libc/posix/tst-rfc3484-3.c Fri Jan 11 00:22:59 2008
@@ -66,6 +66,7 @@
 #define naddrs (sizeof (addrs) / sizeof (addrs[0]))
 static struct addrinfo ais[naddrs];
 static struct sort_result results[naddrs];
+static size_t order[naddrs];
 
 static const int expected[naddrs] =
   {
@@ -111,18 +112,19 @@
       memcpy(&results[i].source_addr, &so, sizeof (so));
       results[i].source_addr_len = sizeof (so);
       results[i].source_addr_flags = 0;
-      results[i].service_order = i;
       results[i].prefixlen = 8;
       results[i].index = 0;
+
+      order[i] = i;
     }
 
   struct sort_result_combo combo = { .results = results, .nresults = naddrs };
-  qsort_r (results, naddrs, sizeof (results[0]), rfc3484_sort, &combo);
+  qsort_r (order, naddrs, sizeof (order[0]), rfc3484_sort, &combo);
 
   int result = 0;
   for (int i = 0; i < naddrs; ++i)
     {
-      struct in_addr addr = ((struct sockaddr_in *) (results[i].dest_addr->ai_addr))->sin_addr;
+      struct in_addr addr = ((struct sockaddr_in *) (results[order[i]].dest_addr->ai_addr))->sin_addr;
 
       int here = memcmp (&addr, &addrs[expected[i]].sin_addr,
 			 sizeof (struct in_addr));

Modified: fsf/trunk/libc/posix/tst-rfc3484.c
==============================================================================
--- fsf/trunk/libc/posix/tst-rfc3484.c (original)
+++ fsf/trunk/libc/posix/tst-rfc3484.c Fri Jan 11 00:22:59 2008
@@ -64,6 +64,7 @@
 #define naddrs (sizeof (addrs) / sizeof (addrs[0]))
 static struct addrinfo ais[naddrs];
 static struct sort_result results[naddrs];
+static size_t order[naddrs];
 
 static int expected[naddrs] =
   {
@@ -100,18 +101,19 @@
       memcpy(&results[i].source_addr, &so, sizeof (so));
       results[i].source_addr_len = sizeof (so);
       results[i].source_addr_flags = 0;
-      results[i].service_order = i;
       results[i].prefixlen = 8;
       results[i].index = 0;
+
+      order[i] = i;
     }
 
   struct sort_result_combo combo = { .results = results, .nresults = naddrs };
-  qsort_r (results, naddrs, sizeof (results[0]), rfc3484_sort, &combo);
+  qsort_r (order, naddrs, sizeof (order[0]), rfc3484_sort, &combo);
 
   int result = 0;
   for (int i = 0; i < naddrs; ++i)
     {
-      struct in_addr addr = ((struct sockaddr_in *) (results[i].dest_addr->ai_addr))->sin_addr;
+      struct in_addr addr = ((struct sockaddr_in *) (results[order[i]].dest_addr->ai_addr))->sin_addr;
 
       int here = memcmp (&addr, &addrs[expected[i]].sin_addr,
 			 sizeof (struct in_addr));

Modified: fsf/trunk/libc/sysdeps/posix/getaddrinfo.c
==============================================================================
--- fsf/trunk/libc/sysdeps/posix/getaddrinfo.c (original)
+++ fsf/trunk/libc/sysdeps/posix/getaddrinfo.c Fri Jan 11 00:22:59 2008
@@ -997,8 +997,10 @@
 struct sort_result
 {
   struct addrinfo *dest_addr;
-  struct sockaddr_storage source_addr;
-  size_t service_order;
+  /* Using sockaddr_storage is for now overkill.  We only support IPv4
+     and IPv6 so far.  If this changes at some point we can adjust the
+     type here.  */
+  struct sockaddr_in6 source_addr;
   uint8_t source_addr_len;
   bool got_source_addr;
   uint8_t source_addr_flags;
@@ -1047,13 +1049,11 @@
 
 
 static int
-get_scope (const struct sockaddr_storage *ss)
+get_scope (const struct sockaddr_in6 *in6)
 {
   int scope;
-  if (ss->ss_family == PF_INET6)
-    {
-      const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *) ss;
-
+  if (in6->sin6_family == PF_INET6)
+    {
       if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
 	{
 	  if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr))
@@ -1067,9 +1067,9 @@
       else
 	scope = in6->sin6_addr.s6_addr[1] & 0xf;
     }
-  else if (ss->ss_family == PF_INET)
-    {
-      const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
+  else if (in6->sin6_family == PF_INET)
+    {
+      const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
 
       size_t cnt = 0;
       while (1)
@@ -1179,18 +1179,15 @@
 
 
 static int
-match_prefix (const struct sockaddr_storage *ss,
+match_prefix (const struct sockaddr_in6 *in6,
 	      const struct prefixentry *list, int default_val)
 {
   int idx;
   struct sockaddr_in6 in6_mem;
-  const struct sockaddr_in6 *in6;
-
-  if (ss->ss_family == PF_INET6)
-    in6 = (const struct sockaddr_in6 *) ss;
-  else if (ss->ss_family == PF_INET)
-    {
-      const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
+
+  if (in6->sin6_family == PF_INET)
+    {
+      const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
 
       /* Convert to IPv6 address.  */
       in6_mem.sin6_family = PF_INET6;
@@ -1209,7 +1206,7 @@
 
       in6 = &in6_mem;
     }
-  else
+  else if (in6->sin6_family != PF_INET6)
     return default_val;
 
   for (idx = 0; ; ++idx)
@@ -1241,18 +1238,18 @@
 
 
 static int
-get_label (const struct sockaddr_storage *ss)
+get_label (const struct sockaddr_in6 *in6)
 {
   /* XXX What is a good default value?  */
-  return match_prefix (ss, labels, INT_MAX);
+  return match_prefix (in6, labels, INT_MAX);
 }
 
 
 static int
-get_precedence (const struct sockaddr_storage *ss)
+get_precedence (const struct sockaddr_in6 *in6)
 {
   /* XXX What is a good default value?  */
-  return match_prefix (ss, precedence, 0);
+  return match_prefix (in6, precedence, 0);
 }
 
 
@@ -1272,9 +1269,11 @@
 static int
 rfc3484_sort (const void *p1, const void *p2, void *arg)
 {
-  const struct sort_result *a1 = (const struct sort_result *) p1;
-  const struct sort_result *a2 = (const struct sort_result *) p2;
+  const size_t idx1 = *(const size_t *) p1;
+  const size_t idx2 = *(const size_t *) p2;
   struct sort_result_combo *src = (struct sort_result_combo *) arg;
+  struct sort_result *a1 = &src->results[idx1];
+  struct sort_result *a2 = &src->results[idx2];
 
   /* Rule 1: Avoid unusable destinations.
      We have the got_source_addr flag set if the destination is reachable.  */
@@ -1287,10 +1286,10 @@
   /* Rule 2: Prefer matching scope.  Only interesting if both
      destination addresses are IPv6.  */
   int a1_dst_scope
-    = get_scope ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
+    = get_scope ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
 
   int a2_dst_scope
-    = get_scope ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
+    = get_scope ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
 
   if (a1->got_source_addr)
     {
@@ -1330,11 +1329,11 @@
   if (a1->got_source_addr)
     {
       int a1_dst_label
-	= get_label ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
+	= get_label ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
       int a1_src_label = get_label (&a1->source_addr);
 
       int a2_dst_label
-	= get_label ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
+	= get_label ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
       int a2_src_label = get_label (&a2->source_addr);
 
       if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
@@ -1346,9 +1345,9 @@
 
   /* Rule 6: Prefer higher precedence.  */
   int a1_prec
-    = get_precedence ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
+    = get_precedence ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
   int a2_prec
-    = get_precedence ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
+    = get_precedence ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
 
   if (a1_prec > a2_prec)
     return -1;
@@ -1364,27 +1363,54 @@
 	 (most?) cases.  */
       if (a1->index != a2->index)
 	{
-	  if (a1->native == -1 || a2->native == -1)
-	    {
-	      /* If we do not have the information use 'native' as the
-		 default.  */
-	      int a1_native = 0;
-	      int a2_native = 0;
-	      __check_native (a1->index, &a1_native, a2->index, &a2_native);
+	  int a1_native = a1->native;
+	  int a2_native = a2->native;
+
+	  if (a1_native == -1 || a2_native == -1)
+	    {
+	      uint32_t a1_index;
+	      if (a1_native == -1)
+		{
+		  /* If we do not have the information use 'native' as
+		     the default.  */
+		  a1_native = 0;
+		  a1_index = a1->index;
+		}
+	      else
+		a1_index = 0xffffffffu;
+
+	      uint32_t a2_index;
+	      if (a2_native == -1)
+		{
+		  /* If we do not have the information use 'native' as
+		     the default.  */
+		  a2_native = 0;
+		  a2_index = a2->index;
+		}
+	      else
+		a2_index = 0xffffffffu;
+
+	      __check_native (a1_index, &a1_native, a2_index, &a2_native);
 
 	      /* Fill in the results in all the records.  */
 	      for (int i = 0; i < src->nresults; ++i)
-		{
-		  if (a1->native == -1 && src->results[i].index == a1->index)
+		if (src->results[i].index == a1_index)
+		  {
+		    assert (src->results[i].native == -1
+			    || src->results[i].native == a1_native);
 		    src->results[i].native = a1_native;
-		  if (a2->native == -1 && src->results[i].index == a2->index)
+		  }
+		else if (src->results[i].index == a2_index)
+		  {
+		    assert (src->results[i].native == -1
+			    || src->results[i].native == a2_native);
 		    src->results[i].native = a2_native;
-		}
-	    }
-
-	  if (a1->native && !a2->native)
+		  }
+	    }
+
+	  if (a1_native && !a2_native)
 	    return -1;
-	  if (!a1->native && a2->native)
+	  if (!a1_native && a2_native)
 	    return 1;
 	}
     }
@@ -1406,8 +1432,8 @@
 
       if (a1->dest_addr->ai_family == PF_INET)
 	{
-	  assert (a1->source_addr.ss_family == PF_INET);
-	  assert (a2->source_addr.ss_family == PF_INET);
+	  assert (a1->source_addr.sin6_family == PF_INET);
+	  assert (a2->source_addr.sin6_family == PF_INET);
 
 	  /* Outside of subnets, as defined by the network masks,
 	     common address prefixes for IPv4 addresses make no sense.
@@ -1437,8 +1463,8 @@
 	}
       else if (a1->dest_addr->ai_family == PF_INET6)
 	{
-	  assert (a1->source_addr.ss_family == PF_INET6);
-	  assert (a2->source_addr.ss_family == PF_INET6);
+	  assert (a1->source_addr.sin6_family == PF_INET6);
+	  assert (a2->source_addr.sin6_family == PF_INET6);
 
 	  struct sockaddr_in6 *in1_dst;
 	  struct sockaddr_in6 *in1_src;
@@ -1478,7 +1504,7 @@
      compare with the value indicating the order in which the entries
      have been received from the services.  NB: no two entries can have
      the same order so the test will never return zero.  */
-  return a1->service_order < a2->service_order ? -1 : 1;
+  return idx1 < idx2 ? -1 : 1;
 }
 
 
@@ -2100,6 +2126,7 @@
       __libc_once (once, gaiconf_init);
       /* Sort results according to RFC 3484.  */
       struct sort_result results[nresults];
+      size_t order[nresults];
       struct addrinfo *q;
       struct addrinfo *last = NULL;
       char *canonname = NULL;
@@ -2115,8 +2142,8 @@
       for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
 	{
 	  results[i].dest_addr = q;
-	  results[i].service_order = i;
 	  results[i].native = -1;
+	  order[i] = i;
 
 	  /* If we just looked up the address for a different
 	     protocol, reuse the result.  */
@@ -2255,16 +2282,16 @@
 	  __libc_lock_lock (lock);
 	  if (old_once && gaiconf_reload_flag)
 	    gaiconf_reload ();
-	  qsort_r (results, nresults, sizeof (results[0]), rfc3484_sort, &src);
+	  qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
 	  __libc_lock_unlock (lock);
 	}
       else
-	qsort_r (results, nresults, sizeof (results[0]), rfc3484_sort, &src);
+	qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
 
       /* Queue the results up as they come out of sorting.  */
-      q = p = results[0].dest_addr;
+      q = p = results[order[0]].dest_addr;
       for (i = 1; i < nresults; ++i)
-	q = q->ai_next = results[i].dest_addr;
+	q = q->ai_next = results[order[i]].dest_addr;
       q->ai_next = NULL;
 
       /* Fill in the canonical name into the new first entry.  */