2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: NewStackSwap() - Call a function with swapped stack.
9 #include <aros/asmcall.h>
10 #include <aros/debug.h>
11 #include <exec/tasks.h>
12 #include <proto/exec.h>
15 * The following includes need to go in this particular order!
16 * We need to define _XOPEN_SOURCE (done in the first line of exec_platform.h)
17 * for the proper context definition under Darwin before include any host headers,
18 * otherwise ucontext_t will get only partial definition and getcontext() will clobber
21 #include "exec_intern.h"
26 static void trampoline(IPTR (*func
)(), IPTR
*ret
, IPTR
*args
)
28 /* this was called from NewStackSwap() which also called Disable */
34 bug("[NewStackSwap] Stack swapping done\n");
35 bug("[NewStackSwap] SP at 0x%p\n", AROS_GET_SP
);
36 bug("[NewStackSwap] Function address: 0x%p\n", func
);
37 for (i
= 0; i
< 8; i
++)
38 bug("[NewStackSwap] args[%u] = 0x%p\n", i
, (void *)args
[i
]);
41 *ret
= func(args
[0], args
[1], args
[2], args
[3],
42 args
[4], args
[5], args
[6], args
[7]);
44 /* this was called from NewStackSwap() which will enable again */
48 AROS_LH3(IPTR
, NewStackSwap
,
49 AROS_LHA(struct StackSwapStruct
*, sss
, A0
),
50 AROS_LHA(LONG_FUNC
, entry
, A1
),
51 AROS_LHA(struct StackSwapArgs
*, args
, A2
),
52 struct ExecBase
*, SysBase
, 134, Exec
)
56 struct Task
*me
= FindTask(NULL
);
58 volatile APTR splower
, spupper
;
59 ucontext_t ucx
, ucx_return
;
61 D(bug("NewStackSwap(0x%p, 0x%p, 0x%p, 0x%p)\n", sss
, entry
, args
, SysBase
));
62 DB2(bug("[NewStackSwap] Context size: %u\n", sizeof(ucontext_t
)));
64 Disable(); /* To avoid random crashes during startup */
65 PD(SysBase
).SysIFace
->getcontext(&ucx
);
69 D(bug("[NewStackSwap] getcontext() done, arguments: 0x%p, 0x%p, 0x%p, 0x%p\n", sss
, entry
, args
, SysBase
));
71 /* Prepare the alternate stack */
72 ucx
.uc_stack
.ss_sp
= sss
->stk_Lower
;
73 ucx
.uc_stack
.ss_size
= (size_t)sss
->stk_Pointer
- (size_t)sss
->stk_Lower
;
74 ucx
.uc_stack
.ss_flags
= SS_ONSTACK
;
75 ucx
.uc_link
= &ucx_return
;
77 if (me
->tc_Flags
& TF_STACKCHK
)
78 memset(ucx
.uc_stack
.ss_sp
, 0xE1, ucx
.uc_stack
.ss_size
);
80 D(bug("[NewStackSwap] Prepared stack: 0x%p - 0x%p (size %u bytes)\n", sss
->stk_Lower
, sss
->stk_Pointer
, ucx
.uc_stack
.ss_size
));
82 PD(SysBase
).SysIFace
->makecontext(&ucx
, (void *(*)()) trampoline
, 3, entry
, &ret
, args
->Args
);
85 DB2(bug("[NewStackSwap] Prepared context, doing stack swap\n"));
87 /* Remember original stack limits */
88 splower
= me
->tc_SPLower
;
89 spupper
= me
->tc_SPUpper
;
91 /* Disable(), otherwise stack check will fail */
94 /* Set new stack limits, swapcontext() will change the stack itself */
95 me
->tc_SPLower
= sss
->stk_Lower
;
96 me
->tc_SPUpper
= sss
->stk_Upper
;
98 /* We Enable() in trampoline */
99 PD(SysBase
).SysIFace
->swapcontext(&ucx_return
, &ucx
);
102 me
->tc_SPLower
= splower
;
103 me
->tc_SPUpper
= spupper
;
109 } /* NewStackSwap() */