summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/i386
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/i386')
-rw-r--r--sysdeps/unix/sysv/linux/i386/clone.S7
-rw-r--r--sysdeps/unix/sysv/linux/i386/sigaction.c37
-rw-r--r--sysdeps/unix/sysv/linux/i386/sys/ucontext.h106
3 files changed, 147 insertions, 3 deletions
diff --git a/sysdeps/unix/sysv/linux/i386/clone.S b/sysdeps/unix/sysv/linux/i386/clone.S
index 7f758a52a8..0aec95e219 100644
--- a/sysdeps/unix/sysv/linux/i386/clone.S
+++ b/sysdeps/unix/sysv/linux/i386/clone.S
@@ -23,6 +23,7 @@
#include <sysdep.h>
#define _ERRNO_H 1
#include <bits/errno.h>
+#include <asm-syntax.h>
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
@@ -63,6 +64,12 @@ ENTRY(__clone)
thread_start:
subl %ebp,%ebp /* terminate the stack frame */
call *%ebx
+#ifdef PIC
+ call L(here)
+L(here):
+ popl %ebx
+ addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
+#endif
pushl %eax
call JUMPTARGET (_exit)
diff --git a/sysdeps/unix/sysv/linux/i386/sigaction.c b/sysdeps/unix/sysv/linux/i386/sigaction.c
index 3f9d9463a0..99ed694f49 100644
--- a/sysdeps/unix/sysv/linux/i386/sigaction.c
+++ b/sysdeps/unix/sysv/linux/i386/sigaction.c
@@ -28,17 +28,48 @@
#include <kernel_sigaction.h>
+extern int __syscall_rt_signal (int, const struct sigaction *,
+ struct sigaction *, size_t);
+
+/* The variable is shared between all wrappers around signal handling
+ functions which have RT equivalents. It is defined in sigsuspend.c. */
+extern int __libc_have_rt_sigs;
+
+
/* If ACT is not NULL, change the action for SIG to *ACT.
If OACT is not NULL, put the old action for SIG in *OACT. */
int
__sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
{
- struct kernel_sigaction k_newact, k_oldact;
+ struct old_kernel_sigaction k_newact, k_oldact;
int result;
+ /* First try the RT signals. */
+ if (__libc_have_rt_sigs)
+ {
+ struct sigaction nact;
+
+ nact.sa_handler = act->sa_handler;
+ memcpy (&nact.sa_mask, &act->sa_mask, sizeof (sigset_t));
+ nact.sa_flags = act->sa_flags;
+
+ nact.sa_restorer = ((act->sa_flags & SA_NOMASK)
+ ? &&restore_nomask : &&restore);
+
+ /* XXX The size argument hopefully will have to be changed to the
+ real size of the user-level sigset_t. */
+ result = __syscall_rt_sigaction (sig, &nact, oact,
+ _NSIG / (8 * sizeof (long int)));
+
+ if (result >= 0 || errno != ENOSYS)
+ return result;
+
+ __libc_have_rt_sigs = 0;
+ }
+
if (act)
{
- k_newact.sa_handler = act->sa_handler;
+ k_newact.k_sa_handler = act->sa_handler;
k_newact.sa_mask = act->sa_mask.__val[0];
k_newact.sa_flags = act->sa_flags;
@@ -62,7 +93,7 @@ __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
if (oact)
{
- oact->sa_handler = k_oldact.sa_handler;
+ oact->sa_handler = k_oldact.k_sa_handler;
oact->sa_mask.__val[0] = k_oldact.sa_mask;
oact->sa_flags = k_oldact.sa_flags;
oact->sa_restorer = k_oldact.sa_restorer;
diff --git a/sysdeps/unix/sysv/linux/i386/sys/ucontext.h b/sysdeps/unix/sysv/linux/i386/sys/ucontext.h
new file mode 100644
index 0000000000..ccc32b661a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/sys/ucontext.h
@@ -0,0 +1,106 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef _SYS_UCONTEXT_H
+#define _SYS_UCONTEXT_H 1
+
+#include <features.h>
+#include <signal.h>
+
+/* We need the signal context definitions even if they are not used
+ included in <signal.h>. */
+#include <bits/sigcontext.h>
+
+
+/* Type for general register. */
+typedef int greg_t;
+
+/* Number of general registers. */
+#define NGREG 19
+
+/* Container for all general registers. */
+typedef greg_t gregset_t[NGREG];
+
+/* Number of each register is the `gregset_t' array. */
+enum
+{
+ GS = 0,
+#define GS GS
+ FS,
+#define FS FS
+ ES,
+#define ES ES
+ DS,
+#define DS DS
+ EDI,
+#define EDI EDI
+ ESI,
+#define ESI ESI
+ EBP,
+#define EBP EBP
+ ESP,
+#define ESP ESP
+ EBX,
+#define EBX EBX
+ EDX,
+#define EDX EDX
+ ECX,
+#define ECX ECX
+ EAX,
+#define EAX EAX
+ TRAPNO,
+#define TRAPNO TRAPNO
+ ERR,
+#define ERR ERR
+ EIP,
+#define EIP EIP
+ CS,
+#define CS CS
+ EFL,
+#define EFL EFL
+ UESP,
+#define UESP UESP
+ SS
+#define SS SS
+};
+
+/* Structure to describe FPU registers. */
+typedef struct _fpstate *fpregset_t;
+
+/* Context to describe whole processor state. */
+typedef struct
+ {
+ gregset_t gregs;
+ /* Due to Linux's history we have to use a pointer here. The SysV/i386
+ ABI requires a struct with the values. */
+ fpregset_t fpregs;
+ unsigned long int oldmask;
+ unsigned long int cr2;
+ } mcontext_t;
+
+/* Userlevel context. */
+typedef struct ucontext
+ {
+ unsigned long int uc_flags;
+ struct ucontext *uc_links;
+ stack_t uc_stack;
+ mcontext_t uc_mcontext;
+ __sigset_t uc_sigmask;
+ } ucontext_t;
+
+#endif /* sys/ucontext.h */