[comp.sys.amiga.misc] Multitasking Definitions

mwm@raven.relay.pa.dec.com (Mike (My Watch Has Windows) Meyer) (01/21/91)

In article <15750@sdcc6.ucsd.edu> djohnson@beowulf.ucsd.edu (Darin Johnson) writes:
   In article <42149@nigel.ee.udel.edu> new@ee.udel.edu (Darren New) writes:
   >Please tell me the difference between coroutines and lightweight
   >processes.  I always thought that lightweight processes were two
   >'tasks' (i.e., independant program counters) sharing the same address
   >space.

   Lightweight processes (LWP) and co-routines (CR) have much in common, 
   and some people blur the definition.  Usually however, LWP's have the
   ability to context switch anywhere, like any process.  CR's need only
   change context at IO, semaphores, and other special calls.  CR's are
   a language construct, whereas LWP's are an OS construct.  CR's require
   much less OS and machine support, but require more compiler support
   (co-routines share the same stack, global vars, etc).

That pretty much sums it up, but I'd have put it a different way (one
which I think highlights the critical differences): LWPs are scheduled
by an external entity as a set of independent threads of control; CRs
are a single thread that is passed between the CRs, with each CR
deciding when to pass it to another CR, and which one gets it, and
taking responsibility for saving whatever state it needs to restart.

   Actually, to avoid confusion, compiler support is not needed.  CR's can
   be done in assembler without much fuss - device drivers often do this
   (usually when LWP's are unavailable).

Further, if you're willing to do the appropriate magic, you can get
LWPs without OS support specifically for them; but it's a lot of fuss.

	<mike
--
Here's a song about absolutely nothing.			Mike Meyer
It's not about me, not about anyone else,		mwm@pa.dec.com
Not about love, not about being young.			decwrl!mwm
Not about anything else, either.

mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) (01/24/91)

In article <672@tnc.UUCP> m0154@tnc.UUCP (GUY GARNETT) writes:
   This is my understanding of the "threads" or "lightweight processes"
   issue; feel free to correct me if I am not up to date on the
   terminology.

   "threads", or "lightweight processes" are separate execution traces
   which share the address spaces with one or more other processes,
   regardless of the other processes weight.  They were designed to allow
   many of the simpler multitasking jobs (like re-drawing the screen or
   recalculating the spreadsheet) to be done with lower overhead.  They
   are implemented in OS/2 and perhaps the Mach kernal.

The definition is right. The reason for creation (at least in the Unix
world) is wrong. There, they were built because Unix didn't have a way
off sharing data between distinct proceses (code has been shared
between processes running the same program for quite a while now).

   "coroutines" are the individual processes in a cooperatinve
   multitasking environment.

That's not the definition as I learned it. Coroutines are a
programming technic, wherein each coroutine calls the others as
subroutines. Instead of going to that subroutine and returning, it
goes to that subroutine, which eventually calls another coroutine.
The next time a coroutine is invoked after calling a corouinte, it
sees that coroutine returning. Unlike cooperative multitasking, all
coroutine calls are known at link time. Also, each coroutine specifies
which task starts next; this isn't left up to a scheduler somewhere.

   As I understand it, the Amiga does not have "threads" or "lightweight
   processes".

It depends on how you define the phrase :-). If you define it as a
task with low-context-switch overhead between another task, then all
Amiga tasks are lightweight.

   Although all of the tasks and processes on the Amiga share an address
   space, it is not intended that there be multiple execution traces
   through the same code and data (with the well-defined exception of
   certian operating system code).  You *CAN* do it, but you do not get
   the same benefits that threads get - the operating system overhead is
   the same, and writing code to work this way adds its own overhead.

There is a CBM-supported way of creating such tasks. This looks a lot
like thread creation on OSF. In fact, doing a Posix-compliant threads
library for AmigaDOS shouldn't be to hard.

	<mike
