Merge "Remove more BSD cruft from the public headers."
authorElliott Hughes <enh@google.com>
Tue, 23 Dec 2014 20:14:52 +0000 (20:14 +0000)
committerGerrit Code Review <noreply-gerritcodereview@google.com>
Tue, 23 Dec 2014 20:14:52 +0000 (20:14 +0000)
18 files changed:
benchmarks/pthread_benchmark.cpp
libc/arch-mips/include/machine/elf_machdep.h
libc/bionic/libc_init_common.cpp
libc/bionic/pthread_create.cpp
libc/bionic/pthread_detach.cpp
libc/bionic/pthread_exit.cpp
libc/bionic/pthread_internal.h
libc/bionic/pthread_internals.cpp
libc/bionic/pthread_join.cpp
libc/bionic/pthread_key.cpp
libc/dns/net/gethnamaddr.c [moved from libc/dns/gethnamaddr.c with 99% similarity]
libc/dns/net/nsdispatch.c
libc/dns/net/sethostent.c
libc/upstream-openbsd/lib/libc/stdio/vfprintf.c
libc/upstream-openbsd/lib/libc/stdio/vfwprintf.c
linker/Android.mk
linker/linker.cpp
tests/stdio_test.cpp

index 92e59982f7c9013d3c32af279d6ced0b6f0c6795..42023e04ae84662b623dcf485c883e0bf095d894 100644 (file)
@@ -47,6 +47,21 @@ static void BM_pthread_getspecific(int iters) {
 }
 BENCHMARK(BM_pthread_getspecific);
 
+static void BM_pthread_setspecific(int iters) {
+  StopBenchmarkTiming();
+  pthread_key_t key;
+  pthread_key_create(&key, NULL);
+  StartBenchmarkTiming();
+
+  for (int i = 0; i < iters; ++i) {
+    pthread_setspecific(key, NULL);
+  }
+
+  StopBenchmarkTiming();
+  pthread_key_delete(key);
+}
+BENCHMARK(BM_pthread_setspecific);
+
 static void DummyPthreadOnceInitFunction() {
 }
 
@@ -137,3 +152,80 @@ static void BM_pthread_rw_lock_write(int iters) {
   pthread_rwlock_destroy(&lock);
 }
 BENCHMARK(BM_pthread_rw_lock_write);
+
+static void* IdleThread(void*) {
+  return NULL;
+}
+
+static void BM_pthread_create(int iters) {
+  StopBenchmarkTiming();
+  pthread_t thread;
+
+  for (int i = 0; i < iters; ++i) {
+    StartBenchmarkTiming();
+    pthread_create(&thread, NULL, IdleThread, NULL);
+    StopBenchmarkTiming();
+    pthread_join(thread, NULL);
+  }
+}
+BENCHMARK(BM_pthread_create);
+
+static void* RunThread(void*) {
+  StopBenchmarkTiming();
+  return NULL;
+}
+
+static void BM_pthread_create_and_run(int iters) {
+  StopBenchmarkTiming();
+  pthread_t thread;
+
+  for (int i = 0; i < iters; ++i) {
+    StartBenchmarkTiming();
+    pthread_create(&thread, NULL, RunThread, NULL);
+    pthread_join(thread, NULL);
+  }
+}
+BENCHMARK(BM_pthread_create_and_run);
+
+static void* ExitThread(void*) {
+  StartBenchmarkTiming();
+  pthread_exit(NULL);
+}
+
+static void BM_pthread_exit_and_join(int iters) {
+  StopBenchmarkTiming();
+  pthread_t thread;
+
+  for (int i = 0; i < iters; ++i) {
+    pthread_create(&thread, NULL, ExitThread, NULL);
+    pthread_join(thread, NULL);
+    StopBenchmarkTiming();
+  }
+}
+BENCHMARK(BM_pthread_exit_and_join);
+
+static void BM_pthread_key_create(int iters) {
+  StopBenchmarkTiming();
+  pthread_key_t key;
+
+  for (int i = 0; i < iters; ++i) {
+    StartBenchmarkTiming();
+    pthread_key_create(&key, NULL);
+    StopBenchmarkTiming();
+    pthread_key_delete(key);
+  }
+}
+BENCHMARK(BM_pthread_key_create);
+
+static void BM_pthread_key_delete(int iters) {
+  StopBenchmarkTiming();
+  pthread_key_t key;
+
+  for (int i = 0; i < iters; ++i) {
+    pthread_key_create(&key, NULL);
+    StartBenchmarkTiming();
+    pthread_key_delete(key);
+    StopBenchmarkTiming();
+  }
+}
+BENCHMARK(BM_pthread_key_delete);
index d27d43183560587f8bf1637e91310ee54bafd0ae..0aacedfe8c52901784ee5ebb274662251e7dcfcf 100644 (file)
 #define        DT_MIPS_GOTSYM          0x70000013      /* first dynamic sym in got */
 #define DT_MIPS_HIPAGENO       0x70000014
 #define        DT_MIPS_RLD_MAP         0x70000016      /* address of loader map */
