| Re .1: thanks for subbing my nose to this obvious fact! :-}
After changing my shareable like follows, everything is OK. Is there a simpler way
to achieve the same?
Wilfried
/*--- s.c --- */
#pragma extern_model save
#pragma extern_model strict_refdef "my_gbl_data" shr,wrt,gbl
int X;
#pragma extern_model strict_refdef "my_gbl_ptr" shr,wrt,gbl
int *Y = &X;
#pragma extern_model restore
|
|
:After changing my shareable like follows, everything is OK.
:Is there a simpler way to achieve the same?
I prefer globals -- private- or pagefile-backed -- to COMMON blocks.
#include <descrip.h>
#include <lib$routines.h>
#include <psldef.h>
#include <rms.h>
#include <secdef.h>
#include <ssdef.h>
#include <starlet.h>
#include <stdio.h>
#include <string.h>
#include <stsdef.h>
#include <unixlib.h>
#define MAXACCLEN 16
struct ItemList3
{
short int ItemLength;
short int ItemCode;
void *ItemBuffer;
void *ItemRetLen;
};
struct RmsFileContext
{
struct FAB fab;
struct NAM nam;
char rss[NAM$C_MAXRSS];
short max_rec_siz;
char *data_buffer;
};
#define P0SPACE ((void*)0x0200)
#define BOGUSMAX 10
RmsFileOpen( struct FAB *fab, char *FileName, char *DefFileName )
{
int RetStat;
*fab = cc$rms_fab;
fab->fab$l_alq = 10;
fab->fab$b_fac = 0;
fab->fab$l_fop = FAB$M_UFO | FAB$M_CIF;
fab->fab$b_shr = FAB$M_UPI | FAB$M_SHRPUT | FAB$M_SHRGET | FAB$M_SHRUPD;
fab->fab$l_fna = FileName;
fab->fab$b_fns = strlen( FileName );
fab->fab$l_dna = DefFileName;
fab->fab$b_dns = strlen( DefFileName );
/*
// Attempt to open the file...
*/
RetStat = sys$create( fab, 0, 0 );
if ( !$VMS_STATUS_SUCCESS( RetStat ) )
return RetStat;
return RetStat;
}
main()
{
int RetStat;
struct ItemList3 ItmLst[10];
$DESCRIPTOR( SecDsc, "FACNAM_GLOBAL_SECTION_NAME" );
int i;
void *InAdr1[2] = {P0SPACE,P0SPACE};
void *RetAdr1[2] = {NULL,NULL};
void *InAdr2[2] = {P0SPACE,P0SPACE};
void *RetAdr2[2] = {NULL,NULL};
struct FAB Fab1, Fab2;
struct insec
{
int Bogus[BOGUSMAX];
} *Sec1, *Sec2;
/*
// Create and open, and map the global section...
*/
RetStat = RmsFileOpen( &Fab1, "BOGUS", "SYS$SCRATCH:.TMP" );
if (!$VMS_STATUS_SUCCESS( RetStat ))
lib$signal( RetStat );
RetStat = sys$crmpsc( InAdr1, RetAdr1, PSL$C_USER,
SEC$M_EXPREG | SEC$M_WRT | SEC$M_DZRO | SEC$M_GBL,
&SecDsc,
0, 0, Fab1.fab$l_stv, 1, 0, 0, 0 );
if (!$VMS_STATUS_SUCCESS( RetStat ))
lib$signal( RetStat );
/*
// Create and open, and map the global section again...
*/
RetStat = RmsFileOpen( &Fab2, "BOGUS", "SYS$SCRATCH:.TMP" );
if (!$VMS_STATUS_SUCCESS( RetStat ))
lib$signal( RetStat );
RetStat = sys$crmpsc( InAdr2, RetAdr2, PSL$C_USER,
SEC$M_EXPREG | SEC$M_WRT | SEC$M_GBL,
&SecDsc,
0, 0, Fab2.fab$l_stv, 1, 0, 0, 0 );
if (!$VMS_STATUS_SUCCESS( RetStat ))
lib$signal( RetStat );
/*
// Write the information to one "window"...
// ... read the data back from the other.
*/
Sec1 = RetAdr1[0];
Sec2 = RetAdr2[0];
for ( i = 0; i < BOGUSMAX; i++)
Sec1->Bogus[i] = i;
for ( i = 0; i < BOGUSMAX; i++)
printf( "Bogus[%d] = %d\n", i, Sec2->Bogus[i] );
return SS$_NORMAL;
}
|
| /*
You could also go with a LIB$INITIALIZE routine
to init the data at startup (if it needs it).
If the data is really write shared among several
processes, then you would the proper mutexes around
the init sequence.
*/
#pragma extern_model save
#pragma extern_model strict_refdef "my_gbls" shr,wrt,gbl,ovr
int X;
int *Y;
#pragma extern_model restore
static int init_code( int (*)() , int , int );
/*
Create the LIB$INITIALIZE psect. This psect contains a
list of addresses that are the initialization routines.
*/
#pragma member_alignment save
#pragma nomember_alignment byte
#pragma extern_model save
#pragma extern_model strict_refdef "LIB$INITIALIZE" noshr,nopic,nowrt
#pragma message save
#pragma message disable (WRTINNOWRT)
int (*initialize[])(int (*)() , int , int)
= { init_code };
#pragma message restore
#pragma member_alignment restore
#pragma extern_model restore
#include lib$routines
/*
Make a reference to the LIB$INITIALIZE routine. It is never
called by us directly, we only make it visable to the linker.
*/
extern int lib$initialize();
/*
Description:
This routine is the first initialization routine.
Inputs:
corout Address of a function.
cli Address of a CLI callback function
imghdr Address of the processes image header.
Outputs:
None
Routine Value:
None
*/
#include <stdio.h>
static int init_code( int (*corout)(), int cli, int imghdr)
{
void *a = (void *)lib$initialize ; /* Force reference to routine */
printf("In init code\n");
if (!Y) Y = &X ;
return 1;
}
|
| .4> After changing my shareable like follows, everything is OK.
Well, not quite. Y still isn't shared. Your tests don't discover this,
since you're always assigning it the value of &X, the same as its initial
value. If you try assigning something else, you'll see the initial value
reappear each time you run your program.
If you avoid the link-time initialization you can make Y be shared too.
.4 shows a way to defer the initialization until run-time. Be careful
if it's legal for Y==0 sometimes -- the code in .4 will reset it to &X
if a program is started while Y==0.
Or perhaps you never really needed Y at all, or never needed it to be shared...
|