Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to index page
Thread view  Board view
kerravon

E-mail

Sydney, Free World South,
08.05.2025, 00:24
 

hot dos (Developers)

When I run DOS 4.0 or Freedos under Virtualbox or qemu, it maxes out a CPU core (as far as I can tell).

Even though it is just sitting at the command prompt waiting for a keystroke.

Any idea what is causing that?

I would have expected the BIOS provided by Virtualbox/qemu to just ask the underlying host for a keystroke and that would put it to sleep.

I guess the timer interrupts will still be firing, but those too are internal to Virtualbox/qemu so I expect them to be small, even if it doesn't have the smarts to recognize that in this situation it doesn't need to run them at all.

Thanks. Paul.

ecm

Homepage E-mail

Düsseldorf, Germany,
08.05.2025, 00:36

@ kerravon
 

hot dos

> When I run DOS 4.0 or Freedos under Virtualbox or qemu, it maxes out a CPU
> core (as far as I can tell).
>
> Even though it is just sitting at the command prompt waiting for a
> keystroke.
>
> Any idea what is causing that?
>
> I would have expected the BIOS provided by Virtualbox/qemu to just ask the
> underlying host for a keystroke and that would put it to sleep.
>
> I guess the timer interrupts will still be firing, but those too are
> internal to Virtualbox/qemu so I expect them to be small, even if it
> doesn't have the smarts to recognize that in this situation it doesn't need
> to run them at all.
>
> Thanks. Paul.

You have to idle the machine while waiting. Unfortunately most DOS and ROM-BIOS do not do that. Try loading fdapm apmdos (most aggressive savings) or fdapm adv:reg (less aggressive to minimise delays).

A build is available at https://pushbx.org/ecm/download/fdapm.zip This build supports the fdapm unload command.

---
l

kerravon

E-mail

Sydney, Free World South,
08.05.2025, 01:25

@ ecm
 

hot dos

> You have to idle the machine while waiting.

Wow - that's fascinating! I have fdapm under Freedos
already, so I tried "fdapm /apmdos" and it brought
things under control.

I also saw the spinup/spindown and realized that
someone needs to be responsible for switching off
the disks when they are not in use.

> Unfortunately most DOS and ROM-BIOS do not do that.

You say "unfortunately" - but I have a question. Whose
responsibility do you think it ideally is to do this work?

And especially the spinning down of disks. If you know
you are waiting for a keystroke, should you begin the
disk spindown procedure straight away, or does that
cause an issue if the user is touch-typing and the next
keystroke is 0.1 seconds away?

If a complex algorithm is required, then perhaps it is
best relegated to DOS. And in fact, DOS would ideally
have the smarts to see that a keystroke is not enough
to wake up the disk - it should only be done if after
sufficient keystrokes, there is some request for disk
services.

Thanks. Paul.

ecm

Homepage E-mail

Düsseldorf, Germany,
08.05.2025, 10:42

@ kerravon
 

hot dos

> > Unfortunately most DOS and ROM-BIOS do not do that.
>
> You say "unfortunately" - but I have a question. Whose
> responsibility do you think it ideally is to do this work?

Whoever is in a polling loop. When you call 16.00 then the int 16h handler goes into a polling loop until a keypress is available. When you call 21.08, either the DOS goes into a polling loop, or else it translates the call to a 16.00 (or 16.10, 16.20) so again the int 16h handler does the polling loop. The same is true of 21.0A, it has to do a polling loop at some point if no complete input line is available yet.

This also means if your *application* does a polling loop, then it should idle the machine while waiting. This can be querying keypresses using DOS stdin (21.0B), or the int 16.01/16.11/16.21, or mouse movement or clicks, or serial port data reception. If no input is received, then there is an opportunity to wait until something happens, so the CPU should be idled.

For instance, idling with sti and hlt, if it works, may let the CPU idle until the next IRQ arrives, be it a timer, keyboard event, serial I/O, etc.