+#define DT_MIPS_RLD_MAP2       0x70000035      /* offset of loader map, used for PIE */
 
 /*
  * ELF Flags
index 2a6a03b5d688462c520c2adbff3a49d064c2c6dc..15b3fd5e1177e144989cb99ba536451239096bdc 100644 (file)
@@ -74,9 +74,7 @@ uintptr_t __stack_chk_guard = 0;
 void __libc_init_tls(KernelArgumentBlock& args) {
   __libc_auxv = args.auxv;
 
-  static void* tls[BIONIC_TLS_SLOTS];
   static pthread_internal_t main_thread;
-  main_thread.tls = tls;
 
   // Tell the kernel to clear our tid field when we exit, so we're like any other pthread.
   // As a side-effect, this tells us our pid (which is the same as the main thread's tid).
@@ -96,7 +94,7 @@ void __libc_init_tls(KernelArgumentBlock& args) {
   __init_thread(&main_thread, false);
   __init_tls(&main_thread);
   __set_tls(main_thread.tls);
-  tls[TLS_SLOT_BIONIC_PREINIT] = &args;
+  main_thread.tls[TLS_SLOT_BIONIC_PREINIT] = &args;
 
   __init_alternate_signal_stack(&main_thread);
 }
index c99e69c90fcc42ead98099c11542daf190040370..c47b750484537b6a45c370747aa705ff2567e158 100644 (file)
@@ -35,6 +35,7 @@
 #include "pthread_internal.h"
 
 #include "private/bionic_macros.h"
+#include "private/bionic_prctl.h"
 #include "private/bionic_ssp.h"
 #include "private/bionic_tls.h"
 #include "private/libc_logging.h"
@@ -72,6 +73,10 @@ void __init_alternate_signal_stack(pthread_internal_t* thread) {
     ss.ss_flags = 0;
     sigaltstack(&ss, NULL);
     thread->alternate_signal_stack = ss.ss_sp;
+
+    // We can only use const static allocated string for mapped region name, as Android kernel
+    // uses the string pointer directly when dumping /proc/pid/maps.
+    prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ss.ss_sp, ss.ss_size, "thread signal stack");
   }
 }
 
@@ -101,31 +106,64 @@ int __init_thread(pthread_internal_t* thread, bool add_to_thread_list) {
   return error;
 }
 
-static void* __create_thread_stack(pthread_internal_t* thread) {
+static void* __create_thread_stack(const pthread_attr_t& attr) {
   // Create a new private anonymous map.
   int prot = PROT_READ | PROT_WRITE;
   int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
-  void* stack = mmap(NULL, thread->attr.stack_size, prot, flags, -1, 0);
+  void* stack = mmap(NULL, attr.stack_size, prot, flags, -1, 0);
   if (stack == MAP_FAILED) {
     __libc_format_log(ANDROID_LOG_WARN,
                       "libc",
                       "pthread_create failed: couldn't allocate %zd-byte stack: %s",
-                      thread->attr.stack_size, strerror(errno));
+                      attr.stack_size, strerror(errno));
     return NULL;
   }
 
   // Set the guard region at the end of the stack to PROT_NONE.
-  if (mprotect(stack, thread->attr.guard_size, PROT_NONE) == -1) {
+  if (mprotect(stack, attr.guard_size, PROT_NONE) == -1) {
     __libc_format_log(ANDROID_LOG_WARN, "libc",
                       "pthread_create failed: couldn't mprotect PROT_NONE %zd-byte stack guard region: %s",
-                      thread->attr.guard_size, strerror(errno));
-    munmap(stack, thread->attr.stack_size);
+                      attr.guard_size, strerror(errno));
+    munmap(stack, attr.stack_size);
     return NULL;
   }
 
   return stack;
 }
 
+static int __allocate_thread(pthread_attr_t* attr, pthread_internal_t** threadp, void** child_stack) {
+  if (attr->stack_base == NULL) {
+    // The caller didn't provide a stack, so allocate one.
+    // Make sure the stack size and guard size are multiples of PAGE_SIZE.
+    attr->stack_size = BIONIC_ALIGN(attr->stack_size, PAGE_SIZE);
+    attr->guard_size = BIONIC_ALIGN(attr->guard_size, PAGE_SIZE);
+    attr->stack_base = __create_thread_stack(*attr);
+    if (attr->stack_base == NULL) {
+      return EAGAIN;
+    }
+  } else {
+    // The caller did provide a stack, so remember we're not supposed to free it.
+    attr->flags |= PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK;
+  }
+
+  // Thread stack is used for two sections:
+  //   pthread_internal_t.
+  //   regular stack, from top to down.
+  uint8_t* stack_top = reinterpret_cast<uint8_t*>(attr->stack_base) + attr->stack_size;
+  stack_top -= sizeof(pthread_internal_t);
+  pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(stack_top);
+
+  // No need to check stack_top alignment. The size of pthread_internal_t is 16-bytes aligned,
+  // and user allocated stack is guaranteed by pthread_attr_setstack.
+
+  thread->attr = *attr;
+  __init_tls(thread);
+
+  *threadp = thread;
+  *child_stack = stack_top;
+  return 0;
+}
+
 static int __pthread_start(void* arg) {
   pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(arg);
 
@@ -158,43 +196,21 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
   // Inform the rest of the C library that at least one thread was created.
   __isthreaded = 1;
 
-  pthread_internal_t* thread = __create_thread_struct();
-  if (thread == NULL) {
-    return EAGAIN;
-  }
-
+  pthread_attr_t thread_attr;
   if (attr == NULL) {
-    pthread_attr_init(&thread->attr);
+    pthread_attr_init(&thread_attr);
   } else {
-    thread->attr = *attr;
+    thread_attr = *attr;
     attr = NULL; // Prevent misuse below.
   }
 
-  // Make sure the stack size and guard size are multiples of PAGE_SIZE.
-  thread->attr.stack_size = BIONIC_ALIGN(thread->attr.stack_size, PAGE_SIZE);
-  thread->attr.guard_size = BIONIC_ALIGN(thread->attr.guard_size, PAGE_SIZE);
-
-  if (thread->attr.stack_base == NULL) {
-    // The caller didn't provide a stack, so allocate one.
-    thread->attr.stack_base = __create_thread_stack(thread);
-    if (thread->attr.stack_base == NULL) {
-      __free_thread_struct(thread);
-      return EAGAIN;
-    }
-  } else {
-    // The caller did provide a stack, so remember we're not supposed to free it.
-    thread->attr.flags |= PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK;
+  pthread_internal_t* thread = NULL;
+  void* child_stack = NULL;
+  int result = __allocate_thread(&thread_attr, &thread, &child_stack);
+  if (result != 0) {
+    return result;
   }
 
-  // Make room for the TLS area.
-  // The child stack is the same address, just growing in the opposite direction.
-  // At offsets >= 0, we have the TLS slots.
-  // At offsets < 0, we have the child stack.
-  thread->tls = reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(thread->attr.stack_base) +
-                  thread->attr.stack_size - BIONIC_ALIGN(BIONIC_TLS_SLOTS * sizeof(void*), 16));
-  void* child_stack = thread->tls;
-  __init_tls(thread);
-
   // Create a mutex for the thread in TLS to wait on once it starts so we can keep
   // it from doing anything until after we notify the debugger about it
   //
@@ -211,7 +227,7 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
 
   int flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM |
       CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
-  void* tls = thread->tls;
+  void* tls = reinterpret_cast<void*>(thread->tls);
 #if defined(__i386__)
   // On x86 (but not x86-64), CLONE_SETTLS takes a pointer to a struct user_desc rather than
   // a pointer to the TLS itself.
@@ -229,7 +245,6 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
     if (!thread->user_allocated_stack()) {
       munmap(thread->attr.stack_base, thread->attr.stack_size);
     }
-    __free_thread_struct(thread);
     __libc_format_log(ANDROID_LOG_WARN, "libc", "pthread_create failed: clone failed: %s", strerror(errno));
     return clone_errno;
   }
index a8608e3a7ad099f36704b25d2f712f6231baf566..715acf13a8b047b9bdc5567fa41a730413dbf4a4 100644 (file)
@@ -46,7 +46,7 @@ int pthread_detach(pthread_t t) {
 
   if (thread->tid == 0) {
     // Already exited; clean up.
-    _pthread_internal_remove_locked(thread.get());
+    _pthread_internal_remove_locked(thread.get(), true);
     return 0;
   }
 
index a6bb36312c075c39959d0284617d247dfe25d542..e04cf8e7f8246682ee406e61117a77a1447d1998 100644 (file)
@@ -90,7 +90,7 @@ void pthread_exit(void* return_value) {
   // Keep track of what we need to know about the stack before we lose the pthread_internal_t.
   void* stack_base = thread->attr.stack_base;
   size_t stack_size = thread->attr.stack_size;
-  bool user_allocated_stack = thread->user_allocated_stack();
+  bool free_stack = false;
 
   pthread_mutex_lock(&g_thread_list_lock);
   if ((thread->attr.flags & PTHREAD_ATTR_FLAG_DETACHED) != 0) {
@@ -98,24 +98,18 @@ void pthread_exit(void* return_value) {
     // First make sure that the kernel does not try to clear the tid field
     // because we'll have freed the memory before the thread actually exits.
     __set_tid_address(NULL);
-    _pthread_internal_remove_locked(thread);
-  } else {
-    // Make sure that the pthread_internal_t doesn't have stale pointers to a stack that
-    // will be unmapped after the exit call below.
-    if (!user_allocated_stack) {
-      thread->attr.stack_base = NULL;
-      thread->attr.stack_size = 0;
-      thread->tls = NULL;
+
+    // pthread_internal_t is freed below with stack, not here.
+    _pthread_internal_remove_locked(thread, false);
+    if (!thread->user_allocated_stack()) {
+      free_stack = true;
     }
-    // pthread_join is responsible for destroying the pthread_internal_t for non-detached threads.
-    // The kernel will futex_wake on the pthread_internal_t::tid field to wake pthread_join.
   }
   pthread_mutex_unlock(&g_thread_list_lock);
 
-  if (user_allocated_stack) {
-    // Cleaning up this thread's stack is the creator's responsibility, not ours.
-    __exit(0);
-  } else {
+  // Detached threads exit with stack teardown, and everything deallocated here.
+  // Threads that can be joined exit but leave their stacks for the pthread_join caller to clean up.
+  if (free_stack) {
     // We need to munmap the stack we're running on before calling exit.
     // That's not something we can do in C.
 
@@ -126,5 +120,7 @@ void pthread_exit(void* return_value) {
     sigprocmask(SIG_SETMASK, &mask, NULL);
 
     _exit_with_stack_teardown(stack_base, stack_size);
+  } else {
+    __exit(0);
   }
 }
index c5136c93cbfff8fb58f2e773c9d10d7ac8a4e510..95097b7ea0b54f7ef89bdd3b697513fec9615bdf 100644 (file)
@@ -30,6 +30,8 @@
 
 #include <pthread.h>
 
+#include "private/bionic_tls.h"
+
 /* Has the thread been detached by a pthread_join or pthread_detach call? */
 #define PTHREAD_ATTR_FLAG_DETACHED 0x00000001
 
