diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/Dist | 1 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/makecontext.S | 113 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/setcontext.S | 96 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/swapcontext.S | 129 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/ucontext_i.h | 41 |
6 files changed, 389 insertions, 0 deletions
@@ -1,3 +1,12 @@ +2001-04-07 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/getcontext.S: New file. + * sysdeps/unix/sysv/linux/i386/setcontext.S: New file. + * sysdeps/unix/sysv/linux/i386/makecontext.S: New file. + * sysdeps/unix/sysv/linux/i386/swapcontext.S: New file. + * sysdeps/unix/sysv/linux/i386/ucontext_i.h: New file. + * sysdeps/unix/sysv/linux/i386/Dist: Add ucontext_i.h. + 2001-04-07 Andreas Jaeger <aj@suse.de> * sysdeps/ieee754/ldbl-96/e_j1l.c (__ieee754_y1l): Use sincos diff --git a/sysdeps/unix/sysv/linux/i386/Dist b/sysdeps/unix/sysv/linux/i386/Dist index e08e6bec06..30a5b63c81 100644 --- a/sysdeps/unix/sysv/linux/i386/Dist +++ b/sysdeps/unix/sysv/linux/i386/Dist @@ -14,3 +14,4 @@ sys/procfs.h sys/reg.h sys/user.h sys/vm86.h +ucontext_i.h diff --git a/sysdeps/unix/sysv/linux/i386/makecontext.S b/sysdeps/unix/sysv/linux/i386/makecontext.S new file mode 100644 index 0000000000..a68e66c3f5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/makecontext.S @@ -0,0 +1,113 @@ +/* Create new context. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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. */ + +#include <sysdep.h> + +#include "ucontext_i.h" + + +ENTRY(__makecontext) + movl 4(%esp), %eax + + /* Load the address of the function we are supposed to run. */ + movl 8(%esp), %ecx + + /* Compute the address of the stack. The information comes from + to us_stack element. */ + movl oSS_SP(%eax), %edx + movl %ecx, oEIP(%eax) + addl oSS_SIZE(%eax), %edx + + /* Put the next context on the new stack (from the uc_link + element). */ + movl oLINK(%eax), %ecx + movl %ecx, -4(%edx) + + /* Remember the number of parameters for the exit handler since + it has to remove them. We store the number in the EBX register + which the function we will call must preserve. */ + movl 12(%esp), %ecx + movl %ecx, oEBX(%eax) + + /* Make room on the new stack for the parameters. */ + negl %ecx + leal -8(%edx,%ecx,4), %edx + negl %ecx + /* Store the future stack pointer. */ + movl %edx, oESP(%eax) + + /* Copy all the parameters. */ + jecxz 2f +1: movl 12(%esp,%ecx,4), %eax + movl %eax, (%edx,%ecx,4) + decl %ecx + jnz 1b +2: + + /* If the function we call returns we must continue with the + context which is given in the uc_link element. To do this + set the return address for the function the user provides + to a little bit of helper code which does the magic (see + below). */ +#ifdef PIC + call 1f +1: popl %ecx + addl $L(exitcode)-1b, %ecx + movl %ecx, (%edx) +#else + movl $L(exitcode), (%edx) +#endif + /* 'makecontext' returns no value. */ + ret + + /* This is the helper code which gets called if a function which + is registered with 'makecontext' returns. In this case we + have to install the context listed in the uc_link element of + the context 'makecontext' manipulated at the time of the + 'makecontext' call. If the pointer is NULL the process must + terminate. */ +L(exitcode): + /* This removes the parameters passed to the function given to + 'makecontext' from the stack. EBX contains the number of + parameters (see above). */ + leal (%esp,%ebx,4), %esp + +#ifdef PIC + call 1f +1: popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx +#endif + popl %eax /* This is the next context. */ + testl %eax, %eax + je 2f /* If it is zero exit. */ + + pushl %eax + call JUMPTARGET(__setcontext) + /* If this returns (which can happen if the syscall fails) we'll + exit the program with the return error value (-1). */ + +2: pushl %eax + call JUMPTARGET(exit) + /* The 'exit' call should never return. In case it does cause + the process to terminate. */ + hlt +END(__makecontext) + +weak_alias(__makecontext, makecontext) diff --git a/sysdeps/unix/sysv/linux/i386/setcontext.S b/sysdeps/unix/sysv/linux/i386/setcontext.S new file mode 100644 index 0000000000..cd4b1bfe8a --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/setcontext.S @@ -0,0 +1,96 @@ +/* Install given context. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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. */ + +#include <sysdep.h> + +#include "ucontext_i.h" + + +ENTRY(__setcontext) + /* Load address of the context data structure. */ + movl 4(%esp), %eax + + /* Get the current signal mask. Note that we preserve EBX in case + the system call fails and we return from the function with an + error. */ + pushl %ebx + xorl %edx, %edx + leal oSIGMASK(%eax), %ecx + movl $SIG_SETMASK, %ebx + movl $__NR_sigprocmask, %eax + int $0x80 + popl %ebx + cmpl $-4095, %eax /* Check %eax for error. */ + jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ + + /* EAX was modified, reload it. */ + movl 4(%esp), %eax + + /* Restore the floating-point context. Not the registers, only the + rest. */ + movl oFPREGS(%eax), %ecx + fldenv (%ecx) + + /* Restore the FS and GS segment registers. */ + movl oGS(%eax), %edx + movl oFS(%eax), %ecx + movw %dx, %gs + movw %cx, %fs + + /* Load the new stack pointer. */ + movl oESP(%eax), %ecx + /* Make room for 8 registers and the return address. We will load + the values from the stack. */ + subl $36, %ecx + + /* Move the values of all the 32-bit registers (except ESP) on + the stack. This happens in the form the 'popa' instruction + expects it. Before this block put the address of the code + to execute. */ + movl oEDI(%eax), %ebx + movl oESI(%eax), %edx + movl oEBP(%eax), %esi + movl oEBX(%eax), %edi + movl %ebx, (%ecx) + movl %edx, 4(%ecx) + movl %esi, 8(%ecx) + movl %edi, 16(%ecx) + movl oEDX(%eax), %ebx + movl oECX(%eax), %edx + movl oEAX(%eax), %esi + movl oEIP(%eax), %edi + movl %ebx, 20(%ecx) + movl %edx, 24(%ecx) + movl %esi, 28(%ecx) + movl %edi, 32(%ecx) + + /* Set the new stack address. The stack points now to the block + we put the register content in. */ + movl %ecx, %esp + /* Restore the register content. */ + popa + /* The following 'ret' will pop the addres of the code and jump + to it. */ + +L(pseudo_end): + ret +PSEUDO_END(__setcontext) + +weak_alias(__setcontext, setcontext) diff --git a/sysdeps/unix/sysv/linux/i386/swapcontext.S b/sysdeps/unix/sysv/linux/i386/swapcontext.S new file mode 100644 index 0000000000..5fdf76050b --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/swapcontext.S @@ -0,0 +1,129 @@ +/* Save current context and install the given one. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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. */ + +#include <sysdep.h> + +#include "ucontext_i.h" + + +ENTRY(__swapcontext) + /* Load address of the context data structure we save in. */ + movl 4(%esp), %eax + + /* Return value of swapcontext. EAX is the only register whose + value is not preserved. */ + movl $0, oEAX(%eax) + + /* Save the 32-bit register values and the return address. */ + movl %ecx, oECX(%eax) + movl %edx, oEDX(%eax) + movl %edi, oEDI(%eax) + movl %esi, oESI(%eax) + movl %ebp, oEBP(%eax) + movl (%esp), %ecx + movl %ecx, oEIP(%eax) + leal 4(%esp), %ecx + movl %ecx, oESP(%eax) + movl %ebx, oEBX(%eax) + + /* Save the FS and GS segment register. */ + xorl %edx, %edx + xorl %ecx, %ecx + movw %gs, %dx + movw %fs, %cx + movl %edx, oGS(%eax) + movl %ecx, oFS(%eax) + + /* We have separate floating-point register content memory on the + stack. We use the __fpregs_mem block in the context. Set the + links up correctly. */ + leal oFPREGSMEM(%eax), %ecx + movl %ecx, oFPREGS(%eax) + /* Save the floating-point context. */ + fnstenv (%ecx) + + /* Load address of the context data structure we have to load. */ + movl 8(%esp), %ecx + + /* Save the current signal mask and install the new one. */ + pushl %ebx + leal oSIGMASK(%eax), %edx + leal oSIGMASK(%ecx), %ecx + movl $SIG_SETMASK, %ebx + movl $__NR_sigprocmask, %eax + int $0x80 + popl %ebx + cmpl $-4095, %eax /* Check %eax for error. */ + jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ + + /* EAX was modified, reload it. */ + movl 8(%esp), %eax + + /* Restore the floating-point context. Not the registers, only the + rest. */ + movl oFPREGS(%eax), %ecx + fldenv (%ecx) + + /* Restore the FS and GS segment registers. */ + movl oGS(%eax), %edx + movl oFS(%eax), %ecx + movw %dx, %gs + movw %cx, %fs + + /* Load the new stack pointer. */ + movl oESP(%eax), %ecx + /* Make room for 8 registers and the return address. We will load + the values from the stack. */ + subl $36, %ecx + + /* Move the values of all the 32-bit registers (except ESP) on + the stack. This happens in the form the 'popa' instruction + expects it. Before this block put the address of the code + to execute. */ + movl oEDI(%eax), %ebx + movl oESI(%eax), %edx + movl oEBP(%eax), %esi + movl oEBX(%eax), %edi + movl %ebx, (%ecx) + movl %edx, 4(%ecx) + movl %esi, 8(%ecx) + movl %edi, 16(%ecx) + movl oEDX(%eax), %ebx + movl oECX(%eax), %edx + movl oEAX(%eax), %esi + movl oEIP(%eax), %edi + movl %ebx, 20(%ecx) + movl %edx, 24(%ecx) + movl %esi, 28(%ecx) + movl %edi, 32(%ecx) + + /* Set the new stack address. The stack points now to the block + we put the register content in. */ + movl %ecx, %esp + /* Restore the register content. */ + popa + /* The following 'ret' will pop the addres of the code and jump + to it. */ + +L(pseudo_end): + ret +PSEUDO_END(__swapcontext) + +weak_alias(__swapcontext, swapcontext) diff --git a/sysdeps/unix/sysv/linux/i386/ucontext_i.h b/sysdeps/unix/sysv/linux/i386/ucontext_i.h new file mode 100644 index 0000000000..863c1adb7a --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/ucontext_i.h @@ -0,0 +1,41 @@ +/* Offsets and other constants needed in the *context() function + implementation. + Copyright (C) 2001 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. */ + +#define SIG_BLOCK 0 +#define SIG_SETMASK 2 + +/* Offsets of the fields in the ucontext_t structure. */ +#define oLINK 4 +#define oSS_SP 8 +#define oSS_SIZE 16 +#define oGS 20 +#define oFS 24 +#define oEDI 36 +#define oESI 40 +#define oEBP 44 +#define oESP 48 +#define oEBX 52 +#define oEDX 56 +#define oECX 60 +#define oEAX 64 +#define oEIP 76 +#define oFPREGS 96 +#define oSIGMASK 108 +#define oFPREGSMEM 236 |