Closed mateuszviste closed 3 months ago
The facility to unilize an $IDLE$ driver seems to be there. Perhaps we ask Michal Necasek if he would provide us with the source of his driver, so we can include it?
We would have to provide a small utility that enables /disables the driver, but that should not be a problem. It is basically getting a pointer to the idle data via INT21,4458 and then setting a flag. In DR-DOS it is an internal COMMAND.COM command. So we can simply look how COMMAND is doing it:
Btw. that FDAPM also causes trouble on FreeDOS for me. My Pentium system gets slow as hell. There were also reports from other people that it makes their system slow.
Looking at the code there seems to be no provision of checking whether ms_idle_ptr actually returns something valid. So that may make systems running the DR-DOS command.com crash if the kernel does not match.
Thanks for your insight. I am not sure l this $IDLE$ framework provides an added value. Since it still requires an extra driver, we could just as well ignore it and use a standalone HLT-emitting TSR that would be compatible with any kernel. There are a couple of them floating around. FDAPM is cool software and it can certainly be tweaked to be less aggressive, but being GPL I'd rather replace it by something else (possibly tinier and more primitive), hence why I was hoping EDR might have such thing embedded already, like the FreeDOS kernel. Too bad.
Should be possible to replace the driver calls with some sort of HLT instruction. But this idle thing is a topic for itself and can easily break things, so I would not rush into implementing this.
follow-up ticket: #79
Should be possible to replace the driver calls with some sort of HLT instruction. But this idle thing is a topic for itself and can easily break things, so I would not rush into implementing this.
I agree. I was low-key hoping that during the migration from DR-DOS to EDR this part might have been simplified or modernized already, but since it is not the case I do not think it would be wise trying to hack it now. This requires extensive tests with different CPUs (esp. ancient ones) to makes sure it won't freeze the computer.
Btw. may I ask what is the reason for FDAPM being enabled instead of using IDLEHLT, does this save more energy by disabling more "things". It seems to make some BIOS calls for energy saving?!?
Btw. may I ask what is the reason for FDAPM being enabled instead of using IDLEHLT, does this save more energy by disabling more "things". It seems to make some BIOS calls for energy saving?!?
Yes it does save more energy (or rather - limits the energy consumption in a wider number of scenarios/applications), but it was not the reason why I initially opted for FDAPM instead of IDLEHALT. The reason was that FDAPM explicitely fails on ancient 8086-class PCes, while I am not sure what IDLEHALT would do and if it was really tested on pre-386 PCs. The FreeDOS people tend to focus on 90s-era hardware, while I am more interested in the legacy IBM PC compatibility. On such hardware HLT has no power (nor thermal) impact, it starts being interesting somewhere around 486 tech. So FDAPM seemed like a reasonable approach.
I've tested HLTIDLE from https://pcdosretro.gitlab.io/hltidle.htm and it is also behaving nicely. Decreases my VirtualBox instance to about 4% CPU usage and has a memory footprint of 208 bytes. It does not intercept int 28h. Comes with ASM sources, although licensing is a mystery. Seems to be written by Vernon Brooks, although I did not find a definitive confirmation of this. I've added HLTIDLE into SvarDOS packages this morning. The TSR is able to detect itself (so it never loads twice) and appears to have some advanced logic to avoid issues related to HLT-ing the CPU during floppy drive operations.
extra note about HLTIDLE: it comes with an interesting feature, quoting the documentation:
HLTIDLE is a small TSR program which uses 192 bytes of memory and may be loaded into upper memory. If the LO parameter is specified then HLTIDLE will relocate itself to the unused area from 556h to 5BFh (segment 50h) effectively using no DOS memory at all.
Tested it, and it works. HLTIDLE does not even appear in the MEM/C output. Dunno how safe it is, though -- Bernd was mentioning a couple of days ago that the EDR kernel might use segment 50h for some internal buffering.
I adapted Robert's EIDL to my tsr example. This needs 192 Bytes of resident memory, MCB included, and installs without creating fragmentation, using PSP relocation. It includes an AMIS-compliant multiplexer and thus will detect if it is already installed, and allows uninstalling a resident instance as well. It also allows to disable or re-enable a resident instance without uninstalling too. And it doesn't leak an SFT entry if you install it as eidl > NUL
.
Repo is at https://hg.pushbx.org/ecm/eidl and current build should appear at https://pushbx.org/ecm/download/eidl.zip later today (in 6h as of writing).
That would definitively be an upgrade comparing to the earlier version. Btw. FDAPM also fragments memory, perhaps by freeing its environment and not relocating?!?
That would definitively be an upgrade comparing to the earlier version. Btw. FDAPM also fragments memory, perhaps by freeing its environment and not relocating?!?
Yes, I think that is what happens. I do have an fdapm fork at https://hg.pushbx.org/ecm/fdapm/ but I think I didn't change the allocation method for the main TSR. Did add an unload command though. IDLEDPMS I fully merged with my AMIS tsr example.
In https://hg.pushbx.org/ecm/fdapm/rev/c61c8fc35753 I added freeing file handles and the environment, but the environment was freed at another spot already prior to this changeset if you look at the patch. (Freeing file handles prior to 21.31 is required to avoid leaking SFT entries.)
So @mateuszviste perhaps we should update both te EIDL and FDAPM SvarDOS packages with @ecm-pushbx updates?
In https://hg.pushbx.org/ecm/fdapm/rev/c61c8fc35753 I added freeing file handles and the environment, but the environment was freed at another spot already prior to this changeset if you look at the patch. (Freeing file handles prior to 21.31 is required to avoid leaking SFT entries.)
This looks very good, thanks!
So @mateuszviste perhaps we should update both te EIDL and FDAPM SvarDOS packages with @ecm-pushbx updates?
In principle - of course. But these are "forks" for the time being, so I think it would be healthier to either wait for their eventual upstream inclusion or ask ECM to change their names so there is no confusion about which package is better/newer, esp. if new versions of these packages are released in the future by the original authors... @ecm-pushbx - any thoughts on this? Also, would you recommend using your improved EIDL in place of FDAPM as a default power-saving solution, or do you think FDAPM is a safer choice?
In https://hg.pushbx.org/ecm/fdapm/rev/c61c8fc35753 I added freeing file handles and the environment, but the environment was freed at another spot already prior to this changeset if you look at the patch. (Freeing file handles prior to 21.31 is required to avoid leaking SFT entries.)
This looks very good, thanks!
So @mateuszviste perhaps we should update both te EIDL and FDAPM SvarDOS packages with @ecm-pushbx updates?
In principle - of course. But these are "forks" for the time being, so I think it would be healthier to either wait for their eventual upstream inclusion or ask ECM to change their names so there is no confusion about which package is better/newer, esp. if new versions of these packages are released in the future by the original authors... @ecm-pushbx - any thoughts on this?
It seems unlikely to me that upstream will release new versions but it's your call. Perhaps fdapmecm and eidlecm could install the same files as plain fdapm and eidl?
Also, would you recommend using your improved EIDL in place of FDAPM as a default power-saving solution, or do you think FDAPM is a safer choice?
fdapm is quite complex and commonly known to cause some slowdown, which is approximately zero concern for eidl's int 28h hook. On the other hand fdapm may catch polling loops to the keyboard (eg 16.01) or mouse that may otherwise cause 100% CPU use, I'm not sure. Ideally any application would implement idling by itself as for example lDebug does when its polling loops are used.
Perhaps fdapmecm and eidlecm could install the same files as plain fdapm and eidl?
Sounds good. I might be off-computer for a couple of days now, but will remember to make such packages as soon as I have access to a keyboard.
fdapm is quite complex and commonly known to cause some slowdown, which is approximately zero concern for eidl's int 28h hook. On the other hand fdapm may catch polling loops to the keyboard (eg 16.01) or mouse
Well, EIDL is always slowing down the system because it executes a hlt unconditionally at every int28 instead of assessing if the system is truly idle, but in practice it seems to be less intrusive than FDAPM with "APMDOS" settings anyway.
For SvarDOS I tend to prefer simpler/tinier/cheaper solutions even if somewhat limited. After all SvarDOS is only meant to provide a minimalist baseline, then users are free to extend it with whatever packages they wish. That's why I find EIDL appealing... especially if it has you looking over it :) and saving a couple of KiBs on the floppies is always welcome.
fdapm is quite complex and commonly known to cause some slowdown, which is approximately zero concern for eidl's int 28h hook. On the other hand fdapm may catch polling loops to the keyboard (eg 16.01) or mouse
Well, EIDL is always slowing down the system because it executes a hlt unconditionally at every int28 instead of assessing if the system is truly idle, but in practice it seems to be less intrusive than FDAPM with "APMDOS" settings anyway.
Interrupt 28h is only supposed to be called if the system is idle, however. It is usually called in the kernel parts that implement standard input and output, while waiting for a keypress to arrive.
Quoth the interrupt list: https://fd.lod.bz/rbil/interrup/dos_kernel/28.html#4166
This interrupt is invoked each time one of the DOS character input functions loops while waiting for input.
Ideally any application would implement idling by itself as for example lDebug does when its polling loops are used.
@ecm-pushbx since you are a freedos contributor already, would you mind adding this in the otherwise great edit program it ships ? alternatively if you dont care enough or don't have enough time, could you point me to the ldebug snippet that does it so i can try to implement it myself? that would be really helpful.
Ideally any application would implement idling by itself as for example lDebug does when its polling loops are used.
@ecm-pushbx since you are a freedos contributor already, would you mind adding this in the otherwise great edit program it ships ?
I've not built edit yet, so it isn't easy for me to add and test this.
alternatively if you dont care enough or don't have enough time, could you point me to the ldebug snippet that does it so i can try to implement it myself? that would be really helpful.
The main logic is in the getc function. If a flag like biosidles
is set and input is from the ROM-BIOS int 16h then this just calls int 16.00 and assumes the int 16h handler will idlr appropriately. Likewise for if opt2_getc_idle
is clear and input is from DOS stdin.
Otherwise, including always if input is from serial I/O, this calls getc_if_any
in a polling loop. This function will call eg 16.01 and if it indicates a keypress is available then it also calls eg 16.00. If the getc_if_any
call returns reporting no keypress, we call the idle
function then loop back to poll again.
This function is also in lineio.asm. It can be called in Protected Mode or Real/Virtual 86 Mode. It will try running 2F.1680 first, in the current mode then calling down to 86 Mode from PM, then try to run sti
\ hlt
(which DPMI hosts may not like so there is a flag to control it). The int 2Fh function is to allow the host to know we're idle in a standard way instead of going straight to hlt
.
In edit you'll likely have to poll for both keyboard input and mouse input. Once you receive either, handle it. If neither is available in an iteration, idle.
Interrupt 28h is only supposed to be called if the system is idle, however. It is usually called in the kernel parts that implement standard input and output, while waiting for a keypress to arrive.
In the hltidle documentation Vernon Brooks says:
INT 28h is called once for every 64 characters output (every 4 characters output in DOS 2.x and 3.x) via INT 21h function 02h (note INT 21h function 09h uses the function 02h code)
This is the reason he gives for not abusing int 28 in hltidle. It seems he was involved in PC-DOS development back in the day, but maybe this every-64th-char thing is not happening on other DOSes.
The FreeDOS kernel has an IDLEHALT setting (config.sys) that enables a power saving mechanism emitting hlt instructions whenever the PC is idle. This helps keeping the CPU temperature in check.
Apparently DR-DOS had a framework stub for something similar: https://www.os2museum.com/wp/idle-dr-dos/
Does EDR still has this? Or maybe can it emit the HLTs on its own?
This would enable SvarDOS getting rid of FDAPM.