[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: OT: down with memory protection!



I don't think I explained myself very well the first time, so I'll try again.

My goal is to create a system where it is practical to write programs that are
composed of reusable small sub-programs, a bit like the shell, or like OO but
with small, active objects that can have a thread of their own, and with no
practical limit to the number of such active objects.


I'll try to clarify what I am talking about:

- a new C-like language, compiler and kernel

- the language is designed to provide "safe pointers", where each pointer's
  range and rwx access are declared in the program (sometimes implicitly).

- the compiler tries to prove that a routine can access only the memory it has
  declared it will.  If the compiler can't prove this, it requires the
  programmer to supply a proof, or to insert assertions to ensure correctness.

- the kernel uses one big address space for all user and kernel processes, it
  does not remap or protect memory when it switches between processes.

- the compiler and loader are responsible for enforcing memory and device
  access restrictions, not the process switcher.

- processes share code and data with byte resolution, not page resolution.
  IPC involves shared buffers and objects, eliminating the need to copy memory.

- swap-space may be used, but the total size of memory is limited to what the
  CPU can address - 4GB for a 32-bit CPU, much more for 64-bit CPU.

- processes are never interrupted in the middle of what they are doing, they
  call "yield" at opportune moments to allow other processes to run.
  This is called "cooperative multitasking", or "non-preemptive scheduling".

- the compiler tries to prove that a routine will call yield frequently.
  If the compiler can't do this, it requires the programmer to supply such a
  proof, or insert extra calls to "yield".

- the language allows atomic sections to be declared instead of calling yield.
  The compiler will then insert calls to "yield" wherever necessary.

- a program uses static frames or a pool of shared frames rather than a
  monolithic stack

- systems composed of very many very small processes perform well, as processes
  are very lightweight, and switching is very fast.


One problem I can see with this idea is that without per-process virtual
memory, allocating large blocks of contiguous memory may fail if the address
space gets fragmented.  Maybe not a problem - if programs are highly modular,
programs won't require contiguous memory; and very large chunks of data can be
implemented in files instead of in memory, or stored in lots of smaller chunks.


Some responses to comments:

> You think this guy is a CompSci student with just enough knowledge
> to be dangerous?

heh, thanks, I like to be dangerous.  I'm not a CompSci student, and I think
I'm fairly knowledgable about programming and Unix.  Doesn't mean I don't have
crazy ideas from time to time though - hopefully this isn't one of them.

> Also, hardware _does_ malfunction.

That is a good point, without memory protection the faulty ram could cause more
problems before it was noticed.  I don't think this is a major issue though -
if your ram is hosed, its probably a good idea to restore from a backup anyway.

> > and the compiler and programmer could be required to prove that the code
> > would not loop forever without calling yield.
> 
> This is provably impossible.  Reference "the halting problem".

Turing showed only that it is possible to construct an program which cannot be
proven either to halt or not to halt.  The vast majority of real-world programs
are not like this.

We shouldn't abandon the idea of proving that algorithms behave properly
because some pathological algorithms are intractable.

> Most software, the vast preponderance of software, has no proof as to
> its correctness.

I am only talking about very weak correctness: correctly bounded memory access,
and guaranteed termination of some small routines.  I don't need to know
whether your program does what it's meant to do, only that it interacts with
the system correctly.

> The stack is a really important innovation in organizing algorithms and
> thinking about algorithms. Without it, one cannot think about recursive
> descent. If you think it would be nice to see its demise, you have probably
> never confronted a real algorithm. 

I meant I would like to see the demise of the monolithic unix/C style process
stack, not stacks in general.  Using lots of coroutines in C is impractical
because each coroutine requires its own oversized stack.  I think it would be
better to use static frames for non-recursive functions that don't yield, and
allocate other frames from dynamic pools indexed by size.  This could be done
efficiently.  "stackless python" does something like this for python.


Sam



Reply to: