A little about the HP3000

Today’s anonymously submitted story is a case where WTF isn’t the code itself, per se. This could probably be CodeSOD, and we’ll get to the code, but there’s much more to the story.

Our applicant, let’s call them Janice, worked for a financial institution with a number of legacy systems. One such system was the HP3000 minicomputer. “Mini”, of course, means “refrigerator-sized”.

The HP3000 itself is an interesting, albeit peripheral story, as it is one of the product launch stories incredibly wrong. Let’s talk a little about history.

We start with the 1966 HP2100, which Hewlett Packard did nothing to design, but instead bought the company that designed it. The fundamental innovation of the HP2100 was that it was similar in architecture to the PDP-8, but supported full 16-bit memory, instead of the PDP’s 12-bit.

HP didn’t really know what it was buying – they marketed it as a “test and instrumentation” system and were surprised when companies bought it for back office operations. They ended up with one of the most popular minicomputers for office use, even though it wasn’t designed for that purpose.

That’s how the “Alfa” and “Omega” projects began. The Alpha is a hardware refresh of the 2100, with a better memory model. The Omega was a major redesign for 32-bit memory, which would have allowed it to support a whopping 4MB of RAM. There was only one problem with the Omega design: they didn’t have the means to actually finish it. The project was discontinued in 1970, throwing some of the staff into “wear black armbands at work” levels of mourning.

Unfortunately, while the Omega was being worked on, the scope of the Alpha was shrinking, resulting in another project management that was not certain to be deliverable. But there was a market for a time-sharing minicomputer, so they continued despite the concerns.

The HP2000 line had a time-sharing system that used multiple processors. There was a front-end processor that handled user interactions. There was also the actual CPU that ran the programs. This meant that time sharing was simplified – the CPU just ran programs in a circular fashion and didn’t have to worry about boring things like user input. In essence, it was really just a batch processing system with a multi-user interface.

Alpha designers wanted to support full multiprogramming, instead of this hybrid model. But they also needed to support traditional batch processing as well as real-time execution. So the team split off to create the components of the “Multi-Programming Executive” module, which would enable all these features.

Alpha, which was still 16-bit, didn’t have the luxury of 4 MB of RAM – it had 128 kB. MPE used much more memory than 128kB. This led to a lot of downtime as the developers worked to whittle the MPE down to something usable while marketing looked at the deadlines and said, “We should have sold this thing months ago!”

The result was a huge war between engineering and marketing, where marketing made promises to customers about what performance would be, engineering told marketing what real performance would be (significantly worse than what marketing promised), and then management would demand engineering “proof” that marketing’s over-promises could be delivered.

The initial shipping date was November 1972, and by God, they were shipped on time. Nothing really worked, but they sent. The first computer out the door was returned almost immediately. It could only handle two simultaneous users before it slowed to a crawl, crashing every ten minutes. By December, HP had it down to “crashing every two hours.” They continued to ship machines even though they had to cut back on features and reliability promises.

Those frequent crashes also hid another bug: after running for 24 days, the HP3000 clock would overcharge (2^31 milliseconds) and the clock would magically turn back 25 days. As one sysop of a purchased HP3000 said: “The original MPE designers never thought the OS would stay on for 25+ days straight”.

After a bunch of management reshuffles, Hewlett Packard’s titular Packard has sent a memo: production is halting and all computers sold are being recalled. Customers were offered the HP2000 instead, or they could wait until the fall of 1973 for a revised version – which would only support 4-6 users, far less than the initial marketing promise of 64. This didn’t make anyone happy, and some customers are reported to have cried over disappointments.

Along with the sales hiatus, the entire computer underwent a design overhaul. The resulting machine was faster and cheaper and can actually handle 8 simultaneous users. A year after its failed launch, the HP3000 returned to the market and ended up a resounding success.

It was so successful that HP continued to support the HP3000 until 2010, which is where Janice enters our story. Around 2006, she needed to update some Pascal code. That code used a lot of bitmasks to handle flags, which is normal, regular a fairly simple function in Pascal – the language has a standard set of bitwise operations. So Janice was surprised when she saw:

