And what is the thing that recognizes, approves and executes each IL?
People. Using signed
No, no, no. The "IL" for any native code compilers are the host architecture's native instruction set.
Let's keep this discussion in context. You expressed horror at the idea of an OS that depended on a single IL. What exactly is your horror in reaction to? To answer that, we have to consider the nature of an IL. An IL exposes two things, an instruction set and a machine model. Surely, your reaction could not have been to the instruction set, as that is nearly transparent to the language-implementor. At the level of the instruction set, compiling to CIL is really no different than compiling to PowerPC or x86. It's completely transparent from the point of view of the programmer.
What you experessed horror to, whether you realize it or not, is the idea that the OS imposes a particular machine model on the program. The machine model is something that is not transparent to the language implementor or the programmer. If the IL doesn't expose arbitrary pointer arithmetic, you'll have a check of a time implementing or using a language that features pointers. Now, to finally get back to my point: while it is regrettable that the OS must impose a particular machine model, it is almost inevitable, and indeed, UNIX imposes a very specific (and often burdensome) one. UNIX is deeply intertwined with the C machine model (serially-executing, interruptable processes accessing uniform, unprotected, untyped, and contiguous memory). Of course, the machine looks nothing like that underneath. Significant layers of hardware and software are involved in making a modern superscaler multicore NUMA machine look like a PDP-11. Nonetheless, from the point of view of language implementors and programmers, that's exactly what a UNIX machine looks like.
An OS based on a safe IL will not be any less (or more) guilty of imposing a particular machine model: it will simply expose one that looks different. Implementors of unsafe languages will have to go through contortions to target such a machine, but that's really no different than what implementors of safe languages have to go through to target a UNIX machine!
Oh no doubt Linux uses gccisms. It's probably 80-90% C, and 5-10% asm, and 5-10% gcc extensions.
80-90% C is not C, it's "C-like". I personally thing its a stupid distinction, but you're the one attempting to make it (for Lisp). I'm just pointing out that, in that case, you should make it for C too.
The main issue with Lisp is the runtime environment. Would you call Lisp without garbage collection Lisp?
Without a GC? Likely not, but then again, we're not talking about removing the GC. That is not necessary to make a language suitable for writing kernels. We're talking about adding functionality to allow the specification of in-memory representation ("read-mem", "write-mem", "read-io-port", "write-io-port"). If C with an external function "read-io-port()" is still C, I don't see why the same isn't true for Lisp.
Have you even seen such a beast?
Multiple such beasts. Movitz is one such example. Sure, it's not particularly sophisticated, but that's because one guy is working on it. Popularity and suitability are two different things.
On some LCDs, yes they have. On my 2405FPW (which uses an S-PVA panel), the black around the edges of a Slashdot page (like around the add) is blacker than the LCD on my laptop turned off. Indeed, the limiting factor appears to be the slight reflection from the ambient lighting.
It does not forbid variations in field padding, however. The rules for how fields are padded are predictable, but that does not change the fact that they are not "byte for byte" translations.
You certainly can, but it's stupid because a) it's brittle and can break with future changes to the struct, and b) it's pottentially nonportable across architectures with endianness differences.
And c), it's non-portable because ANSI says nothing about the precise size of types or their alignment (and hence the internal padding of the struct).
By definition, a microkernel is composed almost exclusively by such code. Where is the advantage of using a higher-level language then?
Hardly. Even microkernels are full of logic (validating user input, for example). Even if you say a microkernel spends 50% of its code banging registers and memory locations (likely a gross overestimation), that's still 50% you don't have to write in a low-level language.
Right, so you move from doing manual memory management, to doing manual GC management. How is this a big win exactly?
Because memory protection is still enforced.
Says who? It's not good enough for people who want to ensure their system can be used for hard realtime.
Says everybody who is perfectly happy using Linux, Windows, BSD, OS X, etc, even with their unpredictable latencies of hundreds of milliseconds. Most kernels are not hard real-time. Those that are can be written in an approprite hard-real time language (either a safe one with a RTGC, or C with no MMU, no VM, and a RT malloc).
You'd seriously recommend building an entire operating system, kernel included, on a single IL?
To quibble: there is no reason to use a single IL. It just needs a trusted compiler for each IL it does support. Furthermore, what exactly do you think C is anyway? It's essentially the common IL for UNIX. The C machine model is deeply ingrained within UNIX, just as much as the CIL machine model is ingrained within the.NET CLR. Even if you do use a single IL, which you don't have to, it's really no different from existing systems.
Depends on how you use it, certainly. The CPU time isn't what concerns me, the fact that it's explicit and predictable is what matters here.
If I understand the term the same way, you're talking about something like what is used in the MLton compiler, which automatically inferences regions and allocates to them. Such region management is not any more explicit or predictable than GC or regular malloc() for that matter. I suppose you can include annotations in the program to delineate regions, but then why not just use the "preallocate and disable collection" idiom in a regular GC?
Certainly. That's not the problem though; BitC itself has a Lisp/Scheme syntax, so it's not a limitation of the language, but the operational semantics. Lisp requires GC. Lisp cannot grant you sufficient control of the runtime. Thus, Lisp is unsuitable. If you modify Lisp to support these features, great, but then you no longer have Lisp, just something Lisp-like.
What exactly do you think the Linux kernel is written in? In C? If I recall correctly, there is no inline asm in C99. Rather, Linux is written in a C-like language. You generally cannot write an OS kernel in C, because there is no way to emit traps, handle interrupts, etc, from C. You need to extend the language with an asm library (or inline asm), which is exactly what Lisps do. So sure, you can call them "Lisp-like" languages instead, but be aware that if you don't start applying the same reasoning to C, you're being inconsistent.
This also doesn't change the fact that C memory layouts translate directly byte-for-byte from source, to in-memory representation.
Which is not true on any modern C implementation. You can't depend on code layout at all, stack layout varies between compilers (and optimization settings), as does struct layout. No careful programmer does something like write() directly from a struct, and expect it to behave properly in any reasonable fashion.
Thus, kernels must still be written in low-level languages that allow explicit control over representation.
Bollocks. Kernels just need to be written in languages that allow direct control over in-memory representation for code that needs it. Any high-level language that offers functions for operating on machine-words fits the bill. This is true of all modern Lisps, which need such capabilities for accessing C libraries.
GC is non-predictable, so it's already out the window for any systems that hope to schedule anything close to realtime.
Most memory management algorithms are non-predictable. Nobody who writes real-time code believes that malloc() is suitable for real-time use. In "real" real-time code, you use the idiom of pre-allocating everything you need before you hit the critical path. This idiom holds for both GC'ed languages (in which you turn off the GC in the critical path), and manually-managed languages. Beyond that, define "close to real time"? Are Linux, Windows, et-al, close enough for you? The MPS has maximum pause times of around 50ms on my 3-year-old P4 2.0GHz. I can get pause times higher just by accidentally referencing a page that the VM has swapped out. The simple truth is that most people don't need hard real-time. Soft real-time is good enough, and on modern CPUs, GC can do that.
Even "realtime garbage collection algorithms" don't yet have the numbers to justify their use in critical kernel paths. I've read that their mutator overheads are still above 50%, which is unacceptable in this domain.
It's a very contrived scenario in which hard-real time guarantees are required, the mutator is highly CPU intensive, and the required performance cannot be achieved by simply doubling CPU capacity. To be honest, I can't think of any such scenarios!
Language-level safety of the latter sort is a dead-end; you will never be able to sell to any appreciably sized market, a system that depends on a single language to run everything.
*Cough*.NET *Cough*. Seriously, there is no reason the language in question must be a high-level language usable for programmers. The language could be something like the.NET IL, which other languages could target.
Cyclone with region memory management is potentially even better than Ada in constrained environments.
Region memory management has *very* real problems in constrained environments. It is lower overhead than GC in CPU time, but must necessarily keep garbage around a lot longer.
The technology, the knowledge exists, it just hasn't been brought together in a sufficiently low-language with which we can build microkernels. That's the drive behind BitC.
Any decent Lisp compiler has low-level instructions (which could be blocked for user-level programs). You'd need some ASM for things like writing to I/O ports and special registers, but you need that for C as well.
Memory and type safety is all you need to be able to dispense with the hardware level protections on existing CPUs. Proof carrying code might get you better protection guarantees, but it's not necessary to offer the level of protection offered by existing MMUs.
On a RISC machine, C is a huge step up from assembler. The C "machine model" is designed around a non-pipelined CPU that handles one instruction at a time, and has a uniform memory. Modern CPUs look nothing like that. They usually have several relatively deep pipelines, and a memory hierarchy with access costs that differ by orders of magnitude. In assembler, you can precisely tune the code scheduling to take advantage of that architecture. In C, you have to trust the compiler to do it. Good C compilers usually can, but then again, so can good ML compilers. However, the fact that the compiler can transform the program into something close to machine code doesn't change the fact that C programs, to begin with, are quite far away from machine code.
Can you honestly tell me with a straight face that JITC techniques, garbage collection, and other high-level features are competitive with C for producing such code?
I'm not well-versed on JIts, but garbage collectors generally have better cache behavior than most manual memory managers. Compacting GC's tend to increase cache locality by compating live data together.
Without proof-carrying code or hardware support, ensuring memory protection at any granularity without implementing a full-blown virtual machine is impossible.
I don't see how this reply answers my question. You claimed that technology needs to be developed to allow depending on language-level safety on existing machines. I said the technology is already there, all that is required is some mechanism for allowing the system to verify that a program was compiled on a trusted compiler. Heck, you could even likely use DRM for such purposes.
Eh, what? Define "proof-carrying code". Most Lisp compilers will (unless they are told not to) generate safe code. Both existing Dylan compilers will also. I'm sure the Haskell and ML compilers do as well. Would signing one of the resulting binaries count as "proof-carrying code"?
Certified compilers, proof-carrying code, etc. is possible, but the implementations aren't here yet (Coyotos is implementing BitC).
I don't know what "technology" there needs to be. There are lots of native-code compilers that generate "safe" code. All that's required is some form of code-signing to guarantee that a program was compiled on such a compiler. Or, distribute applications in some intermediate-representation, then have them be compiled to machine-code, on a trusted compiler, at install-time.
Like it or not, hardware page-level protection is the best we have, and microkernels are thus far the best way of exploiting this widely deployed architecture.
Correction. Not "best we have" but "what we're stuck with". The "best we have" is using the optimizer technology developed for Lisp, Smalltalk, and now Java to make typechecks and rangechecks cheap, and allow programs to ditch the hardware-level "memory protection tax" that current CPUs are stuck with.
You mean using seperate memory spaces is slower than writing all your apps in an interpreted language?
There is no reason a safe language needs to be interpreted. Java and C# aren't (they are JIT'd), while C#, Lisp, ML (and a host of others), are usually or can be native-compiled.
If it is true, then you would have to put the interpreter(s) in the kernel so no one could ever run a C program.
In a single-address space system, the kernel ceases to have any particular significance. In a system designed for safe langauges, you wouldn't need an interpreter for safe languages, but you would need one for C.
I think we just need faster context switching.
That's like saying "I just think air resistance needs to be lower". Superscaler CPUs have lots of context that needs to be saved. The more powerful the CPU, the more complex it will be, and the more context it will need to save on a switch.
C is a very good language for writing an operating system assuming that you are competant enough in C to get the job done, because it is close(ish) to the machine.
C is nothing like the machine. It was back in the PDP-11 days, but not now. C assumes a scaler execution model (with no parallelism to speak of). CPUs are superscaler, vector, and multicore. C assumes unprotected linear memory, while modern CPUs (like the K8), have protected, non-uniform memory.
C++ isn't a memory protecting language. It's all the OO overhead of Java, with none of the automatic memory-managment advantages, and with the optimizer-defeating pointer-induced ambiguity of C.
+1 Insightful:) I would have added a "Lisp or ML" to
If the microkernel was combined with a safe language, like Java or C#
but whatever.
Are point about speed is absolutely spot-on. Memory-protection has a very significant overhead that most C folks don't really consider, that safe languages do not need. Let's consider the Athlon64. If you look at the die, you'll see that a very significant amount of real-estate is devoted to data and instruction TLBs, page-table walking hardware, etc. Get rid of all that, and you could easily increase integer execution resources by 33%. Then consider that even in the case of a TLB hit, memory protection increases the L1 cache latency by 50% (2 cycles for access, 1 cycle for TLB lookup). That's assuming you don't have to do a page-table lookup, which could cost a thousand cycles or more. Now, consider the overhead in the OS. Every system call now takes a couple of hundred clock cycles, because of the protection-level switch, instead of a dozen for a regular function call. Now, consider all that extra memory (up to several percent of your total RAM), and CPU time (from the page-scanning daemons) used up by the OS's VM.
In comparison, what's the cost of a safe language? Some type-checks and range-checks, which, even when they aren't completely optimized-away, are cheap and easy to issue in parallel with regular code on a CPU with speculative execution.
The above discussion is rather oversimplified. First, Mach isn't really an academic kernel. It was developed in rather close cooperation between the academic and commercial spaces. Moreover, it predates QNX4 by over five years, and Neutrino by more than a decade. Neutrino is really good, but its also designed with an enormous amount of hindsight about what went wrong with Mach at CMU, OSF, IBM, DEC, NeXT, etc.
Your biggest mistake is that you say academic microkernels are "lousy", but then criticize EROS, L4, and Minix for not being successful. This indicates a deep misunderstanding of the nature of these projects. None of these microkernels are designed to compete with commercial microkernels. They are research projects, each designed to explore a particular avenue of microkernel research. EROS is designed to explore security, L4 to explore performance, and Minix is designed to be used as a teaching tool. All of these projects are successful at what they are designed to do. L4 in particular posts excellent performance figures. To say that they are not commercially successful is pointless --- they're not trying to be. You might as well criticize K42 (a commercial microkernel from IBM) for not being successful!
Your description of how things stand is quite accurate, but meaningless. I'm not arguing that the pro-choice stance isn't based in morality, I'm saying that the pro-life precepts of morality are inconsistent. Through their actions, they suggest that they will not give up luxury to save the lives of actualized children, but through their words, they suggest that they would give up their child to save the lives of potential children!
As far as I know, you'd be perfectly within your legal rights to do that. Most people would consider that a moral failing, but you are not legally obliged to save anyone's life.
And what is the thing that recognizes, approves and executes each IL?
People. Using signed
No, no, no. The "IL" for any native code compilers are the host architecture's native instruction set.
Let's keep this discussion in context. You expressed horror at the idea of an OS that depended on a single IL. What exactly is your horror in reaction to? To answer that, we have to consider the nature of an IL. An IL exposes two things, an instruction set and a machine model. Surely, your reaction could not have been to the instruction set, as that is nearly transparent to the language-implementor. At the level of the instruction set, compiling to CIL is really no different than compiling to PowerPC or x86. It's completely transparent from the point of view of the programmer.
What you experessed horror to, whether you realize it or not, is the idea that the OS imposes a particular machine model on the program. The machine model is something that is not transparent to the language implementor or the programmer. If the IL doesn't expose arbitrary pointer arithmetic, you'll have a check of a time implementing or using a language that features pointers. Now, to finally get back to my point: while it is regrettable that the OS must impose a particular machine model, it is almost inevitable, and indeed, UNIX imposes a very specific (and often burdensome) one. UNIX is deeply intertwined with the C machine model (serially-executing, interruptable processes accessing uniform, unprotected, untyped, and contiguous memory). Of course, the machine looks nothing like that underneath. Significant layers of hardware and software are involved in making a modern superscaler multicore NUMA machine look like a PDP-11. Nonetheless, from the point of view of language implementors and programmers, that's exactly what a UNIX machine looks like.
An OS based on a safe IL will not be any less (or more) guilty of imposing a particular machine model: it will simply expose one that looks different. Implementors of unsafe languages will have to go through contortions to target such a machine, but that's really no different than what implementors of safe languages have to go through to target a UNIX machine!
Oh no doubt Linux uses gccisms. It's probably 80-90% C, and 5-10% asm, and 5-10% gcc extensions.
80-90% C is not C, it's "C-like". I personally thing its a stupid distinction, but you're the one attempting to make it (for Lisp). I'm just pointing out that, in that case, you should make it for C too.
The main issue with Lisp is the runtime environment. Would you call Lisp without garbage collection Lisp?
Without a GC? Likely not, but then again, we're not talking about removing the GC. That is not necessary to make a language suitable for writing kernels. We're talking about adding functionality to allow the specification of in-memory representation ("read-mem", "write-mem", "read-io-port", "write-io-port"). If C with an external function "read-io-port()" is still C, I don't see why the same isn't true for Lisp.
Have you even seen such a beast?
Multiple such beasts. Movitz is one such example. Sure, it's not particularly sophisticated, but that's because one guy is working on it. Popularity and suitability are two different things.
On some LCDs, yes they have. On my 2405FPW (which uses an S-PVA panel), the black around the edges of a Slashdot page (like around the add) is blacker than the LCD on my laptop turned off. Indeed, the limiting factor appears to be the slight reflection from the ambient lighting.
Yes. The fact that CRT's are headache inducing heat machines has nothing to do with it...
ANSI C strictly forbids field reordering.
It does not forbid variations in field padding, however. The rules for how fields are padded are predictable, but that does not change the fact that they are not "byte for byte" translations.
You certainly can, but it's stupid because a) it's brittle and can break with future changes to the struct, and b) it's pottentially nonportable across architectures with endianness differences.
And c), it's non-portable because ANSI says nothing about the precise size of types or their alignment (and hence the internal padding of the struct).
By definition, a microkernel is composed almost exclusively by such code. Where is the advantage of using a higher-level language then?
Hardly. Even microkernels are full of logic (validating user input, for example). Even if you say a microkernel spends 50% of its code banging registers and memory locations (likely a gross overestimation), that's still 50% you don't have to write in a low-level language.
Right, so you move from doing manual memory management, to doing manual GC management. How is this a big win exactly?
Because memory protection is still enforced.
Says who? It's not good enough for people who want to ensure their system can be used for hard realtime.
Says everybody who is perfectly happy using Linux, Windows, BSD, OS X, etc, even with their unpredictable latencies of hundreds of milliseconds. Most kernels are not hard real-time. Those that are can be written in an approprite hard-real time language (either a safe one with a RTGC, or C with no MMU, no VM, and a RT malloc).
You'd seriously recommend building an entire operating system, kernel included, on a single IL?
.NET CLR. Even if you do use a single IL, which you don't have to, it's really no different from existing systems.
To quibble: there is no reason to use a single IL. It just needs a trusted compiler for each IL it does support. Furthermore, what exactly do you think C is anyway? It's essentially the common IL for UNIX. The C machine model is deeply ingrained within UNIX, just as much as the CIL machine model is ingrained within the
Depends on how you use it, certainly. The CPU time isn't what concerns me, the fact that it's explicit and predictable is what matters here.
If I understand the term the same way, you're talking about something like what is used in the MLton compiler, which automatically inferences regions and allocates to them. Such region management is not any more explicit or predictable than GC or regular malloc() for that matter. I suppose you can include annotations in the program to delineate regions, but then why not just use the "preallocate and disable collection" idiom in a regular GC?
Certainly. That's not the problem though; BitC itself has a Lisp/Scheme syntax, so it's not a limitation of the language, but the operational semantics. Lisp requires GC. Lisp cannot grant you sufficient control of the runtime. Thus, Lisp is unsuitable. If you modify Lisp to support these features, great, but then you no longer have Lisp, just something Lisp-like.
What exactly do you think the Linux kernel is written in? In C? If I recall correctly, there is no inline asm in C99. Rather, Linux is written in a C-like language. You generally cannot write an OS kernel in C, because there is no way to emit traps, handle interrupts, etc, from C. You need to extend the language with an asm library (or inline asm), which is exactly what Lisps do. So sure, you can call them "Lisp-like" languages instead, but be aware that if you don't start applying the same reasoning to C, you're being inconsistent.
This also doesn't change the fact that C memory layouts translate directly byte-for-byte from source, to in-memory representation.
Which is not true on any modern C implementation. You can't depend on code layout at all, stack layout varies between compilers (and optimization settings), as does struct layout. No careful programmer does something like write() directly from a struct, and expect it to behave properly in any reasonable fashion.
Thus, kernels must still be written in low-level languages that allow explicit control over representation.
Bollocks. Kernels just need to be written in languages that allow direct control over in-memory representation for code that needs it. Any high-level language that offers functions for operating on machine-words fits the bill. This is true of all modern Lisps, which need such capabilities for accessing C libraries.
GC is non-predictable, so it's already out the window for any systems that hope to schedule anything close to realtime.
Most memory management algorithms are non-predictable. Nobody who writes real-time code believes that malloc() is suitable for real-time use. In "real" real-time code, you use the idiom of pre-allocating everything you need before you hit the critical path. This idiom holds for both GC'ed languages (in which you turn off the GC in the critical path), and manually-managed languages. Beyond that, define "close to real time"? Are Linux, Windows, et-al, close enough for you? The MPS has maximum pause times of around 50ms on my 3-year-old P4 2.0GHz. I can get pause times higher just by accidentally referencing a page that the VM has swapped out. The simple truth is that most people don't need hard real-time. Soft real-time is good enough, and on modern CPUs, GC can do that.
Even "realtime garbage collection algorithms" don't yet have the numbers to justify their use in critical kernel paths. I've read that their mutator overheads are still above 50%, which is unacceptable in this domain.
It's a very contrived scenario in which hard-real time guarantees are required, the mutator is highly CPU intensive, and the required performance cannot be achieved by simply doubling CPU capacity. To be honest, I can't think of any such scenarios!
Language-level safety of the latter sort is a dead-end; you will never be able to sell to any appreciably sized market, a system that depends on a single language to run everything.
.NET *Cough*. Seriously, there is no reason the language in question must be a high-level language usable for programmers. The language could be something like the .NET IL, which other languages could target.
*Cough*
Cyclone with region memory management is potentially even better than Ada in constrained environments.
Region memory management has *very* real problems in constrained environments. It is lower overhead than GC in CPU time, but must necessarily keep garbage around a lot longer.
The technology, the knowledge exists, it just hasn't been brought together in a sufficiently low-language with which we can build microkernels. That's the drive behind BitC.
Any decent Lisp compiler has low-level instructions (which could be blocked for user-level programs). You'd need some ASM for things like writing to I/O ports and special registers, but you need that for C as well.
Memory and type safety is all you need to be able to dispense with the hardware level protections on existing CPUs. Proof carrying code might get you better protection guarantees, but it's not necessary to offer the level of protection offered by existing MMUs.
Please read a basic economics text. They spell out quite clearly why minimum wages hurt everyone involved.
C is barely a step up above assembler.
On a RISC machine, C is a huge step up from assembler. The C "machine model" is designed around a non-pipelined CPU that handles one instruction at a time, and has a uniform memory. Modern CPUs look nothing like that. They usually have several relatively deep pipelines, and a memory hierarchy with access costs that differ by orders of magnitude. In assembler, you can precisely tune the code scheduling to take advantage of that architecture. In C, you have to trust the compiler to do it. Good C compilers usually can, but then again, so can good ML compilers. However, the fact that the compiler can transform the program into something close to machine code doesn't change the fact that C programs, to begin with, are quite far away from machine code.
Can you honestly tell me with a straight face that JITC techniques, garbage collection, and other high-level features are competitive with C for producing such code?
I'm not well-versed on JIts, but garbage collectors generally have better cache behavior than most manual memory managers. Compacting GC's tend to increase cache locality by compating live data together.
Without proof-carrying code or hardware support, ensuring memory protection at any granularity without implementing a full-blown virtual machine is impossible.
I don't see how this reply answers my question. You claimed that technology needs to be developed to allow depending on language-level safety on existing machines. I said the technology is already there, all that is required is some mechanism for allowing the system to verify that a program was compiled on a trusted compiler. Heck, you could even likely use DRM for such purposes.
Eh, what? Define "proof-carrying code". Most Lisp compilers will (unless they are told not to) generate safe code. Both existing Dylan compilers will also. I'm sure the Haskell and ML compilers do as well. Would signing one of the resulting binaries count as "proof-carrying code"?
Certified compilers, proof-carrying code, etc. is possible, but the implementations aren't here yet (Coyotos is implementing BitC).
I don't know what "technology" there needs to be. There are lots of native-code compilers that generate "safe" code. All that's required is some form of code-signing to guarantee that a program was compiled on such a compiler. Or, distribute applications in some intermediate-representation, then have them be compiled to machine-code, on a trusted compiler, at install-time.
Like it or not, hardware page-level protection is the best we have, and microkernels are thus far the best way of exploiting this widely deployed architecture.
Correction. Not "best we have" but "what we're stuck with". The "best we have" is using the optimizer technology developed for Lisp, Smalltalk, and now Java to make typechecks and rangechecks cheap, and allow programs to ditch the hardware-level "memory protection tax" that current CPUs are stuck with.
You mean using seperate memory spaces is slower than writing all your apps in an interpreted language?
There is no reason a safe language needs to be interpreted. Java and C# aren't (they are JIT'd), while C#, Lisp, ML (and a host of others), are usually or can be native-compiled.
If it is true, then you would have to put the interpreter(s) in the kernel so no one could ever run a C program.
In a single-address space system, the kernel ceases to have any particular significance. In a system designed for safe langauges, you wouldn't need an interpreter for safe languages, but you would need one for C.
I think we just need faster context switching.
That's like saying "I just think air resistance needs to be lower". Superscaler CPUs have lots of context that needs to be saved. The more powerful the CPU, the more complex it will be, and the more context it will need to save on a switch.
C is a very good language for writing an operating system assuming that you are competant enough in C to get the job done, because it is close(ish) to the machine.
C is nothing like the machine. It was back in the PDP-11 days, but not now. C assumes a scaler execution model (with no parallelism to speak of). CPUs are superscaler, vector, and multicore. C assumes unprotected linear memory, while modern CPUs (like the K8), have protected, non-uniform memory.
C++ isn't a memory protecting language. It's all the OO overhead of Java, with none of the automatic memory-managment advantages, and with the optimizer-defeating pointer-induced ambiguity of C.
+1 Insightful :) I would have added a "Lisp or ML" to
If the microkernel was combined with a safe language, like Java or C#
but whatever.
Are point about speed is absolutely spot-on. Memory-protection has a very significant overhead that most C folks don't really consider, that safe languages do not need. Let's consider the Athlon64. If you look at the die, you'll see that a very significant amount of real-estate is devoted to data and instruction TLBs, page-table walking hardware, etc. Get rid of all that, and you could easily increase integer execution resources by 33%. Then consider that even in the case of a TLB hit, memory protection increases the L1 cache latency by 50% (2 cycles for access, 1 cycle for TLB lookup). That's assuming you don't have to do a page-table lookup, which could cost a thousand cycles or more. Now, consider the overhead in the OS. Every system call now takes a couple of hundred clock cycles, because of the protection-level switch, instead of a dozen for a regular function call. Now, consider all that extra memory (up to several percent of your total RAM), and CPU time (from the page-scanning daemons) used up by the OS's VM.
In comparison, what's the cost of a safe language? Some type-checks and range-checks, which, even when they aren't completely optimized-away, are cheap and easy to issue in parallel with regular code on a CPU with speculative execution.
The above discussion is rather oversimplified. First, Mach isn't really an academic kernel. It was developed in rather close cooperation between the academic and commercial spaces. Moreover, it predates QNX4 by over five years, and Neutrino by more than a decade. Neutrino is really good, but its also designed with an enormous amount of hindsight about what went wrong with Mach at CMU, OSF, IBM, DEC, NeXT, etc.
Your biggest mistake is that you say academic microkernels are "lousy", but then criticize EROS, L4, and Minix for not being successful. This indicates a deep misunderstanding of the nature of these projects. None of these microkernels are designed to compete with commercial microkernels. They are research projects, each designed to explore a particular avenue of microkernel research. EROS is designed to explore security, L4 to explore performance, and Minix is designed to be used as a teaching tool. All of these projects are successful at what they are designed to do. L4 in particular posts excellent performance figures. To say that they are not commercially successful is pointless --- they're not trying to be. You might as well criticize K42 (a commercial microkernel from IBM) for not being successful!
Holy crap. That bio page is impressive. Sounds like the upper-brass is chock-full of x86-64 and Alpha guys!
Your description of how things stand is quite accurate, but meaningless. I'm not arguing that the pro-choice stance isn't based in morality, I'm saying that the pro-life precepts of morality are inconsistent. Through their actions, they suggest that they will not give up luxury to save the lives of actualized children, but through their words, they suggest that they would give up their child to save the lives of potential children!
As far as I know, you'd be perfectly within your legal rights to do that. Most people would consider that a moral failing, but you are not legally obliged to save anyone's life.