Merge "Clean up update_headers.sh."
diff --git a/libc/bionic/clone.cpp b/libc/bionic/clone.cpp
index b50a96d..3a20aa9 100644
--- a/libc/bionic/clone.cpp
+++ b/libc/bionic/clone.cpp
@@ -38,6 +38,11 @@
// Called from the __bionic_clone assembler to call the thread function then exit.
extern "C" __LIBC_HIDDEN__ void __start_thread(int (*fn)(void*), void* arg) {
+ pthread_internal_t* self = __get_thread();
+ if (self && self->tid == -1) {
+ self->tid = syscall(__NR_gettid);
+ }
+
int status = (*fn)(arg);
__exit(status);
}
@@ -105,6 +110,9 @@
// If any other cases become important, we could use a double trampoline like __pthread_start.
self->set_cached_pid(parent_pid);
self->tid = caller_tid;
+ } else if (self->tid == -1) {
+ self->tid = syscall(__NR_gettid);
+ self->set_cached_pid(self->tid);
}
return clone_result;
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index ffe94f4..32ea255 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -36,9 +36,6 @@
pthread_internal_t* self = __get_thread();
- // Remember the parent pid and invalidate the cached value while we fork.
- pid_t parent_pid = self->invalidate_cached_pid();
-
int result = clone(nullptr,
nullptr,
(CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD),
@@ -47,10 +44,11 @@
nullptr,
&(self->tid));
if (result == 0) {
+ // Update the cached pid, since clone() will not set it directly (as
+ // self->tid is updated by the kernel).
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/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 660679f..b488e82 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -426,7 +426,7 @@
}
}
-static void TestGetPidCachingWithFork(int (*fork_fn)()) {
+static void TestGetPidCachingWithFork(int (*fork_fn)(), void (*exit_fn)(int)) {
pid_t parent_pid = getpid();
ASSERT_EQ(syscall(__NR_getpid), parent_pid);
@@ -436,7 +436,7 @@
// We're the child.
ASSERT_NO_FATAL_FAILURE(AssertGetPidCorrect());
ASSERT_EQ(parent_pid, getppid());
- _exit(123);
+ exit_fn(123);
} else {
// We're the parent.
ASSERT_EQ(parent_pid, getpid());
@@ -460,7 +460,7 @@
}
}
-static void TestGetTidCachingWithFork(int (*fork_fn)()) {
+static void TestGetTidCachingWithFork(int (*fork_fn)(), void (*exit_fn)(int)) {
pid_t parent_tid = GetTidForTest();
ASSERT_EQ(syscall(__NR_gettid), parent_tid);
@@ -472,7 +472,7 @@
EXPECT_EQ(getpid(), GetTidForTest()) << "real tid is " << syscall(__NR_gettid)
<< ", pid is " << syscall(__NR_getpid);
ASSERT_NO_FATAL_FAILURE(AssertGetTidCorrect());
- _exit(123);
+ exit_fn(123);
} else {
// We're the parent.
ASSERT_EQ(parent_tid, GetTidForTest());
@@ -481,15 +481,15 @@
}
TEST(UNISTD_TEST, getpid_caching_and_fork) {
- TestGetPidCachingWithFork(fork);
+ TestGetPidCachingWithFork(fork, exit);
}
TEST(UNISTD_TEST, gettid_caching_and_fork) {
- TestGetTidCachingWithFork(fork);
+ TestGetTidCachingWithFork(fork, exit);
}
TEST(UNISTD_TEST, getpid_caching_and_vfork) {
- TestGetPidCachingWithFork(vfork);
+ TestGetPidCachingWithFork(vfork, _exit);
}
static int CloneLikeFork() {
@@ -497,11 +497,11 @@
}
TEST(UNISTD_TEST, getpid_caching_and_clone_process) {
- TestGetPidCachingWithFork(CloneLikeFork);
+ TestGetPidCachingWithFork(CloneLikeFork, exit);
}
TEST(UNISTD_TEST, gettid_caching_and_clone_process) {
- TestGetTidCachingWithFork(CloneLikeFork);
+ TestGetTidCachingWithFork(CloneLikeFork, exit);
}
static int CloneAndSetTid() {
@@ -525,7 +525,7 @@
}
TEST(UNISTD_TEST, gettid_caching_and_clone_process_settid) {
- TestGetTidCachingWithFork(CloneAndSetTid);
+ TestGetTidCachingWithFork(CloneAndSetTid, exit);
}
static int CloneStartRoutine(int (*start_routine)(void*)) {
@@ -572,6 +572,22 @@
AssertChildExited(clone_result, 123);
}
+static int CloneChildExit(void*) {
+ AssertGetPidCorrect();
+ AssertGetTidCorrect();
+ exit(33);
+}
+
+TEST(UNISTD_TEST, clone_fn_and_exit) {
+ int clone_result = CloneStartRoutine(CloneChildExit);
+ ASSERT_NE(-1, clone_result);
+
+ AssertGetPidCorrect();
+ AssertGetTidCorrect();
+
+ AssertChildExited(clone_result, 33);
+}
+
static void* GetPidCachingPthreadStartRoutine(void*) {
AssertGetPidCorrect();
return NULL;
diff --git a/tools/versioner/src/DeclarationDatabase.h b/tools/versioner/src/DeclarationDatabase.h
index e957019..cf3589b 100644
--- a/tools/versioner/src/DeclarationDatabase.h
+++ b/tools/versioner/src/DeclarationDatabase.h
@@ -173,9 +173,9 @@
fprintf(out, "\n%s ", indent_str.c_str());
if (!calculateAvailability(&avail)) {
- fprintf(out, "invalid availability");
+ fprintf(out, "invalid availability\n");
} else {
- fprintf(out, "%s", to_string(avail).c_str());
+ fprintf(out, "%s\n", to_string(avail).c_str());
}
}
}
@@ -209,7 +209,6 @@
for (auto& it : declarations) {
it.second.dump(base_path, out, 4);
- fprintf(out, "\n");
}
}
};
diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp
index 74650d5..2f0656c 100644
--- a/tools/versioner/src/versioner.cpp
+++ b/tools/versioner/src/versioner.cpp
@@ -276,6 +276,21 @@
return result;
}
+static std::set<CompilationType> getCompilationTypes(const Declaration* decl) {
+ std::set<CompilationType> result;
+ for (const auto& it : decl->availability) {
+ result.insert(it.first);
+ }
+ return result;
+}
+
+template<typename T>
+static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) {
+ std::vector<T> intersection;
+ std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(intersection));
+ return intersection;
+}
+
// Perform a sanity check on a symbol's declarations, enforcing the following invariants:
// 1. At most one inline definition of the function exists.
// 2. All of the availability declarations for a symbol are compatible.
@@ -287,18 +302,23 @@
static bool checkSymbol(const Symbol& symbol) {
std::string cwd = getWorkingDir() + "/";
- const Declaration* inline_definition = nullptr;
+ std::unordered_map<const Declaration*, std::set<CompilationType>> inline_definitions;
for (const auto& decl_it : symbol.declarations) {
const Declaration* decl = &decl_it.second;
if (decl->is_definition) {
- if (inline_definition) {
- fprintf(stderr, "versioner: multiple definitions of symbol %s\n", symbol.name.c_str());
- symbol.dump(cwd);
- inline_definition->dump(cwd);
- return false;
+ std::set<CompilationType> compilation_types = getCompilationTypes(decl);
+ for (const auto& inline_def_it : inline_definitions) {
+ auto intersection = Intersection(compilation_types, inline_def_it.second);
+ if (!intersection.empty()) {
+ fprintf(stderr, "versioner: conflicting inline definitions:\n");
+ fprintf(stderr, " declarations visible in: %s\n", Join(intersection, ", ").c_str());
+ decl->dump(cwd, stderr, 4);
+ inline_def_it.first->dump(cwd, stderr, 4);
+ return false;
+ }
}
- inline_definition = decl;
+ inline_definitions[decl] = std::move(compilation_types);
}
DeclarationAvailability availability;
diff --git a/tools/versioner/tests/multiple_definition/expected_fail b/tools/versioner/tests/multiple_definition/expected_fail
new file mode 100644
index 0000000..6c531bd
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/expected_fail
@@ -0,0 +1,7 @@
+versioner: conflicting inline definitions:
+ declarations visible in: arm-9 [fob = 32], arm-9 [fob = 64], arm-12 [fob = 32], arm-12 [fob = 64]
+ static definition @ headers/foo.h:1:1
+ no availability
+ static definition @ headers/bar.h:1:1
+ no availability
+versioner: sanity check failed
diff --git a/tools/versioner/tests/multiple_definition/headers/bar.h b/tools/versioner/tests/multiple_definition/headers/bar.h
new file mode 100644
index 0000000..a9d0197
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/headers/bar.h
@@ -0,0 +1,3 @@
+static int foo() {
+ return 0;
+}
diff --git a/tools/versioner/tests/multiple_definition/headers/foo.h b/tools/versioner/tests/multiple_definition/headers/foo.h
new file mode 100644
index 0000000..a9d0197
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/headers/foo.h
@@ -0,0 +1,3 @@
+static int foo() {
+ return 0;
+}
diff --git a/tools/versioner/tests/multiple_definition/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/multiple_definition/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
@@ -0,0 +1 @@
+foo
diff --git a/tools/versioner/tests/multiple_definition/run.sh b/tools/versioner/tests/multiple_definition/run.sh
new file mode 100644
index 0000000..e4abbe7
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/run.sh
@@ -0,0 +1 @@
+versioner headers -p platforms -r arm -a 9 -a 12 -i
diff --git a/tools/versioner/tests/multiple_definition_ok/headers/bar.h b/tools/versioner/tests/multiple_definition_ok/headers/bar.h
new file mode 100644
index 0000000..c3c87bb
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition_ok/headers/bar.h
@@ -0,0 +1,5 @@
+#if __ANDROID_API__ == 12
+static int foo() {
+ return 0;
+}
+#endif
diff --git a/tools/versioner/tests/multiple_definition_ok/headers/foo.h b/tools/versioner/tests/multiple_definition_ok/headers/foo.h
new file mode 100644
index 0000000..9da9b2a
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition_ok/headers/foo.h
@@ -0,0 +1,5 @@
+#if __ANDROID_API__ == 9
+static int foo() {
+ return 0;
+}
+#endif
diff --git a/tools/versioner/tests/multiple_definition_ok/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/multiple_definition_ok/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition_ok/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
@@ -0,0 +1 @@
+foo
diff --git a/tools/versioner/tests/multiple_definition_ok/run.sh b/tools/versioner/tests/multiple_definition_ok/run.sh
new file mode 100644
index 0000000..e4abbe7
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition_ok/run.sh
@@ -0,0 +1 @@
+versioner headers -p platforms -r arm -a 9 -a 12 -i