mirror of
git://sourceware.org/git/glibc.git
synced 2024-12-03 04:01:43 +08:00
nptl: Move Linux createthread to nptl
git mv -f sysdeps/unix/sysv/linux/createthread.c nptl/createthread.c No functional change.
This commit is contained in:
parent
76b0c59e33
commit
65ba6fa431
@ -1,6 +1,7 @@
|
||||
/* Low-level thread creation for NPTL. Stub version.
|
||||
Copyright (C) 2014-2021 Free Software Foundation, Inc.
|
||||
/* Low-level thread creation for NPTL. Linux version.
|
||||
Copyright (C) 2002-2021 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,30 +17,137 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <sched.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <atomic.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <tls.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <arch-fork.h>
|
||||
|
||||
#ifdef __NR_clone2
|
||||
# define ARCH_CLONE __clone2
|
||||
#else
|
||||
# define ARCH_CLONE __clone
|
||||
#endif
|
||||
|
||||
/* See the comments in pthread_create.c for the requirements for these
|
||||
two macros and the create_thread function. */
|
||||
|
||||
#define START_THREAD_DEFN \
|
||||
static void __attribute__ ((noreturn)) start_thread (void)
|
||||
#define START_THREAD_SELF THREAD_SELF
|
||||
static int __attribute__ ((noreturn)) start_thread (void *arg)
|
||||
#define START_THREAD_SELF arg
|
||||
|
||||
/* pthread_create.c defines this using START_THREAD_DEFN
|
||||
We need a forward declaration here so we can take its address. */
|
||||
static int start_thread (void *arg) __attribute__ ((noreturn));
|
||||
|
||||
static int
|
||||
create_thread (struct pthread *pd, const struct pthread_attr *attr,
|
||||
bool *stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran)
|
||||
{
|
||||
/* If the implementation needs to do some tweaks to the thread after
|
||||
it has been created at the OS level, it can set STOPPED_START here. */
|
||||
/* Determine whether the newly created threads has to be started
|
||||
stopped since we have to set the scheduling parameters or set the
|
||||
affinity. */
|
||||
bool need_setaffinity = (attr != NULL && attr->extension != NULL
|
||||
&& attr->extension->cpuset != 0);
|
||||
if (attr != NULL
|
||||
&& (__glibc_unlikely (need_setaffinity)
|
||||
|| __glibc_unlikely ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0)))
|
||||
*stopped_start = true;
|
||||
|
||||
pd->stopped_start = *stopped_start;
|
||||
if (__glibc_unlikely (*stopped_start))
|
||||
/* See CONCURRENCY NOTES in nptl/pthread_create.c. */
|
||||
/* See CONCURRENCY NOTES in nptl/pthread_creat.c. */
|
||||
lll_lock (pd->lock, LLL_PRIVATE);
|
||||
|
||||
return ENOSYS;
|
||||
/* We rely heavily on various flags the CLONE function understands:
|
||||
|
||||
CLONE_VM, CLONE_FS, CLONE_FILES
|
||||
These flags select semantics with shared address space and
|
||||
file descriptors according to what POSIX requires.
|
||||
|
||||
CLONE_SIGHAND, CLONE_THREAD
|
||||
This flag selects the POSIX signal semantics and various
|
||||
other kinds of sharing (itimers, POSIX timers, etc.).
|
||||
|
||||
CLONE_SETTLS
|
||||
The sixth parameter to CLONE determines the TLS area for the
|
||||
new thread.
|
||||
|
||||
CLONE_PARENT_SETTID
|
||||
The kernels writes the thread ID of the newly created thread
|
||||
into the location pointed to by the fifth parameters to CLONE.
|
||||
|
||||
Note that it would be semantically equivalent to use
|
||||
CLONE_CHILD_SETTID but it is be more expensive in the kernel.
|
||||
|
||||
CLONE_CHILD_CLEARTID
|
||||
The kernels clears the thread ID of a thread that has called
|
||||
sys_exit() in the location pointed to by the seventh parameter
|
||||
to CLONE.
|
||||
|
||||
The termination signal is chosen to be zero which means no signal
|
||||
is sent. */
|
||||
const int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SYSVSEM
|
||||
| CLONE_SIGHAND | CLONE_THREAD
|
||||
| CLONE_SETTLS | CLONE_PARENT_SETTID
|
||||
| CLONE_CHILD_CLEARTID
|
||||
| 0);
|
||||
|
||||
TLS_DEFINE_INIT_TP (tp, pd);
|
||||
|
||||
if (__glibc_unlikely (ARCH_CLONE (&start_thread, STACK_VARIABLES_ARGS,
|
||||
clone_flags, pd, &pd->tid, tp, &pd->tid)
|
||||
== -1))
|
||||
return errno;
|
||||
|
||||
/* It's started now, so if we fail below, we'll have to cancel it
|
||||
and let it clean itself up. */
|
||||
*thread_ran = true;
|
||||
|
||||
/* Now we have the possibility to set scheduling parameters etc. */
|
||||
if (attr != NULL)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* Set the affinity mask if necessary. */
|
||||
if (need_setaffinity)
|
||||
{
|
||||
assert (*stopped_start);
|
||||
|
||||
res = INTERNAL_SYSCALL_CALL (sched_setaffinity, pd->tid,
|
||||
attr->extension->cpusetsize,
|
||||
attr->extension->cpuset);
|
||||
|
||||
if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res)))
|
||||
err_out:
|
||||
{
|
||||
/* The operation failed. We have to kill the thread.
|
||||
We let the normal cancellation mechanism do the work. */
|
||||
|
||||
pid_t pid = __getpid ();
|
||||
INTERNAL_SYSCALL_CALL (tgkill, pid, pd->tid, SIGCANCEL);
|
||||
|
||||
return INTERNAL_SYSCALL_ERRNO (res);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the scheduling parameters. */
|
||||
if ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0)
|
||||
{
|
||||
assert (*stopped_start);
|
||||
|
||||
res = INTERNAL_SYSCALL_CALL (sched_setscheduler, pd->tid,
|
||||
pd->schedpolicy, &pd->schedparam);
|
||||
|
||||
if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res)))
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,153 +0,0 @@
|
||||
/* Low-level thread creation for NPTL. Linux version.
|
||||
Copyright (C) 2002-2021 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <sched.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <atomic.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <tls.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <arch-fork.h>
|
||||
|
||||
#ifdef __NR_clone2
|
||||
# define ARCH_CLONE __clone2
|
||||
#else
|
||||
# define ARCH_CLONE __clone
|
||||
#endif
|
||||
|
||||
/* See the comments in pthread_create.c for the requirements for these
|
||||
two macros and the create_thread function. */
|
||||
|
||||
#define START_THREAD_DEFN \
|
||||
static int __attribute__ ((noreturn)) start_thread (void *arg)
|
||||
#define START_THREAD_SELF arg
|
||||
|
||||
/* pthread_create.c defines this using START_THREAD_DEFN
|
||||
We need a forward declaration here so we can take its address. */
|
||||
static int start_thread (void *arg) __attribute__ ((noreturn));
|
||||
|
||||
static int
|
||||
create_thread (struct pthread *pd, const struct pthread_attr *attr,
|
||||
bool *stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran)
|
||||
{
|
||||
/* Determine whether the newly created threads has to be started
|
||||
stopped since we have to set the scheduling parameters or set the
|
||||
affinity. */
|
||||
bool need_setaffinity = (attr != NULL && attr->extension != NULL
|
||||
&& attr->extension->cpuset != 0);
|
||||
if (attr != NULL
|
||||
&& (__glibc_unlikely (need_setaffinity)
|
||||
|| __glibc_unlikely ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0)))
|
||||
*stopped_start = true;
|
||||
|
||||
pd->stopped_start = *stopped_start;
|
||||
if (__glibc_unlikely (*stopped_start))
|
||||
/* See CONCURRENCY NOTES in nptl/pthread_creat.c. */
|
||||
lll_lock (pd->lock, LLL_PRIVATE);
|
||||
|
||||
/* We rely heavily on various flags the CLONE function understands:
|
||||
|
||||
CLONE_VM, CLONE_FS, CLONE_FILES
|
||||
These flags select semantics with shared address space and
|
||||
file descriptors according to what POSIX requires.
|
||||
|
||||
CLONE_SIGHAND, CLONE_THREAD
|
||||
This flag selects the POSIX signal semantics and various
|
||||
other kinds of sharing (itimers, POSIX timers, etc.).
|
||||
|
||||
CLONE_SETTLS
|
||||
The sixth parameter to CLONE determines the TLS area for the
|
||||
new thread.
|
||||
|
||||
CLONE_PARENT_SETTID
|
||||
The kernels writes the thread ID of the newly created thread
|
||||
into the location pointed to by the fifth parameters to CLONE.
|
||||
|
||||
Note that it would be semantically equivalent to use
|
||||
CLONE_CHILD_SETTID but it is be more expensive in the kernel.
|
||||
|
||||
CLONE_CHILD_CLEARTID
|
||||
The kernels clears the thread ID of a thread that has called
|
||||
sys_exit() in the location pointed to by the seventh parameter
|
||||
to CLONE.
|
||||
|
||||
The termination signal is chosen to be zero which means no signal
|
||||
is sent. */
|
||||
const int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SYSVSEM
|
||||
| CLONE_SIGHAND | CLONE_THREAD
|
||||
| CLONE_SETTLS | CLONE_PARENT_SETTID
|
||||
| CLONE_CHILD_CLEARTID
|
||||
| 0);
|
||||
|
||||
TLS_DEFINE_INIT_TP (tp, pd);
|
||||
|
||||
if (__glibc_unlikely (ARCH_CLONE (&start_thread, STACK_VARIABLES_ARGS,
|
||||
clone_flags, pd, &pd->tid, tp, &pd->tid)
|
||||
== -1))
|
||||
return errno;
|
||||
|
||||
/* It's started now, so if we fail below, we'll have to cancel it
|
||||
and let it clean itself up. */
|
||||
*thread_ran = true;
|
||||
|
||||
/* Now we have the possibility to set scheduling parameters etc. */
|
||||
if (attr != NULL)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* Set the affinity mask if necessary. */
|
||||
if (need_setaffinity)
|
||||
{
|
||||
assert (*stopped_start);
|
||||
|
||||
res = INTERNAL_SYSCALL_CALL (sched_setaffinity, pd->tid,
|
||||
attr->extension->cpusetsize,
|
||||
attr->extension->cpuset);
|
||||
|
||||
if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res)))
|
||||
err_out:
|
||||
{
|
||||
/* The operation failed. We have to kill the thread.
|
||||
We let the normal cancellation mechanism do the work. */
|
||||
|
||||
pid_t pid = __getpid ();
|
||||
INTERNAL_SYSCALL_CALL (tgkill, pid, pd->tid, SIGCANCEL);
|
||||
|
||||
return INTERNAL_SYSCALL_ERRNO (res);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the scheduling parameters. */
|
||||
if ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0)
|
||||
{
|
||||
assert (*stopped_start);
|
||||
|
||||
res = INTERNAL_SYSCALL_CALL (sched_setscheduler, pd->tid,
|
||||
pd->schedpolicy, &pd->schedparam);
|
||||
|
||||
if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res)))
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user