Splitting up the kernel
Jeffrey Lee (213) 6048 posts |
This is a subject which I don’t think we’ve had a proper discussion about before. Basically I’m wondering whether anyone has any objections to the idea of splitting up the kernel into separate modules, similar to how ROL did it. Mainly I’d expect this would involve splitting the VDU driver out into one or more separate modules (VDU and sprite handling is probably the largest part of the kernel source), but I wouldn’t rule out splitting out extra things at a later date – trying to pare the kernel down to the bare minimum functionality (CPU, memory, SWIs/vectors/interrupts, module chain) In the past I’ve always thought that it would be best to avoid splitting up bits of the kernel until we have an immediate need to do so, but I’m starting to wonder if that’s the wrong approach to take – if the kernel was in smaller chunks now, it might make people feel more inclined to get involved. Whether that’s just with regular development tasks (smaller code base = easier to understand), or more blue-sky stuff like rewriting components in higher level languages (which might not necessarily be C), experimenting with multi-core support, etc. Stuff which the core developers would love to play around with but can’t justify the time for (partly because we’re too busy with other stuff, partly because big chunks are harder to play with than small ones) So although I don’t have any immediate plans to split up the kernel I figured it would be a good idea to at least find out how everyone feels about the idea. E.g. whether it should only be done when there’s a clear need/requirement to do it, or whether we should be allowed to split up the kernel as and when we feel like it – with no immediate gains, just the potential of future gains. I guess one reason why we can’t split up the kernel right now would be that we still need to maintain the legacy zero page layout. But once we get the first stable zero page relocated OS release out the door I’m hoping we’ll be free to butcher the kernel workspace without fear of pitchfork wielding mobs collecting at the gates. |
rob andrews (112) 200 posts |
I think this is a good idea, this maybe a silly question but has anyone ever done a diagram of how and what the parts of the kernel do??. The reason i ask is that being a visual person i like to have a picture in my mind of the object that i am about to take apart to better understand how it works, as you say smaller parts easier to manage and develop. |
Frederick Bambrough (1372) 837 posts |
Today only. Free rat ona stick with every fork sold. |
Steve Pampling (1551) 8180 posts |
Aw shucks, go for it.
Brilliant idea, too much of a monolith at the moment. Isn’t this likely to involve amending the HAL to something where it becomes a basic shim to present a roughly identical1 pseudo-hardware to the kernel level? 1 Additional hardware features on different boards would probably be presented by HAL extensions rather than a whole rewrite. |
Jeffrey Lee (213) 6048 posts |
No diagrams, but I did write some words once: https://www.riscosopen.org/wiki/documentation/show/Kernel%20notes (n.b. a couple of bits are now out of date, e.g. the CAM is now 4 words per entry) One thing to bear in mind is that the kernel code is pretty mundane stuff. There’s nothing groundbreaking in there. s.ChangeDyn is a massive file that deals with dynamic areas, but the algorithms and techniques it uses are all very simple. But the fact that the file is (a) so big and (b) written in assembler makes it a complete pain to maintain. Rewriting s.ChangeDyn (and potentially other bits of the memory management) in C is one of the things on my wishlist, perhaps to be attempted if/when I add LPAE support to the kernel.
That’s basically the definition of what the HAL is :-) Besides, most of the kernel doesn’t talk to the HAL, so I don’t think there are going to be any major issues.
We already have support for that – ‘HAL devices’. On startup the HAL registers its devices with the OS, and then modules look for device types which they recognise and then either drive the hardware directly or use device-specific APIs to talk to (thin) drivers in the HAL. Some of the older modules (USB, PCI, serial) still use direct HAL calls to detect the available hardware, but all new ones are being written to use HAL devices. |
Rick Murray (539) 13861 posts |
<mode=“bastard”> If we’re going to suggest “work that might need to be done but isn’t necessary right now”, might I suggest a more capable network stack? </mode> <mode=“nice”> That sounds like a useful idea. </mode> Seriously now: I don’t think the size of the kernel should be offputting to anybody. The lesser issue is that it is a wall of assembler. Small or large, it’s still a bit “eeeek!” to look at. The primary issue, however, is that it runs in SVC mode, so any problem or quirk will probably crash the entire machine – and RISC OS doesn’t have much in the way of debugging and reporting facilities. I’m writing some important (to an app of mine) routines in a module as C code. Testing, tracing, and debugging is heavy abuse of DADebug because DDT just can’t deal with module code. Now consider the kernel. How does one diagnose a kernel crash? How do you? Emulator? JTAG? Or lots and lots of print statements to see where it falls over?
Butcher the hell out of it. Keep Aemulor and ADDFS in the loop as they may need specific information, but there’s precious little else with a convincing reason to be touching kernel workspace. To quote the PRM p1-360: In general, though, it is very dangerous to write to these other areas, or rely on certain locations containing given information, as these are subject to change. You should always use OS routines to access operating system workspace.
What is necessary to invoke the C runtime? I’ve wondered how early it would be possible to invoke C and if it could live in kernel land without things getting complicated. If somebody has a couple of hours free some rainy weekend day, could they please rejig that horrible mess of Wimp code? I don’t go near the Wimp much as I get fed up trying to find things in that messy code given sequential numbers. Ugh. What’s wrong with calling the files things like “icons” and “windows” and “polling” and “task”(init/shutdown) and so on, and grouping the relevant bits of code together? It seems the files are sort of thematic, so it shouldn’t be too much to rename them, then cut’n’paste stray functions to where they ought to belong, surely? Mmm, ep4 of Boku dake ga Inai Machi is up. Time to go. ;-) |
Jeffrey Lee (213) 6048 posts |
Me? Generally a mix of (serial) debug output and stack dumps, assisted by my own tool for address-to-line conversion. So yeah, not very straightforward, and almost certainly a turn-off for any aspiring kernel hackers.
The trick there is to not invoke the C runtime, or to replace it with your own. SpriteExtend and VFPSupport are two modules I know of which use C without using CLib. Some of the HALs also have bits of C in them. There is a bit of black magic involved (picking the right compiler flags, adjusting register usage to be APCS compliant, dealing with the magic stack words that contain the relocation offsets), and the amount and type of magic will vary depending on circumstance, but it is definitely possible to get things working. I should probably try writing a document at some point which covers the different approaches that I’ve seen/used. But to backtrack a bit to the subject of buggy/crashy code, one of the “higher level languages (which might not necessarily be C)” which I was thinking would be interesting to try out is Rust, due to its memory safety guarantees. But that would almost certainly be a “research project” rather than something I’d expect to see go into the official OS sources – the language is still a bit too new and obscure. |
Rick Murray (539) 13861 posts |
Thus essentially meaning the compiler is being used to translate readable code into assembler?
Mmm, two things to take a peek at.
Sounds a bit of a hack – fun! |
Rick Murray (539) 13861 posts |
Be nice as a effect if we could have the stable and development versions booting the same way (re. callbacks).
Why? The kernel should function in more or less the same way on each machine, with an abstraction layer translating what the kernel wants to what is really there – the infamous HAL. |
Jess Hampshire (158) 865 posts |
Am I right in thinking that currently the HAL is just a section in the source code that is changed for different platforms? If so, a more flexible arrangement would be for it to be separate, so that each platform has its HAL module and then there is only one versions of RISC OS. (An emulator could provide the HAL interface, rather than faking hardware.) This would be similar to the old BIOS/MSDOS situation. |
Rick Murray (539) 13861 posts |
Mmm, now which bit of code deals with memory management and sorting out what gets paged where when the Wimp needs it? Still, it isn’t a big deal as there are differences in each build – BCMVideo for the Pi, OMAPVideo for the Beagle family…I have wondered why these were not part of the HAL, but it never bothered me enough to actually ask. You do realise that current ARM SoCs do not support hardware discovery, don’t you? So unlike a PC where a one-size-fits-all installation of Ubuntu or whatever can boot and get itself started; ARM versions tend to be specific to the intended hardware platform. If you want to see for yourself, install Raspian and then try booting it on a Beagle… |
David Feugey (2125) 2709 posts |
It will reduce for sure the size of the BSP, sorry, the HAL. |
Rick Murray (539) 13861 posts |
We are going to have to agree to disagree on this. I suggest you read the following: https://www.riscosopen.org/wiki/documentation/show/RISC%20OS%20Hardware%20Abstraction The HAL is not intended to become a complicated driver module, because if it does then what’s the point? The hardware driving has simply changed place. Instead, the HAL is supposed to provide an interface between what the OS thinks is there, and the hardware itself. For instance, pretty much every SoC has a serial port and an IIC interface. RISC OS supports the use of a serial port (OS_SerialOp) and IIC (IIC_Control / OS_IICOp), but these devices behave differently on each SoC. They may be very different, as IIC often is, or they may be similar but in different locations of the memory map (as serial often is). In these cases, the operating system kicks the requests down to the HAL which does the low level interfacing. It’s a bit like a simplified version of a PC’s BIOS (back in the DOS era, that is). The HAL probably also translates interrupts and exceptions from the SoC specifics into a generic thing the OS can work with. I say probably as I recall seeing an IRQ file in the HAL sources, but not had much of a look at the very low level stuff. There be dragons, etc. Obviously there is a lot of direct hardware finagling in dedicated modules – SDIO and anything to do with video come to mind, because there are still a lot of legacy assumptions within the OS. Witness numerous people changing their software to work with the Titanium’s “backwards” colour ordering. Why? This should be something the OS/HAL/video driver can do for itself. But doesn’t… The HAL is not a complete hardware driver replacement. It is a stepping stone to begin the delicate task of moving hardware dependence from the OS into a specific bit of code that sits below the kernel. There is obviously more to be done in this respect, but it is not a bad start. However, while RISC OS is mostly the same from one machine to the next! it can never be identical. Consider your favourite language – BASIC. Consider the instruction |
Steve Pampling (1551) 8180 posts |
I think the general thread here is that we’d like to move to the next stepping stone. One nearer the bank. |
Rick Murray (539) 13861 posts |
I’m not sure that splitting up the kernel would necessarily do much for hardware abstraction, but there is an awful pile of crap that desperately needs it’s own API. I mean – look at OS_Byte. Wow, what a mess of random “stuff”. How to read the keyboard? OS_Byte um something. How to read CMOS bytes? OS_Byte um something else. Yuck. So, yes, as much as it is sad to dupe something the other guys did a long time ago, it is something with merit. |
David Feugey (2125) 2709 posts |
True but there are things that must precede the kernel, and things that can come later. The first one is HAL, the second one could be in modules. And sometimes (C lib), you’re between the two and there is no good solution :) It’s correct to see the HAL as a BIOS. IMHO, it’s better than having a BSP, AKA, a specific kernel for a specific board. In a perfect world, all the BSP thing should be reserved to HAL. The kernel should only be affected by differences in ARM instruction set, so by optimisations when you compile it. |
Jeffrey Lee (213) 6048 posts |
What is necessary to invoke the C runtime? I’ve wondered how early it would be possible to invoke C and if it could live in kernel land without things getting complicated. It’s not yet complete, but this should cover the main points. |
André Timmermans (100) 655 posts |
That’s a lot of details, which should come handy for people converting hardware drivers into modules. For people wishing to convert some of the existing ARM code into C, here is my experience with the TimPlayer module which was at first pure ARM code. I started by converting all the soundtrack format loaders to C without using the C library so it fits this thread well. The tricks that I used were quite simple: Note that for globals like tables of constants, due to the way Norcroft C handles constants, instead of defining a function to return their adress, I used the following hack: extern void MyTable(void); and used MYTABLE[x] in the code (IIRC the C compiler gave a warning on that kind of function to data conversion but let it pass). The most annoying parts where: All in all, it is best to convert parts of the code which are pretty much self contained. |
Sprow (202) 1158 posts |
Coming to this thread a bit late (I made a note to remember to comment, just keep ignoring my note!), I think there’s a careful choice to be made about where to make the cut. Pulling the VDU/sprite handling out sounds like exactly the right kind of granularity to be operating on. It’s a big chuck of code, and is already vectorised through VDUV and SpriteV and (like the BBC Micro MOS) has its own chunk of workspace and workspace offset through VDUWS macro. With a little CVS server side cunning the sources could be copied over and retain their change history (though obviously none of the old ones would build standalone, you could at least see the historical bug fixes). Certainly when I’m hunting for something in the kernel sources I do: select-all, adjust click on VDU, adjust click on AMBControl, drag to StrongEd. At the other extreme is what ROL did. I think they were almost on a religious quest to put one OS-SWI per module, seemingly to no actual benefit (their change logs used to make interesting reading as all sorts of bugs occurred due to splitting out the code, but it seems they’ve been removed from the internet archive now) other than to say “look how many modules you’re getting for your subscription”. This in itself causes a problem due to the limited number of module frugal bits. However, I don’t see any burning urgency to make the first move. There’s only 90 source files in total (46 if you exclude AMBControl and VDU like I often do), if a prospective developer is put off by that (compared with say, the size of the Linux kernel) they probably should start with something easier to chew. |
Steve Pampling (1551) 8180 posts |
I think most of the change work was Justin and the benefit was probably smaller discrete items for him to work on. Working as a full team it probably wouldn’t make sense. PS. Removal, hmm, yes. I think that was one of Aaron’s hissy fits around the time ROL went terminal. Shame, making more information available to all would have been nicer and probably a bit more adult. |