[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::decc

Title:DECC
Notice:General DEC C discussions
Moderator:TLE::D_SMITHNTE
Created:Fri Nov 13 1992
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:2212
Total number of notes:11045

2123.0. "global data in shareable image on OpenVMS Alpha ?" by VNASWS::WILFRIED (Wilfried Bergmann, Austria) Wed Mar 19 1997 10:10

OpenVMS 7.1, DEC C V5.5-002

The following example is stripped down from customer questions.

We have the following files:
	S.C	shareable image containing global, writeable data
	A.C	user of S.C

Question:
   A sets X in S.C to 17. If I run A a second time, X doesn't contain 17,
   but the initial value set in S.C. Why? Am I doing something wrong?

Thanks for your help!
Regards,
	Wilfried
------------------------------< S.C >-------------------------------------
#pragma extern_model save
#pragma extern_model strict_refdef "my_gbls" shr,wrt,gbl
int  X;
int *Y = &X;
#pragma extern_model restore
------------------------------< A.C >-------------------------------------
#include <stdio.h>

#pragma extern_model save
#pragma extern_model strict_refdef "my_gbls" shr, wrt, gbl

extern int  X;
extern int *Y;

#pragma extern_model restore


main ()
 {
  printf ("before any modifications\n");
  printf ("X (%x) = %d\n", &X, X);
  printf ("Y (%x) = %d\n", Y, *Y);

  X = 17;
  Y = &X;

  printf ("after setting X = 17\n");
  printf ("X (%x) = %d\n", &X, X);
  printf ("Y (%x) = %d\n", Y, *Y);

 }
----------------------------------------------------------------------------
$ CC/SHARE S
$ LINK/SHARE S,SYS$INPUT/OPT
symbol_vector=(x=data,y=data)
$ copy s.exe sys$share:
$ instal replace sys$share:s.exe /share /write
$ cc a
$ link a,sys$input/opt
Sys$Share:s.exe/share
$ run a
FATUM� r a
before any modifications
X (32000) = 0
Y (32000) = 0
after setting X = 17
X (32000) = 17
Y (32000) = 17
FATUM� r a
before any modifications
X (32000) = 0
Y (32000) = 0
after setting X = 17
X (32000) = 17
Y (32000) = 17
FATUM�
T.RTitleUserPersonal
Name
DateLines
2123.1CSC64::BLAYLOCKIf at first you doubt,doubt again.Wed Mar 19 1997 12:5521
#pragma extern_model save
#pragma extern_model strict_refdef "my_gbls" shr,wrt,gbl
int  X;
int *Y = &X;
#pragma extern_model restore


This sequence causes Y to contain shareable address data.  That
makes the psect that it resides in copy on ref.  Thus you get
a new copy of the section every time you initially map to
it.

On an OpenVMS VAX system you get the messages:

%LINK-I-BASDUERRS, basing image due to errors in relocatable references
%LINK-W-ADRWRTDAT, address data in shareable writable section
        in psect my_gbls offset %X00000004
        in module A file KGB$ROOT:[JUNK]A.OBJ;8

With this construct.

2123.2solutionVNASWS::WILFRIEDWilfried Bergmann, AustriaThu Mar 20 1997 04:2217
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
2123.3Run-time vs Link-time data sharingXDELTA::HOFFMANSteve, OpenVMS EngineeringThu Mar 20 1997 10:12120
: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;
    }

2123.4CSC64::BLAYLOCKIf at first you doubt,doubt again.Thu Mar 20 1997 10:5679
/*

	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;
}

2123.5You may still have a problem.WIBBIN::NOYCEPulling weeds, pickin&#039; stonesThu Mar 20 1997 13:3713
.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...
2123.6CSC64::BLAYLOCKIf at first you doubt,doubt again.Thu Mar 20 1997 17:2712
For multiple processes sharing the data, the initialization
of a shared Y as in

	Y = &X ;

is not too kosher anyway.  The VA of X in process A may not
be the VA of X in process B.  It only works if the address
is 'based' as it would be on an OpenVMS VAX system (from the
original example) or all applications using the sharable
are identical.  Y needs to be private (copy on ref)
for this type of thing (referencing) to work.