@@ -72,8 +74,6 @@ struct pthread_internal_t {
     return (attr.flags & PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK) != 0;
   }
 
-  void** tls;
-
   pthread_attr_t attr;
 
   __pthread_cleanup_t* cleanup_stack;
@@ -86,16 +86,16 @@ struct pthread_internal_t {
 
   pthread_mutex_t startup_handshake_mutex;
 
+  void* tls[BIONIC_TLS_SLOTS];
+
   /*
    * The dynamic linker implements dlerror(3), which makes it hard for us to implement this
    * per-thread buffer by simply using malloc(3) and free(3).
    */
 #define __BIONIC_DLERROR_BUFFER_SIZE 512
   char dlerror_buffer[__BIONIC_DLERROR_BUFFER_SIZE];
-};
+} __attribute__((aligned(16))); // Align it as thread stack top below it should be aligned.
 
-__LIBC_HIDDEN__ pthread_internal_t* __create_thread_struct();
-__LIBC_HIDDEN__ void __free_thread_struct(pthread_internal_t*);
 __LIBC_HIDDEN__ int __init_thread(pthread_internal_t* thread, bool add_to_thread_list);
 __LIBC_HIDDEN__ void __init_tls(pthread_internal_t* thread);
 __LIBC_HIDDEN__ void __init_alternate_signal_stack(pthread_internal_t*);
