|
Packit |
6c4009 |
/* Create new context.
|
|
Packit |
6c4009 |
Copyright (C) 2012-2018 Free Software Foundation, Inc.
|
|
Packit |
6c4009 |
This file is part of the GNU C Library.
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
The GNU C Library is free software; you can redistribute it and/or
|
|
Packit |
6c4009 |
modify it under the terms of the GNU Lesser General Public
|
|
Packit |
6c4009 |
License as published by the Free Software Foundation; either
|
|
Packit |
6c4009 |
version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
The GNU C Library is distributed in the hope that it will be useful,
|
|
Packit |
6c4009 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
6c4009 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
6c4009 |
Lesser General Public License for more details.
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
You should have received a copy of the GNU Lesser General Public
|
|
Packit |
6c4009 |
License along with the GNU C Library; if not, see
|
|
Packit |
6c4009 |
<http://www.gnu.org/licenses/>. */
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
#include <sysdep.h>
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
#include "ucontext_i.h"
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
ENTRY(__makecontext)
|
|
Packit |
6c4009 |
move.l 4(%sp), %a0
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Get the address of the function we are supposed to run. */
|
|
Packit |
6c4009 |
move.l 8(%sp), oPC(%a0)
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Compute the address of the stack. The information comes from
|
|
Packit |
6c4009 |
to us_stack element. */
|
|
Packit |
6c4009 |
move.l oSS_SP(%a0), %a1
|
|
Packit |
6c4009 |
add.l oSS_SIZE(%a0), %a1
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Remember the number of parameters for the exit handler since
|
|
Packit |
6c4009 |
it has to remove them. We store the number in the D7 register
|
|
Packit |
6c4009 |
which the function we will call must preserve. */
|
|
Packit |
6c4009 |
move.l 12(%sp), %d1
|
|
Packit |
6c4009 |
move.l %d1, oGREGS+7*4(%a0)
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Make room on the new stack for the parameters.
|
|
Packit |
6c4009 |
Room for the arguments, return address (== 1f) and
|
|
Packit |
6c4009 |
oLINK pointer is needed. */
|
|
Packit |
6c4009 |
neg.l %d1
|
|
Packit |
6c4009 |
lea -8(%a1,%d1.l*4), %a1
|
|
Packit |
6c4009 |
neg.l %d1
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Store the future stack pointer. */
|
|
Packit |
6c4009 |
move.l %a1, oSP(%a0)
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Put the next context on the new stack (from the uc_link
|
|
Packit |
6c4009 |
element). */
|
|
Packit |
6c4009 |
move.l oLINK(%a0), 4(%a1,%d1.l*4)
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Copy all the parameters. */
|
|
Packit |
6c4009 |
1: subq.l #1,%d1
|
|
Packit |
6c4009 |
jmi 2f
|
|
Packit |
6c4009 |
move.l 16(%sp,%d1.l*4), 4(%a1,%d1.l*4)
|
|
Packit |
6c4009 |
jra 1b
|
|
Packit |
6c4009 |
2:
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* If the function we call returns we must continue with the
|
|
Packit |
6c4009 |
context which is given in the uc_link element. To do this
|
|
Packit |
6c4009 |
set the return address for the function the user provides
|
|
Packit |
6c4009 |
to a little bit of helper code which does the magic (see
|
|
Packit |
6c4009 |
below). */
|
|
Packit |
6c4009 |
lea 1f(%pc), %a0
|
|
Packit |
6c4009 |
move.l %a0, (%a1)
|
|
Packit |
6c4009 |
/* 'makecontext' returns no value. */
|
|
Packit |
6c4009 |
rts
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* This is the helper code which gets called if a function which
|
|
Packit |
6c4009 |
is registered with 'makecontext' returns. In this case we
|
|
Packit |
6c4009 |
have to install the context listed in the uc_link element of
|
|
Packit |
6c4009 |
the context 'makecontext' manipulated at the time of the
|
|
Packit |
6c4009 |
'makecontext' call. If the pointer is NULL the process must
|
|
Packit |
6c4009 |
terminate.
|
|
Packit |
6c4009 |
Make sure to separate the return label from the previous unwind
|
|
Packit |
6c4009 |
region, because the unwinder uses ra-1 to find the FDE. */
|
|
Packit |
6c4009 |
cfi_endproc
|
|
Packit |
6c4009 |
nop
|
|
Packit |
6c4009 |
1:
|
|
Packit |
6c4009 |
/* This removes the parameters passed to the function given to
|
|
Packit |
6c4009 |
'makecontext' from the stack. D7 contains the number of
|
|
Packit |
6c4009 |
parameters (see above). */
|
|
Packit |
6c4009 |
lea (%sp,%d7.l*4), %sp
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
tst.l (%sp) /* Check the next context. */
|
|
Packit |
6c4009 |
jeq 2f /* If it is zero exit. */
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
jbsr JUMPTARGET(__setcontext)
|
|
Packit |
6c4009 |
/* If this returns (which can happen if the syscall fails) we'll
|
|
Packit |
6c4009 |
exit the program with the return error value (-1). */
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
move.l %d0, (%sp)
|
|
Packit |
6c4009 |
2: jbsr HIDDEN_JUMPTARGET(exit)
|
|
Packit |
6c4009 |
/* The 'exit' call should never return. In case it does cause
|
|
Packit |
6c4009 |
the process to terminate. */
|
|
Packit |
6c4009 |
illegal
|
|
Packit |
6c4009 |
cfi_startproc
|
|
Packit |
6c4009 |
END(__makecontext)
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
weak_alias (__makecontext, makecontext)
|