1995-04-03 06:08:59 +08:00
|
|
|
/* longjmp cleanup function for unwinding past signal handlers.
|
2019-01-01 08:11:28 +08:00
|
|
|
Copyright (C) 1995-2019 Free Software Foundation, Inc.
|
1997-02-15 12:31:36 +08:00
|
|
|
This file is part of the GNU C Library.
|
1995-04-03 06:08:59 +08:00
|
|
|
|
1997-02-15 12:31:36 +08:00
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
2001-07-06 12:58:11 +08:00
|
|
|
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.
|
1995-04-03 06:08:59 +08:00
|
|
|
|
1997-02-15 12:31:36 +08:00
|
|
|
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
|
2001-07-06 12:58:11 +08:00
|
|
|
Lesser General Public License for more details.
|
1995-04-03 06:08:59 +08:00
|
|
|
|
2001-07-06 12:58:11 +08:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
2012-02-10 07:18:22 +08:00
|
|
|
License along with the GNU C Library; if not, see
|
Prefer https to http for gnu.org and fsf.org URLs
Also, change sources.redhat.com to sourceware.org.
This patch was automatically generated by running the following shell
script, which uses GNU sed, and which avoids modifying files imported
from upstream:
sed -ri '
s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g
s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g
' \
$(find $(git ls-files) -prune -type f \
! -name '*.po' \
! -name 'ChangeLog*' \
! -path COPYING ! -path COPYING.LIB \
! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \
! -path manual/texinfo.tex ! -path scripts/config.guess \
! -path scripts/config.sub ! -path scripts/install-sh \
! -path scripts/mkinstalldirs ! -path scripts/move-if-change \
! -path INSTALL ! -path locale/programs/charmap-kw.h \
! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \
! '(' -name configure \
-execdir test -f configure.ac -o -f configure.in ';' ')' \
! '(' -name preconfigure \
-execdir test -f preconfigure.ac ';' ')' \
-print)
and then by running 'make dist-prepare' to regenerate files built
from the altered files, and then executing the following to cleanup:
chmod a+x sysdeps/unix/sysv/linux/riscv/configure
# Omit irrelevant whitespace and comment-only changes,
# perhaps from a slightly-different Autoconf version.
git checkout -f \
sysdeps/csky/configure \
sysdeps/hppa/configure \
sysdeps/riscv/configure \
sysdeps/unix/sysv/linux/csky/configure
# Omit changes that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines
git checkout -f \
sysdeps/powerpc/powerpc64/ppc-mcount.S \
sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
# Omit change that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline
git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 13:40:42 +08:00
|
|
|
<https://www.gnu.org/licenses/>. */
|
1995-04-03 06:08:59 +08:00
|
|
|
|
|
|
|
#include <hurd.h>
|
2005-12-22 06:16:34 +08:00
|
|
|
#include <thread_state.h>
|
hurd: Replace threadvars with TLS
This gets rid of a lot of kludge and gets closer to other ports.
* hurd/Makefile (headers): Remove threadvar.h.
(inline-headers): Remove threadvar.h.
* hurd/Versions (GLIBC_2.0: Remove __hurd_sigthread_stack_base,
__hurd_sigthread_stack_end, __hurd_sigthread_variables,
__hurd_threadvar_max, __hurd_errno_location.
(HURD_CTHREADS_0.3): Add pthread_getattr_np, pthread_attr_getstack.
* hurd/hurd/signal.h: Do not include <hurd/threadvar.h>.
(_hurd_self_sigstate): Use THREAD_SELF to get _hurd_sigstate.
(_HURD_SIGNAL_H_EXTERN_INLINE): Use THREAD_SELF to get _hurd_sigstate,
unless TLS is not initialized yet, in which case we do not need a
critical section yet anyway.
* hurd/hurd/threadvar.h: Include <tls.h>, do not include
<machine-sp.h>.
(__hurd_sigthread_variables, __hurd_threadvar_max): Remove variables
declarations.
(__hurd_threadvar_index): Remove enum.
(_HURD_THREADVAR_H_EXTERN_INLINE): Remove macro.
(__hurd_threadvar_location_from_sp,__hurd_threadvar_location): Remove
inlines.
(__hurd_reply_port0): New variable declaration.
(__hurd_local_reply_port): New macro.
* hurd/hurdsig.c (__hurd_sigthread_variables): Remove variable.
(interrupted_reply_port_location): Add thread_t parameter. Use it
with THREAD_TCB to access thread-local variables.
(_hurdsig_abort_rpcs): Pass ss->thread to
interrupted_reply_port_location.
(_hurd_internal_post_signal): Likewise.
(_hurdsig_init): Use presence of cthread_fork instead of
__hurd_threadvar_stack_mask to start signal thread by hand.
Remove signal thread threadvar initialization.
* hurd/hurdstartup.c: Do not include <hurd/threadvar.h>
* hurd/sigunwind.c: Include <hurd/threadvar.h>
(_hurdsig_longjmp_from_handler): Use __hurd_local_reply_port instead
of threadvar.
* sysdeps/mach/hurd/Versions (libc.GLIBC_PRIVATE): Add
__libc_lock_self0.
(ld.GLIBC_2.0): Remove __hurd_sigthread_stack_base,
__hurd_sigthread_stack_end, __hurd_sigthread_variables.
(ld.GLIBC_PRIVATE): Add __libc_lock_self0.
* sysdeps/mach/hurd/cthreads.c: Add __libc_lock_self0.
* sysdeps/mach/hurd/dl-sysdep.c (errno, __hurd_sigthread_stack_base,
__hurd_sigthread_stack_end, __hurd_sigthread_variables, threadvars,
__hurd_threadvar_stack_offset, __hurd_threadvar_stack_mask): Do not
define variables.
* sysdeps/mach/hurd/errno-loc.c: Do not include <errno.h> and
<hurd/threadvar.h>.
[IS_IN(rtld)] (rtld_errno): New variable.
[IS_IN(rtld)] (__errno_location): New weak function.
[!IS_IN(rtld)]: Include "../../../csu/errno-loc.c".
* sysdeps/mach/hurd/errno.c: Remove file.
* sysdeps/mach/hurd/fork.c: Include <hurd/threadvar.h>
(__fork): Remove THREADVAR_SPACE macro and its use.
* sysdeps/mach/hurd/i386/init-first.c (__hurd_threadvar_max): Remove
variable.
(init): Do not initialize threadvar.
* sysdeps/mach/hurd/i386/libc.abilist (__hurd_threadvar_max): Remove
symbol.
* sysdeps/mach/hurd/i386/sigreturn.c (__sigreturn): Use
__hurd_local_reply_port instead of threadvar.
* sysdeps/mach/hurd/i386/tls.h (tcbhead_t): Add reply_port and
_hurd_sigstate fields.
(HURD_DESC_TLS, __LIBC_NO_TLS, THREAD_TCB): New macro.
* sysdeps/mach/hurd/i386/trampoline.c: Remove outdated comment.
* sysdeps/mach/hurd/libc-lock.h: Do not include <hurd/threadvar.h>.
(__libc_lock_owner_self): Use &__libc_lock_self0 and THREAD_SELF
instead of threadvar.
* sysdeps/mach/hurd/libc-tsd.h: Remove file.
* sysdeps/mach/hurd/mig-reply.c (GETPORT, reply_port): Remove macros.
(use_threadvar, global_reply_port): Remove variables.
(__hurd_reply_port0): New variable.
(__mig_get_reply_port): Use __hurd_local_reply_port and
__hurd_reply_port0 instead of threadvar.
(__mig_dealloc_reply_port): Likewise.
(__mig_init): Do not initialize threadvar.
* sysdeps/mach/hurd/profil.c: Fix comment.
2018-03-18 06:27:34 +08:00
|
|
|
#include <hurd/threadvar.h>
|
2006-01-11 03:09:01 +08:00
|
|
|
#include <jmpbuf-unwind.h>
|
1995-04-03 06:08:59 +08:00
|
|
|
#include <assert.h>
|
2005-12-29 04:40:03 +08:00
|
|
|
#include <stdint.h>
|
1995-04-03 06:08:59 +08:00
|
|
|
|
|
|
|
|
|
|
|
/* _hurd_setup_sighandler puts a link on the `active resources' chain so that
|
|
|
|
_longjmp_unwind will call this function with the `struct sigcontext *'
|
|
|
|
describing the context interrupted by the signal, when `longjmp' is jumping
|
|
|
|
to an environment that unwinds past the interrupted frame. */
|
|
|
|
|
|
|
|
void
|
|
|
|
_hurdsig_longjmp_from_handler (void *data, jmp_buf env, int val)
|
|
|
|
{
|
|
|
|
struct sigcontext *scp = data;
|
|
|
|
struct hurd_sigstate *ss = _hurd_self_sigstate ();
|
|
|
|
int onstack;
|
|
|
|
inline void cleanup (void)
|
|
|
|
{
|
|
|
|
/* Destroy the MiG reply port used by the signal handler, and restore
|
|
|
|
the reply port in use by the thread when interrupted. */
|
hurd: Replace threadvars with TLS
This gets rid of a lot of kludge and gets closer to other ports.
* hurd/Makefile (headers): Remove threadvar.h.
(inline-headers): Remove threadvar.h.
* hurd/Versions (GLIBC_2.0: Remove __hurd_sigthread_stack_base,
__hurd_sigthread_stack_end, __hurd_sigthread_variables,
__hurd_threadvar_max, __hurd_errno_location.
(HURD_CTHREADS_0.3): Add pthread_getattr_np, pthread_attr_getstack.
* hurd/hurd/signal.h: Do not include <hurd/threadvar.h>.
(_hurd_self_sigstate): Use THREAD_SELF to get _hurd_sigstate.
(_HURD_SIGNAL_H_EXTERN_INLINE): Use THREAD_SELF to get _hurd_sigstate,
unless TLS is not initialized yet, in which case we do not need a
critical section yet anyway.
* hurd/hurd/threadvar.h: Include <tls.h>, do not include
<machine-sp.h>.
(__hurd_sigthread_variables, __hurd_threadvar_max): Remove variables
declarations.
(__hurd_threadvar_index): Remove enum.
(_HURD_THREADVAR_H_EXTERN_INLINE): Remove macro.
(__hurd_threadvar_location_from_sp,__hurd_threadvar_location): Remove
inlines.
(__hurd_reply_port0): New variable declaration.
(__hurd_local_reply_port): New macro.
* hurd/hurdsig.c (__hurd_sigthread_variables): Remove variable.
(interrupted_reply_port_location): Add thread_t parameter. Use it
with THREAD_TCB to access thread-local variables.
(_hurdsig_abort_rpcs): Pass ss->thread to
interrupted_reply_port_location.
(_hurd_internal_post_signal): Likewise.
(_hurdsig_init): Use presence of cthread_fork instead of
__hurd_threadvar_stack_mask to start signal thread by hand.
Remove signal thread threadvar initialization.
* hurd/hurdstartup.c: Do not include <hurd/threadvar.h>
* hurd/sigunwind.c: Include <hurd/threadvar.h>
(_hurdsig_longjmp_from_handler): Use __hurd_local_reply_port instead
of threadvar.
* sysdeps/mach/hurd/Versions (libc.GLIBC_PRIVATE): Add
__libc_lock_self0.
(ld.GLIBC_2.0): Remove __hurd_sigthread_stack_base,
__hurd_sigthread_stack_end, __hurd_sigthread_variables.
(ld.GLIBC_PRIVATE): Add __libc_lock_self0.
* sysdeps/mach/hurd/cthreads.c: Add __libc_lock_self0.
* sysdeps/mach/hurd/dl-sysdep.c (errno, __hurd_sigthread_stack_base,
__hurd_sigthread_stack_end, __hurd_sigthread_variables, threadvars,
__hurd_threadvar_stack_offset, __hurd_threadvar_stack_mask): Do not
define variables.
* sysdeps/mach/hurd/errno-loc.c: Do not include <errno.h> and
<hurd/threadvar.h>.
[IS_IN(rtld)] (rtld_errno): New variable.
[IS_IN(rtld)] (__errno_location): New weak function.
[!IS_IN(rtld)]: Include "../../../csu/errno-loc.c".
* sysdeps/mach/hurd/errno.c: Remove file.
* sysdeps/mach/hurd/fork.c: Include <hurd/threadvar.h>
(__fork): Remove THREADVAR_SPACE macro and its use.
* sysdeps/mach/hurd/i386/init-first.c (__hurd_threadvar_max): Remove
variable.
(init): Do not initialize threadvar.
* sysdeps/mach/hurd/i386/libc.abilist (__hurd_threadvar_max): Remove
symbol.
* sysdeps/mach/hurd/i386/sigreturn.c (__sigreturn): Use
__hurd_local_reply_port instead of threadvar.
* sysdeps/mach/hurd/i386/tls.h (tcbhead_t): Add reply_port and
_hurd_sigstate fields.
(HURD_DESC_TLS, __LIBC_NO_TLS, THREAD_TCB): New macro.
* sysdeps/mach/hurd/i386/trampoline.c: Remove outdated comment.
* sysdeps/mach/hurd/libc-lock.h: Do not include <hurd/threadvar.h>.
(__libc_lock_owner_self): Use &__libc_lock_self0 and THREAD_SELF
instead of threadvar.
* sysdeps/mach/hurd/libc-tsd.h: Remove file.
* sysdeps/mach/hurd/mig-reply.c (GETPORT, reply_port): Remove macros.
(use_threadvar, global_reply_port): Remove variables.
(__hurd_reply_port0): New variable.
(__mig_get_reply_port): Use __hurd_local_reply_port and
__hurd_reply_port0 instead of threadvar.
(__mig_dealloc_reply_port): Likewise.
(__mig_init): Do not initialize threadvar.
* sysdeps/mach/hurd/profil.c: Fix comment.
2018-03-18 06:27:34 +08:00
|
|
|
mach_port_t *reply_port = &__hurd_local_reply_port;
|
1995-04-03 06:08:59 +08:00
|
|
|
if (*reply_port)
|
1996-04-11 02:36:02 +08:00
|
|
|
{
|
|
|
|
mach_port_t port = *reply_port;
|
|
|
|
/* Assigning MACH_PORT_DEAD here tells libc's mig_get_reply_port
|
|
|
|
not to get another reply port, but avoids mig_dealloc_reply_port
|
|
|
|
trying to deallocate it after the receive fails (which it will,
|
|
|
|
because the reply port will be bogus, regardless). */
|
|
|
|
*reply_port = MACH_PORT_DEAD;
|
|
|
|
__mach_port_destroy (__mach_task_self (), port);
|
|
|
|
}
|
2015-11-25 08:09:13 +08:00
|
|
|
if (scp->sc_reply_port)
|
|
|
|
__mach_port_destroy (__mach_task_self (), scp->sc_reply_port);
|
1995-04-03 06:08:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
__spin_lock (&ss->lock);
|
|
|
|
/* We should only ever be called from _longjmp_unwind (in jmp-unwind.c),
|
|
|
|
which calls us inside a critical section. */
|
1996-05-04 17:46:57 +08:00
|
|
|
assert (__spin_lock_locked (&ss->critical_section_lock));
|
1995-04-03 06:08:59 +08:00
|
|
|
/* Are we on the alternate signal stack now? */
|
1998-08-09 04:02:34 +08:00
|
|
|
onstack = (ss->sigaltstack.ss_flags & SS_ONSTACK);
|
1995-04-03 06:08:59 +08:00
|
|
|
__spin_unlock (&ss->lock);
|
|
|
|
|
|
|
|
if (onstack && ! scp->sc_onstack)
|
|
|
|
{
|
|
|
|
/* We are unwinding off the signal stack. We must use sigreturn to
|
|
|
|
do it robustly. Mutate the sigcontext so that when sigreturn
|
|
|
|
resumes from that context, it will be as if `__longjmp (ENV, VAL)'
|
|
|
|
were done. */
|
|
|
|
|
|
|
|
struct hurd_userlink *link;
|
|
|
|
|
2005-12-28 13:42:30 +08:00
|
|
|
inline uintptr_t demangle_ptr (uintptr_t x)
|
|
|
|
{
|
|
|
|
# ifdef PTR_DEMANGLE
|
|
|
|
PTR_DEMANGLE (x);
|
|
|
|
# endif
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
1995-04-03 06:08:59 +08:00
|
|
|
/* Continue _longjmp_unwind's job of running the unwind
|
|
|
|
forms for frames being unwound, since we will not
|
|
|
|
return to its loop like this one, which called us. */
|
|
|
|
for (link = ss->active_resources;
|
2005-12-28 13:42:30 +08:00
|
|
|
link && _JMPBUF_UNWINDS (env[0].__jmpbuf, link, demangle_ptr);
|
1995-04-03 06:08:59 +08:00
|
|
|
link = link->thread.next)
|
|
|
|
if (_hurd_userlink_unlink (link))
|
|
|
|
{
|
|
|
|
if (link->cleanup == &_hurdsig_longjmp_from_handler)
|
|
|
|
{
|
|
|
|
/* We are unwinding past another signal handler invocation.
|
|
|
|
Just finish the cleanup for this (inner) one, and then
|
|
|
|
swap SCP to restore to the outer context. */
|
|
|
|
cleanup ();
|
|
|
|
scp = link->cleanup_data;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
(*link->cleanup) (link->cleanup_data, env, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define sc_machine_thread_state paste(sc_,machine_thread_state)
|
|
|
|
#define paste(a,b) paste1(a,b)
|
|
|
|
#define paste1(a,b) a##b
|
|
|
|
|
|
|
|
/* There are no more unwind forms to be run!
|
|
|
|
Now we can just have the sigreturn do the longjmp for us. */
|
|
|
|
_hurd_longjmp_thread_state
|
|
|
|
((struct machine_thread_state *) &scp->sc_machine_thread_state,
|
|
|
|
env, val);
|
|
|
|
|
|
|
|
/* Restore to the same current signal mask. If sigsetjmp saved the
|
|
|
|
mask, longjmp has already restored it as desired; if not, we
|
|
|
|
should leave it as it is. */
|
|
|
|
scp->sc_mask = ss->blocked;
|
|
|
|
|
|
|
|
/* sigreturn expects the link added by _hurd_setup_sighandler
|
|
|
|
to still be there, but _longjmp_unwind removed it just before
|
|
|
|
calling us. Put it back now so sigreturn can find it. */
|
|
|
|
link = (void *) &scp[1];
|
|
|
|
assert (! link->resource.next && ! link->resource.prevp);
|
|
|
|
assert (link->thread.next == ss->active_resources);
|
2005-01-20 03:26:29 +08:00
|
|
|
assert (link->thread.prevp == &ss->active_resources);
|
1995-04-03 06:08:59 +08:00
|
|
|
if (link->thread.next)
|
|
|
|
link->thread.next->thread.prevp = &link->thread.next;
|
|
|
|
ss->active_resources = link;
|
|
|
|
|
|
|
|
/* We must momentarily exit the critical section so that sigreturn
|
|
|
|
does not get upset with us. But we don't want signal handlers
|
|
|
|
running right now, because we are presently in the bogus state of
|
|
|
|
having run all the unwind forms back to ENV's frame, but our SP is
|
|
|
|
still inside those unwound frames. */
|
|
|
|
__spin_lock (&ss->lock);
|
1996-05-04 17:46:57 +08:00
|
|
|
__spin_unlock (&ss->critical_section_lock);
|
1995-04-03 06:08:59 +08:00
|
|
|
ss->blocked = ~(sigset_t) 0 & ~_SIG_CANT_MASK;
|
|
|
|
__spin_unlock (&ss->lock);
|
|
|
|
|
|
|
|
/* Restore to the modified signal context that now
|
|
|
|
performs `longjmp (ENV, VAL)'. */
|
|
|
|
__sigreturn (scp);
|
|
|
|
assert (! "sigreturn returned!");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We are not unwinding off the alternate signal stack. So nothing
|
|
|
|
really funny is going on here. We can just clean up this handler
|
|
|
|
frame and let _longjmp_unwind continue unwinding. */
|
|
|
|
cleanup ();
|
|
|
|
ss->intr_port = scp->sc_intr_port;
|
|
|
|
}
|