diff options
author | Thomas Schwinge <thomas@codesourcery.com> | 2019-12-29 16:04:51 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2019-12-29 16:54:08 +0100 |
commit | a678c13b8f9fa67c6cffe6ecf4ba1d5e53479e1b (patch) | |
tree | cb62c6fb5a84d4cdcb6d46f78318fb1818481af3 /sysdeps/mach/hurd/i386/makecontext.S | |
parent | 344e755248ce02c0f8d095d11cc49e340703d926 (diff) | |
download | glibc-a678c13b8f9fa67c6cffe6ecf4ba1d5e53479e1b.tar.gz glibc-a678c13b8f9fa67c6cffe6ecf4ba1d5e53479e1b.tar.xz glibc-a678c13b8f9fa67c6cffe6ecf4ba1d5e53479e1b.zip |
hurd: Add getcontext, makecontext, setcontext, swapcontext
Adapted from the Linux x86 functions. Not thoroughly tested, but manual testing as well as glibc tests look fine, and manual -lpthread testing also looks fine (within the given bounds for a new stack to be used with makecontext). This has also been in use in Debian since 2013.
Diffstat (limited to 'sysdeps/mach/hurd/i386/makecontext.S')
-rw-r--r-- | sysdeps/mach/hurd/i386/makecontext.S | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/sysdeps/mach/hurd/i386/makecontext.S b/sysdeps/mach/hurd/i386/makecontext.S new file mode 100644 index 0000000000..e2f8afc895 --- /dev/null +++ b/sysdeps/mach/hurd/i386/makecontext.S @@ -0,0 +1,130 @@ +/* Create new context. + Copyright (C) 2001-2019 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 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 <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 + + /* 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. + Room for the arguments, return address (== L(exitcode)) and + oLINK pointer is needed. One of the pointer sizes is subtracted + after aligning the stack. */ + negl %ecx + leal -4(%edx,%ecx,4), %edx + negl %ecx + + /* Align the stack. */ + andl $0xfffffff0, %edx + subl $4, %edx + + /* Store the future stack pointer. */ + movl %edx, oESP(%eax) + + /* Put the next context on the new stack (from the uc_link + element). */ + movl oLINK(%eax), %eax + movl %eax, 4(%edx,%ecx,4) + + /* 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 + cfi_adjust_cfa_offset (4) +1: popl %ecx + cfi_adjust_cfa_offset (-4) + addl $L(exitcode)-1b, %ecx + movl %ecx, (%edx) +#else + movl $L(exitcode), (%edx) +#endif + /* We need to terminate the FDE here instead of after ret because + the unwinder looks at ra-1 for unwind information. */ + cfi_endproc + + /* '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 + + cmpl $0, (%esp) /* Check the next context. */ + je 2f /* If it is zero exit. */ + + call HIDDEN_JUMPTARGET(__setcontext) + /* If this returns (which can happen if the syscall fails) we'll + exit the program with the return error value (-1). */ + jmp L(call_exit) + +2: + /* Exit with status 0. */ + xorl %eax, %eax + +L(call_exit): + /* Align the stack and pass the exit code (from %eax). */ + andl $0xfffffff0, %esp + subl $12, %esp + pushl %eax + + call HIDDEN_JUMPTARGET(exit) + /* The 'exit' call should never return. In case it does cause + the process to terminate. */ + hlt + cfi_startproc +END(__makecontext) + +weak_alias (__makecontext, makecontext) |