Memory model for the LLL
Mike Prince
mprince@crl.com
Sun, 11 Dec 1994 03:01:01 -0800 (PST)
On Sat, 10 Dec 1994, Chris Harris wrote:
> On Fri, 9 Dec 1994, Mike Prince wrote:
> > On Thu, 8 Dec 1994, Francois-Rene Rideau wrote:
> > > What will be our memory model for the LLL ?
> >
> > 32 bit segments, each owned by a toolbox, or agent for resolving scope.
>
> Would this use native x86 segments or some abstraction of them? It seems
> fairly limiting to be able to only have one code, one stack, and four
> data segs in memory at once. All that and many processors don't support
> native segments. Wouldn't a flat address space w/ paging be easier?
I would hope in the x86 implementation that the LLL segments could map
directly to x86 segments. Each agent has access to only a few stacks at
a time from it's "inventory". I'm still playing with the exact layout
(methinks an A, [X,Y maybe], Path (for sure), and Code (for sure
again)). This would correlate very nicely to A=DS,Path=SS,Code=CS, and
X=ES. (Where why Y, I don't know yet). Remember, an agent has an
inventory of "stacks" to choose from, and at any time can pick a new one
(read ES or DS changes).
I'm programming a version right now using C with a flat address space, so
I know that version will work as well. What I hoped to gain from
segments is not having to continually bounds check segment accesses.
BTW, I'm way against paging. Our optimization routines should keep the
most active toolboxes in memory. I don't favor fragmenting toolboxes
and inheriting another "optimization" problem of paging stuff to and from
disk. I believe we could eliminate paging, DSM, RPC's, conventional
filesystems, disk caches, etc with this design.
> Are you saying that any size variable could be requested, from 1-bit to
> 512-bit, or only certain #s within a certain range?
>
> Oh, I'd Also be curious about specifying floating-point #s. Do most
> processors out there follow the same IEEE standards, and thus have the
> same level of precision?
I'm advocating having 8,16, and 32 _signed_ numbers as well as a float
(64 bit or 80 bit). As with Forth, bigger things can by synthesized.
I'm not a big hardware guru, and haven't kept up on what THE standard for
floats is, anyone know? I suspect it's a 64 to align on words to help
the CPU's out.
> Say, this isn't really on topic, but I'm curious how you plan to
> migrate/store agents, and represent concurrency in the LLL. In my mental
> picture now, agents fly around to whatever toolbox they need, and then
> run the code and use the data in that toolbox. That's neat, but what IS
> an agent? I've heard you say its a process, and that's okay, but my view
> of a process is some code and data, laid out like unix processes. If you
> take away the code from this view (Its hidden in tools, right?), then a
> process simply becomes a collection of stacks. How does this work?
View an agent like a CPU state, with registers being;
ToolBoxSegmentHandle points to array of pointers to toolbox stacks
AgentSegmentHandle points to array of pointers to agent stacks
ASegmentHandle points to A's segment (our current stack)
ASegmentOffset (top of data stack)
PathSegmentHandle points to Path's segment
PathSegmentOffset (SP)
CodeSegmentHandle points to Code's segment
CodeSegmentOffset (IP)
When an agent's time slice is up only the above registers are saved for
it's state. When it is revived, the segments may have moved, but the
handles are always the same. Typically the actual start of the segment
will be resolved using the handle during agent waking so as not to have
to resolve it for every memory access. The segments should never move
around during agent execution, only once they've been stopped.
An agent has (almost) exclusive power over the CPU until a sync instruction
(x86 type 3 interrupt) is executed. Remember, because we generated the
code, we can be sure they are there. Normally this interrupt vector
points to an IRET. But, if an agents time slot is up, something
external has happened, or an agent is getting a little too close to
it's stack bounds, the kernel rewrites the IRET and the agents
execution is shut down at a "stall point". Stall points are very
important because they align with our LLL instructions. When moving
executing agents and their tool boxes to different machines, we must
give the new machine a LLL based IP.
> Also, how do you schedule agents? Are there fork/join ops in the LLL, or
> is there some other way (a kernel toolbox?)?
We have to have two agent queues; one to service interrupts and another
for everyone else. But we could chain these two together, always putting
the interrupt servicers ahead of everyone else (the way it should be).
As such I expect we can get away with one modified queue, with a short-cut
for interrupt service agents.
I am planning on having a fork LLL instruction, joining would be a higher
level operation using semaphores and exchanging data using global
stacks. I don't think the join will be a LLL operation, but I'm not dead
set in any direction yet.
> Enough agreement, though. =) I still think that the user should get a
> higher-level view of things, complete with inheritance, etc.. Toolboxes
> are cool, but objects could be more productive.... (Not to mention fun.
> hehe....)
Absolutely. That is what I'm hoping Fare and the HLL people will
provide. I've been cranking out some code and building a basic debugger
interface for the kernel/loader. No matter what I do, programming in LLL
is going to be a bitter experience. I'm even contemplating building a
quick MLL (medium level language) to get me through the rough spots. At
least I'd like to generate structured code, not goto'd spaghetti.
Mike