Remove mps_tramp, deprecated since release 1.111.0.

This commit is contained in:
Gareth Rees 2020-08-31 21:33:17 +01:00
parent 93ad2ed32a
commit 2e9c91a2bd
18 changed files with 80 additions and 213 deletions

View file

@ -60,9 +60,8 @@ static mps_addr_t make(void)
}
static void *test(void *arg, size_t s)
static void test(mps_arena_t arena)
{
mps_arena_t arena;
mps_fmt_t format;
mps_chain_t chain;
mps_root_t exactRoot, ambigRoot;
@ -71,9 +70,6 @@ static void *test(void *arg, size_t s)
mps_ap_t busy_ap;
mps_addr_t busy_init;
arena = (mps_arena_t)arg;
(void)s; /* unused */
die(EnsureHeaderFormat(&format, arena), "make header format");
die(mps_chain_create(&chain, arena, 1, testChain), "chain_create");
die(mps_pool_create(&pool, arena, mps_class_ams(), format, chain,
@ -148,8 +144,6 @@ static void *test(void *arg, size_t s)
mps_chain_destroy(chain);
mps_fmt_destroy(format);
mps_arena_release(arena);
return NULL;
}
@ -157,7 +151,6 @@ int main(int argc, char *argv[])
{
mps_arena_t arena;
mps_thr_t thread;
void *r;
testlib_init(argc, argv);
@ -167,7 +160,7 @@ int main(int argc, char *argv[])
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create");
} MPS_ARGS_END(args);
die(mps_thread_reg(&thread, arena), "thread_reg");
mps_tramp(&r, test, arena, 0);
test(arena);
mps_thread_dereg(thread);
mps_arena_destroy(arena);

View file

@ -277,7 +277,7 @@ static void test(mps_arena_t arena,
/* setup -- set up pools for the test
*
* v serves two purposes:
* guff serves two purposes:
* - a pseudo stack base for the stack root.
* - pointer to a guff structure, which packages some values needed
* (arena and thr mostly)
@ -288,9 +288,9 @@ struct guff_s {
mps_thr_t thr;
};
static void *setup(void *v, size_t s)
ATTRIBUTE_NOINLINE
static void setup(struct guff_s *guff)
{
struct guff_s *guff;
mps_arena_t arena;
mps_pool_t leafpool;
mps_pool_t tablepool;
@ -300,12 +300,10 @@ static void *setup(void *v, size_t s)
mps_root_t stack;
mps_thr_t thr;
guff = (struct guff_s *)v;
(void)s;
arena = guff->arena;
thr = guff->thr;
die(mps_root_create_thread(&stack, arena, thr, v),
die(mps_root_create_thread(&stack, arena, thr, guff),
"Root Create\n");
die(mps_fmt_create_A(&dylanfmt, arena, dylan_fmt_A()),
"Format Create\n");
@ -339,8 +337,6 @@ static void *setup(void *v, size_t s)
mps_fmt_destroy(dylanweakfmt);
mps_fmt_destroy(dylanfmt);
mps_root_destroy(stack);
return NULL;
}
@ -349,7 +345,6 @@ int main(int argc, char *argv[])
struct guff_s guff;
mps_arena_t arena;
mps_thr_t thread;
void *r;
testlib_init(argc, argv);
@ -362,7 +357,7 @@ int main(int argc, char *argv[])
die(mps_thread_reg(&thread, arena), "thread_reg");
guff.arena = arena;
guff.thr = thread;
mps_tramp(&r, setup, &guff, 0);
setup(&guff);
mps_thread_dereg(thread);
mps_arena_destroy(arena);

View file

@ -281,7 +281,7 @@ static void test(mps_arena_t arena,
/* setup -- set up pools for the test
*
* v serves two purposes:
* guff serves two purposes:
* - a pseudo stack base for the stack root.
* - pointer to a guff structure, which packages some values needed
* (arena and thr mostly)
@ -292,9 +292,9 @@ struct guff_s {
mps_thr_t thr;
};
static void *setup(void *v, size_t s)
ATTRIBUTE_NOINLINE
static void setup(struct guff_s *guff)
{
struct guff_s *guff;
mps_arena_t arena;
mps_pool_t leafpool;
mps_pool_t tablepool;
@ -304,12 +304,10 @@ static void *setup(void *v, size_t s)
mps_root_t stack;
mps_thr_t thr;
guff = (struct guff_s *)v;
(void)s;
arena = guff->arena;
thr = guff->thr;
die(mps_root_create_thread(&stack, arena, thr, v),
die(mps_root_create_thread(&stack, arena, thr, guff),
"Root Create\n");
die(EnsureHeaderFormat(&dylanfmt, arena), "EnsureHeaderFormat");
die(EnsureHeaderWeakFormat(&dylanweakfmt, arena), "EnsureHeaderWeakFormat");
@ -341,8 +339,6 @@ static void *setup(void *v, size_t s)
mps_fmt_destroy(dylanweakfmt);
mps_fmt_destroy(dylanfmt);
mps_root_destroy(stack);
return NULL;
}
@ -351,7 +347,6 @@ int main(int argc, char *argv[])
struct guff_s guff;
mps_arena_t arena;
mps_thr_t thread;
void *r;
testlib_init(argc, argv);
@ -364,7 +359,7 @@ int main(int argc, char *argv[])
die(mps_thread_reg(&thread, arena), "thread_reg");
guff.arena = arena;
guff.thr = thread;
mps_tramp(&r, setup, &guff, 0);
setup(&guff);
mps_thread_dereg(thread);
mps_arena_destroy(arena);

View file

@ -233,13 +233,13 @@ struct guff_s {
mps_thr_t thr;
};
/* v serves two purposes:
/* guff serves two purposes:
* A pseudo stack base for the stack root.
* Pointer to a guff structure, which packages some values needed
* (arena and thr mostly) */
static void *setup(void *v, size_t s)
ATTRIBUTE_NOINLINE
static void setup(struct guff_s *guff)
{
struct guff_s *guff;
mps_arena_t arena;
mps_pool_t leafpool;
mps_pool_t tablepool;
@ -249,12 +249,10 @@ static void *setup(void *v, size_t s)
mps_root_t stack;
mps_thr_t thr;
guff = (struct guff_s *)v;
(void)s;
arena = guff->arena;
thr = guff->thr;
die(mps_root_create_thread(&stack, arena, thr, v),
die(mps_root_create_thread(&stack, arena, thr, guff),
"Root Create\n");
die(mps_fmt_create_A(&dylanfmt, arena, dylan_fmt_A()),
"Format Create\n");
@ -285,25 +283,22 @@ static void *setup(void *v, size_t s)
mps_fmt_destroy(dylanweakfmt);
mps_fmt_destroy(dylanfmt);
mps_root_destroy(stack);
return NULL;
}
static void *setup_thr(void *v)
{
struct guff_s guff;
mps_arena_t arena = (mps_arena_t)v;
mps_arena_t arena = v;
mps_thr_t thread;
void *r;
die(mps_thread_reg(&thread, arena), "thread_reg");
guff.arena = arena;
guff.thr = thread;
mps_tramp(&r, setup, &guff, 0);
setup(&guff);
mps_thread_dereg(thread);
return r;
return NULL;
}

View file

@ -114,11 +114,10 @@ static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pool,
/* test -- the body of the test */
static void *test(void *arg, size_t s)
static void test(mps_arena_t arena)
{
mps_addr_t busy_init;
mps_ap_t busy_ap;
mps_arena_t arena;
mps_chain_t chain;
mps_fmt_t format;
mps_root_t exactRoot, ambigRoot;
@ -126,9 +125,6 @@ static void *test(void *arg, size_t s)
size_t i;
unsigned long objs;
arena = (mps_arena_t)arg;
(void)s; /* unused */
die(dylan_fmt(&format, arena), "fmt_create");
die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create");
@ -230,15 +226,12 @@ static void *test(void *arg, size_t s)
mps_pool_destroy(pool_g);
mps_chain_destroy(chain);
mps_fmt_destroy(format);
return NULL;
}
int main(int argc, char *argv[])
{
mps_arena_t arena;
mps_thr_t thread;
void *r;
testlib_init(argc, argv);
@ -247,7 +240,7 @@ int main(int argc, char *argv[])
mps_message_type_enable(arena, mps_message_type_gc());
die(mps_arena_commit_limit_set(arena, 2*testArenaSIZE), "set limit");
die(mps_thread_reg(&thread, arena), "thread_reg");
mps_tramp(&r, test, arena, 0);
test(arena);
mps_thread_dereg(thread);
report(arena);
mps_arena_destroy(arena);

View file

@ -133,7 +133,7 @@ static void register_indirect_tree(mps_word_t tree, mps_arena_t arena)
static void *root[rootCOUNT];
static void *test(void *arg, size_t s)
static void test(mps_arena_t arena)
{
mps_ap_t ap;
mps_fmt_t fmt;
@ -141,13 +141,9 @@ static void *test(void *arg, size_t s)
mps_word_t finals;
mps_pool_t amc;
mps_root_t mps_root;
mps_arena_t arena;
mps_message_t message;
size_t i;
arena = (mps_arena_t)arg;
(void)s;
die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create\n");
die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create");
die(mps_pool_create(&amc, arena, mps_class_amc(), fmt, chain),
@ -256,8 +252,6 @@ static void *test(void *arg, size_t s)
mps_pool_destroy(amc);
mps_chain_destroy(chain);
mps_fmt_destroy(fmt);
return NULL;
}
@ -265,14 +259,13 @@ int main(int argc, char *argv[])
{
mps_arena_t arena;
mps_thr_t thread;
void *r;
testlib_init(argc, argv);
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
"arena_create\n");
die(mps_thread_reg(&thread, arena), "thread_reg\n");
mps_tramp(&r, test, arena, 0);
test(arena);
mps_thread_dereg(thread);
mps_arena_destroy(arena);

View file

@ -711,10 +711,7 @@ extern mps_res_t mps_stack_scan_ambig(mps_ss_t, mps_thr_t,
void *, size_t);
/* Protection Trampoline and Thread Registration */
typedef void *(*mps_tramp_t)(void *, size_t);
extern void (mps_tramp)(void **, mps_tramp_t, void *, size_t);
/* Thread Registration */
extern mps_res_t mps_thread_reg(mps_thr_t *, mps_arena_t);
extern void mps_thread_dereg(mps_thr_t);

View file

@ -1630,18 +1630,6 @@ void mps_root_destroy(mps_root_t mps_root)
}
void (mps_tramp)(void **r_o,
void *(*f)(void *p, size_t s),
void *p, size_t s)
{
AVER(r_o != NULL);
AVER(FUNCHECK(f));
/* Can't check p and s as they are interpreted by the client */
*r_o = (*f)(p, s);
}
mps_res_t mps_thread_reg(mps_thr_t *mps_thr_o, mps_arena_t arena)
{
Thread thread;

View file

@ -358,9 +358,8 @@ static void arena_commit_test(mps_arena_t arena)
}
static void *test(void *arg, size_t s)
static void test(mps_arena_t arena)
{
mps_arena_t arena;
mps_fmt_t format;
mps_chain_t chain;
mps_root_t exactAreaRoot, exactTableRoot, ambigAreaRoot, ambigTableRoot,
@ -380,9 +379,6 @@ static void *test(void *arg, size_t s)
size_t rampCount = 0;
mps_res_t res;
arena = (mps_arena_t)arg;
testlib_unused(s);
if (rnd() & 1) {
printf("Using auto_header format.\n");
die(EnsureHeaderFormat(&format, arena), "EnsureHeaderFormat");
@ -573,8 +569,6 @@ static void *test(void *arg, size_t s)
mps_pool_destroy(amcpool);
mps_chain_destroy(chain);
mps_fmt_destroy(format);
return NULL;
}
@ -586,7 +580,6 @@ int main(int argc, char *argv[])
mps_arena_t arena;
mps_thr_t thread;
mps_root_t reg_root;
void *r;
void *marker = ▮
testlib_init(argc, argv);
@ -622,7 +615,7 @@ int main(int argc, char *argv[])
break;
}
mps_tramp(&r, test, arena, 0);
test(arena);
switch (rnd() % 2) {
default:
case 0:

View file

@ -326,15 +326,12 @@ static void validate(void)
}
static void *go(void *p, size_t s)
static void test(void)
{
mps_fmt_t format;
mps_chain_t chain;
mps_addr_t base;
testlib_unused(p);
testlib_unused(s);
die(mps_pool_create_k(&mpool, arena, mps_class_mvff(), mps_args_none),
"pool create");
@ -373,8 +370,6 @@ static void *go(void *p, size_t s)
mps_chain_destroy(chain);
mps_fmt_destroy(format);
mps_arena_release(arena);
return NULL;
}
@ -520,14 +515,11 @@ static void copy(mps_addr_t object, mps_addr_t to)
int main(int argc, char *argv[])
{
void *r;
testlib_init(argc, argv);
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
"mps_arena_create");
mps_tramp(&r, &go, NULL, 0);
test();
mps_arena_destroy(arena);
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);

View file

@ -723,9 +723,8 @@ static mps_addr_t make(void)
/* test -- the actual stress test */
static void *test(void *arg, size_t s)
static void test(mps_arena_t arena)
{
mps_arena_t arena;
mps_fmt_t format;
mps_root_t exactRoot, ambigRoot;
size_t lastStep = 0, i, r;
@ -736,9 +735,6 @@ static void *test(void *arg, size_t s)
mps_chain_t chain;
static mps_gen_param_s genParam = {1024, 0.2};
arena = (mps_arena_t)arg;
(void)s; /* unused */
die(mps_fmt_create_A(&format, arena, dylan_fmt_A()), "fmt_create");
die(mps_chain_create(&chain, arena, 1, &genParam), "chain_create");
@ -825,8 +821,6 @@ static void *test(void *arg, size_t s)
mps_pool_destroy(pool);
mps_chain_destroy(chain);
mps_fmt_destroy(format);
return NULL;
}
@ -834,14 +828,13 @@ int main(int argc, char *argv[])
{
mps_arena_t arena;
mps_thr_t thread;
void *r;
testlib_init(argc, argv);
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
"arena_create");
die(mps_thread_reg(&thread, arena), "thread_reg");
mps_tramp(&r, test, arena, 0);
test(arena);
mps_thread_dereg(thread);
mps_arena_destroy(arena);

View file

@ -40,17 +40,28 @@
/* Function attributes */
/* These are also defined in config.h */
#if defined(MPS_BUILD_GC) || defined(MPS_BUILD_LL)
/* GCC: <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-format-function-attribute>
/* Attribute for functions that take a printf-like format argument, so
* that the compiler can check the format specifiers against the types
* of the arguments.
* GCC: <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-format-function-attribute>
* Clang: <https://clang.llvm.org/docs/AttributeReference.html#format-gnu-format>
*/
#if defined(MPS_BUILD_GC) || defined(MPS_BUILD_LL)
#define ATTRIBUTE_FORMAT(ARGLIST) __attribute__((__format__ ARGLIST))
#else
#define ATTRIBUTE_FORMAT(ARGLIST)
#endif
/* Attribute for functions that must not be inlined.
* GCC: <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noinline-function-attribute>
* MSVC: <https://docs.microsoft.com/en-us/cpp/cpp/noinline>
*/
#if defined(MPS_BUILD_GC) || defined(MPS_BUILD_LL)
#define ATTRIBUTE_NOINLINE __attribute__((__noinline__))
#elif defined(MPS_BUILD_MV)
#define ATTRIBUTE_NOINLINE __declspec(noinline)
#else
#define ATTRIBUTE_NOINLINE
#endif

View file

@ -34,7 +34,7 @@
*
* main() has the list of testscripts.
*
* testscriptA() sets up a new arena and trampolines to testscriptB().
* testscriptA() sets up a new arena and calls testscriptB().
*
* testscriptB() creates pools and objects for this test script.
*
@ -704,21 +704,16 @@ static void testscriptC(mps_arena_t arena, mps_ap_t ap, const char *script)
}
/* testscriptB -- create pools and objects; call testscriptC
*
* Is called via mps_tramp, so matches mps_tramp_t function prototype,
* and use trampDataStruct to pass parameters.
*/
/* testscriptB -- create pools and objects; call testscriptC */
typedef struct trampDataStruct {
typedef struct testDataStruct {
mps_arena_t arena;
mps_thr_t thr;
const char *script;
} trampDataStruct;
} testDataStruct;
static void *testscriptB(void *arg, size_t s)
static void testscriptB(testDataStruct *testData)
{
trampDataStruct trampData;
mps_arena_t arena;
mps_thr_t thr;
const char *script;
@ -731,11 +726,9 @@ static void *testscriptB(void *arg, size_t s)
mps_ap_t ap;
void *stack_starts_here; /* stack scanning starts here */
Insist(s == sizeof(trampDataStruct));
trampData = *(trampDataStruct*)arg;
arena = trampData.arena;
thr = trampData.thr;
script = trampData.script;
arena = testData->arena;
thr = testData->thr;
script = testData->script;
die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create");
die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create");
@ -781,12 +774,10 @@ static void *testscriptB(void *arg, size_t s)
mps_pool_destroy(amc);
mps_chain_destroy(chain);
mps_fmt_destroy(fmt);
return NULL;
}
/* testscriptA -- create arena, thr, and tramp; call testscriptB
/* testscriptA -- create arena and thr; call testscriptB
*/
static void testscriptA(const char *script)
{
@ -794,9 +785,7 @@ static void testscriptA(const char *script)
int si, sb; /* sscanf items, sscanf bytes */
unsigned long arenasize = 0;
mps_thr_t thr;
mps_tramp_t trampFunction;
trampDataStruct trampData;
void *trampResult;
testDataStruct testData;
si = sscanf(script, "Arena(size %lu)%n", &arenasize, &sb);
cdie(si == 1, "bad script command: Arena(size %%lu)");
@ -815,13 +804,11 @@ static void testscriptA(const char *script)
/* thr: used to stop/restart multiple threads */
die(mps_thread_reg(&thr, arena), "thread");
/* tramp: used for protection (barrier hits) */
/* call testscriptB! */
trampFunction = testscriptB;
trampData.arena = arena;
trampData.thr = thr;
trampData.script = script;
mps_tramp(&trampResult, trampFunction, &trampData, sizeof trampData);
testData.arena = arena;
testData.thr = thr;
testData.script = script;
testscriptB(&testData);
mps_thread_dereg(thr);
mps_arena_destroy(arena);

View file

@ -66,7 +66,7 @@
*
* main() has the list of testscripts.
*
* testscriptA() sets up a new arena and trampolines to testscriptB().
* testscriptA() sets up a new arena and calls testscriptB().
*
* testscriptB() creates pools and objects for this test script.
*
@ -283,21 +283,16 @@ static void testscriptC(mps_arena_t arena, const char *script)
}
/* testscriptB -- create pools and objects; call testscriptC
*
* Is called via mps_tramp, so matches mps_tramp_t function prototype,
* and use trampDataStruct to pass parameters.
*/
/* testscriptB -- create pools and objects; call testscriptC */
typedef struct trampDataStruct {
typedef struct testDataStruct {
mps_arena_t arena;
mps_thr_t thr;
const char *script;
} trampDataStruct;
} testDataStruct;
static void *testscriptB(void *arg, size_t s)
static void testscriptB(testDataStruct *testData)
{
trampDataStruct trampData;
mps_arena_t arena;
mps_thr_t thr;
const char *script;
@ -311,11 +306,9 @@ static void *testscriptB(void *arg, size_t s)
int N = myrootCOUNT - 1;
void *stack_starts_here; /* stack scanning starts here */
Insist(s == sizeof(trampDataStruct));
trampData = *(trampDataStruct*)arg;
arena = trampData.arena;
thr = trampData.thr;
script = trampData.script;
arena = testData->arena;
thr = testData->thr;
script = testData->script;
die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create");
die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create");
@ -386,20 +379,16 @@ static void *testscriptB(void *arg, size_t s)
mps_pool_destroy(amc);
mps_chain_destroy(chain);
mps_fmt_destroy(fmt);
return NULL;
}
/* testscriptA -- create arena, thr, and tramp; call testscriptB
/* testscriptA -- create arena and thr; call testscriptB
*/
static void testscriptA(const char *script)
{
mps_arena_t arena;
mps_thr_t thr;
mps_tramp_t trampFunction;
trampDataStruct trampData;
void *trampResult;
testDataStruct testData;
printf("Script: \"%s\"\n Create arena etc.\n", script);
@ -411,13 +400,11 @@ static void testscriptA(const char *script)
/* thr: used to stop/restart multiple threads */
die(mps_thread_reg(&thr, arena), "thread");
/* tramp: used for protection (barrier hits) */
/* call testscriptB! */
trampFunction = testscriptB;
trampData.arena = arena;
trampData.thr = thr;
trampData.script = script;
mps_tramp(&trampResult, trampFunction, &trampData, sizeof trampData);
testData.arena = arena;
testData.thr = thr;
testData.script = script;
testscriptB(&testData);
mps_thread_dereg(thr);
mps_arena_destroy(arena);

View file

@ -61,8 +61,7 @@ because the wrapper will be a root.
_`.req.nofault`: The memory containing objects managed by the pool
must not be protected. The client must be allowed to access these
objects without using the MPS trampoline (the exception mechanism,
q.v.).
objects without hitting an MPS barrier.
Overview

View file

@ -41,6 +41,11 @@ Interface changes
:c:func:`mps_pool_free_size` and :c:func:`mps_pool_total_size`
instead.
#. The deprecated function :c:func:`mps_tramp` has been removed. The
MPS has had no need for a trampoline, and client programs have not
needed to take any special precautions before calling functions in
the MPS, since version 1.111.
#. The keyword argument ``MPS_KEY_SPARE_COMMIT_LIMIT`` to
:c:func:`mps_arena_create_k`, and the functions
:c:func:`mps_arena_spare_commit_limit` and

View file

@ -847,53 +847,6 @@ Deprecated in version 1.111
============ ============== =============
.. c:function:: void mps_tramp(void **r_o, mps_tramp_t f, void *p, size_t s)
.. deprecated::
The MPS trampoline is no longer required on any operating
system supported by the MPS.
Call a function via the MPS trampoline.
``r_o`` points to a location that will store the result of calling
``f``.
``f`` is the function to call.
``p`` and ``s`` are arguments that will be passed to ``f`` each
time it is called. This is intended to make it easy to pass, for
example, an array and its size as parameters.
The MPS relies on :term:`barriers (1)` to protect memory
that is in an inconsistent state. On some operating systems,
barrier hits generate exceptions that have to be caught by a
handler that is on the stack. On these operating systems, any code
that uses memory managed by the MPS must be called from inside
such an exception handler, that is, inside a call to
:c:func:`mps_tramp`.
If you have multiple threads that run code that uses memory
managed by the MPS, each thread must execute such code inside a
call to :c:func:`mps_tramp`.
.. index::
single: trampoline
.. c:type:: void *(*mps_tramp_t)(void *p, size_t s)
.. deprecated::
The MPS trampoline is no longer required on any operating
system supported by the MPS.
The type of a function called by :c:func:`mps_tramp`.
``p`` and ``s`` are the corresponding arguments that were passed
to :c:func:`mps_tramp`.
.. c:function:: void mps_arena_expose(mps_arena_t arena)
.. deprecated::

View file

@ -14,7 +14,6 @@ static void test(void *stack_pointer)
{
mps_arena_t arena;
comment("Entered trampoline");
mmqa_pause(10);
cdie(mps_arena_create(&arena, mps_arena_class_vm(), mmqaArenaSIZE), "create arena");
comment("Created arena");
@ -32,7 +31,6 @@ int main(void)
comment("Started");
mmqa_pause(10);
run_test(test);
comment("Left trampoline");
mmqa_pause(10);
pass();
return 0;