Windows in its earliest days was simply a shell that ran on top of MS-DOS, which means that Windows 3.1 itself was actually just a standard MS-DOS application like any other.

Yet, MS-DOS is not a multitasking operating system, and at the same time, Windows applications were compiled native-code binaries that ran without any form of managed environment. So, how exactly was multitasking of Windows binaries achieved if Windows 3.1 was simply a regular old MS-DOS program itself? Are there any old technical documents still floating around that describe the early Windows architecture internally?

  • 23
    Not entirely true. Windows 3.1 would switch the processor to protected mode, which allowed memory segmentation and other goodies that helped manage a multi-process environment. It was not simply a "MS-DOS application like any other." (Thus, it required at least an 80286 processor for those features)
    – Joe
    Commented Jun 7, 2016 at 23:43
  • 7
    Joe, windows 2.x and 1.x don't switch to protected mode. Even on windows 3.0 was "optional".
    – Zardoz89
    Commented Jun 8, 2016 at 5:22
  • 12
    @Joe Windows actually emulated "protected mode" if it wasn't available. It only really went "hardware protected" with preëmptive multi-tasking on a 386 CPU (not 286), and even then, it consisted of multiple virtual machines, some of which were "real" (for MS DOS applications) and some of which were "protected". Depending on your hardware and software configuration, Windows came all the way from "a thin GUI client on top of DOS" to "a full blown preëmptively multi-tasked OS that just happens to be started from a DOS loader instead of a bootloader".
    – Luaan
    Commented Jun 8, 2016 at 8:57
  • 12
    Raymond Chen has written a lot about how old versions of Windows worked on his blog, The Old New Thing. I recommend a perusal of the history tag on The Old New Thing.
    – user
    Commented Jun 8, 2016 at 13:37
  • 7
    Interestingly, TopView and DESQview went even above and beyond Windows and had full preemptive multitasking for (well behaved) DOS programs! The lack of memory protection (especially the interrupt table) meant that errant programs could wreak havoc. However, there's nothing that stops multitasking under DOS. There's just a lack of things to make it easy. Commented Jun 11, 2016 at 17:57

3 Answers 3


For Win16 programs, Windows implemented co-operative multitasking. Its implementation was based upon the "message loop" architecture of every Windows program.

The duty of every program was to endlessly run in a loop in which a call to the GetMessage function was performed. This function call looks whether a message to this process is in the queue. If there is one, it is retrieved (GetMessage), optionally translated (TranslateMessage, done to convert keyboard shortcuts into menu actions) and finally, passed to the window procedure (DispatchMessage).

If there is no message available in the queue, Windows suspends the current task and gives the CPU to another task. This task will try to retrieve a message from its queue as well, yielding the CPU to another task if no message is present and so on.

If a program needed to perform background tasks while there were no pending messages in its queue, it would call PeekMessage instead of GetMessage. This didn't make the task relinquish the CPU, as PeekMessage would immediately return to the caller task to inform it whether a message is available or not. This was used to time-multiplex message processing with another time-consuming task (think of a 3D program rendering but letting the user cancel that render by pressing a "Cancel" button).

If this time-consuming task was actually very time-consuming, a well-behaved program should call the Yield function from time to time, to relinquish the CPU and let other tasks run.

A badly-behaved program could easily hog the CPU by not retrieving messages too often or by spending too much time in a window procedure function.

The situation was quite different for MS-DOS boxes. They ran using the V8086 mode of the 80386 (if Windows was running in enhanced mode). Windows-aware programs ran in the so-called System VM (Virtual Machine 1). DOS boxes ran from VM 2 upwards.

DOS programs usually were badly-behaved programs, so Windows assigned each DOS box a different virtual machine. Virtual machines used pre-emptive multitasking in Windows 3.1, so each DOS box could run concurrently to others and to any Windows-aware program.

  • 5
    In MSDOS Int 28h worked as an idle call when it was waiting for input. Also when running with DPMI hosts (such as windows 3.x) you could call int 2fh function 1680h (Release current virtual machines time slice) I added these to a Dos based application to improve the performance when running under Windows. (exact details may be wrong it's over 20 years ago now)
    – PeterI
    Commented Jun 8, 2016 at 14:07
  • 8
    A TSR program didn´t have to do anything with multitasking. They usually intercepted some DOS or BIOS vector so they would be triggered by some event (press a hot key, the timer interrupt, activity on the disk, etc). About int 28h and int 2Fh, those mechanisms came into scene when Windows was marketed. Before that, many DOS programs were made so no one of them was aware of such added functionality. Instead, programmers learned soon how to directly write on the screen, read keyboard, etc, making the DOS world a wilder place than the old west... Commented Jun 8, 2016 at 17:04
  • 2
    ...Those system calls of course helped DOS programs to behave a little better in the new Windows world, but the majority of them, just didn´t use them. Anyway, my answer has been edited to not to cause misinformation :) Commented Jun 8, 2016 at 17:04
  • 2
    Remember that DOS+Windows 3.1 also had Standard Mode, which was somewhat different to the 386 Enhanced Mode that you describe here.
    – JdeBP
    Commented Jun 8, 2016 at 18:31
  • 3
    As someone who tried to take advantage of that multiple DOS box thing - it wasn't as stable as one might like. I presume due to all the weirdness that DOS programs were wont to commit, the system had a tendency to get crash when running multiple DOS boxes. Commented May 21, 2017 at 2:21