@@ -105,7 +105,7 @@ __LIBC_HIDDEN__ void _pthread_internal_add(pthread_internal_t* thread);
 extern "C" __LIBC64_HIDDEN__ pthread_internal_t* __get_thread(void);
 
 __LIBC_HIDDEN__ void pthread_key_clean_all(void);
-__LIBC_HIDDEN__ void _pthread_internal_remove_locked(pthread_internal_t* thread);
+__LIBC_HIDDEN__ void _pthread_internal_remove_locked(pthread_internal_t* thread, bool free_thread);
 
 /*
  * Traditionally we gave threads a 1MiB stack. When we started
index 33cddd74e771683f587a9398275b234e60ee0449..7c30e6e4ad413e667bf7382e66823d4f9f33d850 100644 (file)
 pthread_internal_t* g_thread_list = NULL;
 pthread_mutex_t g_thread_list_lock = PTHREAD_MUTEX_INITIALIZER;
 
-pthread_internal_t* __create_thread_struct() {
-  void* result = mmap(NULL, sizeof(pthread_internal_t), PROT_READ | PROT_WRITE,
-                      MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
-  if (result == MAP_FAILED) {
-    __libc_format_log(ANDROID_LOG_WARN, "libc",
-                      "__create_thread_struct() failed: %s", strerror(errno));
-    return NULL;
-  }
-  return reinterpret_cast<pthread_internal_t*>(result);
-}
-
-void __free_thread_struct(pthread_internal_t* thread) {
-  int result = munmap(thread, sizeof(pthread_internal_t));
-  if (result != 0) {
-    __libc_format_log(ANDROID_LOG_WARN, "libc",
-                      "__free_thread_struct() failed: %s", strerror(errno));
-  }
-}
-
-void _pthread_internal_remove_locked(pthread_internal_t* thread) {
+void _pthread_internal_remove_locked(pthread_internal_t* thread, bool free_thread) {
   if (thread->next != NULL) {
     thread->next->prev = thread->prev;
   }
@@ -70,10 +51,11 @@ void _pthread_internal_remove_locked(pthread_internal_t* thread) {
     g_thread_list = thread->next;
   }
 
-  // The main thread is not heap-allocated. See __libc_init_tls for the declaration,
-  // and __libc_init_common for the point where it's added to the thread list.
-  if ((thread->attr.flags & PTHREAD_ATTR_FLAG_MAIN_THREAD) == 0) {
-    __free_thread_struct(thread);
+  // For threads using user allocated stack (including the main thread), the pthread_internal_t
+  // can't be freed since it is on the stack.
+  if (free_thread && !(thread->attr.flags & PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK)) {
+    // Use one munmap to free the whole thread stack, including pthread_internal_t.
+    munmap(thread->attr.stack_base, thread->attr.stack_size);
   }
 }
 
index 0cbed62bad51f3ada3f6bb5e047ad929c1e8f6db..e3350efd35169b8efbd3523bf72323d0a41c0928 100644 (file)
@@ -74,6 +74,6 @@ int pthread_join(pthread_t t, void** return_value) {
     *return_value = thread->return_value;
   }
 
-  _pthread_internal_remove_locked(thread.get());
+  _pthread_internal_remove_locked(thread.get(), true);
   return 0;
 }
index b47ef229d8c009d6fcec466894109d807d8379dd..49b72e9deaec6fb268a9e13f62e8ea92cc3824e7 100644 (file)
@@ -213,16 +213,6 @@ int pthread_key_delete(pthread_key_t key) {
   // Clear value in all threads.
   pthread_mutex_lock(&g_thread_list_lock);
   for (pthread_internal_t*  t = g_thread_list; t != NULL; t = t->next) {
-    // Skip zombie threads. They don't have a valid TLS area any more.
-    // Similarly, it is possible to have t->tls == NULL for threads that
-    // were just recently created through pthread_create() but whose
-    // startup trampoline (__pthread_start) hasn't been run yet by the
-    // scheduler. t->tls will also be NULL after a thread's stack has been
-    // unmapped but before the ongoing pthread_join() is finished.
-    if (t->tid == 0 || t->tls == NULL) {
-      continue;
-    }
-
     t->tls[key] = NULL;
   }
   tls_map.DeleteKey(key);
similarity index 99%
rename from libc/dns/gethnamaddr.c
rename to libc/dns/net/gethnamaddr.c
index 63a6a60d3e218f4f7d6bbe1ba5cac7cd6844a302..8f5800a434460f70a0d14965eb6b371c16613eb9 100644 (file)
@@ -1208,7 +1208,7 @@ _dns_gethtbyname(void *rv, void *cb_data, va_list ap)
        free(buf);
        __res_put_state(res);
        if (hp == NULL)
-               switch (h_errno) {
+               switch (*info->he) {
                case HOST_NOT_FOUND:
                        return NS_NOTFOUND;
                case TRY_AGAIN:
@@ -1326,6 +1326,7 @@ _dns_gethtbyaddr(void *rv, void   *cb_data, va_list ap)
        *info->he = NETDB_SUCCESS;
        return NS_SUCCESS;
 nospc:
+       errno = ENOSPC;
        *info->he = NETDB_INTERNAL;
        return NS_UNAVAIL;
 }
index fb6d8f6ab0ee4949d405e7dd87e90b5f09c360cd..d025592a0473a101d9b05e929d91f64dba83e497 100644 (file)
@@ -71,6 +71,7 @@
 #include <sys/cdefs.h>
 
 #include <assert.h>
+#include <errno.h>
 #include <nsswitch.h>
 #include <stdarg.h>
 #include <strings.h>
@@ -133,6 +134,10 @@ nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
                                continue;
                        if (result & srclist[i].flags)
                                break;
+                       /* Stop trying next resolver when there is a memory space fatal error. */
+                       if ((result & NS_UNAVAIL) != 0 && errno == ENOSPC) {
+                         break;
+                       }
                }
        }
        result &= NS_STATUSMASK;        /* clear private flags in result */
