#include "src/unistd/fork.h"
#include "src/__support/OSUtil/pid.h"
#include "src/__support/OSUtil/syscall.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/threads/fork_callbacks.h"
#include "src/__support/threads/thread.h"
#include "src/errno/libc_errno.h"
#include <signal.h>
#include <sys/syscall.h>
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(pid_t, fork, (void)) {
invoke_prepare_callbacks();
pid_t parent_tid = self.get_tid();
self.invalidate_tid();
ProcessIdentity::start_fork();
#ifdef SYS_fork
pid_t ret = LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_fork);
#elif defined(SYS_clone)
pid_t ret = LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_clone, SIGCHLD, 0);
#else
#error "fork and clone syscalls not available."
#endif
if (ret < 0) {
libc_errno = static_cast<int>(-ret);
return -1;
}
if (ret == 0) {
self.refresh_tid();
ProcessIdentity::refresh_cache();
ProcessIdentity::end_fork();
invoke_child_callbacks();
return 0;
}
self.refresh_tid(parent_tid);
ProcessIdentity::end_fork();
invoke_parent_callbacks();
return ret;
}
}