http://www.phparch.com \ May 2019 \ 37
Memory Abstractions
Internal Apparatus
- Make the update (deduct 100 points from Alice; add 100
points to Bob) - Release the lock (commit transaction)
Even operating system programmers—as we are about
to see—get this wrong. Here is the correct “critical region”
sequence: - Lock out other processes (begin transaction)
- Check/verify the prerequisite conditions
- Make the update
- Release the lock (commit transaction)
So what is the possible bug? Another process, running
simultaneously, could have changed the pool size after we
checked the pool size and before we locked out interrupts. In
modern terms, we’ve just hit the concept of thread safety^9.
Do we care about thread safety with PHP? Yes, we do!
Check the PHP downloads for Windows^10 page, for example.
Each version contains both “Non Thread Safe” and “Thread
Safe” versions. The Obtaining PHP^11 page has a list of exten-
sions, noting “those marked with a * are to the best of our
knowledge not thread safe; they are not recommended for
use in a multi-threaded environment.”
A multi-threaded environment is where we have several
threads of execution, all sharing the same memory, variables,
and data structures. It’s easy to picture several PHP requests
all sharing the same database table, but it’s more difficult to
picture several PHP requests sharing the same in-memory
objects and variables.
PHP is typically deployed (as the “LAMP” stack of Linux,
Apache, MySQL, PHP) in an isolated-process environment.
Each PHP request cycle is its own process. It does not share
memory or state with any other PHP request’s processing.
However, we now have tools such as ReactPHP which let
us run a PHP-based server. We need to allow for sharing
memory and other resources across individual requests.
In our operating system example, we have several (unseen)
operating system threads all able to interrupt each other
between one line of code and the next. One thread needs to
lock out all other threads while it updates the shared data
structure.
Let’s get back to our story. I was busily transferring into
the software training group to teach the operating system
internals. I sat through the whole sequence since I’d be
teaching part of it. That’s great, but we actually had two oper-
ating systems to learn. There was the mainframe operating
system—a two-week class that I’d be teaching—and the I/O
Subsystem, a mini-supercomputer in its own right, with its
real-time operating system written in its unique assembler
language. And another two weeks of class. It was nuts.
9 thread safety: https://en.wikipedia.org/wiki/Thread_safety
10 PHP downloads for Windows: https://windows.php.net/download
11 Obtaining PHP: https://php.net/faq.obtaining
The I/O Subsystem (IOS) processors contained only 128KB
of memory, the same as the Apple IIe and IIc personal
computers available at the time—but it was awfully fast.
The operating system, data structures, I/O buffers, channel
drivers, everything, had to share that 128KB. The IOS soft-
ware was built around two concepts: speed (a given), and
memory management.
The IOS class included a class project. We each needed
to write an “overlay” that does something, much like “hello
world.” That sounds trivial, but it isn’t. It’s something like
writing an extension to the Linux kernel. The student overlay
needs to get registered with the rest of the operating system
software. We need to then boot the multi-million-dollar
mainframe with the modified IOS software. When something
doesn’t work as expected, the instructor may or may not be
able to help.
Rebuilding the software might mean waiting until the next
day for another try, and we’re already at the last couple of class
days. Most students completed the assignment as 20-30 lines
of code: Display something on the operator console and exit.
I, on the other hand, asked around. Had anyone ever created
a game program as their assignment? Nope. It’s never been
done. With limited class time and minimal test time, there’s
a good reason that new students never made the attempt in a
new just-learned assembly language.
So I wrote an adventure game, inspired by Colossal Cave
Adventure. It’s a tour of Switzerland (above ground), with
a maze of twisty passages nearly all alike (mid-game), and
a final puzzle involving Arabic words (brutal end game).
We had just moved back to Minnesota after living in Saudi
Arabia; thus a challenge in Arabic seemed like the right thing
to do.
The program did have a problem, which I considered a
feature at the time. You could not exit the program except by
winning (completing) it. One had to solve the whole thing or
reboot the Cray mainframe. Oops! It took over the operator
console by design, blocking any other sysadmin activity from
happening on that particular console.
So what good does this bit of time travel do us today? Then,
as now, memory management is a central consideration of
running software. The details don’t matter, but the concepts
do.
With Adventure-style games, the back story is crucial. If you
lose the flyer that came with the game, the game won’t make
any sense. Now we have the back story for Swiss Adventure
(1986), an obscure game hidden inside an obscure operating
system.
Swiss Adventure will be one of our learning tools, beginning
next month. The original was constrained in that the entire
operating system ran on hardware with only 131,072 (128K)
bytes of memory, and Swiss Adventure was hidden inside that
operating system. It was an adventure in memory manage-
ment more than anything else; just what we need!
Let’s see some of these memory concepts in action.