Merge "Generalize the clone function slightly."
am: 0155995e8d
* commit '0155995e8d4471d0e530c8bbfac88c4a8a68fbb1':
Generalize the clone function slightly.
Change-Id: I40b5ab2913811a7140a1104340f30aaedc8358fc
This commit is contained in:
commit
6c8de255ec
3 changed files with 20 additions and 10 deletions
|
@ -47,7 +47,7 @@ int clone(int (*fn)(void*), void* child_stack, int flags, void* arg, ...) {
|
|||
void* new_tls = NULL;
|
||||
int* child_tid = NULL;
|
||||
|
||||
if (!child_stack) {
|
||||
if (fn != nullptr && child_stack == nullptr) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
@ -76,7 +76,16 @@ int clone(int (*fn)(void*), void* child_stack, int flags, void* arg, ...) {
|
|||
pid_t parent_pid = self->invalidate_cached_pid();
|
||||
|
||||
// Actually do the clone.
|
||||
int clone_result = __bionic_clone(flags, child_stack, parent_tid, new_tls, child_tid, fn, arg);
|
||||
int clone_result;
|
||||
if (fn != nullptr) {
|
||||
clone_result = __bionic_clone(flags, child_stack, parent_tid, new_tls, child_tid, fn, arg);
|
||||
} else {
|
||||
#if defined(__x86_64__) // sys_clone's last two arguments are flipped on x86-64.
|
||||
clone_result = syscall(__NR_clone, flags, child_stack, parent_tid, child_tid, new_tls);
|
||||
#else
|
||||
clone_result = syscall(__NR_clone, flags, child_stack, parent_tid, new_tls, child_tid);
|
||||
#endif
|
||||
}
|
||||
|
||||
// We're the parent, so put our known pid back in place.
|
||||
// We leave the child without a cached pid, but:
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
|
||||
#include "pthread_internal.h"
|
||||
|
||||
#define FORK_FLAGS (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD)
|
||||
|
||||
int fork() {
|
||||
__bionic_atfork_run_prepare();
|
||||
|
||||
|
@ -41,11 +39,13 @@ int fork() {
|
|||
// 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, FORK_FLAGS, NULL, NULL, &(self->tid), NULL);
|
||||
#else
|
||||
int result = syscall(__NR_clone, FORK_FLAGS, NULL, NULL, NULL, &(self->tid));
|
||||
#endif
|
||||
int result = clone(nullptr,
|
||||
nullptr,
|
||||
(CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD),
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&(self->tid));
|
||||
if (result == 0) {
|
||||
self->set_cached_pid(gettid());
|
||||
__bionic_atfork_run_child();
|
||||
|
|
|
@ -55,7 +55,8 @@ TEST(sched, clone_errno) {
|
|||
// Check that our hand-written clone assembler sets errno correctly on failure.
|
||||
uintptr_t fake_child_stack[16];
|
||||
errno = 0;
|
||||
ASSERT_EQ(-1, clone(NULL, &fake_child_stack[16], CLONE_THREAD, NULL));
|
||||
// If CLONE_THREAD is set, CLONE_SIGHAND must be set too.
|
||||
ASSERT_EQ(-1, clone(child_fn, &fake_child_stack[16], CLONE_THREAD, NULL));
|
||||
ASSERT_EQ(EINVAL, errno);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue