[Mono-dev] Mono Continuations and MicroThreads

Tomi Valkeinen tomba at bat.org
Mon Apr 3 17:13:25 EDT 2006


Hello,

This small project started when I stumbled upon a presentation 
(http://www.stackless.com/Members/rmtew/code/PyCon2006-StacklessEvePresentation.zip) 
about EVE online (http://www.eve-online.com/), and read about stackless 
python. I had known about stackless before that but I never really looked 
at what's it about. Well, it looked cool but I don't like python. So the 
next step was clear.

Attached is a small patch to mono runtime that implements continuations 
for amd64 and x86 linux, two C# files that implement basic 
MicroThread-stuff, and some C# test programs. You can also get a full 
package, including patched mono, mcs, stackless python at 
http://batmud.bat.org/~tomba/monoco-20060403-rel.tar.bz2 .

----

First a brief introduction to continuations (my continuations, I guess 
they can be implemented in slightly different ways):

A continuation is an object that can be used to store the current 
execution state and it can then be used to restore the stored state later. 
"Execution state" here means the stack, which includes call stack and 
local variables, and the processor's registers. When the stored state is 
restored the program execution looks like it jumps back to the position 
where the state was saved, with all the local variables restored. A short 
example:

static void Main()
{
     Continuation c = new Continuation();
     c.Mark();
     int foo = 123;
     int val = c.Store(0);
     Console.WriteLine("{0} {1}", val, foo);
     foo = 321;
     if (val < 5)
         c.Resume(val + 1);
}

prints:

0 123
1 123
2 123
3 123
4 123
5 123

You can ignore Mark() for now (it is used to mark the topmost frame to be 
stored). Store(x) stores the current state to the continuation, and 
returns the given integer x. Resume(y) restores the stored state, and 
returns the given integer y. Note that the integer y given to Resume is 
actually returned from the Store() method, because that's where we are 
after the state has been restored.

This was a short and confusing introduction, but you can find more 
information about continuations from the Net.

----

So continuations basically store a piece of stack to its own storage. This 
piece of stack includes the LMF structure saved by the managed-to-native 
wrapper, and that is used to restore the registers. After the stack and 
registers are restored, the instruction pointer is set to just after the 
call-instruction (in the wrapper) to the store function.

I used these continuations to implement (with C#) MicroThreads and a 
scheduler for the MicroThreads, and also semaphores, channels (as in 
stackless python), and a socket class. These can be found in the test 
directory, System.MicroThreads.*.cs files. They are rather quickly put 
together, so expect them to fail if you use them in a way I haven't used 
them. Especially the sockets are very hackish, I just wanted to see if the 
concept works. Also, MicroThreads are not thread-safe =).

MicroThreads look much like normal OS threads to the coder, but they are 
ran in the same OS thread and are scheduled 
non-preemptively/cooperatively, ie. the running thread has to yield 
willingly. MicroThreads should be lighter than OS threads, and in theory 
you could have lots of them (tens of thousands?) and still run fine. This 
would be great for many applications, particularly for multi-user 
environments/games which is what I'm interested in. I've also thought 
about leaving continuations out and implementing MicroThreads directly 
with native code. I guess this would make MicroThreads more optimal, but I 
haven't used much time to study this option yet.

Included are a couple of simple benchmark tests, written for both 
stackless and mono. The mono versions were slightly slower, but not much.

About the overall implementation: IT'S A HACK! =). It works, but I know 
many ways to break it. It lacks sanity checks. It probably misses a few 
arguments every now and then. It kinda ignores GC, which probably will 
also break it. The new GC will probably break it even more. I haven't even 
thought about CAS. Not forgetting the millions of things that I don't know 
about that will also break it. But still, the tests I've included work, 
and it's been great fun playing with them.

----

My first question to the list is: is anyone else interested in this, using 
continuations and/or developing them further? Shall I keep quiet from this 
on or do you want to hear more?

My second question is: how to make the native code better? I don't know 
much about Mono internals, this was my first mono runtime project so all 
feedback is appreciated. Also I'd very much like to hear if someone can 
point out why this way of implementing continuations to Monois 
fundamentally flawed. This requires reading the code, but if some of you 
Mono-gurus have the time and can educate me...

Well that's that. Feel free to ask anything that comes to your mind about 
this.

  Tomi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: monoco-20060403-patch.tar.gz
Type: application/octet-stream
Size: 10538 bytes
Desc: 
Url : http://lists.ximian.com/pipermail/mono-devel-list/attachments/20060404/61bb4732/attachment.obj 


More information about the Mono-devel-list mailing list