--
Cats will be cats and cats will be cool			Mike Meyer
Cats can be callous and cats can be cruel		mwm@pa.dec.com
Cats will be cats, remember this words!			decwrl!mwm
Cats will be cats and cats eat birds.

peter@sugar.hackercorp.com (Peter da Silva) (01/28/91)

In article <MWM.91Jan21105153@raven.relay.pa.dec.com> mwm@raven.relay.pa.dec.com (Mike (My Watch Has Windows) Meyer) writes:
> [CRs take] responsibility for saving whatever state it needs to restart.

What state is this? A coroutine's state is just its stack, and that's saved
by the co-call.

> Further, if you're willing to do the appropriate magic, you can get
> LWPs without OS support specifically for them; but it's a lot of fuss.

All you need is the ability to set up a stack context, and switch to another
stack. Then add a round-robin scheduler. It's not a *lot* of fuss but it does
tend to be machine, compiler, and even compiler revision dependent.
-- 
Peter da Silva.   `-_-'
<peter@sugar.hackercorp.com>.

mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) (01/29/91)

In article <7641@sugar.hackercorp.com> peter@sugar.hackercorp.com (Peter da Silva) writes:

   In article <MWM.91Jan21105153@raven.relay.pa.dec.com> mwm@raven.relay.pa.dec.com (Mike (My Watch Has Windows) Meyer) writes:
   > [CRs take] responsibility for saving whatever state it needs to restart.

   What state is this? A coroutine's state is just its stack, and that's saved
   by the co-call.

Yes, there's very little state. But it's saved by the co-call, which
is part of your program. You deleted the comparison to LWPs, where the
state is saved by something outside of your program.

   > Further, if you're willing to do the appropriate magic, you can get
   > LWPs without OS support specifically for them; but it's a lot of fuss.

   All you need is the ability to set up a stack context, and switch to another
   stack. Then add a round-robin scheduler. It's not a *lot* of fuss but it
   does tend to be machine, compiler, and even compiler revision dependent.

Ok, so it depends on what you consider a "lot". As an exercise,
implementing co-routines isn't a lot of fuss. As part of another
project where it's a distraction from solving the problem, it can be.


	<mike
--
And then up spoke his own dear wife,			Mike Meyer
Never heard to speak so free.				mwm@pa.dec.com
"I'd rather a kiss from dead Matty's lips,		decwrl!mwm
Than you or your finery."

peter@sugar.hackercorp.com (Peter da Silva) (02/05/91)

In article <MWM.91Jan28115114@raven.pa.dec.com> mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) writes:
> In article <7641@sugar.hackercorp.com> peter@sugar.hackercorp.com (Peter da Silva) writes:
>    What state is this? A coroutine's state is just its stack, and that's saved
>    by the co-call.

> Yes, there's very little state. But it's saved by the co-call, which
> is part of your program.

Not at all, it might be a system call. In fact, in some realtime execs
it *is* a system call, the core of the scheduler, and LWPs are built on
top of co-call. It gives you more control of the task in a hard real-time
situation.

> You deleted the comparison to LWPs, where the
> state is saved by something outside of your program.

And, again, LWPs are implemented in many ways. I've implemented LWPs on
top of coroutines to get a multithreaded Forth system running under
RSX-11 and CP/M-80. It ran fine on the 8080, though when Karl added a
clock interrupt and made the threads run pre-emptively we had to put
a semaphore around all the BDOS and BIOS calls.

> Ok, so it depends on what you consider a "lot". As an exercise,
> implementing co-routines isn't a lot of fuss. As part of another
> project where it's a distraction from solving the problem, it can be.

True, but that's got nothing to do with whether or not there's any magic
difference between LWPs and coroutines. There isn't. LWPs inherently
have little more state than coroutines. The only difference is the
existence of a routine to handle the scheduling... instead of
"co-call(routine)" it's "co_call(self->next)".
-- 
Peter da Silva.   `-_-'
<peter@sugar.hackercorp.com>.