In lDebug the idling is done in getc within lineio.asm. The idle function is also in this file. Note that several options flags can be used to modify the application's behaviour.

> And especially the spinning down of disks. If you know
> you are waiting for a keystroke, should you begin the
> disk spindown procedure straight away, or does that
> cause an issue if the user is touch-typing and the next
> keystroke is 0.1 seconds away?
>
> If a complex algorithm is required, then perhaps it is
> best relegated to DOS. And in fact, DOS would ideally
> have the smarts to see that a keystroke is not enough
> to wake up the disk - it should only be done if after
> sufficient keystrokes, there is some request for disk
> services.

Spinning down disks is vastly less important than idling the CPU during input polling loops.

---
l

kerravon

E-mail

Sydney, Free World South,
08.05.2025, 12:55

@ ecm
 

hot dos

> For instance, idling with sti and hlt, if it
> works,

What is the reason this might not work?

> may let the CPU idle until the next IRQ arrives, be it a timer,
> keyboard event, serial I/O, etc.

I was thinking about the philosophy of this. I am
tempted to replace (or raise a bug report) on the
BIOS used by Virtualbox.

But that seems a bit impractical.

But also it is unclear to me how DOS 4.0 etc could
be logically changed - correctly - ie without needing
the timer to save the day.

If there is no timer to save the day, then if I do a
BIOS request to see if there is a keystroke pending,
and then do a HLT if I have nothing, well - the
keystroke may have come in and been processed just
before I did the HLT. In which case the system will
hang waiting for an interrupt that will never come.

So it makes more sense - logically - to do this in
the BIOS instead - even if it means waiting for a
bug fix (or forking it).

I was thinking that on the other hand, if I was
waiting for input from either the serial port or
the keyboard, then it would make more sense to do
it in DOS 4.0. But that's exactly why I don't do
multitasking of any sort. I don't want any such
complication in my code. I want to get a simple
system working first. Which means you read from
the keyboard and then wait.

I do have code to wait on the serial port, but
it relies on manipulating the hardware.



; enable interrupts and then halt until interrupt hit
hltintgo:
hloop:
; I believe hlt will be interrupted by other interrupts, like
; the timer interrupt, so we need to do it in a loop
sti
hlt
cli
jmp hloop
hltinthit:
; remove return address, segment and flags from the stack as we
; do not intend to return to the jmp following the hlt instruction
; that was likely interrupted
add esp, 12
; note that interrupts will be disabled again (I think) by virtue
; of the fact that an interrupt occurred. The caller would have
; disabled interrupts already, so we are returning to the same
; disabled state.
ret


intaddr = (unsigned long)hltinthit;

/* we are interested in this interrupt */
xch = PREADB(imr);
xch &= ~(1 << (intno % 8));
PWRITEB(imr, xch);

uartEnableGPO2(&uart);

/* uartEnableModem(&uart); */
/* uartRaiseDTR(&uart); */
/* uartRaiseRTS(&uart); */
/* uartCTS(&uart); */
intdesc1 = (0x8 << 16) | (intaddr & 0xffff);
intdesc2 = (intaddr & 0xffff0000)
| (1 << 15)
| (0 << 13)
| (0x0e << 8);
disable();
G_intloc[(intno + 0xb0) * 2] = intdesc1;
G_intloc[(intno + 0xb0) * 2 + 1] = intdesc2;
uartEnableRxRDY(&uart);
hltintgo();
/* if I immediately disable UART interrupts, I can no
longer read the old pending id of RxRDY.
If I read the pending ids, RxRDY just gets reasserted,
presumably because I haven't actually read the
character yet.
If I try reading the character, a new character may
come in and I'll miss it.
So the safest thing to do is just disable interrupts
and assume that RxRDY was hit, since that was the only
thing actually enabled, and I don't bother reading the
interrupt ids. */
G_intloc[(intno + 0xb0) * 2] = old1;
G_intloc[(intno + 0xb0) * 2 + 1] = old2;
uartDisableInts(&uart);
enable();
ch = uartRecCh(&uart);
PWRITEB(0x20, 0x20);
uartDisableGPO2(&uart);

