              <<< VAXAXP::NOTES$:[NOTES$LIBRARY]VMSNOTES.NOTE;1 >>>
               -< VAX and Alpha VMS - Digital Internal Use Only >-
================================================================================
Note 733.8           Shareable and lock on OVMS AXP problem               8 of 8
COMEUP::SIMMONDS "loose canon"                      226 lines  21-JUN-1997 09:15
--------------------------------------------------------------------------------
    Re: .0,.6
    
    The two critical problems with your UWSS code are :
    
    1. INIT_NUMERO.PAS locks a resource name which has a trailing <SPACE>
       but uwstd.c does not.
    2. uwstd.c queues and dequeues EXECUTIVE Mode locks, but the initial
       resource created by INIT_NUMERO.PAS is guarded by a USER Mode lock.
    
    A minimally corrected version of uwstd.c which works follows.. but you
    should really make the other changes suggested by Steve H.  Use diff.
    to reveal all the changes..  I didn't bother to try your non-uwss code.
    
    John.
    ----
/*
**
*/

/* And now, on with the program... */
#include <string.h>

#include <descrip.h>
#include <stsdef>
#include <ssdef.h>
#include <psldef.h>
#include <lckdef.h>
#include <chfdef.h>
#include <builtins.h>
#include <lib$routines.h>
#include <starlet.h>
#include <prdef.h>
#include <psldef.h>
#include <plvdef.h>


/*
*/
#define PRIVALL 0x0ffffffff

#define PRV$_ENABLE 1
#define PRV$_DISABLE 0
#define PRV$_PERMANENT 1
#define PRV$_TEMPORARY 0

#define LOAD_DESCRIPTOR(descriptor,string,length)       \
    {                                                   \
    descriptor.dsc$w_length = length;                   \
    descriptor.dsc$b_dtype = DSC$K_DTYPE_T;             \
    descriptor.dsc$b_class = DSC$K_CLASS_S;             \
    descriptor.dsc$a_pointer = string;                  \
    }

typedef struct _quad {
    unsigned long int Low;
    unsigned long int High;
    } QUADRA;

typedef struct {
    int _value;
    int _msgsize;
    char *_message;
    } user_message_t;

typedef struct _lkiosb {
		unsigned short int	Cond_Code   ;
	        unsigned short int	Reserved    ;
		unsigned int		Lck_Id	;
		unsigned int		Unique_Upper ;
		unsigned int		Unique_Lower ;
		unsigned int		spare[2];
		} LKIOSB;

// #pragma member_alignment
static LKIOSB lkiosb; 

static unsigned int prvadr[2];   /* Assumed to take no real storage*/
static unsigned int prvsave[2];  /* for private storage*/

static unsigned char savecpt;

/* "Forward routine" declarations */

int     first_service(int *);
int     rundown_handler(void);

int     numero_objet (struct _quad *, struct _quad *, char *);

/* Kernel and exec routine lists: */
int (*(kernel_table[]))(int *) = {first_service};

int (*(exec_table[]))(struct _quad *, struct _quad *, char *) = {numero_objet };
/*
** 
*/

/*
**
*/


#define EXEC_ROUTINE_COUNT sizeof(exec_table)/sizeof(int *)
#define KERNEL_ROUTINE_COUNT sizeof(kernel_table)/sizeof(int *)


int kernel_flags [] = {0,0} ;
int exec_flags [] = {0,0} ;


#ifdef __ALPHA
#pragma extern_model save
#pragma extern_model strict_refdef "USER_SERVICES"
#endif
extern const PLV user_services = {
        PLV$C_TYP_CMOD,         /* type */
        0,                      /* version */
        {
        {KERNEL_ROUTINE_COUNT,   /* # of kernel routines */
        EXEC_ROUTINE_COUNT,     /* # of exec routines */
        kernel_table,           /* kernel routine list */
        exec_table,             /* exec routine list */
        rundown_handler,        /* kernel rundown handler */
        rundown_handler,        /* exec rundown handler */
        0,                      /* no RMS dispatcher */
        kernel_flags,                      /* kernel routine flags */
        exec_flags}                     /* exec routine flags */
        }
        };
#ifdef __ALPHA
#pragma extern_model restore
#endif

/*
*/

int first_service(int *ptr)
{
    return SS$_NORMAL;			/* Indicate success */
}

/*
*/
int rundown_handler(void)
{
    return SS$_NORMAL;			/* Indicate success */
}

int numero_objet ( QUADRA * numObjetPtr, QUADRA *dummy,  char *str)
{
unsigned long
    sts,
    sts_rtn;
char Nom_Ressource[15] ;

static struct dsc$descriptor_s dsc_resource;
// static struct dsc$descriptor_s Resource_dsc;

$DESCRIPTOR(Resource_dsc, "Numéros$Dummy " );




//    prvadr[0] |= PRIVALL;
//    prvadr[1]  = 0;
//    sts_rtn= SS$_BADPARAM;
//    sts = SYS$SETPRV (PRV$_ENABLE,prvadr,PRV$_TEMPORARY,prvsave);
//    if (!(sts & 1)) lib$signal (sts);

    lkiosb.Unique_Lower = 0;
    lkiosb.Unique_Upper = 0;
    lkiosb.Cond_Code    = 0;
    lkiosb.Lck_Id       = 0;

    sts = 0;
    
    sts = sys$enqw (0, LCK$K_PWMODE,
		    &lkiosb, 
                    (LCK$M_VALBLK | LCK$M_SYSTEM), 
                    &Resource_dsc, 0, 0, 0, 0, PSL$C_USER, 0);


    if ( (sts != SS$_NORMAL) ||
       (lkiosb.Cond_Code != SS$_NORMAL) ||
	(lkiosb.Unique_Upper == 0 ))
    {

        /*	 
	**  Dequeue the resource cause it's not handle
	**  correctly by the system.
	*/	 

	dummy->High = lkiosb.spare[1];
	dummy->Low = lkiosb.spare[0];

	numObjetPtr->High = lkiosb.Lck_Id ;
	numObjetPtr->Low = lkiosb.Cond_Code;

	(void)strncpy (str, Resource_dsc.dsc$a_pointer, Resource_dsc.dsc$w_length );
	str[Resource_dsc.dsc$w_length]='\0';
        /*	 
        */	 
	if (sts != 1) sts_rtn = sts;
	if (lkiosb.Cond_Code != 1) sts_rtn = sts;
	if (lkiosb.Unique_Upper == 0 ) sts_rtn = 155;
    }
    else
    {
        lkiosb.Unique_Lower++ ;
        /*
        **	Set the new value in the return value
        */
	numObjetPtr->High = lkiosb.Unique_Upper ;
	numObjetPtr->Low = lkiosb.Unique_Lower ;
	sts_rtn = SS$_NORMAL;
    }
    sts = sys$deq (lkiosb.Lck_Id, 
	           &lkiosb.Unique_Upper,
    	           PSL$C_USER, 0);
    if (sts != SS$_NORMAL) sts_rtn = 65;

//    sts = sys$setprv (PRV$_DISABLE,prvsave,PRV$_TEMPORARY,0);
//    if (sts != SS$_NORMAL) sts_rtn = 75;

    return sts_rtn;

}