Found a great answer on Super User that explains it really well!

Windows 3.1 uses cooperative multi-tasking – meaning that each application that is in the process of running is instructed to periodically check a message queue to find out if any other application is asking for use of the CPU and, if so, to yield control to that application. However, many Windows 3.1 applications would check the message queue only infrequently, or not at all, and monopolize control of the CPU for as much time as they required. A pre-emptive multi-tasking system like Windows 95 will take CPU control away from a running application and distribute it to those that have a higher priority based on the system’s needs.

Source: https://superuser.com/a/726367/541767

  • 10
    "A pre-emptive multi-tasking system like Windows 95 will take CPU control away from a running application and distribute it to those that have a higher priority based on the system’s needs." -- this bit is only half-true, windows 95 premptively multitasked 32-bit code but it cooperatively multitasked 16-bit code and it was sufficiently reliant on 16-bit code that freezing the 16-bit side would freeze the whole UI. Commented Jun 8, 2016 at 13:30
  • 2
    @Peter: »reliant« is a string word here. Windows 95 tried hard to keep 16-bit applications in the illusion that they are in complete control of the computer. That's why there were a lot of hooks that routed Windows-native things through old 16-bit layers when necessary to allow old things (e.g. DOS device drivers) to still work. Those were often the places where a 16-bit application could stall or crash the OS. However, it's not so much that Windows needed those 16-bit parts to run, nor did 32-bit Windows applications. As far as I know they were only active when a 16-bit program was running.
    – Joey
    Commented Jun 9, 2016 at 7:43
  • 4
    @Joey - no, the graphics subsystem on Windows 95 was (entirely) still implemented in the 16-bit GDI and User DLLs; the 32-bit APIs were implemented through thunks to the 16-bit libraries. That also meant every GUI interaction required the global lock for running 16-bit code. Commented Mar 7, 2017 at 7:12
  • 5
    @joey The entire 16 bit subsystem ran in a single thread in Windows 95. and the GDI was also 95% identical to the Win3.1 GDI and therefore 16 bit. In order to give the GDI and the 16 bit apps the illusion that they were running in Win 3.1, there was a single global lock that was taken by 16 bit apps and 32 bit apps while they were calling into the GDI.If any process hung while holding the lock, the entire graphics display would freeze, giving the illusion that the machine had frozen.
    – JeremyP
    Commented Dec 5, 2017 at 9:02

A "regular old MS-DOS program" can do absolutely anything. Modern operating systems run processes in sandboxes with limited privileges, where many things are either impossible or allowed only through OS services. MS-DOS wasn't like that. Once it transferred control to your code, you were in complete control of the machine. MS-DOS remained resident in RAM as what amounted to a library of useful subroutines. You could ignore it, or even overwrite it with Linux.

Earlier answers said that Win16 tasks were cooperatively multitasked, which is true, but I think it misses the point of the question. The question was how Windows could do something (multitasking) that is usually seen as the domain of the OS, and wasn't supported by MS-DOS. The answer is that Windows did whatever it wanted. The reasons it used cooperative rather than preemptive multitasking for Win16 programs were completely unrelated to limitations of MS-DOS.

  • Very true. One can think of any program running under MS-DOS as a "potential operating system". If the program has the routines to assume control over the interrupt facility, set up paging, and directly interact with devices, DOS won't stop it from doing so. Along those lines, I'd note it's also possible to start Linux from an MS-DOS real mode environment. The loader just sets up a similar environment to which the bootloaders do. When Linux starts there's nothing to stop it from switching the machine into protected mode and taking over. Windows 3.x did basically the same thing.
    – RETRAC
    Commented Jul 31, 2022 at 15:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .