Schol-R-LEA wrote:
eekee wrote:
I know why systems written in C or certain other languages are much nicer with an MMU. What I'm looking for is opinions on developing an OS in other languages without an MMU, or using certain programming techniques to minimize the risk.
Actually, I'm wondering why a Lisper would only take hardware seriously if it has one, Schol-R-LEA.
It isn't so much that I don't take systems without an MMU seriously, personally, so much as that I would expect most of the others here wouldn't.
Most of them? Oh, okay.
Schol-R-LEA wrote:
OTOH, Lisp systems have a
long history of accelerated hardware and hardware memory support; the various
Lisp Machines all had MMUs, for example, as well as tagged memory. I would certainly love to see tagged memory architectures return for that very reason (as well as hoping that hardware-based capability security will finally reach the mainstream). While the usual approach to memory management doesn't play well with the usual approaches to garbage collection, that doesn't necessarily have to be the case if the two are designed to work together. However, I intend to flexible enough that, if a given system doesn't have an MMU, I can do without it.
I didn't know the Lisp Machines had MMUs. I don't know why I assumed they hadn't; foolish of me. Cool that you could do without it.
Schol-R-LEA wrote:
On the gripping hand, most 32-bit systems today - even microcontrollers - have MMUs.
This has happened so fast! Doesn't seem long ago that few of them had MMUs. There were all these optional features which variants of a given SoC did or didn't have, an MMU sometimes being amongst them. I guess a few ARM SoCs have had microcontrollers for a long time. I still have my PXA-270 based Zaurus SL-C3200 which has a MMU. It's over 10 years old now.
Schol-R-LEA wrote:
eekee wrote:
I thought Lisp was a safe language.
Setting aside the question of whether there is such a thing,
Yeah. I sort-of know there probably isn't, but the wishful thinking is strong with me.
Schol-R-LEA wrote:
I am guessing that this ties into the misunderstanding of Lisp being primarily an interpreted language, as well as the matter of garbage collection implementations. Thing is, there's not really such as thing as 'an interpreted language' vs 'a compiled language' - with enough effort and run-time sleight-of-hand, pretty much any language can be compiled for even code which explicitly accesses the code translator. While many, many Lisp interpreters have been written as class projects (because it is dead easy, and a useful example project), most 'serious' Lisp systems are compiled (often to native code), and usually can mix-and-match interpreted and compiled code transparently in ones designed after the early 1970s (see the
Lambda Papers for the breakthroughs that made this feasible). For some systems, even the Lisp Listeners (the interactive REPL) are compile-and-go rather than interpreted.
My misunderstanding was to do with the garbage collector and the way data is handled. I've known about compiled Lisps for a long time, although I didn't know the original intention was to compile the language until I read another of your posts today.
Schol-R-LEA wrote:
(As I understand it, most Forth implementations also mix interpretation and compilation, but in a different manner, with the interpreter walking through the words of a given named operation until it finds a built-in or compiled word, and then calling it as native code. Comments and corrections welcome.)
That is the traditional way Forth is implemented, and no doubt the majority of implementations follow it, but I have installed right now four compiled Forths; 2 each closed and open source. Like serious Lisp systems, they compile the code but have REPLs too. (Swift Forth, VFX Forth, GForth and SP-Forth.)
I do wish more than one of them (Swift Forth) would allow control structures at the prompt. One which doesn't (SP-Forth) does supports anonymous functions [and I think lambdas?], so I guess I could work it that way. I'm planning an enhanced REPL whatever language I use. (APL was considered at one point.)
Schol-R-LEA wrote:
As for garbage collection, that helps a lot in minimizing the possibilities of trivial memory leaks and wild pointers, no question. However, it comes with trade offs. First, you are replacing a large number of potential failure points with (conceptually at least) one much bigger one, and debugging garbage collectors is notoriously difficult. The bigger issue is that while the most common classes of memory problems are avoided, several less common ones still remain, most notably the problems that come when a very long running process doesn't release the memory it is using somehow - as long as the memory still has live references, it won't be freed by the collector, and while most memory references go stale as a matter of course, if the process is recursing heavily such that prior memory used in prior calls is still 'live' it can result in a something akin to a memory leak. There are some ways around this, but that's just one possible problem.
I admit I forgot about debugging the garbage collector. Didn't really know that it's a notorious problem. That's a shame.
I understand leaks, but was thinking of them as a different problem. I don't see much difference with or without an MMU. Without; the leaking process gets stopped at allocation time rather than use. It's not nice with programs which allocate a lot of space ahead of time, but that's not really a leak as such.
Dare I say I hate recursion? (I need my alien smileys again.
) I'd rather use a little extra code and save bloating up the stack or putting the exit condition into the interface. Of course, sometimes it's there already. Tail call optimization doesn't fit every case, does it? Although I imagine it could with a wrapper function, which could also take care of the interface... *shrug*
Schol-R-LEA wrote:
Also, naively implemented garbage collection does not interact well with naively implemented paging. However, this wasn't a problem with the Lisp Machines (for example), because they used a more sophisticated approach which let the two facilities work together (and the systems had hardware support for GC that tweaked the performance of this even more). In my system, too, I intend for the paging and the garbage collectors (plural, as I mean to have a hierarchical memory manager) will be coordinated with each other, rather than fighting against each other.
Am I right in assuming the hardware GC support worked with the memory tags?
I've been thinking about paging in the last couple of years. I couldn't see it working well with garbage collection. Coordinating them makes sense.
Schol-R-LEA wrote:
Mind you, I mean to do some seriously odd things in my OS, such as using
runtime code synthesis in a high-level language,
Awesome!
Also slightly terrifying!
Schol-R-LEA wrote:
Xanalogical storage instead of a conventional file system,
This deserves another new thread, I have a lot to say about local hypertext, much of it based on 10 years experience. I love it! I don't like the Xanadu project though...
Schol-R-LEA wrote:
and using a combination of a portable AST, code templates, and compiler hints as the fuel for a JIT compiler, rather than the more common bytecode approach for portability.
What's AST? In any case, this sounds wild too!
Schol-R-LEA wrote:
Some of this may not work out. It is more a series of experiments than anything else.
It sounds like a series of most fascinating experiments! Well, so long as you don't do as Ted Nelson did and start obsessing over something unworkable. But again, other thread, and I won't be posting it tonight because it's past midnight.