xch = PREADB(imr);
xch |= (1 << (intno % 8));


BFN. Paul.

ecm

Homepage E-mail

Düsseldorf, Germany,
08.05.2025, 20:07

@ kerravon
 

hot dos

> > For instance, idling with sti and hlt, if it
> > works,
>
> What is the reason this might not work?

Virtual Machines or Virtual 86 Mode Monitors may either support idling with HLT, ignore the HLT silently, or even treat it as a fault exception. Likewise in DPMI Protected Mode, a HLT may not be supported by the DPMI host.

On dosemu2's (native mode, no KVM) DPMI host HLT leads to a GPF.

Using HDPMI32 on a qemu VM (no KVM), HLT appears to be fully supported, both running without throwing an exception and apparently idling the CPU.

---
l

kerravon

E-mail

Sydney, Free World South,
08.05.2025, 23:21

@ ecm
 

hot dos

> > > For instance, idling with sti and hlt, if it
> > > works,
> >
> > What is the reason this might not work?
>
> Virtual Machines or Virtual 86 Mode Monitors may either support idling with
> HLT, ignore the HLT silently, or even treat it as a fault exception.
> Likewise in DPMI Protected Mode, a HLT may not be supported by the DPMI
> host.
>
> On dosemu2's (native mode, no KVM) DPMI host HLT leads to a GPF.

This would only be if you are actually in protected
mode though, right?

I am interested in adding hlt to DOS 4.0 which would
be real mode. It should always be a valid instruction,
right?

ecm

Homepage E-mail

Düsseldorf, Germany,
09.05.2025, 01:16

@ kerravon
 

hot dos

> This would only be if you are actually in protected
> mode though, right?

Yes.

> I am interested in adding hlt to DOS 4.0 which would
> be real mode. It should always be a valid instruction,
> right?

In Real 86 Mode yes. But the DOS can run with an EMM using V86 Mode, and then HLT may or may not work in the 86 Mode code.

---
l

kerravon

E-mail

Sydney, Free World South,
09.05.2025, 02:01

@ ecm
 

hot dos

> > This would only be if you are actually in protected
> > mode though, right?
>
> Yes.
>
> > I am interested in adding hlt to DOS 4.0 which would
> > be real mode. It should always be a valid instruction,
> > right?
>
> In Real 86 Mode yes. But the DOS can run with an EMM using V86 Mode, and
> then HLT may or may not work in the 86 Mode code.

I'm not familiar with V86 mode.

So DOS 4.0 can run in V86 mode, and then some instructions
are potentially no longer available? Is it just HLT or
could I potentially be denied access to do OUT etc?

And if so, I should ideally avoid such instructions and
do what instead? BIOS calls? ie with the benefit of
hindsight, DOS 4.0 shouldn't issue HLT etc, it should
instead just do BIOS calls?

Ringding

09.05.2025, 14:33

@ kerravon
 

hot dos

> So DOS 4.0 can run in V86 mode, and then some instructions
> are potentially no longer available? Is it just HLT or
> could I potentially be denied access to do OUT etc?

Of course you can. This is the entire point of V86 mode!

kerravon

E-mail

Sydney, Free World South,
09.05.2025, 15:22

@ Ringding
 

hot dos

> > So DOS 4.0 can run in V86 mode, and then some instructions
> > are potentially no longer available? Is it just HLT or
> > could I potentially be denied access to do OUT etc?
>
> Of course you can. This is the entire point of V86 mode!

I thought the whole point was to run DOS.

Unless DOS happened to be written a certain way,
you need to supply DOS with everything it needs.
You can't deny DOS the instructions it needs
to operate! If you're going to stop DOS from
working, you don't need any special mode - you
simply say "you can't run DOS anymore".

