improved and documented new stack-registration trampoline
svn: r10677
This commit is contained in:
parent
c127e5fdb7
commit
d406fb6dcf
|
@ -688,7 +688,7 @@ Registers an extension's global variable that can contain Scheme
|
||||||
|
|
||||||
@function[(int scheme_main_setup
|
@function[(int scheme_main_setup
|
||||||
[int no_auto_statics]
|
[int no_auto_statics]
|
||||||
[Scheme_Main main]
|
[Scheme_Env_Main main]
|
||||||
[int argc]
|
[int argc]
|
||||||
[char** argv])]{
|
[char** argv])]{
|
||||||
|
|
||||||
|
@ -697,10 +697,10 @@ calling @cpp{scheme_basic_env}, and then calls @var{main} with the
|
||||||
namespace, @var{argc}, and @var{argv}. (The @var{argc} and @var{argv}
|
namespace, @var{argc}, and @var{argv}. (The @var{argc} and @var{argv}
|
||||||
are just passed on to @var{main}, and are not inspected in any way.)
|
are just passed on to @var{main}, and are not inspected in any way.)
|
||||||
|
|
||||||
The @cpp{Scheme_Main} type is defined as follows:
|
The @cpp{Scheme_Env_Main} type is defined as follows:
|
||||||
|
|
||||||
@verbatim[#:indent 4]{
|
@verbatim[#:indent 4]{
|
||||||
typedef int (*Scheme_Main)(Scheme_Env *env,
|
typedef int (*Scheme_Env_Main)(Scheme_Env *env,
|
||||||
int argc, char **argv);
|
int argc, char **argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,6 +711,24 @@ explicitly registered with the garbage collector; see
|
||||||
@secref["im:memoryalloc"] for more information.}
|
@secref["im:memoryalloc"] for more information.}
|
||||||
|
|
||||||
|
|
||||||
|
@function[(int scheme_main_stack_setup
|
||||||
|
[int no_auto_statics]
|
||||||
|
[Scheme_Nested_Main main]
|
||||||
|
[void* data])]{
|
||||||
|
|
||||||
|
A more primitive variant of @cpp{scheme_main_setup} that initializes
|
||||||
|
the GC stack base but does not create the initial namespace (so an
|
||||||
|
embedding application can perform other operations that involve
|
||||||
|
garbage-collected data before creating a namespace).
|
||||||
|
|
||||||
|
The @var{data} argument is passed through to @var{main}, where the
|
||||||
|
@cpp{Scheme_Nested_Main} type is defined as follows:
|
||||||
|
|
||||||
|
@verbatim[#:indent 4]{
|
||||||
|
typedef int (*Scheme_Nested_Main)(void *data);
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
@function[(void scheme_set_stack_base
|
@function[(void scheme_set_stack_base
|
||||||
[void* stack_addr]
|
[void* stack_addr]
|
||||||
[int no_auto_statics])]{
|
[int no_auto_statics])]{
|
||||||
|
@ -739,7 +757,7 @@ must be the beginning or end of a local-frame registration. Worse, in
|
||||||
CGC or 3m, if @cpp{real_main} is declared @cpp{static}, the compiler
|
CGC or 3m, if @cpp{real_main} is declared @cpp{static}, the compiler
|
||||||
may inline it and place variables containing collectable values deeper
|
may inline it and place variables containing collectable values deeper
|
||||||
in the stack than @cpp{dummy}. To avoid these problems, use
|
in the stack than @cpp{dummy}. To avoid these problems, use
|
||||||
@cpp{scheme_main_setup}, instead.}
|
@cpp{scheme_main_setup} or @cpp{scheme_main_stack_setup}, instead.}
|
||||||
|
|
||||||
@function[(void scheme_set_stack_bounds
|
@function[(void scheme_set_stack_bounds
|
||||||
[void* stack_addr]
|
[void* stack_addr]
|
||||||
|
|
|
@ -296,13 +296,16 @@ To embed PLT Scheme CGC in a program, follow these steps:
|
||||||
installing from source also places this file in the installation's
|
installing from source also places this file in the installation's
|
||||||
@filepath{include} directory.}
|
@filepath{include} directory.}
|
||||||
|
|
||||||
@item{Start your main program through the @cpp{scheme_main_setup}
|
@item{Start your main program through the @cpp{scheme_main_setup} (or
|
||||||
trampoline, and put all uses of MzScheme functions inside the
|
@cpp{scheme_main_stack_setup}) trampoline, and put all uses of
|
||||||
function passed to @cpp{scheme_main_setup}. The @cpp{scheme_main_setup}
|
MzScheme functions inside the function passed to
|
||||||
function registers the current C stack location with the memory
|
@cpp{scheme_main_setup}. The @cpp{scheme_main_setup} function
|
||||||
manager. It also creates the initial namespace @cpp{Scheme_Env*} by
|
registers the current C stack location with the memory manager. It
|
||||||
calling @cppi{scheme_basic_env} and passing the result to the
|
also creates the initial namespace @cpp{Scheme_Env*} by calling
|
||||||
function provided to @cpp{scheme_main_setup}.}
|
@cppi{scheme_basic_env} and passing the result to the function
|
||||||
|
provided to @cpp{scheme_main_setup}. (The
|
||||||
|
@cpp{scheme_main_stack_setup} trampoline registers the C stack with
|
||||||
|
the memory manager without creating a namespace.)}
|
||||||
|
|
||||||
@item{Configure the namespace by adding module declarations. The
|
@item{Configure the namespace by adding module declarations. The
|
||||||
initial namespace contains declarations only for a few primitive
|
initial namespace contains declarations only for a few primitive
|
||||||
|
|
|
@ -252,7 +252,7 @@ int actual_main(int argc, char **argv)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int main_after_stack(void *data, int argc, char *argv[])
|
static int main_after_stack(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int rval;
|
int rval;
|
||||||
|
|
||||||
|
@ -299,9 +299,24 @@ static int main_after_stack(void *data, int argc, char *argv[])
|
||||||
/* Just jumps to generic main. */
|
/* Just jumps to generic main. */
|
||||||
|
|
||||||
#ifndef wx_msw
|
#ifndef wx_msw
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
} Main_Args;
|
||||||
|
|
||||||
|
static int call_main_after_stack(void *data)
|
||||||
|
{
|
||||||
|
Main_Args *ma = (Main_Args *)data;
|
||||||
|
return main_after_stack(ma->argc, ma->argv);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
return scheme_main_stack_setup(1, main_after_stack, NULL, argc, argv);
|
Main_Args ma;
|
||||||
|
ma.argc = argc;
|
||||||
|
ma.argv = argv;
|
||||||
|
return scheme_main_stack_setup(1, call_main_after_stack, &ma);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -517,22 +532,19 @@ typedef struct {
|
||||||
int wm_is_mred;
|
int wm_is_mred;
|
||||||
HINSTANCE hInstance;
|
HINSTANCE hInstance;
|
||||||
HINSTANCE hPrevInstance;
|
HINSTANCE hPrevInstance;
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
int nCmdShow;
|
int nCmdShow;
|
||||||
} WinMain_Args;
|
} WinMain_Args;
|
||||||
|
|
||||||
static int call_main_after_stack(int argc, char *argv[])
|
static int WinMain_after_stack(void *_wma)
|
||||||
{
|
|
||||||
return main_after_stack(NULL, argc, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int WinMain_after_stack(void *_wma, int argc, char **argv)
|
|
||||||
{
|
{
|
||||||
WinMain_Args *wma = (WinMain_Args *)_wma;
|
WinMain_Args *wma = (WinMain_Args *)_wma;
|
||||||
|
|
||||||
return wxWinMain(wma->wm_is_mred, wma->hInstance, wma->hPrevInstance,
|
return wxWinMain(wma->wm_is_mred, wma->hInstance, wma->hPrevInstance,
|
||||||
argc, argv,
|
wma->argc, wma->argv,
|
||||||
wma->nCmdShow,
|
wma->nCmdShow,
|
||||||
call_main_after_stack);
|
main_after_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
int APIENTRY WinMain_dlls_ready(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR ignored, int nCmdShow)
|
int APIENTRY WinMain_dlls_ready(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR ignored, int nCmdShow)
|
||||||
|
@ -628,9 +640,11 @@ int APIENTRY WinMain_dlls_ready(HINSTANCE hInstance, HINSTANCE hPrevInstance, LP
|
||||||
wma.wm_is_mred = wm_is_mred;
|
wma.wm_is_mred = wm_is_mred;
|
||||||
wma.hInstance = hInstance;
|
wma.hInstance = hInstance;
|
||||||
wma.hPrevInstance = hPrevInstance;
|
wma.hPrevInstance = hPrevInstance;
|
||||||
|
wma.argc = argc;
|
||||||
|
wma.argv = argv;
|
||||||
wma.nCmdShow = nCmdShow;
|
wma.nCmdShow = nCmdShow;
|
||||||
|
|
||||||
return scheme_main_stack_setup(1, WinMain_after_stack, &wma, argc, argv);
|
return scheme_main_stack_setup(1, WinMain_after_stack, &wma);
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef MZ_PRECISE_GC
|
# ifdef MZ_PRECISE_GC
|
||||||
|
|
|
@ -1697,12 +1697,12 @@ MZ_EXTERN void scheme_set_stack_base(void *base, int no_auto_statics);
|
||||||
MZ_EXTERN void scheme_set_stack_bounds(void *base, void *deepest, int no_auto_statics);
|
MZ_EXTERN void scheme_set_stack_bounds(void *base, void *deepest, int no_auto_statics);
|
||||||
|
|
||||||
/* Stack-preparation start-up: */
|
/* Stack-preparation start-up: */
|
||||||
typedef int (*Scheme_Startup_Main)(void *data, int argc, char **argv);
|
typedef int (*Scheme_Nested_Main)(void *data);
|
||||||
MZ_EXTERN int scheme_main_stack_setup(int no_auto_statics, Scheme_Startup_Main _main, void *data, int argc, char **argv);
|
MZ_EXTERN int scheme_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, void *data);
|
||||||
|
|
||||||
/* More automatic start-up: */
|
/* More automatic start-up: */
|
||||||
typedef int (*Scheme_Main)(Scheme_Env *env, int argc, char **argv);
|
typedef int (*Scheme_Env_Main)(Scheme_Env *env, int argc, char **argv);
|
||||||
MZ_EXTERN int scheme_main_setup(int no_auto_statics, Scheme_Main _main, int argc, char **argv);
|
MZ_EXTERN int scheme_main_setup(int no_auto_statics, Scheme_Env_Main _main, int argc, char **argv);
|
||||||
|
|
||||||
|
|
||||||
MZ_EXTERN void scheme_register_static(void *ptr, long size);
|
MZ_EXTERN void scheme_register_static(void *ptr, long size);
|
||||||
|
|
|
@ -213,7 +213,7 @@ int actual_main(int argc, char *argv[]);
|
||||||
/* Prepare for delayload, then call main_after_dlls */
|
/* Prepare for delayload, then call main_after_dlls */
|
||||||
|
|
||||||
static int main_after_dlls(int argc, MAIN_char **MAIN_argv);
|
static int main_after_dlls(int argc, MAIN_char **MAIN_argv);
|
||||||
static int main_after_stack(void *data, int argc, MAIN_char **MAIN_argv);
|
static int main_after_stack(void *data);
|
||||||
|
|
||||||
# ifdef MZ_PRECISE_GC
|
# ifdef MZ_PRECISE_GC
|
||||||
START_XFORM_SKIP;
|
START_XFORM_SKIP;
|
||||||
|
@ -240,23 +240,34 @@ END_XFORM_SKIP;
|
||||||
/************************ main_after_dlls **************************/
|
/************************ main_after_dlls **************************/
|
||||||
/* Prep stack for GC, then call main_after_stack (indirectly) */
|
/* Prep stack for GC, then call main_after_stack (indirectly) */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int argc;
|
||||||
|
MAIN_char **argv;
|
||||||
|
} Main_Args;
|
||||||
|
|
||||||
static int main_after_dlls(int argc, MAIN_char **argv)
|
static int main_after_dlls(int argc, MAIN_char **argv)
|
||||||
{
|
{
|
||||||
return scheme_main_stack_setup(1,
|
Main_Args ma;
|
||||||
(Scheme_Startup_Main)main_after_stack, NULL,
|
ma.argc = argc;
|
||||||
argc, (char **)argv);
|
ma.argv = argv;
|
||||||
|
return scheme_main_stack_setup(1, main_after_stack, &ma);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************ main_after_stack *************************/
|
/************************ main_after_stack *************************/
|
||||||
/* Phase 1 setup, then call actual_main (indirectly) */
|
/* Phase 1 setup, then call actual_main (indirectly) */
|
||||||
|
|
||||||
static int main_after_stack(void *data, int argc, MAIN_char **MAIN_argv)
|
static int main_after_stack(void *data)
|
||||||
{
|
{
|
||||||
int rval;
|
int rval;
|
||||||
|
int argc;
|
||||||
|
MAIN_char **MAIN_argv;
|
||||||
#ifdef WINDOWS_UNICODE_MAIN
|
#ifdef WINDOWS_UNICODE_MAIN
|
||||||
char **argv;
|
char **argv;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
argc = ((Main_Args *)data)->argc;
|
||||||
|
MAIN_argv = ((Main_Args *)data)->argv;
|
||||||
|
|
||||||
#if defined(OSKIT) && !defined(OSKIT_TEST) && !KNIT
|
#if defined(OSKIT) && !defined(OSKIT_TEST) && !KNIT
|
||||||
oskit_prepare(&argc, &argv);
|
oskit_prepare(&argc, &argv);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -89,30 +89,36 @@ void scheme_set_stack_base(void *base, int no_auto_statics)
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Scheme_Main _main;
|
Scheme_Env_Main _main;
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
} Scheme_Main_Data;
|
} Scheme_Main_Data;
|
||||||
|
|
||||||
static int call_with_basic(void *data, int argc, char **argv)
|
static int call_with_basic(void *data)
|
||||||
{
|
{
|
||||||
Scheme_Main _main = ((Scheme_Main_Data *)data)->_main;
|
Scheme_Main_Data *ma = (Scheme_Main_Data *)data;
|
||||||
return _main(scheme_basic_env(), argc, argv);
|
Scheme_Env_Main _main = ma->_main;
|
||||||
|
|
||||||
|
return _main(scheme_basic_env(), ma->argc, ma->argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
int scheme_main_setup(int no_auto_statics, Scheme_Main _main, int argc, char **argv)
|
int scheme_main_setup(int no_auto_statics, Scheme_Env_Main _main, int argc, char **argv)
|
||||||
{
|
{
|
||||||
Scheme_Main_Data d;
|
Scheme_Main_Data d;
|
||||||
d._main = _main;
|
d._main = _main;
|
||||||
return scheme_main_stack_setup(no_auto_statics, call_with_basic, &d, argc, argv);
|
d.argc = argc;
|
||||||
|
d.argv = argv;
|
||||||
|
return scheme_main_stack_setup(no_auto_statics, call_with_basic, &d);
|
||||||
}
|
}
|
||||||
|
|
||||||
int scheme_main_stack_setup(int no_auto_statics, Scheme_Startup_Main _main, void *data, int argc, char **argv)
|
int scheme_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, void *data)
|
||||||
{
|
{
|
||||||
void *stack_start;
|
void *stack_start;
|
||||||
int volatile return_code;
|
int volatile return_code;
|
||||||
|
|
||||||
scheme_set_stack_base(PROMPT_STACK(stack_start), no_auto_statics);
|
scheme_set_stack_base(PROMPT_STACK(stack_start), no_auto_statics);
|
||||||
|
|
||||||
return_code = _main(data, argc, argv);
|
return_code = _main(data);
|
||||||
|
|
||||||
#ifdef MZ_PRECISE_GC
|
#ifdef MZ_PRECISE_GC
|
||||||
/* Trick xform conversion to keep start_addr: */
|
/* Trick xform conversion to keep start_addr: */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user