I started writing my first OS before anyone that I knew (including myself) had internet access. I had no Intel manuals or anyone to explain things or any of that. What I did have was about 20 pages (photo-copied from a book I can't remember) that described 8086 assembly, another book that I "borrowed indefinitely" from a public library that described BIOS functions and not much else (The Peter Norton Programmer's Guide to the IBM PC), and an old assembler (A86). Due to a massive lack of knowledge my first OS was a real mode OS. It could best be described as "single-user, single-tasking, megalithic" (the "OS" was literally one bootable binary containing the OS and its applications).Kevin wrote:No, that's not what I'm doing. I absolutely agree that this break-even point exists. Discussing about its existence would be a waste of time and totally uninteresting. The interesting question is where it is, and I claim that for typical non-trivial projects (let's say > 30 KLOC, just to have a number) you never mess up your design enough that a rewrite from scratch would be the better option - because in practice nobody writes Minecraft when he really wanted to write a kernel.Brendan wrote:Different people may have different ideas about where this "point of equality" is. That's fine - every case is different, and it's up to each developer to make up their own mind for their own specific case.
Attempting to argue that this "point of equality" doesn't exist and that incremental change is always better regardless of how much code needs to be redesigned and rewritten make no sense at all. This is what you're trying to do. Your argument/s are obvious nonsense.
There wouldn't have been more than about 10 lines of code that was useful for the second version of the OS.
My second OS used protected mode with plain 32-bit paging; and was a "single-user, single-CPU, multi-tasking" micro-kernel (when I started writing it very few people had computers with more than 256 MiB of RAM so things like PAE seemed like a waste of time, and only rare/expensive severs had multiple CPUs so that seemed pointless too). It only supported 80 * 25 text mode. The memory management wasn't too good. The scheduler was crap (hardware task switching, round robin). The device driver model was hideous (device drivers ran at CPL=1 in a special "driver area" that was mapped into every address space). Ironically, the IPC supported both synchronous messaging and asynchronous messaging (I dropped support for synchronous messaging in later kernels). The code itself "worked", but it was limited and messy (poor modularity) and made too many assumptions about the hardware (rock solid on 80486 and Pentium systems, but unreliable on anything newer).
There wouldn't have been more than about 10 lines of code that was useful for the third version of the OS (near then end, every piece of code I looked at looked like it was written by someone that had never written an OS before).
My third OS was similar, but everything was just plain better - support for PAE, support for graphics modes/VBE, much more efficient memory management, greatly improved scheduler, much better driver model, etc (and a lot less stability problems - I'd started to gather a pool of test machines by that stage).
There wouldn't have been more than about 10 lines of code that was useful for the fourth version of the OS.
Times change, and hardware changes with it. Not long after Intel introduced hyper-threading and multi-core CPUs it became obvious that ever-increasing clock speeds was going to stop and be replaced with ever-increasing CPUs instead. At around the same time AMD introduced long mode. My fourth OS was similar to my third in spirit, but very different in implementation - mostly due to multi-CPU and long mode, but also because I was growing more confident and wanted "commercial quality" rather than just "hobbyist" - a greater emphasis on fault tolerance (and error detection and error handling in general), things like CRC checks in executable headers, version numbering to allow "auto-update", my first serious look at internationalisation, etc.
There wouldn't be more than about 10 lines of code that I consider useful for the fifth version of my OS.
When I started writing the fourth version of my OS I just assumed the BIOS would always be there. Along comes UEFI and the design of the boot code (and the interface between the kernel and the boot code) needs some serious redesign. The fourth OS also taught me a lot about locking, scalability and multi-CPU (and just like before, the experience I gained means I can do far better next time). I also started having other ideas - refining the project's goals (resolution independence and colour space independence, hot-plug CPUs, etc). Things that I assumed I'd want to support (e.g. C, HTML, etc) I no longer want. The memory management needs to change, the scheduler needs to change, etc. I don't want my current abilities to be limited by my previous knowledge or past decisions.
I haven't seriously started the fifth version yet. I did a bunch more research (a few boot code prototypes, including messing about with UEFI, etc) and real life got in the way a bit. I'm expecting to start again in a few months.
When you start again from scratch you worry if it's the right thing to do. Even after you've started again it's natural to wonder if you should've kept working away on your old crappy code. It's not until you get about half way through the rewrite and look back at what you've accomplished (and how much better it is than the old code) that you know you made the right decision.
In hindsight, I have no reason to regret any of these rewrites. What I regret most is thinking "it's just a hobby kernel" - if I'd considered it a serious/professional project from the begining maybe I would have spent more time on research and less time on "scope creep".
Cheers,
Brendan