MP/Mのプロセスディスパッチャー内部構造を解析
MP/Mプロセスの核心機構MP/Mは、CP/Mを拡張し、初期の8ビット環境でマルチタスクおよびマルチユーザー機能を実現したOSです。
本稿は、その中核機能であるプロセスディスパッチャーの仕組みを解説しています。
MP/Mのディスパッチャーは、システムコールや割り込みなどのイベント駆動で動作する優先度ベースのスケジューラです。
各プロセスは優先度に基づき待機リスト(RLR)に配置され、最も優先度の高いプロセスがCPUを取得します。
この設計は、限られたハードウェア資源の中で多重性を実現した当時の技術的な偉業と評価されています。
原文の冒頭を表示(英語・3段落のみ)
MP/M, or “Multi-Programming Monitor Control Program” is usually described as a multi-tasking and multi-user version of CP/M. I never had the chance to use it myself, but having learned to program on a Z80‑based microcomputer, I was astonished that something like MP/M could even exist on such limited hardware.At some point I decided to get a better understanding of MP/M’s internals - specifically the part that enables multitasking. The source code I examined is for MPM II and can be downloaded from the Digital Research Source Code web page. To make sense of the design, I also relied on the MP/M and MP/M II manuals from Tim Olmstead Memorial Digital Research CP/M Library.This post is a summary of my findings.Tom Rolander1 completed his master’s degree at the University of Washington in 1976 and soon after was recruited by Intel. There he joined a team that designed and developed RMX/80, a real‑time multitasking operating system for process‑control systems. After leaving Intel and then spending some time consulting for National Semiconductors, Rolander accepted invitation from Gary Kildall to join his company Digital Research Inc. (DRI) in early 1979. Kildall himself had been consulting for Intel since 1972 and, among other things, created the programming language called PL/M.At that time, DRI’s only product was an operating system for Intel 8080 compatible computers called CP/M. CP/M was very simple and flexible, which along with its low price made it the most popular OS for the 8-bit business microcomputers. By 1979, Kildall believed it was time to add support for multitasking and multiple users. One motivation was background printing; another was the fact that computer manufacturers like Altos started producing multiuser microcomputers. Adding a CP/M compatible operating system that would support them was a logical next step.Tom Rolander coded MP/M 1.0 alone, including the core OS, utilities and documentation - he described the experience as “just a huge amount of fun”. Soon after, version 1.1 came out, and then in 1981 version 2.0 and finally 2.1 in early 1982.The operating system was ported to 16-bit Intel architecture by another talented engineer Frank Holsworth in 1980/81 and named MP/M-86. It was followed by a line of “Concurrent” CP/M products which retained the MP/M core design and added features like MS-DOS compatibility. The last incarnation on MP/M family of operating systems was FlexOS which was designed for industrial and point-of-sale applications and outlived DRI by at least a decade.In the MP/M 1.0 User’s Guide, the system is described as “an upward compatible version of CP/M 2.0 with a number of added facilities”. The major additions include support for multiple users, each working on a separate terminal, and multiple tasks per user. For application programmers, MP/M introduced memory bank-switching, inter-process communication (including synchronization), and interrupts. Another interesting feature not available in CP/M was resident system processes which remained in memory alongside the OS. MP/M shipped with several standard resident processes (such as the system status display), and users could write their own.The system was described as providing “real-time” multitasking, which is misleading. MP/M is a cooperative multitasking system that switches tasks at system calls, interrupts, or clock‑tick events. It does not provide deterministic timing guarantees which we would expect from modern real-time systems.Unlike Intel’s RMX which inspired it, MP/M was not intended for process control applications that would require real-time capabilities. It was an alternative to minicomputer time-sharing systems for use from multiple “dumb” terminals in business environment. Many of these time-sharing systems were also described as “real-time” without providing any real time guarantees, so we can assume it was just a difference in terminology.Real-time definitions aside, building a preemptive multitasking system for the Intel 8080 compatible 8-bit CPUs was a real feat. The hardware offered no privilege levels, no memory protection, no thread-specific stacks, no trap instruction, no atomic primitives and only a 64‑kilobyte address space. Preemptive multitasking became a common feature on personal computers only in mid-1990s on Windows and in 2001 on Mac2.As for CP/M compatibility, it was a goal that was only partially achieved. The user guide claims that only “correctly written” CP/M programs (i.e. the ones that use only officially documented system calls) would run under MP/M. In practice, programming 8-bit machines relied not only on using undocumented system routines, but even undocumented CPU instructions.Like CP/M, MP/M is a modular system. The hardware-dependent layer is isolated in a separate module, called XIOS (Extended I/O System) which was implemented by computer manufacturers (OEMs). It is equivalent to the CP/M BIOS but extended to support multiple consoles.BDOS (Basic Disc Operating System) is included for compatibility with CP/M; it provides the same system calls. XDOS (Extended Disk Operating System) implements MP/M specific system calls including ones for managing tasks, memory and consoles. It contains the nucleus: the kernel that manages process dispatching, queue management, flag management, memory management and system timing.The process dispatcher (implemented in NUCLEUS/DISPTCH.ASM) is the heart of the nucleus. It is priority-based, which means that it selects a process with highest priority that is in ready state to transfer the CPU to it. As mentioned, it is not time-driven, but event driven. The events that cause the dispatcher to run are: system calls (BDOS or XDOS), queue operations that cause a process to block, flag wait and set operations, and hardware interrupts.The clock interrupt does not directly preempt tasks; instead, it wakes the Tick Process, which then performs delay‑list maintenance and may cause a higher‑priority process to become ready.A system process called IDLE with very low priority runs when no other process is ready. Each process is associated with a process descriptor structure that contains its priority, status, stack pointer, memory segment, console, BDOS state, and saved CPU registers. The table of descriptors (PDTBL) is defined in NUCLEUS/DATAPG.ASM.A process may be running, ready, or in one of several wait states (queue wait, flag wait, delay, poll, attach/detach, etc.).Processes that become ready are first placed on the Dispatcher Ready List (DRL). The dispatcher then inserts them into the Ready List (RLR), which is ordered by priority. Processes with equal priority are scheduled in round‑robin fashion by reinserting the running process at the end of its priority group. All that happens within the “dispatch” routine in NUCLEUS/DISPTCH.ASM:Interrupts get disabled and a global flag is set to mark the dispatcher is runningThe current process state is saved into its process descriptorThe current process is handled in accordance with its statusDevices are polledProcesses are moved from DLR to RLRThe next active process is selected and its context restored from the PDInterrupts are re-enabled The code was first written in PL/M, and the original source is (partially) preserved as comments, but the production MP/M II nucleus is written in Intel 8080 assembly. It is possible that MP/M 1.0 was written entirely in PL/M and ported to assembly for version 2.0.This concludes my modest look inside the MP/M nucleus. Beyond the dispatcher, the system has other mechanisms worth exploring: queues, flags, resident processes, the delay list… All packed into just a few kilobytes of assembly code. 2To be fair, there were relatively popular systems in mid-1980 that implemented pre-emptive multitasking, including Sinclair QL and Commodore Amiga. They used much more advanced hardware than MP/M.
※ 著作権に配慮し、引用は冒頭3段落までです。続きは元記事をご覧ください。