added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / arch / all-unix / dos / runprocess.c
blob3bc21e24fbdb91667b7a74c282a749644d746d5d
1 /*
2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: RunProcess() - Run a process from an entry point with args
6 Lang: english
7 */
9 #include <aros/asmcall.h> /* LONG_FUNC */
11 #include <dos/dosextens.h>
12 #include <proto/exec.h>
14 #define DEBUG 0
15 #include <aros/debug.h>
17 #include <ucontext.h>
18 #include <stdarg.h>
19 #include <boost/preprocessor/repetition/enum.hpp>
21 #define ARGS(z, n, text) text[n]
22 #define MAXARGS 16
24 static void SwapTaskStackLimits(APTR *lower, APTR *upper)
26 struct Task* this = FindTask(NULL);
27 APTR tmp;
29 tmp = this->tc_SPLower;
30 this->tc_SPLower = *lower;
31 *lower = tmp;
33 tmp = this->tc_SPUpper;
34 this->tc_SPUpper = *upper;
35 *upper = tmp;
38 static void CallEntry(
39 ULONG* Return_Value,
40 APTR pReturn_Addr,
41 struct StackSwapStruct* sss,
42 STRPTR argptr,
43 ULONG argsize,
44 LONG_FUNC entry)
46 #ifndef AROS_UFC3R
47 #error You need to write the AROS_UFC3R macro for your CPU
48 #endif
50 *Return_Value
51 = AROS_UFC3R(ULONG, entry,
52 AROS_UFCA(STRPTR, argptr, A0),
53 AROS_UFCA(ULONG, argsize, D0),
54 AROS_UFCA(struct ExecBase *, SysBase, A6),
55 pReturn_Addr,
56 (sss->stk_Upper - (ULONG)sss->stk_Lower) /* used by m68k-linux arch, needed?? */
60 static void trampoline(void (*func)(), IPTR args[])
62 /* this was called from CallWithStack which also called Disable */
63 Enable();
67 int test;
69 D(bug("swapped context: test = 0x%x\n", &test));
73 func(BOOST_PP_ENUM(MAXARGS, ARGS, args));
75 /* this was called from CallWithStack which will enable again */
76 Disable();
79 BOOL CallWithStack
81 void (*func)(), void* stack, size_t size, int argc, IPTR args[]
84 ucontext_t ucx, ucx_return;
86 Disable(); /* To avoid random crashes during startup */
87 if (argc > MAXARGS || getcontext(&ucx) == -1)
89 Enable();
90 return FALSE;
92 Enable();
94 ucx.uc_stack.ss_sp = stack;
95 ucx.uc_stack.ss_size = size;
96 ucx.uc_stack.ss_flags = SS_ONSTACK;
98 ucx.uc_link = &ucx_return;
100 APTR SPLower = stack, SPUpper = stack + size;
101 #if AROS_STACK_DEBUG
103 UBYTE* startfill = SPLower;
104 const UBYTE* endfill = SPUpper;
106 while (startfill < endfill)
108 *startfill++ = 0xE1;
111 #endif
113 makecontext(&ucx, (void (*)()) trampoline, 2, func, args);
116 we enable again in trampoline, after we have swapped
117 the new stack borders into the task structure
119 Disable();
120 SwapTaskStackLimits(&SPLower, &SPUpper);
122 BOOL success = swapcontext(&ucx_return, &ucx) != -1;
124 SwapTaskStackLimits(&SPLower, &SPUpper);
125 Enable();
127 return success;
130 /**************************************************************************
132 NAME */
133 LONG AROS_SLIB_ENTRY(RunProcess,Dos) (
135 /* SYNOPSIS */
136 struct Process * proc,
137 struct StackSwapStruct * sss,
138 STRPTR argptr,
139 ULONG argsize,
140 LONG_FUNC entry,
141 struct DosLibrary * DOSBase)
143 /* FUNCTION
144 Sets the stack as specified and calls the routine with the given
145 arguments.
147 INPUTS
148 proc - Process context
149 sss - New Stack
150 argptr - Pointer to argument string
151 argsize - Size of the argument string
152 entry - The entry point of the function
153 DOSBase - Pointer to dos.library structure
155 RESULT
156 The return value of (*entry)();
158 NOTES
160 EXAMPLE
162 BUGS
164 SEE ALSO
166 INTERNALS
168 **************************************************************************/
170 ULONG ret;
171 APTR oldReturnAddr = proc->pr_ReturnAddr; /* might be changed by CallEntry */
172 IPTR args[] =
174 (IPTR) &ret,
175 (IPTR) &proc->pr_ReturnAddr,
176 (IPTR) sss,
177 (IPTR) argptr,
178 argsize == -1 ? strlen(argptr) : argsize, /* Compute argsize automatically */
179 (IPTR) entry
184 int test;
185 D(bug("before callwithstack; org context: test = 0x%x\n", &test));
189 /* Call the function with the new stack */
190 CallWithStack(
191 CallEntry,
192 (void *) sss->stk_Lower,
193 (size_t) sss->stk_Upper - (size_t) sss->stk_Lower,
195 args);
199 int test;
200 D(bug("after callwithstack; org context: test = 0x%x\n", &test));
204 proc->pr_ReturnAddr = oldReturnAddr;
206 return ret;