[Gllug] Beagle Board

Vidar Hokstad vidar at aardvarkmedia.co.uk
Tue Jan 13 12:53:21 UTC 2009


On 13 Jan 2009, at 11:54, Bruce Richardson wrote:

> On Tue, Jan 13, 2009 at 09:55:36AM +0000, Vidar wrote:
>>
>> In fact, there was even a preemptive multitasking BASIC extension
>> available for the Commodore 64, though that was a bit of a hack since
>> it could rely on the interpreter loop,
>
> Then it wasn't pre-emptive, it was co-operative. The yielding from one
> process to another was done in a black box, but if one process were to
> hang, there would be nothing to move execution on to the next process.


In fact I don't remember exactly how it was implemented - most likely  
I never looked at it in detail -, but the important aspect for me in  
calling it pre-emptive was that a hanging thread did *not* prevent  
execution from moving to the next thread (for suitable values of "not"  
given that this is a system without memory protection). At least I  
could not find a way of doing it without clobbering the wrong bits of  
memory.

It is *possible* that the interpreter was multiplexing operations  
under the hood, though I am pretty sure it wasn't. If I am wrong about  
that we could argue back and forth whether that means the BASIC  
threads were pre-emptively multitasked (the *observable environment*  
for the running program certainly was) or not. It makes no sense to do  
it that way, though, since it's far easier (a couple hundred bytes of  
asm at most) to do it "properly" using interrupts. You wouldn't need  
to patch the standard interpreter all over the place to prevent the  
possibility of lockups, for starters.

Your reply makes me want to try to track it down and have a look at  
the code to check if I'm remembering it correctly :)

What I meant by saying it could rely on the interpreter loop - which I  
realize was unclear/confusing at best when I re-read it - was that it  
only needed to save/restore the state of the interpreter when  
switching. The C64 basic interpreter maintains *very little* state  
that would not be shared between the threads (the code they were  
running was all part of the same loaded program, and shared the same  
variable space) - it's a handful of byte containing things like the  
line number and position of the currently executing BASIC instruction,  
the program counter, codition codes and three 8 bit registers. More  
importantly, it uses practically no stack space, which you couldn't  
guarantee for a "generic" solution. Relying on specific knowledge of  
the interpreter loop saves some effort particularly in "solving" the  
issue of a single 256 byte stack that can't be moved and moving/ 
relocating data that should not be shared to thread local storage.

In any case, for something that is doing "generic" pre-emptive  
multitasking as long as the programs don't clobber each others code  
and data, there is this kernel for the C64 that I came across after my  
initial reply:  http://www.6502.org/users/andre/osa/oa1.html and http://www.6502.org/users/andre/osa/README.c64
The C64 port overcomes the 8 bit stack pointer issue in two ways:  
Either by splitting the stack between a (small) number of threads  
(cheap, though since the stack is only 256 bytes it's kind of  
limiting, but few C64 programs use more than a few bytes of stack) or  
by copying the stack on each context switch.

Vidar
-- 
Gllug mailing list  -  Gllug at gllug.org.uk
http://lists.gllug.org.uk/mailman/listinfo/gllug




More information about the GLLUG mailing list