Managing Several Coroutines

This version is to overcome one of the loose ends in this project. The first real application of coroutines that I want to demonstrate requires two coroutine connections. This variation supports as many as memory allows.

I considered using a C++ class, instances of which provide a coroutine connection. I had forgotten how much I dislike C++. C itself lacks closure logic and since Apple has discontinued support of gcc I fall back on the ‘C way of doing things’ and add an opaque argument to the PutGet function which locates where the stack-top of the partner lives. I consider this ugly on esthetic grounds. It is, however, a small modification to the one connection version.

The header file
The new PutGet routine takes a new opaque parameter of type sp *. Compiling thus:

clang PutGetD.c -O3 -S
produces this which reveals that the 2nd argument arrives in %rsi.

The new scheme amounts to each side of the routine passing around the stack-top handle of its partner as a hot-potato. (by which I mean that every stack frame of either side carries the address of where the stack-top of the other side is.) The initiator of the coroutine provides an 8 byte cell for an opaque value that is in fact the stack pointer of the side that is not running. Here is the slightly modified technology. The new interface to this is that a 2nd argument to both begin and PutGet is the address of the stack-top, which was abstracted in the one connection version.

The first argument to begin is passed on as the first argument to startR. Its meaning is up to the technology user. The second argument to begin is the address of a cell that holds the stack-top of the coroutine that is not running.

Demo

The same fringe problem is perhaps the standard coroutine demo problem. In this version we have an array A of 3∙220 32 bit integer pairs. Note that indexes into this array are non-negative. A tree is either a negative 32 bit integer or an array index of a pair of trees. The routine bt in this file builds a tree. We call it three times to build three trees, X, Y and Z, each with fringe from array fr. But Z’s fringe has been slightly modified. Routine scan there recursively scans a tree and calls PutGet for each leaf. That two ‘threads’ in that routine will traverse two trees in order to compare the fringe of one with the other.

We compile and run thus:

clang main.c PutGet.s -O3 -Wmost
./a.out
That gives me:
Trees at 000FFFFE, 001FFFFD and 002FFFFC
Whee!
Different at E3D70
which is about what I hoped for.

Linux

In Linux:
gcc mainLin.c PutGetLin.s -O3 -Wall -std=c99
./a.out
works for me.

Loose Ends

Reclaim the extra stack when done.

Perhaps first argument to PutGetR should not appear as begin’s value.

No stack overflow protection.

No test for malloc failure.