[FreeVMS] Re: New release 0.0.54

Subject: [FreeVMS] Re: New release 0.0.54
From: Roger Tucker (roger.tucker@mci.com)
Date: Wed Sep 15 2004 - 04:29:31 CEST


It sure is easy to take things that you thought to be true as always true!

I'm not sure I can explain this, but I in researching the VAX INSQUE and
REMQUE instructions why there was a PAL_INSQUEL_D() routine and a
PAL_REMQUEL_D routines, I found something I never thought about.

Basically, you cannot write a insque() or a remque() routines that are
AST/interrupt safe!
Even the builtin routines _INSQUE(), _REMQUE(), _PAL_INSQUE() and
_PAL_REMQUE() routines are NOT interrupt safe on AXP and cannot be fixed!
The old VAX instructions were... Let me try to explain:

insque(element, queue); // insert at head - works correctly.
insque(element, queue[1]); // insert at tail - fails
remque(pred, &removed_entry); // never safe, even at head or tail.
  For example: remque(queue[0], &entry);
            or: remque(queue[1], &entry);

The problem is, that you cannot dereference the queue (as in queue[1])
without first turning off interrupts, and you don't turn off interrupts
until your in the routine. If you dereference the queue or any element on
the queue before the call and pass it as an argument, an interrupt could go
off, and change the queue out from under you. But it's too late, you have
already dereferenced the queue. Then things would be out of order, or worse
yet, you could insert, modifying an element that has already been removed
from the queue. To prove this, I wrote some test programs on alpha using
the build-in routines, took a look at the assembler. I also took a look at
the insque() and remque() routines that you are using and they are broken as

I belive this is why there are the insque_d() and remque_d() routines -
theses will work since the pointer references are differed until we have
interrupts off. They turn off interrupts before evaluating the pointer.

So, the insque() and remque() routines that you are using do not work, if
they can be interrupted!!!
And there is no way to fix them, without changing them to INSQTI() for SMP,
or INSQUEL_D() for interrupts/ASTs.
The solution is to never use insque() or remque(), even in a non-SMP
environment if you could be interrupted.

Here is a simple example program to prove it.
#include <builtins.h>

static void *queue[2];

void removeit(void)
    void *(*bufptr)[2];
    _REMQUE(queue[1], &bufptr); /* remove from tail */
    (*bufptr)[0] = (*bufptr)[1] = 0; /* zero the pointers to cause an
accvio */

    queue[0] = queue[1] = queue;

    void *test1[2];
    void *test2[2];
    void *test3[2];

    _INSQUE(test1, queue[1]); /* Insert at tail */
    _INSQUE(test2, queue[1]); /* Insert at tail */
    void *tail = queue[1]; /* get the tail */
    removeit(); /* simulate an AST */
    _INSQUE(test3, tail); /* Insert at tail */

Try to write this with the queue.h, queue.c routines and you will find the
exact same problem.
You cannot take the value of queue[1], with interrupts still on!
I searched our code here at MCI and we have several of theses problems as
I even check the AXP documentation and although they are named the same as
the VAX instruction, they do not say that they are interrupt safe!

I'm working on a queue.h and queue.c that works correctly!

I hope you understand all of this,
Roger Tucker

Liste de diffusion FreeVMS
Pour se désinscrire : mailto:freevms-request@ml.free.fr?subject=unsubscribe

This archive was generated by hypermail 2b25 : Wed Sep 15 2004 - 04:27:06 CEST