Kernel 0.11, [arf1]

Andreas Arff ANDREASA@dhhalden.no
24 Mar 93 10:14:49 +0100


This is originaly Michaels mail, but I'll try to sumarize what we agree on.
Now notice this, if we are going get something done in a resonable amount of
time we must start to agree on things, as David mentioned as a postlude in
his last mail.
Now there are very few differences to Winikoffs mail but I suggest we use
Michaels mail as a working draft that will propagate around the world til
we have a draft. We will probably take Peter's ROI and Dennis next spec. and
add them to this list, or maybe add this and Peter's ROI to Dennis list
instead. Anyway we got to agree on the basics.
There are several "fields" which havn't been discussed yet, so I suggest we
look at these first.
Remeber one thing: We can always begin in the simple and step up when we need.
It is easier to see what works bad if there are only simple schems around.


 Kernel -- The Third Attempt
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 [NOTE: I'm starting from a conventional OS and moving away rather then starting
  from objects and moving towards OS -- I feel that this is more likely to
  yield a running system in a short amount of time. As Dennis has pointed out
  we don't have the resources to re-invent the wheel]

 Rather then just present details here I'd like to throw some ideas and
 justifications.

 Idea 1
 ~~~~~~
 We base the kernel on persistent processes.

 [Terminology: In a moment I'll modify this to persistent objects and explain
 the differences. By persistent I mean that it can be swapped out to storage,
 the machine turned off and on and then continued. In practice we would like
 to be able to have a large number of suspended processes on disk]

 This subsumes directories and files -- a directory is just a process that
 accepts queries and returns some identifier for the processes representing files

 Consider now the form of such a server (which incidently bears a striking
 resemblence to the nameservers (or dictionaries)):

     while (accept(request))
         case request of
             type1 : ... handle 1 ...
             type2 : ... handle 2 ...

 This type of code will be very common in the system.
 It allready is in event based systems.

 Why then not have a process declare to the kernel that
 "I handle the following request:
     req1 taking 4 parameters
     req2 taking 3 parameters
 etc."

 This is just an object.
 It has the concept of methods.

This type of code will only be necessary in the lolo's and kernel. Elsewhere
we will implement Virtual Dispatch Tables.

Discussion: How should we implement VDT. Is suggest my approach I have drawn
earlier with ROI. It's difficult to be objective, but of course there are
other ways of doing it.

 [Note: It is open to discussion how much the kernel should know about the form
 of the parameters (Eg. number, type ...)]
We havn't come to an agreement here as I have understod it.

 [note 2: Inheritance has been left out for the moment.
  as have overloading and polymorphism]
Not here either.

 Definition 1
 ~~~~~~~~~~~~
 An object is a process with method declerations.

 Definition 2
 ~~~~~~~~~~~~~
 A Device or "LOw Level Object" (lolo) is an object which
 either i
 (1) has been granted the privilege of being able to refer to certain hardware
 resources. (Eg. disk control registers, ethernet card)
 AND/OR
 (2) Has methods which are invoked upon the reciept of a particular interrupt.
 (Eg. data ready)

 [Note: Most lolo's will have (1) -- I think that few will have ONLY (2)]

We agree upon this.

 Definition 3
 ~~~~~~~~~~~~~
 An OID (Object IDentifier) is an atomic data item that is valid across processes
 (Note: In a distributed system it would be valid across machines too) and
 can be used to address an object.
 The id is an integer.

Also agreed upon.

 Definition 4
 ~~~~~~~~~~~~~
 A Dictionary (Or Name Server) is an object which supports certain lookup
 operations and returns an OID.

Agreed upon.

 [Note: We see the concept of object classes by the type of the supported methods
 falling out. Whether  this should be enforced by the kernel or elsewhere
 or not at all is open to debate]


 Discussion: As can be seen, so far we need system calls to
     * Create new objects
         This must take in parameters describing
             (1) The code
             (2) The method declerations
         These two should/must be together in an executable
             (3) OIDs for the objects which the new object has
                 access to
         This is important -- it replaces the concept of a default
         name server. The only object that is not given an object by
         it's spawner is the initial object. Giving it a nameserver
         is part of the bootstrap process.
     * Destroy objects -- clearly this takes an OID as a parameter
     * Invoking a method
         This takes
             (1) An OID
             (2) The method "name"
             (3) The arguments
         Issues:
             What is the type of the name?
             An integer is the obvious.
An atomic integer as suggested by all of us. See def. 3.
             When would the allocation of these be done?
There are two suggestions; mine and Davids. Any more?
             The permissible type of the arguments?
             in a purely OO system we could just have OIDs and be
             done. In our system it is doubtful that representing
             (eg.) an array by an object would be practicle so we
             need to be able to pass large granularity data between
             objects.

             This is where IPC comes in.
             (I'm using the definition that IPC involves data
              copying between address space]



 A comment on (very) small objects
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 In a pure OO environment one could use an object to represent say an array
 (not to mention an integer)

 This is impracticle if we treat objects as processes since then a method
 invocation involves a context switch.

 This does not prohibit using small objects WITHIN a single larger object it's
 just that these small objects can't be exported to the rest of the system.

 I don't think that we can develop a system supporting small objects with
 reasonable efficiency in reasonable time. It involves too much research.

As I see it, we agree with Dennis here.


 Some Other Issues
 ~~~~~~~~~~~~~~~~~~~~

 These are areas which bear further thought.
 I'll indicate my initial reactions to these issues.
 Rather then spend time filling out the details now (and spark a debate on them)
 I'd like to come to agreement on the basics first.


 ---------
 (1) Memory allocation:
     What kernel calls, how and should we support higher level functionality.
     (Eg. GC etc.)
We have two suggestions here. Either a C-like way of doing it or Fare's way.
(Don't remeber it exactly). I think it was more support for Dennis way of
doing it. (Hope I didn't jump upon anyones toes now:-)

 (2) lolos:
     How do we set an object up as a lolo, how do we give it access to a
     certain region of memory.
     (Implementation: we might need to have the access traped and then redone
      by the kernel after checking -- MMUs don't neccessarily support fine
      grain protection.
      (Eg. this object can read bytes 100-102 and write bytes 103-110 but
      can't touch bytes 0-99 and 111-500)

Still an open question if I remember right.

 (3) Virtual Memory and Address Space
     I think we can more or less agree that seperate objects should not
     be able to read/write each others address space for robustness
     reasons.
     Should we have an address space that is global or local to each object.
     (Note: This IS an independant issue)

We agreed upon local (well - noone else said anything else :-)

     How should VM be done? I think paging is the simplest way.
     DEtails:
         User input to the process if any
         Existance of PHYS_MEM and it's management

Agreed upon paging.
Details havn't been discussed yet, but as far as we have come with the
implementation I belive we could use the MEM_PHYS until we feel we need
swaping.

 (4) Semantics of persistance:
     One way to do persistance is to simply rely on paging -- assume all
     objects are in a very large memory and let paging load them in as
     needed.
     As Dennis has pointed out this is inefficient.
     Another way is swapping -- a process can only be either completely
     swapped out or completely in memory.
     Disadvantage: Lose the ability to save memory by having part of a
         process in memory
     Advantages: (1) Can be done without an MMU
         (2) By letting the user do this manually we allow coarse grain
         manual resource allocation.
         (Sort of like doing a "copy foo TO ramdisk" b4 starting
          and having an automatic save files to hard disk from ramdisk
          when about to shutdown)

We havn't come to an agreement here, since there hasn't been any discussion.
So let me suggest this. This is not a priority issue. We just use the
simplest available scheme, and then we can step up to use a more advanced
scheme when needed.

 (5) Semantics of invocation
     MOOSE is multitasking.
     What happens in the following situation:

     Object X    Object Y    Object Z
     Invoke(Z,1)
                     Starts executing method 1
             Invoke(Z,2)
 The three obvious possibilities are
 (a) Z starts another method in parallel
 (b) Y is blocked until Z finishes
 (c) Y continues and the invocation is queued.

 (a) Gives us multithreading and requires us to have semaphores to co-ordinate
 access to shared data.
 (b) Is the simplest to implement but is less versatile
 (c) Makes invocation asynchronous -- this adds paralellism to the system.

 Notice that under (b) one could have the invoke call return a result.
 Under (c) though the invoke would not return anything (other then
 "this was succesfuly queued" OR "this failed") and the reciever would use
 it's own invoke to return an answer.

 Of course we could (and probly will end up doing) provide more then one.

We have agreed on alternative c, but we implement the simplest scheme first.

 (6) Inheritance
     I've left this out for now.
     One question I would like to raise is WHICH INHERITANCE?
     There are multiple models -- C++, Smalltalk.
     Oh,  and this is without considering multiple inheritance.

Could someone outline the smalltalk way, ada way and the simula way. I'm not
familiar with other then C++, and I havn't studied ADA for a couple of years.

 (7) Polymorphism and Overloading
     So far I've only come across these as language design issues.
      You have a "natural" polymorphism in some commands
      (Eg. mv,rm,cp) when the contents of a file don't matter.

      Could someone expound on their ideas -- how do YOU view the role
      and function of polymorphism in an OS.
Still an open question.

 --------------------------
 And of course, feel free to comment, correct, suggest, debate and/or flame.

 Michael
 Aka. Merlin son of Corwin and Dara, sorcerer and creator of Ghostwheel. :-)

Arff
sig.'s in for 1000 miles service
        --Andreas Arff          andreasa@dhhalden.no--