index f501c8b5abc1f6e77f12f079df10bf1722bcf66a..916421e3329e2220ff86436e2e4de30043d0ad5a 100644 (file)
@@ -116,7 +116,9 @@ _hf_gethtbyname(void *rv, void *cb_data, va_list ap)
        hp = _hf_gethtbyname2(name, af, info);
 #endif
        if (hp == NULL) {
-               *info->he = HOST_NOT_FOUND;
+               if (*info->he == NETDB_INTERNAL && errno == ENOSPC) {
+                       return NS_UNAVAIL;
+               }
                return NS_NOTFOUND;
        }
        return NS_SUCCESS;
@@ -159,8 +161,12 @@ _hf_gethtbyname2(const char *name, int af, struct getnamaddr *info)
 
                hp = netbsd_gethostent_r(hf, info->hp, info->buf, info->buflen,
                    info->he);
-               if (hp == NULL)
+               if (hp == NULL) {
+                       if (*info->he == NETDB_INTERNAL && errno == ENOSPC) {
+                               goto nospc;
+                       }
                        break;
+               }
 
                if (strcasecmp(hp->h_name, name) != 0) {
                        char **cp;
@@ -259,6 +265,9 @@ _hf_gethtbyaddr(void *rv, void *cb_data, va_list ap)
        endhostent_r(&hf);
 
        if (hp == NULL) {
+               if (errno == ENOSPC) {
+                       return NS_UNAVAIL;
+               }
                *info->he = HOST_NOT_FOUND;
                return NS_NOTFOUND;
        }
index 7f8ff31779477f1df85395262bc0c19b2d9e8423..5f4fb7fa9bb561d578a0618cbd526ba407b0a93f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vfprintf.c,v 1.66 2014/05/03 12:36:45 deraadt Exp $   */
+/*     $OpenBSD: vfprintf.c,v 1.67 2014/12/21 00:23:30 daniel Exp $    */
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
@@ -753,10 +753,9 @@ fp_common:
                        if (signflag)
                                sign = '-';
                        if (expt == INT_MAX) {  /* inf or nan */
-                               if (*cp == 'N') {
+                               if (*cp == 'N')
                                        cp = (ch >= 'a') ? "nan" : "NAN";
-                                       sign = '\0';
-                               } else
+                               else
                                        cp = (ch >= 'a') ? "inf" : "INF";
                                size = 3;
                                flags &= ~ZEROPAD;
index ef0ca43b91ff7389a76596830ce0abed897aee88..a6f41232c53bbc9059ef1df1c409d60d18d44122 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vfwprintf.c,v 1.11 2014/06/04 07:45:25 stsp Exp $ */
+/*     $OpenBSD: vfwprintf.c,v 1.12 2014/12/21 00:23:30 daniel Exp $ */
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
@@ -731,10 +731,9 @@ fp_common:
                        if (signflag)
                                sign = '-';
                        if (expt == INT_MAX) {  /* inf or nan */
-                               if (*cp == 'N') {
+                               if (*cp == 'N')
                                        cp = (ch >= 'a') ? L"nan" : L"NAN";
-                                       sign = '\0';
-                               } else
+                               else
                                        cp = (ch >= 'a') ? L"inf" : L"INF";
                                size = 3;
                                flags &= ~ZEROPAD;
index d6e0095757d0df30255b8f9f86d9984e0d3d261f..0383e7b7e395213e311109a107d4abeee0761d81 100644 (file)
@@ -19,6 +19,13 @@ LOCAL_SRC_FILES_x86_64  := arch/x86_64/begin.S
 LOCAL_SRC_FILES_mips    := arch/mips/begin.S
 LOCAL_SRC_FILES_mips64  := arch/mips64/begin.S
 
+# GNU assembler aborted with clang's output for linker.cpp:
+# Assertion failure in get_line_subseg at
+#   /s/ndk-toolchain/src/build/../binutils/binutils-2.24/gas/dwarf2dbg.c line 271.
+ifeq ($(TARGET_ARCH),mips)
+    LOCAL_CLANG_CFLAGS += -integrated-as
+endif
+
 LOCAL_LDFLAGS := \
     -shared \
     -Wl,-Bsymbolic \
index 34099316fe163eda504e9cd52cb7581012bcdb6c..babefeb3c1fb259fd27da4abec33f913e96b29ea 100644 (file)
@@ -2402,6 +2402,13 @@ bool soinfo::prelink_image() {
           *dp = &_r_debug;
         }
         break;
+      case DT_MIPS_RLD_MAP2:
+        // Set the DT_MIPS_RLD_MAP2 entry to the address of _r_debug for GDB.
+        {
+          r_debug** dp = reinterpret_cast<r_debug**>(reinterpret_cast<ElfW(Addr)>(d) + d->d_un.d_val);
+          *dp = &_r_debug;
+        }
+        break;
 
       case DT_MIPS_RLD_VERSION:
       case DT_MIPS_FLAGS:
index 854fc7b7b1703765de829c0449c2a1d848b21fb6..de5eea347f4251aae68044ef01307ea2782375ed 100644 (file)
@@ -364,22 +364,52 @@ TEST(stdio, snprintf_smoke) {
   EXPECT_STREQ("print_me_twice print_me_twice", buf);
 }
 
-TEST(stdio, snprintf_f_special) {
-  char buf[BUFSIZ];
-  snprintf(buf, sizeof(buf), "%f", nanf(""));
-  EXPECT_STRCASEEQ("NaN", buf);
-
-  snprintf(buf, sizeof(buf), "%f", HUGE_VALF);
-  EXPECT_STRCASEEQ("Inf", buf);
-}
-
-TEST(stdio, snprintf_g_special) {
-  char buf[BUFSIZ];
-  snprintf(buf, sizeof(buf), "%g", nan(""));
-  EXPECT_STRCASEEQ("NaN", buf);
-
-  snprintf(buf, sizeof(buf), "%g", HUGE_VAL);
-  EXPECT_STRCASEEQ("Inf", buf);
+template <typename T>
+void CheckInfNan(int snprintf_fn(T*, size_t, const T*, ...),
+                 const T* fmt, const T* fmt_plus,
+                 const T* minus_inf, const T* inf_, const T* plus_inf,
+                 const T* minus_nan, const T* nan_, const T* plus_nan) {
+  T buf[BUFSIZ];
+
+  snprintf_fn(buf, sizeof(buf), fmt, nan(""));
+  EXPECT_STREQ(nan_, buf) << fmt;
+  snprintf_fn(buf, sizeof(buf), fmt, -nan(""));
+  EXPECT_STREQ(minus_nan, buf) << fmt;
+  snprintf_fn(buf, sizeof(buf), fmt_plus, nan(""));
+  EXPECT_STREQ(plus_nan, buf) << fmt_plus;
+  snprintf_fn(buf, sizeof(buf), fmt_plus, -nan(""));
+  EXPECT_STREQ(minus_nan, buf) << fmt_plus;
+
+  snprintf_fn(buf, sizeof(buf), fmt, HUGE_VAL);
+  EXPECT_STREQ(inf_, buf) << fmt;
+  snprintf_fn(buf, sizeof(buf), fmt, -HUGE_VAL);
+  EXPECT_STREQ(minus_inf, buf) << fmt;
+  snprintf_fn(buf, sizeof(buf), fmt_plus, HUGE_VAL);
+  EXPECT_STREQ(plus_inf, buf) << fmt_plus;
+  snprintf_fn(buf, sizeof(buf), fmt_plus, -HUGE_VAL);
+  EXPECT_STREQ(minus_inf, buf) << fmt_plus;
+}
+
+TEST(stdio, snprintf_inf_nan) {
+  CheckInfNan(snprintf, "%a", "%+a", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
+  CheckInfNan(snprintf, "%A", "%+A", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
+  CheckInfNan(snprintf, "%e", "%+e", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
+  CheckInfNan(snprintf, "%E", "%+E", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
+  CheckInfNan(snprintf, "%f", "%+f", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
+  CheckInfNan(snprintf, "%F", "%+F", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
+  CheckInfNan(snprintf, "%g", "%+g", "-inf", "inf", "+inf", "-nan", "nan", "+nan");
+  CheckInfNan(snprintf, "%G", "%+G", "-INF", "INF", "+INF", "-NAN", "NAN", "+NAN");
+}
+
+TEST(stdio, wsprintf_inf_nan) {
+  CheckInfNan(swprintf, L"%a", L"%+a", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
+  CheckInfNan(swprintf, L"%A", L"%+A", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
+  CheckInfNan(swprintf, L"%e", L"%+e", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
+  CheckInfNan(swprintf, L"%E", L"%+E", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
+  CheckInfNan(swprintf, L"%f", L"%+f", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
+  CheckInfNan(swprintf, L"%F", L"%+F", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
+  CheckInfNan(swprintf, L"%g", L"%+g", L"-inf", L"inf", L"+inf", L"-nan", L"nan", L"+nan");
+  CheckInfNan(swprintf, L"%G", L"%+G", L"-INF", L"INF", L"+INF", L"-NAN", L"NAN", L"+NAN");
 }
 
 TEST(stdio, snprintf_d_INT_MAX) {
@@ -439,8 +469,22 @@ TEST(stdio, snprintf_e) {
 TEST(stdio, snprintf_negative_zero_5084292) {
   char buf[BUFSIZ];
 
+  snprintf(buf, sizeof(buf), "%e", -0.0);
+  EXPECT_STREQ("-0.000000e+00", buf);
+  snprintf(buf, sizeof(buf), "%E", -0.0);
+  EXPECT_STREQ("-0.000000E+00", buf);
   snprintf(buf, sizeof(buf), "%f", -0.0);
   EXPECT_STREQ("-0.000000", buf);
+  snprintf(buf, sizeof(buf), "%F", -0.0);
+  EXPECT_STREQ("-0.000000", buf);
+  snprintf(buf, sizeof(buf), "%g", -0.0);
+  EXPECT_STREQ("-0", buf);
+  snprintf(buf, sizeof(buf), "%G", -0.0);
+  EXPECT_STREQ("-0", buf);
+  snprintf(buf, sizeof(buf), "%a", -0.0);
+  EXPECT_STREQ("-0x0p+0", buf);
+  snprintf(buf, sizeof(buf), "%A", -0.0);
+  EXPECT_STREQ("-0X0P+0", buf);
 }
 
 TEST(stdio, snprintf_utf8_15439554) {