make.tmpl: add missing compiler attribute to build_progs
[AROS.git] / arch / all-unix / exec / newstackswap.c
blobd9cee285d158ab1abd0c60e2e2c0678e285774ec
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: NewStackSwap() - Call a function with swapped stack.
6 Lang: english
7 */
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
19 * your stack!
21 #include "exec_intern.h"
23 #include <signal.h>
24 #include <string.h>
26 static void trampoline(IPTR (*func)(), IPTR *ret, IPTR *args)
28 /* this was called from NewStackSwap() which also called Disable */
29 Enable();
31 #if DEBUG
32 int i;
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]);
39 #endif
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 */
45 Disable();
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)
54 AROS_LIBFUNC_INIT
56 struct Task *me = FindTask(NULL);
57 IPTR ret;
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);
66 AROS_HOST_BARRIER
67 Enable();
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);
83 AROS_HOST_BARRIER
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 */
92 Disable();
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);
100 AROS_HOST_BARRIER
102 me->tc_SPLower = splower;
103 me->tc_SPUpper = spupper;
104 Enable();
106 return ret;
108 AROS_LIBFUNC_EXIT
109 } /* NewStackSwap() */