[Info-vax] VMS internals design, was: Re: BASIC and AST routines

Stephen Hoffman seaohveh at hoffmanlabs.invalid
Tue Nov 30 11:31:34 EST 2021


On 2021-11-29 20:38:43 +0000, Chris Scheers said:

> I think this message shows the source of the confusion.
> 
> The AST dispatch/return mechanism has nothing to do with Macro32 or any 
> other language.
> 
> VMS and the VAX hardware were designed together.  The implementation of 
> each affected the other and various decisions and trade offs were made 
> to produce a viable solution given the hardware limitations of the time.
> 
> A large part of what made VMS's capabilities unique in the day was the 
> AST.  This provided capabilities that other OSes (including Linux and 
> Windows) have yet to provide.  Likewise, it also required restrictions 
> that other OSes (including Linux and Windows) do not have.
> 
> In VAX/VMS, there is not a software AST "routine" dispatcher.
> 
> The AST dispatch/routine mechanism is implemented in the VAX hardware.
> 
> The extra "arguments" are the hardware context required by the VAX 
> hardware to correctly execute the AST return.
> 
> The programing practice has always been to ignore those arguments.
> 
> Would a pure software design have done it some other way.  Of course!
> 
> But such a software redesign would have impacted more than just VMS. 
> ASTs are used in many user mode programs.
> 
> If you want to blame something, blame the VAX hardware design.  But, 
> that very design is what made VMS viable in the 1970/1980s time frame.


The VAX/VMS AST delivery code is not hardware. It's software. The code 
is located in module ASTDEL (see routines SCH$QAST, SC$ASTDEL, 
EXE$ASTRET, etc), and the code had the choice of saving arguments onto 
the argument list or saving arguments on the other side of the frame 
pointer for the AST, and the developer chose oddly.

A REI instruction triggers an interrupt to go check for some pending 
work, and that interrupt then runs a whole lot of software. Including 
the CALLG used to pass control to the AST code. Since it was a CALLG 
instruction used to pass control to the AST, passing one argument would 
have worked as well as five. Not that use of a CALLS would have 
significantly changed the flow, other than moving the AP/FP around a 
little and wasting some stack. But we have five arguments.

AST delivery does need to preserve the registers involved (as CALLS and 
CALLG do not preserve R0 and R1 per the calling standard), though the 
visibility of those added arguments on the AST call are basically 
useful only for causing corruptions in apps. Which is what Simon is 
grumbling about. The whole design tends to point to latent 
argument-mismatches in many uses of ASTs, too. That'll be fun to fix, 
just as soon as better diagnostics are enabled in the various 
programming languages the ASTs are written using.

And that AST argument list design is not changing soon. There's no 
reason to change this current ASTDEL argument-list design ~forty years 
on either, absent larger changes such as those involved with some 
hypothetical implementation of object-oriented message-passing support 
on OpenVMS.



> Simon Clubley wrote:
>> On 2021-11-26, abrsvc <dansabrservices at yahoo.com> wrote:
>>> I find these kind of comments somewhat offensive since it is easy to 
>>> criticize the decisions of people made 40 years ago using the context 
>>> of knowledge today.  VMS was designed as a cooperative pairing of both 
>>> hardware and software.  The use of R0 and R1 was for consistency across 
>>> calls and had nothing to do with MACRO32 at all.  Bliss used the same 
>>> register conventions.  If the VMS and VAX engineers knew in the late 
>>> 70's what was known now, I suspect things would have been done 
>>> differently.
>>> 
>> 
>> Hello Dan,
>> 
>> The problem is not the preserving of R0/R1/PC/PS{L}, but the way in 
>> which it was done. This information should be private to the AST 
>> dispatcher that calls the AST routine. It should never be visible to 
>> the called AST routine itself because that is an outright violation of 
>> good modular design and that's as true back when VMS was designed as it 
>> is now.
>> 
>> In case you are familiar with bare metal interrupt programming, you can 
>> compare the calling of an AST routine with the way that an interrupt 
>> handler is called when working with bare metal code or when 
>> implementing an OS itself.
>> 
>> On more advanced MCUs, you can have an assembly language interrupt 
>> dispatcher that calls the actual C language interrupt handler and you 
>> can end up having to save more interrupt state than just the normal 
>> registers in your assembly language interrupt dispatcher.
>> 
>> However, that information is always private to the interrupt 
>> dispatcher, and is _never_ exposed to the interrupt handler itself and 
>> this is so universally true, that I didn't even realise what the AST 
>> registers were being used for until it was pointed out to me.
>> 
>> For example, in one bare metal assembly language interrupt dispatcher I 
>> wrote a while back for an ARM processor and which I was looking at 
>> recently, the dispatcher has to save what is called the priority 
>> limiter register before programming a new value (this allows nested 
>> interrupts to occur).
>> 
>> This is saved onto the stack by the dispatcher before calling the C 
>> language interrupt handler and is restored by the interrupt dispatcher 
>> upon return from the interrupt handler. This information is private to 
>> the dispatcher, it is not visible to the interrupt handler, and I would 
>> never design a system where it was, because that is an utter violation 
>> of modular and good programming practice.
>> 
>> That priority limiter register can be compared to one of those private 
>> AST registers and that's why I consider it so wrong that those private 
>> registers are there in the AST call frame and hence visible to the 
>> called routine as it's an utter violation of good modular design.



As for some of the other replies in this thread...

Threading is now baked into OpenVMS (KP), into Linux (POSIX AIO since 
2.6, io_uring/liburing more recently, etc), and similarly built into 
most other platforms. ASTs aren't particularly unique in 2021.

Ignoring the hardware register stuff in the VAX/VMS AST argument list, 
ASTs are somewhat a pain in the arse as compared with some other 
designs too, but ASTs can and do work. And KP threading isn't all that 
well integrated into the OpenVMS system service calls. There are some 
discussions on mixing threads and ASTs around on OpenVMS, and there are 
subtleties awaiting app developers here. The OpenVMS documentation did 
not cover this area at all well, when last I checked.

As for whether Macro32 was involved in this design? Donno. Kernels 
still tend to mess with registers in some corners, and assemblers are 
still better than that than is C with asm or built-ins, or some other 
alternative. Though we're getting pretty close with the alternatives.

There are other stupid ideas in OpenVMS, such as the successful access 
violation, and using localtime in the system clock.

Oh, and there was a replacement created for VAX/VMS at DEC—built with 
things learned from VMS and other work—and that replacement has been 
quite successful in the market. That replacement? DEC MICA. For some 
posters, a platform which largely sees references around here in the 
comp.os.vms newsgroup as a source of examples of mistakes that OpenVMS 
should... emulate? implement? something.




-- 
Pure Personal Opinion | HoffmanLabs LLC 




More information about the Info-vax mailing list