Ringding

09.05.2025, 16:13

@ kerravon
 

hot dos

Well, the VMM would intercept the forbidden instructions and handle them as it saw fit. Either emulating virtual hardware like the VGA card or the COM port or ignoring them or terminating the offending program.

kerravon

E-mail

Sydney, Free World South,
10.05.2025, 01:32

@ Ringding
 

hot dos

> Well, the VMM would intercept the forbidden instructions and handle them as
> it saw fit. Either emulating virtual hardware like the VGA card or the COM
> port or ignoring them or terminating the offending program.

I'm getting the impression that DOS 4.0 should neither
manipulate the hardware nor use the HLT command, so that
it can run in a virtual environment.

ie with the benefit of hindsight, this is something that
should have been true ever since MSDOS 1.0.

Indeed - it may already be true - I'm not familiar with
DOS internals.

And that MSDOS - from day 1 - should have instead been
doing a BIOS call to do anything hardware-specific.

And IF that is true then it would seem to me that I
need to raise a fault in the BIOS keyboard routine.
It is not DOS 4.0's job to recognize a lousy BIOS
and basically bypass the BIOS keystroke-wait routine
that does a hard poll.

kerravon

E-mail

Sydney, Free World South,
13.05.2025, 09:04

@ ecm
 

hot dos

> > > For instance, idling with sti and hlt, if it
> > > works,
> >
> > What is the reason this might not work?
>
> Virtual Machines or Virtual 86 Mode Monitors may either support idling with
> HLT, ignore the HLT silently, or even treat it as a fault exception.
> Likewise in DPMI Protected Mode, a HLT may not be supported by the DPMI
> host.
>
> On dosemu2's (native mode, no KVM) DPMI host HLT leads to a GPF.

I'm interested in this.

Was MSDOS modified in order to "be nice" to V86 machines?

If so, when was it modified, and is DOS 4.0 "nice"?

Ringding

10.05.2025, 09:21

@ kerravon
 

hot dos

> If there is no timer to save the day, then if I do a
> BIOS request to see if there is a keystroke pending,
> and then do a HLT if I have nothing, well - the
> keystroke may have come in and been processed just
> before I did the HLT. In which case the system will
> hang waiting for an interrupt that will never come.

That’s an interesting observation, and I think that the CPU would have a brief grace time immediately after the return of an ISR, during which it would not enter the halted state.

kerravon

E-mail

Sydney, Free World South,
10.05.2025, 14:40

@ Ringding
 

hot dos

> > If there is no timer to save the day, then if I do a
> > BIOS request to see if there is a keystroke pending,
> > and then do a HLT if I have nothing, well - the
> > keystroke may have come in and been processed just
> > before I did the HLT. In which case the system will
> > hang waiting for an interrupt that will never come.
>
> That’s an interesting observation, and I think that the CPU would have a
> brief grace time immediately after the return of an ISR, during which it
> would not enter the halted state.

But the code in the interrupt routine itself may
have checked to see if there is any keystrokes in
the queue, and if no, it does (some instructions)
before returning to the caller (DOS 4.0).

And during those (some instructions) the keyboard
may have been hit, the interrupt processed, the
key is now in the buffer, ready for next time I
call the "is keyboard hit?" bios interrupt.

But neither the "is keyboard hit?" routine, nor
DOS 4.0, is aware that that has just happened.

So the hlt is executed, and we wait forever, just
as the user waits forever.

Unless there happens to be a timer interrupt to
save the day. (which I don't think, logically,
we should be dependent on to save the day).

RayeR

Homepage

CZ,
12.05.2025, 19:51

@ kerravon
 

hot dos

> And during those (some instructions) the keyboard
> may have been hit, the interrupt processed, the
> key is now in the buffer, ready for next time I
> call the "is keyboard hit?" bios interrupt.

Interesting problem, from what I read here: https://wiki.osdev.org/Interrupts#From_the_keyboard's_perspective

