roelandjansen / pcmos386v501

PC-MOS/386 v5.01 and up, including cdrom driver sources.
GNU General Public License v3.0
418 stars 60 forks source link

Support for Advanced Power Management (APM) in the kernel #96

Open dgorski opened 4 years ago

dgorski commented 4 years ago

https://dos4gw.org/Advance_Power_Management_APM_Functions

I don't know if this is an issue as much as a wishlist item.

Under FreeDOS one can reduce CPU load from 100% to about 2% simply by using the CPU IDLE BIOS call when nothing is going on (which is a lot of the time). This allows one to run many instances of FreeDOS under virtualization without performance penalty.

PCMOS on the other had runs at 100% at all times. This means under virtualization it consumes a great deal of resources.

Since I'm running on a 4-core single thread host, 1 core is always running 100% and causes not only performance concerns, but concern for the hardware itself (a lot of heat for one thing, assymetric heat on only one core for another).

I had implemented a simple int 15 wait in a utility program which helps under DOS (even without running the FDAPM utlity), but this doesn't seem to have any impact under PCMOS (which is to be expected as it's a multitasking kernel).

However, if the kernel implemented the int 15 APM calls, PCMOS would be very well behaved indeed.

stsp commented 4 years ago

I don't think this is a valid conclusion. INT15 should be implemented by bios. Maybe there is some problem with seabios? You can easily check if int15 was hooked by MOS or not.

dgorski commented 4 years ago

I think SeaBIOS is fine as all of this works properly under FreeDOS.

It doesn't look like the PCMOS kernel is aware of APM. This doesn't surprise me, APM was introduced in 1992 as a way to make laptops battery life reasonable. Most of the PCMOS 5.01 files are dated January of 1993... Laptops (portables) were not really the target market.

Anyway, I tried using the FDAPM command from FreeDOS to tell the BIOS to enable APM, and it does appear to, but the OS itself needs to cooperate or it makes no difference. That's why I decided to open this "issue". The kernel needs to call the APM functions in the BIOS when there are idle/wait cycles.

http://wiki.freedos.org/wiki/index.php/FDAPM

I did take look a the MOS kernel source a little bit - it looks like "disk busy" task handling via INT15 is there, but little else (that I can understand). Nothing that I see that's related to APM . As I mentioned, I'm not really surprised, but I thought it might be an interesting problem to takle for an kernel developer type.

PS - the FDAPM tool from FreeDOS is super useful in PCMOS (and DOS) under QEMU as it allows for BIOS calls to "coldboot" for restarts and "poweroff" to shutdown the emulator, all from inside the emulated OS.

stsp commented 4 years ago

In DOS world, the power management happens between the application and bios. In particular, fdapm hooks the needed interrupts (int16, int28, int2f etc) and translates their waits into an APM calls. DOS kernel is not involved. But not so much with MOS, as it simply doesn't call the expected bios calls. For example it implements the keyboard handling itself, instead of calling int16. This is why fdapm can do nothing when mos's native shell is running. I still think that fdapm will help with the apps that call int28 or int2f explicitly for idle, but they are few. So yes, mos doesn't allow fdapm to do most of its work, and therefore, as you say, should became PM-aware itself. Note that even hlt won't work because $386.sys just ignores hlt. So MOS is very active in breaking the PM in any possible way.

dgorski commented 4 years ago

DOS kernel is not involved.

That's a fair point - under a single-tasking OS the app itself is responsible.

Would be nice if the MOS kernel could be nicer when there isn't anything to do...

HStewartGitHome commented 4 years ago

PC-MOS existence was pretty much before Power Management started.

Keep in mind it is older than a lot of developers

One thing I am curious if PC-Emulink source was release - this was my first program, it was done in assembly language and my first task at Software Link. I had fun with and made byte size 8088 bytes.

Stewart

stsp commented 4 years ago

@HStewartGitHome APM requirements for DOS are not that big. The helpers like fdapm or alike, can do the job. The only thing needed, is for the MOS kernel to signal idle to them, by eg int28 calls. I looked at the MOS scheduler, and it seems it has no notion of an idle tasks. It just switches in a round-robin manner between all tasks. So getting APM in, needs to first add a notion of an idle task to MOS, which is probably quite a work.

HStewartGitHome commented 4 years ago

Again MOS was written before APM which was 1992.

https://en.wikipedia.org/wiki/Advanced_Power_Management

My only guess is find out what Interrupts are being executed at that time and figured how to hook in. You maybe able for some situation to alter shell.sys

It has been such a long time.

stsp commented 4 years ago

But I think the problem is not APM, but rather a scheduler. Currently the MOS scheduler just switches to any thread, no matter does it have the work to do or not. You need the new scheduler that will only select the active threads. Such advanced scheduler can think "there is no work to do, lets sleep". And on top of that you can hook APM.

HStewartGitHome commented 4 years ago

The Scheduler was written original written by David Morrow who left within six months after I got there, but mostly work on by Martin. Eventually after the original people left like Jim Bean and David Morrow, Me and Martin became primary developers and for a while only developers.

Please note at this time, a lot of DOS information include Int 28 was consider Un documented and a lot of information came from books like Undocumented DOS.

stsp commented 4 years ago

Yes, but int28 or whatever else, is not the main point. As long as the scheduler have no idea how much work does the thread have (or is it idle), you can't do many many things, including APM. Whether the MOS scheduler is that simple, is only my suspiction. I probably haven't looked closely enough, but all I could find is just a round-robin scheduling. Please correct me if I am wrong. If your scheduler can see that the thread is idle and not switch to it in that case, then adding APM support is going to be just a 10-minutes work.

dgorski commented 4 years ago

It looks like there are two calls in MOSINT38.asm that are related to tasks opting out of timeslices.

ah=06 - time wait an optional task deselection. bx=# of timer ticks this is used by the time slicing with a bx value of 1

ah=07 - wait for event. waits for one of 4 types of events: keystroke, timer ticks, hardware interrupt, serial port status change.

I'm only poking around here, but it seems like there is opportunity already for a process to "sleep" through some timeslices and/or sleep waiting on an event.

Perhaps the concept of an idle task is in fact needed in order to allow all tasks to be sleeping, leaving the idle task to cal HLT or one of the BIOS INTs.

Interesting stuff.

HStewartGitHome commented 4 years ago

I would research where these calls gets call and it likes these could be places where you can place a hook need for APM. This would give a clue on where MOS detects idle time.

Sorry it been 3 decades since working on this stuff. It is even hard to remember the code. I have faint memories on this stuff - but the logic discuss here is basically original stuff - and both David Morrow and Jim Bean only there less than year after I came in 1986.

stsp commented 4 years ago

It would be cool if @HStewartGitHome does the proper research on this! Then we can hook in APM. I can only vaguely remember my own findings, and I think that 06 was not implemented, and 07 was not used.

dgorski commented 4 years ago

06 is indeed undefined/unused but 07 seems to be implemented completely. The comments in the asm file make for an nteresting read. It seems that much of the task related stuff is in that file (INT 38 being used in MOS for MOS specific stuff only).

stsp commented 4 years ago

06 is indeed undefined/unused but 07 seems to be implemented completely.

Have you found if its ever used?

dgorski commented 4 years ago

I haven't found anywhere that it is used inside of MOS, but I also haven't done a very thorough search. I'm wondering if this is something that a MOS-aware application would use, similar to how a desqview-aware or APM-aware application would call their respective idle APIs.

stsp commented 4 years ago

Very probably, but unless at least shell also uses that, there is no way. Also shell is constantly reading from keyboard, so and that alone should have put it asleep, but seemingly doesn't.

HStewartGitHome commented 4 years ago

It would be cool if @HStewartGitHome does the proper research on this! Then we can hook in APM. I can only vaguely remember my own findings, and I think that 06 was not implemented, and 07 was not used.

At this point you probably have more knowledge in this area then me. I been out of touch with for 3 decades and only seeing it on GitHub made me think of it.

One thing I remember that Int 38 could not be called directory, and must be called with vector.

HStewartGitHome commented 4 years ago

Very probably, but unless at least shell also uses that, there is no way. Also shell is constantly reading from keyboard, so and that alone should have put it asleep, but seemingly doesn't.

I just had a small brainstorm - one of things about keyboard handling is that a task could have it own keyboard driver - this is how terminal are implemented - even INT 9 can router from serial input - you could possible create one that handles your special APM needs. It been so long - i maybe out of touch on itl.

stsp commented 4 years ago

Even if the keyboard driver puts the task asleep, its probably not enough. I think you should call to APM only when all tasks are asleep. So IMHO the scheduler is a better place for that, than the keyboard driver. But as a quick hack - indeed, perhaps just sticking int28 to the keyboard driver will do the trick.

I have also found that shell uses "wait for event" stuff, namely in MOXCPCOR.ASM:4352.

HStewartGitHome commented 4 years ago

But that is only use in critical errors

stsp commented 4 years ago

But that is only use in critical errors

That might explain why I tried sticking int28 there, but nothing changed! :) I also tried int28 in int16 - the boot became slow, but nothing changes when shell is polling the kbd.

dgorski commented 4 years ago

I found this link, an HTML version of Ralf Brown's Iterrupt list (RBIL). It shows that the MOS API moved from INT 28 to INT D4 after PC-MOS 3.0, there are a number of "public" API interrupt calls documented (from 3.0+ and 5.01).

For example: http://www.ctyme.com/intr/rb-8439.htm

The full list from DBIL is show on on the "other operating systems" page: http://www.ctyme.com/intr/cat-030.htm

There are a couple of them related to task management.

stsp commented 4 years ago

I don't need MOS's int28. I need bios/APM's int28. Its good that they have moved, so that int28 is spared for APM.

I just didn't try hard enough to find the place for an APM call, and the "naive" targets, like int16 and "wait for event" didn't work out.

You can try that yourself. With build.sh/run.sh its really not a time-consuming task for someone more motivated in this, than myself. :)

HStewartGitHome commented 4 years ago

I don't need MOS's int28. I need bios/APM's int28. Its good that they have moved, so that int28 is spared for APM.

You can do that finding place where MOS store's bios INT 28 vector and doing a Far call to it.

stsp commented 4 years ago

Yes but I don't need this, as the APM handler hooks the int himself. And in certain places of putting int28, I've seen a very slow boot, so the the idling kinda worked. I just need the right place to stick int28 into, not not slow down the boot horribly, and to release the CPU when shell reads the keyboard.

stsp commented 4 years ago

APM handler hooks the int himself. And in certain places of putting int28, I've seen a very slow boot,

This all may sound like a nonsense unless I also state that int28/apm is built into DOS emulators directly, and in a very strange way sometimes. In this particular case int28 is hooked by the emulator, no matter what the underlaing DOS does: whether it hooks it himself or not. The DOS's handler will not be called. So there is simply nothing to care about.