aboutsummaryrefslogtreecommitdiffstats
path: root/libc/bionic
diff options
context:
space:
mode:
Diffstat (limited to 'libc/bionic')
-rw-r--r--libc/bionic/fork.cpp13
-rw-r--r--libc/bionic/getpid.cpp47
-rw-r--r--libc/bionic/jemalloc_wrapper.cpp (renamed from libc/bionic/jemalloc.cpp)16
-rw-r--r--libc/bionic/libc_init_common.cpp17
-rw-r--r--libc/bionic/malloc_debug_check.cpp12
-rw-r--r--libc/bionic/malloc_debug_common.h7
-rw-r--r--libc/bionic/malloc_debug_leak.cpp14
-rw-r--r--libc/bionic/malloc_debug_qemu.cpp10
-rw-r--r--libc/bionic/pthread_create.cpp8
-rw-r--r--libc/bionic/pthread_internal.h20
-rw-r--r--libc/bionic/system_properties.cpp5
11 files changed, 126 insertions, 43 deletions
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index a0f98e42f..6cfc73664 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -31,19 +31,26 @@
#include "pthread_internal.h"
+#define FORK_FLAGS (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD)
+
int fork() {
__bionic_atfork_run_prepare();
pthread_internal_t* self = __get_thread();
- int flags = CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD;
+
+ // Remember the parent pid and invalidate the cached value while we fork.
+ pid_t parent_pid = self->invalidate_cached_pid();
+
#if defined(__x86_64__) // sys_clone's last two arguments are flipped on x86-64.
- int result = syscall(__NR_clone, flags, NULL, NULL, &(self->tid), NULL);
+ int result = syscall(__NR_clone, FORK_FLAGS, NULL, NULL, &(self->tid), NULL);
#else
- int result = syscall(__NR_clone, flags, NULL, NULL, NULL, &(self->tid));
+ int result = syscall(__NR_clone, FORK_FLAGS, NULL, NULL, NULL, &(self->tid));
#endif
if (result == 0) {
+ self->set_cached_pid(gettid());
__bionic_atfork_run_child();
} else {
+ self->set_cached_pid(parent_pid);
__bionic_atfork_run_parent();
}
return result;
diff --git a/libc/bionic/getpid.cpp b/libc/bionic/getpid.cpp
new file mode 100644
index 000000000..a3d5b35c9
--- /dev/null
+++ b/libc/bionic/getpid.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+
+#include "pthread_internal.h"
+
+extern "C" pid_t __getpid();
+
+pid_t getpid() {
+ pthread_internal_t* self = __get_thread();
+
+ // Do we have a valid cached pid?
+ pid_t cached_pid;
+ if (__predict_true(self->get_cached_pid(&cached_pid))) {
+ return cached_pid;
+ }
+
+ // We're still in the dynamic linker or we're in the middle of forking, so ask the kernel.
+ // We don't know whether it's safe to update the cached value, so don't try.
+ return __getpid();
+}
diff --git a/libc/bionic/jemalloc.cpp b/libc/bionic/jemalloc_wrapper.cpp
index 625d789e7..d1fe96056 100644
--- a/libc/bionic/jemalloc.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -14,13 +14,19 @@
* limitations under the License.
*/
+#include <sys/param.h>
#include <unistd.h>
#include "jemalloc.h"
+#include "private/bionic_macros.h"
void* je_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- return je_memalign(pagesize, (bytes + pagesize - 1) & ~(pagesize - 1));
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
+ if (size < bytes) {
+ return NULL;
+ }
+ return je_memalign(pagesize, size);
}
#ifdef je_memalign
@@ -31,11 +37,9 @@ void* je_pvalloc(size_t bytes) {
// but this is not true. Both glibc and dlmalloc round up to the next power
// of 2, so we'll do the same.
void* je_memalign_round_up_boundary(size_t boundary, size_t size) {
- unsigned int power_of_2 = static_cast<unsigned int>(boundary);
- if (power_of_2 != 0) {
- power_of_2 = 1UL << (sizeof(unsigned int)*8 - 1 - __builtin_clz(power_of_2));
- if (power_of_2 != boundary) {
- boundary = power_of_2 << 1;
+ if (boundary != 0) {
+ if (!powerof2(boundary)) {
+ boundary = BIONIC_ROUND_UP_POWER_OF_2(boundary);
}
} else {
boundary = 1;
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index abf2d3674..fa61c3c10 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -86,21 +86,24 @@ static size_t get_main_thread_stack_size() {
void __libc_init_tls(KernelArgumentBlock& args) {
__libc_auxv = args.auxv;
- uintptr_t stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
- size_t stack_size = get_main_thread_stack_size();
- uintptr_t stack_bottom = stack_top - stack_size;
-
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).
main_thread.tid = __set_tid_address(&main_thread.tid);
+ main_thread.set_cached_pid(main_thread.tid);
+
+ // Work out the extent of the main thread's stack.
+ uintptr_t stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
+ size_t stack_size = get_main_thread_stack_size();
+ void* stack_bottom = reinterpret_cast<void*>(stack_top - stack_size);
- // We already have a stack, and we don't want to free it up on exit (because things like
- // environment variables with global scope live on it).
+ // We don't want to free the main thread's stack even when the main thread exits
+ // because things like environment variables with global scope live on it.
pthread_attr_init(&main_thread.attr);
- pthread_attr_setstack(&main_thread.attr, (void*) stack_bottom, stack_size);
+ pthread_attr_setstack(&main_thread.attr, stack_bottom, stack_size);
main_thread.attr.flags = PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK | PTHREAD_ATTR_FLAG_MAIN_THREAD;
__init_thread(&main_thread, false);
diff --git a/libc/bionic/malloc_debug_check.cpp b/libc/bionic/malloc_debug_check.cpp
index faf61bf5c..e4e4c2eb0 100644
--- a/libc/bionic/malloc_debug_check.cpp
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -38,6 +38,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/param.h>
#include <sys/socket.h>
#include <sys/system_properties.h>
#include <sys/types.h>
@@ -47,8 +48,9 @@
#include "debug_mapinfo.h"
#include "debug_stacktrace.h"
-#include "private/libc_logging.h"
#include "malloc_debug_common.h"
+#include "private/bionic_macros.h"
+#include "private/libc_logging.h"
#include "private/ScopedPthreadMutexLocker.h"
#define MAX_BACKTRACE_DEPTH 16
@@ -350,8 +352,8 @@ extern "C" void* chk_memalign(size_t alignment, size_t bytes) {
}
// Make the alignment a power of two.
- if (alignment & (alignment-1)) {
- alignment = 1L << (31 - __builtin_clz(alignment));
+ if (!powerof2(alignment)) {
+ alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
}
// here, alignment is at least MALLOC_ALIGNMENT<<1 bytes
@@ -526,7 +528,7 @@ extern "C" struct mallinfo chk_mallinfo() {
}
extern "C" int chk_posix_memalign(void** memptr, size_t alignment, size_t size) {
- if ((alignment & (alignment - 1)) != 0) {
+ if (!powerof2(alignment)) {
return EINVAL;
}
int saved_errno = errno;
@@ -537,7 +539,7 @@ extern "C" int chk_posix_memalign(void** memptr, size_t alignment, size_t size)
extern "C" void* chk_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
}
diff --git a/libc/bionic/malloc_debug_common.h b/libc/bionic/malloc_debug_common.h
index a0f9972dd..fb2f03d06 100644
--- a/libc/bionic/malloc_debug_common.h
+++ b/libc/bionic/malloc_debug_common.h
@@ -37,6 +37,7 @@
#include <stdint.h>
#include <stdlib.h>
+#include "private/bionic_config.h"
#include "private/libc_logging.h"
#define HASHTABLE_SIZE 1543
@@ -61,12 +62,6 @@
#define Malloc(function) dl ## function
#endif
-// valloc(3) and pvalloc(3) were removed from POSIX 2004. We do not include them
-// for LP64, but the symbols remain in LP32 for binary compatibility.
-#ifndef __LP64__
-#define HAVE_DEPRECATED_MALLOC_FUNCS 1
-#endif
-
// =============================================================================
// Structures
// =============================================================================
diff --git a/libc/bionic/malloc_debug_leak.cpp b/libc/bionic/malloc_debug_leak.cpp
index 2cc38ccf5..308d40b9a 100644
--- a/libc/bionic/malloc_debug_leak.cpp
+++ b/libc/bionic/malloc_debug_leak.cpp
@@ -37,6 +37,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/param.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/system_properties.h>
@@ -48,6 +49,7 @@
#include "debug_stacktrace.h"
#include "malloc_debug_common.h"
+#include "private/bionic_macros.h"
#include "private/libc_logging.h"
#include "private/ScopedPthreadMutexLocker.h"
@@ -255,7 +257,7 @@ extern "C" struct mallinfo fill_mallinfo() {
}
extern "C" int fill_posix_memalign(void** memptr, size_t alignment, size_t size) {
- if ((alignment & (alignment - 1)) != 0) {
+ if (!powerof2(alignment)) {
return EINVAL;
}
int saved_errno = errno;
@@ -266,7 +268,7 @@ extern "C" int fill_posix_memalign(void** memptr, size_t alignment, size_t size)
extern "C" void* fill_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
}
@@ -401,8 +403,8 @@ extern "C" void* leak_memalign(size_t alignment, size_t bytes) {
}
// need to make sure it's a power of two
- if (alignment & (alignment-1)) {
- alignment = 1L << (31 - __builtin_clz(alignment));
+ if (!powerof2(alignment)) {
+ alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
}
// here, alignment is at least MALLOC_ALIGNMENT<<1 bytes
@@ -464,7 +466,7 @@ extern "C" struct mallinfo leak_mallinfo() {
}
extern "C" int leak_posix_memalign(void** memptr, size_t alignment, size_t size) {
- if ((alignment & (alignment - 1)) != 0) {
+ if (!powerof2(alignment)) {
return EINVAL;
}
int saved_errno = errno;
@@ -475,7 +477,7 @@ extern "C" int leak_posix_memalign(void** memptr, size_t alignment, size_t size)
extern "C" void* leak_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
return NULL;
}
diff --git a/libc/bionic/malloc_debug_qemu.cpp b/libc/bionic/malloc_debug_qemu.cpp
index 9b3bb5578..fd5161a7e 100644
--- a/libc/bionic/malloc_debug_qemu.cpp
+++ b/libc/bionic/malloc_debug_qemu.cpp
@@ -47,11 +47,13 @@
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
+#include <sys/param.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
-#include "private/libc_logging.h"
#include "malloc_debug_common.h"
+#include "private/bionic_macros.h"
+#include "private/libc_logging.h"
/* This file should be included into the build only when
* MALLOC_QEMU_INSTRUMENT macro is defined. */
@@ -970,8 +972,8 @@ extern "C" void* qemu_instrumented_memalign(size_t alignment, size_t bytes) {
// size.
if (alignment < DEFAULT_PREFIX_SIZE) {
alignment = DEFAULT_PREFIX_SIZE;
- } else if (alignment & (alignment - 1)) {
- alignment = 1L << (31 - __builtin_clz(alignment));
+ } else if (!powerof2(alignment)) {
+ alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
}
desc.prefix_size = alignment;
desc.requested_bytes = bytes;
@@ -1047,7 +1049,7 @@ extern "C" int qemu_instrumented_posix_memalign(void** memptr, size_t alignment,
extern "C" void* qemu_instrumented_pvalloc(size_t bytes) {
size_t pagesize = sysconf(_SC_PAGESIZE);
- size_t size = (bytes + pagesize - 1) & ~(pagesize - 1);
+ size_t size = BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) { // Overflow
qemu_error_log("<libc_pid=%03u, pid=%03u> pvalloc(%zu): overflow (%zu).",
malloc_pid, getpid(), bytes, size);
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index c4cb262ac..2ded22b0f 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -30,9 +30,11 @@
#include <errno.h>
#include <sys/mman.h>
+#include <unistd.h>
#include "pthread_internal.h"
+#include "private/bionic_macros.h"
#include "private/bionic_ssp.h"
#include "private/bionic_tls.h"
#include "private/libc_logging.h"
@@ -183,8 +185,8 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
}
// Make sure the stack size and guard size are multiples of PAGE_SIZE.
- thread->attr.stack_size = (thread->attr.stack_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
- thread->attr.guard_size = (thread->attr.guard_size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+ 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.
@@ -219,6 +221,8 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
thread->start_routine = start_routine;
thread->start_routine_arg = arg;
+ thread->set_cached_pid(getpid());
+
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;
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 490ae86d4..e05d15c79 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -36,6 +36,26 @@ struct pthread_internal_t {
pid_t tid;
+ private:
+ pid_t cached_pid_;
+
+ public:
+ pid_t invalidate_cached_pid() {
+ pid_t old_value;
+ get_cached_pid(&old_value);
+ set_cached_pid(0);
+ return old_value;
+ }
+
+ void set_cached_pid(pid_t value) {
+ cached_pid_ = value;
+ }
+
+ bool get_cached_pid(pid_t* cached_pid) {
+ *cached_pid = cached_pid_;
+ return (*cached_pid != 0);
+ }
+
void** tls;
pthread_attr_t attr;
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index 761858617..a564c3939 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -55,9 +55,6 @@
#include "private/bionic_futex.h"
#include "private/bionic_macros.h"
-#define ALIGN(x, a) (((x) + (a - 1)) & ~(a - 1))
-
-
static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
@@ -301,7 +298,7 @@ static int map_prop_area()
static void *allocate_obj(const size_t size, uint32_t *const off)
{
prop_area *pa = __system_property_area__;
- const size_t aligned = ALIGN(size, sizeof(uint32_t));
+ const size_t aligned = BIONIC_ALIGN(size, sizeof(uint32_t));
if (pa->bytes_used + aligned > pa_data_size) {
return NULL;
}