question about role of modules in riscos
h0bby1 (2567) 480 posts |
aaaaa |
Jon Abbott (1421) 2651 posts |
Modules can be loaded and unloaded as you like in the most part, ADFFS for example loads and unloads SoundTracker modules and shim modules as per each games requirements. Most apps will have a !Run sequence that will check for particular versions of Modules and load them if required. They’re essentially OO, but way before OO was ever thought up, so there’s a few caveats. In theory all Modules should be able to load, unload, be replaceable or relocated in memory on-the-fly. Where this breaks is with some system wide impacting modules such as CLib where the design wasn’t initially thought through enough. Relocating modules in memory is also now not possible as it was originally intended, due to a few minor design decisions early on. RMTidy for example is now ignored, where in early OS’s it would shuffle all the Modules together to free up slack space in the RMA (Relocatable Module Area – big clue in the name).
If the code needs to service interrupts or be available to many applications, then Modules would be the correct method. That mean that all plugin that all application can potentially use need to be loaded in memory for the whole life time of the system or linked statically as part of the application ? No, they can be loaded and killed as required. Apart from its use in CLib (which is really badly designed) and possibly a few other Acorn language libraries, static linking should be avoided at all costs. Modules are supposed to be dynamic.
Typically you’d avoid loading everything at boot in RISCOS, it’s designed to be dynamic so apps generally load what they require as they load and unload them when they exit if they’re specific to that app. The OS pretty much pioneered what we now have in Windows / Linux, it’s just not kept up with them. |
h0bby1 (2567) 480 posts |
aaaaa |
Jon Abbott (1421) 2651 posts |
Is your questioning with regard to a bare metal OS you’re writing on ARM, or specifically related to how you would implement under RISCOS? I’m not totally clear on what you’re trying to code. In your example case, in the RISCOS world you’d probably want to load all the Modules up front with the program, not load/unload in an OO fashion. Why? 1. Because loading/unloading will fragment the DMA and 2. Memory isn’t an issue under RISCOS like it is in Windows/Linux etc – we don’t require swap files as the apps are so lightweight. However, I’d say your example probably isn’t a good case for Modules as they’re likely to be bespoke to the app. If the app was a suite of apps, then fair enough, Modules would be applicable. If you’re writing bare metal, the worlds your oyster as they say! Full OO with dynamic insertion via linked entry points and multiple versioning on an app/app basis? |
h0bby1 (2567) 480 posts |
aaaaa |
Jon Abbott (1421) 2651 posts |
If I understand correctly, you’ve already written an application that’s essentially a framework that acts like an OS. It sits above the host OS and runs applications within itself and you’re trying to adapt it to RISCOS? Is it available on the web? Do you have a web page you can point too? It might make things a lot clearer as to what you want to achieve and help us assist in adapting it to RISCOS. |
h0bby1 (2567) 480 posts |
aaaaa |
Jon Abbott (1421) 2651 posts |
A select few rather than nobody, kind of expected on an OS this old though as lots of the developers are no longer with us and documentation went somewhat out the window after Acorn closed up. I must admit, I’ve struggled with ADFFS in certain areas and had to resort to documenting several aspects of the OS. ADFS scatter lists and the sound stack are two examples where the documentation wasn’t concise enough that I had to resort to picking the OS source apart. Scatter lists alone took me six months to get working, it should have been a few hours work! Jeffrey is the biggest contributor with regard to knowledge and contribution to RISCOS, if he doesn’t know the only other folk are the ROOL team, but as far as I can tell they’re a secretive bunch and don’t really contribute much here. They come up with new builds in the background, Pi2 for example, but it’s all very secretive and not at all an open process, which is a shame. Maybe they all have day jobs and can’t commit the time on here – who knows.
You might think that, I couldn’t possibly comment. I’d like to see ROOL more involved though, at least more publicly accessible and contributing here on a daily basis. |
h0bby1 (2567) 480 posts |
aaaaa |
David Feugey (2125) 2709 posts |
Yes, and you can do it under RISC OS. But it’s done on the application side, not the system one. The application loads the modules (if there are already loaded, they won’t be again), and application unload the modules (if they are still used, RMKill will failed). It’s a bit like multitasking: provided by the OS, but controlled by applications. It’s very RISC like: you move complexity to applications (for a RISC processor, you move complexity to code). Good point here: there are no strict rules. Bad point: OS does not provide a lot of automation, just a framework to automate. RISC OS is not “do it like that”, but more “do it like you want”. |
Steve Pampling (1551) 8170 posts |
Yup. |
Steve Fryatt (216) 2105 posts |
Jeffrey is the biggest contributor with regard to knowledge and contribution to RISCOS, if he doesn’t know the only other folk are the ROOL team, […] I’m not sure that’s entirely true: others definitely have knowledge of specific areas, and some of the other ex-Acorn people pop up on the newsgroups from time to time with advice. The bottom line, though, is as you say: a lot of the knowledge as gone, and there’s no-one being paid to know how everything hangs together. […] but as far as I can tell they’re a secretive bunch and don’t really contribute much here. They come up with new builds in the background, Pi2 for example, but it’s all very secretive and not at all an open process, which is a shame. Maybe they all have day jobs and can’t commit the time on here – who knows. I’m not sure that’s a very helpful comment, TBH. All of the ROOL people have day jobs, and do the ROOL work in their “spare time” for very little (if any) money. Steve R had some figures that he was presenting at shows a year or so back, which outlined how he and his ROOL colleagues spent the time that they could devote to ROOL: IIRC, most was administrative tasks, and very little was actually OS development. It was actually quite an eye-opener: I suspect that they’re already putting in many more hours than many other folk around here. More of a visible presence would be nice (I’d have appreciated a speedier response to my forum posts and direct emails over the PrintPDF licensing problems a couple of years back, for example), but if a low profile here is the price we have to pay for allowing them to get the important but boring stuff done behind the scenes without breaking them as people, then I think that’s fine. The actual development, which is probably more interesting, is largely left to the volunteers outside of ROOL. You could, of course, roll up your own sleeves and offer to help out; or you could just complain about things and help foster the impression that the ROOL team could find better ways to spend their spare time than working on RISC OS at all… How about contributing documentation (for the Wiki or into CVS) on the stuff that you’ve found out about the OS while working on ADFFS, for example? |
Steve Fryatt (216) 2105 posts |
Really? How does that work? I can’t think of very many modules which track active clients, so how would your average third-party support module know to refuse to die when asked? |
Steve Fryatt (216) 2105 posts |
In fact if i understood clearly, modules are basically supposed to be loaded at boot time, even mostly embbeded in the rom, and then stay resident in memory for the whole life time of the system ? You might be getting confused by the existence of things like the Shared C Library. Fundamentally, modules on RISC OS are “OS extensions”. Once loaded, they’re code that’s always present (at least until they’re *RMKilled), and which can provide * commands and SWI calls, and operate on low-level events. A lot of the core OS is implemented as modules (and the work Justin did on RO4/6 broke more of the kernel out into modules to help make the code more, er, modular), but there’s nothing to say that modules should only be in the system ROM. You can have modules on podule ROMs or extension ROMs (from the days of the A5000), and – of course – you can load modules from disc into the RMA at any time you like. Applications on RISC OS all exist at the same location in memory (&8000 upwards): multitasking is achieved by paging different apps into the memory map in turn, so that only one is ever visible to the system at a given time. This obviously means that an application can’t claim things like events using its own code, as for a lot of the time there will be some completely different code – belonging to another application entirely – paged in at the address that it would give to the OS as its event handler. If you need to claim events or similar (as per the PRM example that you quote), then you need to put that code into a module. You can then choose to either write a small module which communicates with your application via pollwords, or you can put the whole application into a module. I’d do the former, I think, but that option only came in with RISC OS 3. Other uses for modules are to provide services that need to exist all of the time and not get paged out: talking to hardware, performing regular tasks outside of the desktop system, etc. Due to the fact that they’re always present, modules can be shared by multiple clients. Whilst that might be the most visible feature nowadays, it wasn’t always the main point. |
WPB (1391) 352 posts |
I’m not sure, but I think he has done just that. In any case, Jon makes massive contributions to RISC OS – I’d be surprised if he has a lot of time for anything more! Your own contributions, Steve, are much appreciated also. We’re all on the same side. |
h0bby1 (2567) 480 posts |
aaaaa |
Steve Fryatt (216) 2105 posts |
I’m a little surprised that he doesn’t seem to understand how things work around here, then. “It’s all very secretive and not at all an open process” (ie. "it’s all a massive conspiracy) isn’t the kind of helpful comment that I’d expect from someone who’s in touch with what remains of the RISC OS community. Given that the reason for the lack of input appears to be the age-old one of there only being 24 hours in a day, the only way to resolve that is to help out and free up some time for forum contributions. If Jon doesn’t have time for that, then one would have thought that he’d have a good understanding of the problem facing ROOL! |
Steve Fryatt (216) 2105 posts |
Precisely (apologies if it wasn’t clear, but that was a rhetorical question that I was ‘asking’ of David). Given that RISC OS has no runtime dependency tracking, the only way to make such a system work would be for each module to implement its own _Init and _Terminate SWIs that all clients call, and then track those clients (very possibly by giving them handles). When the last active client calls _Terminate, the module knows that it’s free to die. A lot of modules don’t bother with this kind of interface, so there’s no way that they can be killed after use. The only option is if the application author assumes that it’s an undocumented private module and they then ensure that only one client can ever be running at a time – which doesn’t feel to be that great an idea. |
Colin Ferris (399) 1814 posts |
With ref to the CLib – what about having a separate jump table in another module or perhaps a extra RMA claim area – that could be left intact – if a new CLib was loaded? |
Rick Murray (539) 13840 posts |
h0bby1:
TThe difficulty is that “module” encompasses many situations, as the OS itself is practically built out of a large collection of modules. On the other hand, modules are also useful for providing facilities that cannot be sensibly provided in an application. For example the USBeep module that I provided on my blog a few days ago – it does nothing more sophisticated than beep when a USB device is connected, however it demonstrates well a thing that could not be performed in a regular application. There are a lot of “background messages” (Events, Vectors, Service Calls, UpCalls…) that RISC OS provides that are best handled in modules. These modules can either live for the duration of the time the machine is running, or for the time the application that requires them is running.
It depends upon how the program is created. It would be possible to allocate a block of RAM and load code directly into it. This is how the serial blockdrivers work.
Not really, no. But some applications support their own versions. I wrote an application a long time ago that supported “plugins” to provide different types of output. It worked by having a set of files (written in assembler) that were evaluated as the application started. When one was required, it would be loaded into an allocated block of memory. The first word pointed to the plugin name, the second handled file preamble (the stuff to output before the content), then there were routines for “text” and “text with effects” (bitmap for bold, italic, etc), and so on. It wasn’t elegant but it worked and having all of this stuff in separate files instead of all together helped to keep the memory requirements down (this was in the days when 1MiB was a common amount of memory to have installed, which would often be half that once system/screen/etc had all taken their share). These days? I’d just write the output stuff in C and embed them all in the executable. You can afford to be wasteful if your program takes less than a megabyte and you have nearly 200 to play with… I would not support ELF shared objects. Not because I have any problem with ELF, but simply because if the OS (or extension module) does not handle the hard parts by itself, that means that I would have to. Things like ELF will be a lot more flexible and capable than that which I would require, which would (as a side effect) make the code to deal with it more complex. For my plugin, all I needed to do was check the memory size, load it, and then call fixed offsets. That was all I needed. There was nothing fancy like resolving symbols. Jon:
CLib is not badly designed. Sure, it is biting us on the ass now but it has its origins in the days where 8MHz was a typical processor speed. Even when the ARM got faster, like the ARM3, the memory bus speed still sucked. h0bby1:
I think a way of dynamically loading code – either into the application or into a dynamic area – would probably be the best way here. The RMA was limited in size on older machines (a limitation not present in RO5) and it has no garbage collection so “gaps” in the RMA will remain as lost space. Accordingly, large amounts of data and code that are specific to one or two apps and don’t need to interact with the deeper parts of RISC OS are probably best placed elsewhere.
I am thinking that you will probably be best implementing your own dynamic loading mechanism; and given some of the examples this is perhaps best placed in a dynamic area so that it can run on callbacks or events (as applicable) without being swapped out during the normal polling process. RISC OS doesn’t do threads, so you’ll need to handle this sort of stuff yourself. ;-) I also look forward to seeing a practical live demonstration of what you have in mind. Do let us know when you have something executable available. |
Steve Pampling (1551) 8170 posts |
Lot’s of activity outside the sheltered world of these forums I expect. |
Rick Murray (539) 13840 posts |
Sadly, there is – even if it isn’t immediately obvious. Personally, I would make numerous changes to the Wimp so it can support Unicode and act a little more like a more modern OS. I would also make the keyboard handling capable of dealing with Unicode instead of that multiple-keypress hack, plus I would revise a number of the event calls so that Event_Mouse would be capable of reporting scroll positions, plus support for touch panel taps if they need anything extra. There is only one itty-bitty little problem with this glorious plan (asides from, you know, a lack of understanding of the deeper parts of the Wimp code). There is no point doing it if it means every single older application would break. We are pretty much stuck with a lot of legacy cruft, and drastic changes – even if desired – would ultimately be undesirable if existing software fails.
Essentially, RISC OS is a single-task operating system. The rest is smoke and mirrors. ;-)
If modules are small and not full of bloat, I’d say to just leave it there would be better than enforced killing. After all, loading it again may claim more RMA.
No, it doesn’t. But I think this may have been the original idea – SWI OS_ExitAndDie…
The problem, as I see it, is that you are shifting the problem from the application to a place in RMA. It would be more manageable, certainly, as there is only one jump table to patch up. However this must be done in a way that can disable interrupts as the old CLib unloads, loads the new CLib, patches the jump table, and then turns interrupts back on – while at the same time suppressing all of the usual RISC OS background activity such as ServiceCalls and Events. Because you don’t know if a module in C will be responding to them. This is mostly a legacy issue – I believe the current versions of RISC OS 5 (stable and nightly) both have the latest version as it was last updated around 17 months ago as far as I can determine. And right now, we’re mostly doing maintenance and bugfixes so it may not actually be necessary to run the very latest version available… Even so, regularly changing CLib in the course of a system running is not a normal thing to need to do. If a program absolutely must have the latest version, it should be in !System and a reboot should make it available safely. |
David Feugey (2125) 2709 posts |
Of course you’re right on this point. My fault.
Perhaps because existing applications don’t declare their dependencies to the system. And perhaps too because we almost never unload modules. Modules work a bit like DLL, but there are not made for this.
It’s between the two. Loaded when needed, but loaded for all the session.
Dynamic RMA? :) |
Steve Pampling (1551) 8170 posts |
Perhaps if the RMEnsure /RMload of a module added the module to a table of Application <—> module we would have a method keeping track of what was using a module – assuming people think it worthwhile keeping track. |
Vince M Hudd (116) 534 posts |
I can think of precisely one module that does (or did, in a previous incarnation) something along those lines. Jonathan Duddington’s Speak module, back when it was a purely RISC OS development. The documentation asked that any software using it called a SWI to register itself with the module, and to similarly call a SWI to deregister when the app was quitting. All the module itself did was keep a count, and it would remain loaded while the count was greater than zero. |