FUNCTION BITON(A , B : INTEGER): BOOLEAN;
VAR
        C : INTEGER;
BEGIN
        CASE A OF
                15 : C:=1;
                14 : C:=2;
                13 : C:=4;
                12 : C:=8;
                11 : C:=16;
                10 : C:=32;
                9 : C:=64;
                8 : C:=128;
                7 : C:=256;
                6 : C:=512;
                5 : C:=1024;
                4 : C:=2048;
                3 : C:=4096;
                2 : C:=8192;
                1 : C:=16384;
                0 : C:=32768;
        OTHERWISE
                BITON:=FALSE;
        END;
        IF ((B DIV C) MOD 2) = 1 THEN
                BITON:=TRUE
        ELSE
                BITON:=FALSE;
END;

FUNCTION SETBITON(A, B : INTEGER) : INTEGER;
VAR
        C : INTEGER;
BEGIN
        CASE A OF
                15 : C:=1;
                14 : C:=2;
                13 : C:=4;
                12 : C:=8;
                11 : C:=16;
                10 : C:=32;
                9 : C:=64;
                8 : C:=128;
                7 : C:=256;
                6 : C:=512;
                5 : C:=1024;
                4 : C:=2048;
                3 : C:=4096;
                2 : C:=8192;
                1 : C:=16384;
                0 : C:=32768;
        OTHERWISE
                C:=0;
        END;
        IF NOT BITON(A,B) THEN
                SETBITON:=B + C
        ELSE
                SETBITON:=B;
END;

FUNCTION SETBITOFF(A, B : INTEGER) : INTEGER;
VAR
        C : INTEGER;
BEGIN
        CASE A OF
                15 : C:=1;
                14 : C:=2;
                13 : C:=4;
                12 : C:=8;
                11 : C:=16;
                10 : C:=32;
                9 : C:=64;
                8 : C:=128;
                7 : C:=256;
                6 : C:=512;
                5 : C:=1024;
                4 : C:=2048;
                3 : C:=4096;
                2 : C:=8192;
                1 : C:=16384;
                0 : C:=32768;
        OTHERWISE
                C:=0;
        END;
        IF BITON(A,B) THEN
                SETBITOFF:=B - C
        ELSE
                SETBITOFF:=B;
END;

FUNCTION LAND(A,B : INTEGER) : INTEGER;
VAR
        I : INTEGER;
BEGIN
        I:=0;
        REPEAT
                IF BITON(I,A) THEN
                        IF BITON(I,B) THEN
                                A:=SETBITON(I,A)
                        ELSE
                                A:=SETBITOFF(I,A)
                ELSE
                        A:=SETBITOFF(I,A);
                I:=I + 1;
        UNTIL I > 15;
        LAND:=A;
END;

This is a set of hand-crafted essential operations, culminating in LAND, which does bit-wise and (not logical and, which is why it’s annoyingly misnamed). I wouldn’t call code a terribly approach to it, even if it is definitive ineffective access (and when you’re using a 33-year-old computer, efficiency matters), but without built-in bit operations, I can’t see many other options. The biggest problem is that LAND it will set bits that are already on, which is unnecessary AND actually you just need to turn the bits turned off.

Which, as it turns out, is the root of WTF. The programmer responsible was not ignorant of essential operations. The version of Pascal that shipped with the HP3000 simply didn’t have them. Not and, or, notor xor. Not even a shift-left or shift-right operation.

Anyway, this is what happens when I start researching a story and end up being dragged down a rabbit hole. As always, the real value of Wikipedia is as a bibliography. Many of those links have much more detail, but I hope this quick overview was an interesting story.

[Advertisement]

Continuously monitor your servers for configuration changes and report if configuration drift occurs. Get started with Otter today!

Source link

Leave a Reply

Your email address will not be published. Required fields are marked *