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