home *** CD-ROM | disk | FTP | other *** search
- .th CR VII 1/4/75
- .sh NAME
- crfork, crexit, crread, crwrite, crexch, crprior \*- coroutine scheme
- .sh SYNOPSIS
- .nf
- .ft B
- int crfork( \fR[\fB stack, nwords \fR]\fB )
- int stack[];
- int nwords;
- .s3
- crexit()
- .s3
- int crread(connector, buffer, nbytes)
- int *connector[2];
- char *buffer;
- int nbytes;
- .s3
- crwrite(connector, buffer, nbytes)
- int *connector[2];
- char *buffer;
- int nbytes;
- .s3
- crexch(conn1, conn2, i)
- int *conn1[2], *conn2[2];
- int i;
- .s3
- #define logical char *
- crprior(p)
- logical p;
- .fi
- .ft R
- .sh DESCRIPTION
- These functions are named by analogy to
- .it "fork, exit, read, write"
- (II).
- They establish and synchronize `coroutines', which
- behave in many respects like a set of processes working
- in the same address space.
- The functions live in
- .it /usr/lib/cr.a.
- .s3
- Coroutines are placed
- on queues to indicate their state of readiness.
- One coroutine is always distinguished as `running'.
- Coroutines that are runnable but not running
- are registered on a `ready queue'.
- The head member of the ready queue is started whenever no other
- coroutine is specifically caused to be running.
- .s3
- Each connector heads two
- queues:
- .it Connector[0]
- is the queue of unsatisfied
- .it crreads
- outstanding on the connector.
- .it Connector[1]
- is the queue of
- .it crwrites.
- All queues must start empty,
- .it i.e.
- with heads set to zero.
- .s3
- .it Crfork
- is normally called with no arguments.
- It
- places the running coroutine at the head of
- the ready queue, creates a new coroutine, and starts the new
- one running.
- .it Crfork
- returns immediately in the new coroutine with value 0,
- and upon restarting of the old
- coroutine with value 1.
- .s3
- .it Crexit
- stops the running coroutine and does not place it in any queue.
- .s3
- .it Crread
- copies characters from the
- .it buffer
- of the
- .it crwrite
- at the head of the
- .it connector's
- write queue to the
- .it buffer
- of
- .it crread.
- If the write queue is empty, copying is delayed and the running
- coroutine is placed on the read queue.
- The number of characters copied is the minimum of
- .it nbytes
- and the number of characters remaining in the write
- .it buffer,
- and is returned as the value of
- .it crread.
- After copying, the location of the write
- .it buffer
- and the corresponding
- .it nbytes
- are updated appropriately.
- If zero characters remain, the coroutine of the
- .it crwrite
- is moved to the head of the ready queue.
- If the write queue remains nonempty,
- the head member of the read queue is moved to
- the head of the ready queue.
- .s3
- .it Crwrite
- queues the running coroutine on the
- .it connector's
- write queue,
- and records the fact that
- .it nbytes
- (zero or more)
- characters in the string
- .it buffer
- are available to
- .it crreads.
- If the read queue is not empty,
- its head member is started running.
- .s3
- .it Crexch
- exchanges the read queues of connectors
- .it conn1
- and
- .it conn2
- if
- \fIi\fR=0; and it exchanges the write queues if
- \fIi\fR=1.
- If a nonempty read queue that had been paired with an empty write queue
- becomes paired with a nonempty write queue,
- .it crexch
- moves
- the head member of that read queue to the head
- of the ready queue.
- .s3
- .it Crprior
- sets a priority on the running coroutine to
- control the queuing of
- .it crreads
- and
- .it crwrites.
- When queued, the running coroutine will take its place before
- coroutines whose priorities exceed
- its own priority and after others.
- Priorities are compared as logical,
- .it i.e.
- unsigned,
- quantities.
- Initially each coroutine's priority is set as large as possible,
- so default queuing is
- .nh
- FIFO.
- .hy
- .s3
- .bd "Storage allocation."
- The old and new coroutine share the same activation record
- in the function that invoked
- .it crfork,
- so only one may return from the invoking function,
- and then only when the other has completed execution in that function.
- .s3
- The activation record for each function
- execution is dynamically allocated rather than stacked;
- a factor of 3 in running time overhead
- can result if function calls are very frequent.
- The overhead may be overcome by
- providing a separate stack for each coroutine and dispensing with
- dynamic allocation.
- The base (lowest) address and size of the
- new coroutine's stack are supplied to
- .it crfork
- as optional arguments
- .it stack
- and
- .it nwords.
- Stacked allocation and dynamic allocation cannot be mixed
- in one run.
- For stacked operation, obtain the coroutine functions from
- .it /usr/lib/scr.a
- instead of
- .it /usr/lib/cr.a.
- .sh FILES
- /usr/lib/cr.a
- .br
- /usr/lib/scr.a
- .sh DIAGNOSTICS
- `rsave doesn't work' \*- an old C compilation
- has called `rsave'.
- It must be recompiled to work
- with the coroutine scheme.
- .sh BUGS
- Under /usr/lib/cr.a
- each function has just 12 words of anonymous
- stack for hard expressions and arguments
- of further calls, regardless of actual need.
- There is no checking for stack overflow.
- .br
- Under /usr/lib/scr.a
- stack overflow checking is not rigorous.
-