$ type coroutines.c /* Coroutines */ #include struct coroutine { jmp_buf *calling; jmp_buf *env; }; #if 0 int start_coroutine (struct coroutine *cr, int (*f) (void *p, struct coroutine *cr), void *p, int *stack) { int x, y; struct coroutine calling; x = setjmp (*(cr->calling)); if (x == 0) { calling.calling = cr->env; calling.env = cr->calling; /* _SP = stack; */ y = (*f) (p, &calling); } else return x; } #endif int call_coroutine (struct coroutine *cr, int entree) { int x; x = setjmp (*(cr->calling)); if (x == 0) { my_longjmp (*(cr->env), entree); printf ("Error calling coroutine\n"); } else return x; } int coroutine1 (char *p, struct coroutine *calling) { int x; printf ("Lancement coroutine avec parametre <%s>\n", p); x = call_coroutine (calling, (int)"1er parametre coroutine->appelant"); printf ("Appelant retourne <%s> la 1ere fois\n", x); x = call_coroutine (calling, (int)"2eme parametre coroutine->appelant"); printf ("Appelant retourne <%s> la 2eme fois\n", x); x = call_coroutine (calling, (int)"3eme parametre coroutine->appelant"); } test_coroutine () { struct coroutine cr; jmp_buf calling, env; #define STACK_SIZE 1000 int stack[STACK_SIZE]; int x; cr.calling = &calling; cr.env = &env; x = start_coroutine (&cr, coroutine1, (int)"Parametre lancement", stack + STACK_SIZE); printf ("Lancement retourne <%s>\n", x); x = call_coroutine (&cr, (int)"1er appel"); printf ("1er appel retourne <%s>\n", x); x = call_coroutine (&cr, (int)"2eme appel"); printf ("2eme appel retourne <%s>\n", x); } main () { test_coroutine (); } $ type start_coroutine.mar .entry start_coroutine, ^m<> subl2 #20, sp nop pushl #8 calls #1, MALLOC movl r0, -16(fp) moval @4(ap), r0 moval @0(r0), r0 nop pushal (r0) calls #1, SETJMP movl r0, -8(fp) tstl -8(fp) bneq sym.1 movl 4(ap), r0 movl 4(r0), @-16(fp) movl -16(fp), r1 moval @4(ap), r0 movl (r0), 4(r1) movl 16(ap), sp nop pushl -16(fp) nop pushl 12(ap) moval @8(ap), r0 calls #2, (r0) movl r0, -12(fp) brb sym.2 tstl r0 nop sym.1: movl -8(fp), r0 ret sym.2: ret .end $ cc /debug /noopt coroutines $ macro start_coroutine $ link /debug coroutines, start_coroutine %LINK-W-NUDFSYMS, 1 undefined symbol: %LINK-I-UDFSYM, MY_LONGJMP %LINK-W-USEUNDEF, undefined symbol MY_LONGJMP referenced in psect $CODE offset %X00000031 in module COROUTINES file VENUS$DUA1:[JACQUES.D1.COROUTINES]COROUTINES.O BJ;9 $ dir *.mar Directory VENUS$DUA1:[JACQUES.D1.COROUTINES] MY_LONGJMP.MAR;7 MY_LONGJMP1.MAR;1 MY_LONGJMP3.MAR;1 START_COROUTINE.MAR;14 START_COROUTINE1.MAR;1 START_COROUTINE_010894.MAR;1 _LONGJMP.MAR;2 Total of 7 files. $ macro my_longjmp $ type my_longjmp.mar .entry my_longjmp, ^m movl 4(ap), r0 movl (r0)+, r2 movq (r0)+, r2 movq (r0)+, r4 movq (r0)+, r6 movq (r0)+, r8 movq (r0)+, r10 movl 4(r0), fp pushl 8(r0) pushl 12(r0) pushl 8(ap) movl (r0), ap popl r0 popl r1 popl sp jmp (r1) .end $ link /debug coroutines, start_coroutine, my_longjmp $ run /nodeb coroutines Lancement coroutine avec parametre Lancement retourne <1er parametre coroutine->appelant> Appelant retourne <1er appel> la 1ere fois 1er appel retourne <2eme parametre coroutine->appelant> Appelant retourne <2eme appel> la 2eme fois 2eme appel retourne <3eme parametre coroutine->appelant> $