It seems that PIC is blocked to send more IRQs during handling it until you explicitly finish the handling by:

When the CPU finishes handling the interrupt, it tells the PIC that it's OK to resume sending interrupts:
mov al,20h
out 20h,al


So if some key is hit in meantime, KBC should hold it in the internal queue and it will generate new interrupt just after you exit your ISR and do HLT it should fire IRQ again to wake you up. Am I right?

---
DOS gives me freedom to unlimited HW access.

kerravon

E-mail

Sydney, Free World South,
12.05.2025, 23:02

@ RayeR
 

hot dos

> > And during those (some instructions) the keyboard
> > may have been hit, the interrupt processed, the
> > key is now in the buffer, ready for next time I
> > call the "is keyboard hit?" bios interrupt.
>
> Interesting problem, from what I read here:
> https://wiki.osdev.org/Interrupts#From_the_keyboard's_perspective

That article says what the OS should do.

In the case of DOS 4.0, the "OS" is actually
the BIOS. ie it is the BIOS that is doing those
instructions.

> It seems that PIC is blocked to send more IRQs during handling it until you
> explicitly finish the handling by:
>
> When the CPU finishes handling the interrupt, it tells the PIC that it's
> OK to resume sending interrupts:
> mov al,20h
> out 20h,al

>
> So if some key is hit in meantime, KBC should hold it in the internal queue
> and it will generate new interrupt just after you exit your ISR and do HLT
> it should fire IRQ again to wake you up. Am I right?

And those instructions may not even be done in this
situation, as the BIOS call is probably just looking
to see if there is a buffer already in the keyboard
buffer and reporting "no". It's not actually waiting
for the key - that's a different interrupt to call
(and since it goes into a hard loop, I was
contemplating avoiding it).

Even if it was doing those instructions, those
instructions are unlikely to be the last instructions,
as the routine needs to set the return registers
correctly.

And even after the return, I still need to see if a
keystroke was pressed, before choosing to go into a
HLT. So that's non-zero instructions too.

Rugxulo

Homepage

Usono,
08.05.2025, 03:22

@ kerravon
 

hot dos

> When I run DOS 4.0 or Freedos under Virtualbox or qemu, it maxes out a CPU
> core (as far as I can tell).
>
> Even though it is just sitting at the command prompt waiting for a
> keystroke.

FreeDOS also has the IDLEHALT command in FDCONFIG.SYS.

kerravon

E-mail

Sydney, Free World South,
08.05.2025, 07:24

@ Rugxulo
 

hot dos

> > When I run DOS 4.0 or Freedos under Virtualbox or qemu, it maxes out a
> CPU
> > core (as far as I can tell).
> >
> > Even though it is just sitting at the command prompt waiting for a
> > keystroke.
>
> FreeDOS also has the
> IDLEHALT
> command in FDCONFIG.SYS.

Thanks!

IDLEHALT=1

in my config.sys works great.

rmcconne

11.05.2025, 15:15

@ kerravon
 

hot dos

> When I run DOS 4.0 or Freedos under Virtualbox or qemu, it maxes out a CPU
> core (as far as I can tell).
>
> Even though it is just sitting at the command prompt waiting for a
> keystroke.
>
> Any idea what is causing that?
>

Ah yes, the dreaded busy-wait syndrome. This has been a recognized issue since the days of CP/M, with many suggested solutions. For the 8-bit processors, it wasn't much of an problem. They were too slow for it to make a real difference. It wasn't until the second generation of 16-bit CPUs that it actually gained notice, due to the extra heat it generated. A simple Google search on "handling busy-wait" will return lots of ideas and suggestions. I also remember more than one magazine article on the topic back in the late 1900's, but they may be difficult to find now.

Good luck,

Bob

Back to index page
Thread view  Board view
22593 Postings in 2101 Threads, 402 registered users, 28 users online (1 registered, 27 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum