[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