EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  <20042005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 2002  2003  <20042005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Initializer is not a constant / Double checked locking on SMP systems
From: Ralph Lange <[email protected]>
To: Core-Talk Archive <[email protected]>
Date: Fri, 13 Feb 2004 11:08:16 +0100
This is a thread that I thought was worth keeping...

Ralph


--- Begin Message ---
Subject: RE: [Fwd: initializer is not a constant]
From: "Jeff Hill" <[email protected]>
To: "'Eric Norum'" <[email protected]>
Cc: "'mrk'" <[email protected]>, "Andrew Johnson" <[email protected]>, "'Ralph Lange'" <[email protected]>
Date: Tue, 10 Feb 2004 17:29:27 -0700
I have confirmed that the M$ compiler error is related to initializing a
file scope variable with the address of a variable exported from a DLL. I
fault isolated by initializing that same structure member with the address
of a local file scope variable.

It appears that iocshVarDef might be new functionality. One possibility
would be to change the interface and require that the application install
the address of four set and get functions as follows.

double myNumericGetFunction ( void );
void myNumericSetFunction ( double ); 
void myStringGetFunction ( char * pString, unsigned maxLength );
void myStringSetFunction ( const char * pString); 

An advantage of this approach would be better support for application
specific functionality like range checking, state change action activities,
and mutex locking in the set/get functions. Note that on SMP systems mutex
locks are required around even atomic variable access when multiple threads
are involved in order to guarantee cache coherency.

Anyways, a possible option to consider.

PS: If you want to mess with many different data types you could have a type
code, a set/get interface for each of the data types, and have the
application install only the one set/get pair that is needed. 

PPS: All of this starts to sound alot like data access by the way.

PPPS: Give me a call at 505 665 1831 if you would like to discuss this over
the phone.

Jeff

> -----Original Message-----
> From: Eric Norum [mailto:[email protected]] 
> Sent: Tuesday, February 10, 2004 3:52 PM
> To: Jeff Hill
> Cc: 'mrk'
> Subject: Re: [Fwd: initializer is not a constant]
> 
> 
> Jeff Hill wrote:
> >>Hmm...shouldn't that cast be
> >>(void * const)
> >>i.e. a constant pointer to a void, not a pointer to a 
> >>constant void......
> > 
> > 
> > I hadnt looked at your code so far. After a closer 
> inspection I see this:
> > 
> > typedef struct iocshFuncDef {
> >     const char *name;
> >     int nargs;
> >     const iocshArg * const *arg; <=== is being set, I believe
> > }iocshFuncDef;
> > 
> > Therefore the compiler wants a cast like this.
> > 
> > (const iocshArg * const *)
> > 
> > C (but not C++) compilers will probably also accept this.
> > 
> > (const void * const * )
> > 
> 
> I'm not sure what you're getting at here.  The problem is 
> with an iocshVarDef 
> initialization, not with an iocshFuncDef initialization, right?
> 
> static struct iocshVarDef vardefs[] = {
>  >      {"asCaDebug", iocshArgInt,(void *)&asCaDebug},
>  >      {0,iocshArgInt,0}
>  > };
> 
> 
> -- 
> Eric Norum                                 [email protected]
> Advanced Photon Source                     Phone: (630) 252-4793
> Argonne National Laboratory
> 


--- End Message ---
--- Begin Message ---
Subject: Re: [Fwd: initializer is not a constant]
From: Eric Norum <[email protected]>
To: Jeff Hill <[email protected]>
Cc: Andrew Johnson <[email protected]>, "'mrk'" <[email protected]>, "'Ralph Lange'" <[email protected]>
Date: Tue, 10 Feb 2004 18:45:59 -0600

On Feb 10, 2004, at 6:29 PM, Jeff Hill wrote:


I have confirmed that the M$ compiler error is related to initializing a file scope variable with the address of a variable exported from a DLL. I fault isolated by initializing that same structure member with the address
of a local file scope variable.

So the solution is to move the variable declaration to the same source file as the iocshVarDef and to specify the 'extern' in the source file where it's now being declared, right?


It appears that iocshVarDef might be new functionality. One possibility
would be to change the interface and require that the application install
the address of four set and get functions as follows.

double myNumericGetFunction ( void );
void myNumericSetFunction ( double );
void myStringGetFunction ( char * pString, unsigned maxLength );
void myStringSetFunction ( const char * pString);

This is similar to the old method where everything went through the IOC shell -- and lots of people complained that it was too difficult to set up access to variables.


An advantage of this approach would be better support for application
specific functionality like range checking, state change action activities, and mutex locking in the set/get functions. Note that on SMP systems mutex locks are required around even atomic variable access when multiple threads
are involved in order to guarantee cache coherency.

I remain skeptical about this requirement.

--
Eric Norum <[email protected]>
Advanced Photon Source
Argonne National Laboratory
(630) 252-4793


--- End Message ---
--- Begin Message ---
Subject: RE: [Fwd: initializer is not a constant]
From: "Jeff Hill" <[email protected]>
To: "'Eric Norum'" <[email protected]>
Cc: "'Andrew Johnson'" <[email protected]>, "'mrk'" <[email protected]>, "'Ralph Lange'" <[email protected]>
Date: Tue, 10 Feb 2004 18:21:39 -0700
> > Note that on SMP systems mutex locks are required around even 
> > atomic variable access when multiple threads are involved in 
> > order to guarantee cache coherency.
> 
> I remain skeptical about this requirement.
> 

Some interesting things can happen on SMP systems. For example the following
code can result in a failure in strlen() resulting from faulty assumptions
about sequencial ordering of accesses to atomic variable pBill which are not
guarded by a mutex.

extern struct bill {
    char *p;
} * pBill;

void * p = 0;

if ( ! pBill ) {
     lock
     if ( ! pBill ) {
         struct bill * p = malloc (sizeof(bill));
         p->p = malloc(4);
         p->p[0] = '\0';
         pBill = p;
     }
     unlock
}

strlen ( pBill->p );

Changing the code as follows makes it safe.

extern struct bill {
    char *p;
} * pBill;

void * p = 0;

lock
if ( ! pBill ) {
     if ( ! pBill ) {
         struct bill * p = malloc (sizeof(bill));
         p->p = malloc(4);
         p->p[0] = '\0';
         pBill = p;
     }
}
unlock

strlen ( pBill->p );

Admitedly, if you dont allow the iocsh to branch on the contents of a
variable then perhaps you will not run into these issues.

Jeff

> -----Original Message-----
> From: Eric Norum [mailto:[email protected]] 
> Sent: Tuesday, February 10, 2004 5:46 PM
> To: Jeff Hill
> Cc: Andrew Johnson; 'mrk'; 'Ralph Lange'
> Subject: Re: [Fwd: initializer is not a constant]
> 
> 
> 
> On Feb 10, 2004, at 6:29 PM, Jeff Hill wrote:
> 
> >
> > I have confirmed that the M$ compiler error is related to 
> initializing 
> > a
> > file scope variable with the address of a variable exported from a 
> > DLL. I
> > fault isolated by initializing that same structure member with the 
> > address
> > of a local file scope variable.
> 
> So the solution is to move the variable declaration to the 
> same source 
> file as the iocshVarDef and to specify the 'extern' in the 
> source file 
> where it's now being declared, right?
> 
> >
> > It appears that iocshVarDef might be new functionality. One 
> possibility
> > would be to change the interface and require that the application 
> > install
> > the address of four set and get functions as follows.
> >
> > double myNumericGetFunction ( void );
> > void myNumericSetFunction ( double );
> > void myStringGetFunction ( char * pString, unsigned maxLength );
> > void myStringSetFunction ( const char * pString);
> 
> This is similar to the old method where everything went 
> through the IOC 
> shell -- and lots of people complained that it was too 
> difficult to set 
> up access to variables.
> 
> >
> > An advantage of this approach would be better support for 
> application
> > specific functionality like range checking, state change action 
> > activities,
> > and mutex locking in the set/get functions. 





--- End Message ---
--- Begin Message ---
Subject: Re: [Fwd: initializer is not a constant]
From: Eric Norum <[email protected]>
To: Jeff Hill <[email protected]>
Cc: "'Andrew Johnson'" <[email protected]>, "'mrk'" <[email protected]>, "'Ralph Lange'" <[email protected]>
Date: Tue, 10 Feb 2004 20:02:07 -0600

On Feb 10, 2004, at 7:21 PM, Jeff Hill wrote:


Note that on SMP systems mutex locks are required around even
atomic variable access when multiple threads are involved in
order to guarantee cache coherency.

I remain skeptical about this requirement.


Some interesting things can happen on SMP systems. For example the following code can result in a failure in strlen() resulting from faulty assumptions about sequencial ordering of accesses to atomic variable pBill which are not
guarded by a mutex.


My skepticism is rooted in my feeling that cache snooping takes care of situations like this. Perhaps I'm overly optimistic..... I'd really like to see a statement in a hardware manual that made it clear once and for all whether or not a programmer needs to worry about cache coherency at the level shown in your example.

--
Eric Norum <[email protected]>
Advanced Photon Source
Argonne National Laboratory
(630) 252-4793


--- End Message ---
--- Begin Message ---
Subject: RE: [Fwd: initializer is not a constant]
From: "Jeff Hill" <[email protected]>
To: "'Eric Norum'" <[email protected]>
Cc: "'Andrew Johnson'" <[email protected]>, "'mrk'" <[email protected]>, "'Ralph Lange'" <[email protected]>
Date: Wed, 11 Feb 2004 17:02:13 -0700
fyi

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

> -----Original Message-----
> From: Eric Norum [mailto:[email protected]] 
> Sent: Tuesday, February 10, 2004 7:02 PM
> To: Jeff Hill
> Cc: 'Andrew Johnson'; 'mrk'; 'Ralph Lange'
> Subject: Re: [Fwd: initializer is not a constant]
> 
> 
> 
> On Feb 10, 2004, at 7:21 PM, Jeff Hill wrote:
> 
> >
> >>> Note that on SMP systems mutex locks are required around even
> >>> atomic variable access when multiple threads are involved in
> >>> order to guarantee cache coherency.
> >>
> >> I remain skeptical about this requirement.
> >>
> >
> > Some interesting things can happen on SMP systems. For example the 
> > following
> > code can result in a failure in strlen() resulting from faulty 
> > assumptions
> > about sequencial ordering of accesses to atomic variable 
> pBill which 
> > are not
> > guarded by a mutex.
> >
> 
> My skepticism is rooted in my feeling that cache snooping 
> takes care of 
> situations like this.  Perhaps I'm overly optimistic.....
> I'd really like to see a statement in a hardware manual that made it 
> clear once and for all whether or not a programmer needs to 
> worry about 
> cache coherency at the level shown in your example.
> 
> -- 
> Eric Norum <[email protected]>
> Advanced Photon Source
> Argonne National Laboratory
> (630) 252-4793
> 
> 

--- End Message ---
--- Begin Message ---
Subject: Re: [Fwd: initializer is not a constant]
From: Eric Norum <[email protected]>
To: Jeff Hill <[email protected]>
Cc: "'Andrew Johnson'" <[email protected]>, "'mrk'" <[email protected]>, "'Ralph Lange'" <[email protected]>
Date: Wed, 11 Feb 2004 18:20:14 -0600

On Feb 11, 2004, at 6:02 PM, Jeff Hill wrote:


fyi

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Maybe....
but I interpret the message as a statement that Java needs a 'volatile' keyword more than anything else.

--
Eric Norum <[email protected]>
Advanced Photon Source
Argonne National Laboratory
(630) 252-4793


--- End Message ---
--- Begin Message ---
Subject: RE: double checked locking is broken
From: "Jeff Hill" <[email protected]>
To: "'Eric Norum'" <[email protected]>
Cc: "'Andrew Johnson'" <[email protected]>, "'mrk'" <[email protected]>, "'Ralph Lange'" <[email protected]>
Date: Wed, 11 Feb 2004 18:31:24 -0700
> > 
> http://www.cs.umd.edu/> ~pugh/java/memoryModel/DoubleCheckedLocking.html
> 
> Maybe....
> but I interpret the message as a statement that Java needs a 
> 'volatile' keyword more than anything else.

That article is mostly in the context of the JAVA memory model, but any SMP
system, and any standard compliant optimizing C compiler is a far less
certain environment.

http://groups.google.com/groups?selm=MPG.191efc0a3bf86e2e9896e0%40news.hevan
et.com

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&threadm=3ec8e247
%40usenet01.boi.hp.com&rnum=1&prev=/groups%3Fq%3DDavid%2BButenhof%2Bdouble%2
Bchecked%2Block%26hl%3Den%26lr%3D%26ie%3DUTF-8%26oe%3DUTF-8%26selm%3D3ec8e24
7%2540usenet01.boi.hp.com%26rnum%3D1

Jeff


--- End Message ---
--- Begin Message ---
Subject: RE: [Fwd: initializer is not a constant]
From: "Jeff Hill" <[email protected]>
To: "'Eric Norum'" <[email protected]>
Cc: "'Andrew Johnson'" <[email protected]>, "'mrk'" <[email protected]>, "'Ralph Lange'" <[email protected]>
Date: Tue, 10 Feb 2004 18:37:29 -0700

> So the solution is to move the variable declaration to the 
> same source file as the iocshVarDef and to specify the 'extern' in the 
> source file where it's now being declared, right?

That *is* a possible solution (which I didnt consider) although this may be
somewhat unweildy from a code structure veiw point. Someone might ask "where
is that I go to find the definitions of variables that are used by subsystem
pdq". Also, I generally try to have a hierarchical design (a tree net) when
libraries link with each other. That is, its probably best not to have
library A referencing symbols in library B while at the same time library B
references symbols in library A. No problem with one or the other but both
can get messy.

Jeff


--- End Message ---
--- Begin Message ---
Subject: Re: [Fwd: initializer is not a constant]
From: Marty Kraimer <[email protected]>
To: Jeff Hill <[email protected]>
Cc: "'Eric Norum'" <[email protected]>, Andrew Johnson <[email protected]>, "'Ralph Lange'" <[email protected]>
Date: Wed, 11 Feb 2004 08:45:28 -0600
Jeff Hill wrote:

It appears that iocshVarDef might be new functionality. One possibility
would be to change the interface and require that the application install
the address of four set and get functions as follows.

double myNumericGetFunction ( void );
void myNumericSetFunction ( double ); void myStringGetFunction ( char * pString, unsigned maxLength ); void myStringSetFunction ( const char * pString);


This is getting messy. Let's consider what we are doing now and think about what may be wrong.

At issue are iocshVarDef and epicsExportAddress
First consider iocshVarDef

typedef struct iocshVarDef {
    const char *name;
    iocshArgType type;
    void * pval;
}iocshVarDef;

The definition for pval should be

void * const pval;

Because it really really is a constant pointer to a non constant.
This also means the the perl script that generates xxx_registerRecordDeviceDriver.cpp must also cast to (void * const).
I will guess that this will solve the problem Jeff encountered on win32.

Now consider epicsExportAddress

epicsExportAddress(typ,obj) generates the following

epicsShareExtern typ *pobj;
epicsShareDef typ *pobj;

Each of the following in an xxxInclude.dbd file where a application is built
recordtype
device
driver
variable
relies on an epicsShareExtern being defined in a source file.

What can go wrong is that epicsExportAddress could be called with a type that does not match what is specified in the xxxInclude.dbd file. The easiest one for the user to get wrong is variable.

For example lets say code has

double xxxTimeout=2.0
epicsExportAddress(double,xxxTimeout)

and the xxxInclude.dbd has
variable(xxxTimeout,int)

No error will be issued when the application is built. But when is variable is accessed via iocsh bad things happen.

Even the following can happen

code has

epicsExportAddress(rset,aiRSET)

and the Include file has

device(aiRSET)

No error will be generated at build time.

What to do?

Here is a way to ensure that an error is generated at build time (on vxWorks at ld time).

Let epicsExportAddress(typ,obj) generate the following

epicsShareExtern typ *pobjtyp;
epicsShareDef typ *pobjtyp;

For example

double xxxTimeout=2;
epicsExportAddress(double,xxxTimeout) generates
epicsShareExtern double *pxxxTimeoutdouble;
epicsShareDef double *pxxxTimeoutdouble;


registerRecordDeviceDriver.pl will than generate code that fails at build time (on vxWorks at ld time) with undefineds if the xxInclude.dbd file mixes types.

Marty



--- End Message ---
--- Begin Message ---
Subject: Re: [Fwd: initializer is not a constant]
From: Marty Kraimer <[email protected]>
To: Marty Kraimer <[email protected]>
Cc: Jeff Hill <[email protected]>, "'Eric Norum'" <[email protected]>, Andrew Johnson <[email protected]>, "'Ralph Lange'" <[email protected]>
Date: Wed, 11 Feb 2004 13:08:04 -0600
Marty Kraimer wrote:


Let epicsExportAddress(typ,obj) generate the following

epicsShareExtern typ *pobjtyp;
epicsShareDef typ *pobjtyp;

For example

double xxxTimeout=2;
epicsExportAddress(double,xxxTimeout) generates
epicsShareExtern double *pxxxTimeoutdouble;
epicsShareDef double *pxxxTimeoutdouble;


After talking to andrew during lunch we are proposing the syntax


epicsExportAddress(typ,obj) generates

epicsShareExtern typ *pvar_type_obj;
epicsShareDef typ *pvar_type_obj;

For example,

epicsExportAddress(double,xxxTimeout) generates
epicsShareExtern double *pvar_double_xxxTimeout;
epicsShareDef double *pvar_double_Timeout;

Thus

For now the only allowed values for typ are: rset,dest,drvet, int, double.

Unless I hear objections I will make the appropriate changes to epicsExport.h and to registerRecordDeviceDriver.pl

I will also change iocsh.h and registerRecordDeviceDriver.pl so that the pval in iocshVarDef is
    void * const pval;


Any comments before I start?

Marty



--- End Message ---
--- Begin Message ---
Subject: RE: [Fwd: initializer is not a constant]
From: "Jeff Hill" <[email protected]>
To: "'Marty Kraimer'" <[email protected]>
Cc: "'Eric Norum'" <[email protected]>, "'Andrew Johnson'" <[email protected]>, "'Ralph Lange'" <[email protected]>
Date: Wed, 11 Feb 2004 17:52:13 -0700
> Any comments before I start?

Please see previous message about issues on windows with the linker's
initializing a file scope variable with the address of an exported DLL
symbol which is known only at run time.

Workarounds:

o Let the application create the set / get functions by hand (this allows
application specific range check, locking, change of state processing).

o Computer generate the set and get code (this will work on windows even if
the generated code is not in the exporting DLL because it does not link time
initialize a variable with the address of a symbol exported from a DLL).
This approach allows for compile time knowledge of data type specific range
checking.

o Computer generate a function that returns the symbol's address (this will
work on windows even if the generated code is not in the exporting DLL
because it does not link time initialize a variable with the address of a
symbol exported from a DLL).

o Move the variable to iocsh as Eric suggested (this *will* work, but see my
previous message discussing this).

Jeff


> -----Original Message-----
> From: Marty Kraimer [mailto:[email protected]] 
> Sent: Wednesday, February 11, 2004 12:08 PM
> To: Marty Kraimer
> Cc: Jeff Hill; 'Eric Norum'; Andrew Johnson; 'Ralph Lange'
> Subject: Re: [Fwd: initializer is not a constant]
> 
> 
> Marty Kraimer wrote:
> 
> > 
> > Let epicsExportAddress(typ,obj) generate the following
> > 
> > epicsShareExtern typ *pobjtyp;
> > epicsShareDef typ *pobjtyp;
> > 
> > For example
> > 
> > double xxxTimeout=2;
> > epicsExportAddress(double,xxxTimeout) generates
> > epicsShareExtern double *pxxxTimeoutdouble;
> > epicsShareDef double *pxxxTimeoutdouble;
> > 
> 
> After talking to andrew during lunch we are proposing the syntax
> 
> 
> epicsExportAddress(typ,obj) generates
> 
> epicsShareExtern typ *pvar_type_obj;
> epicsShareDef typ *pvar_type_obj;
> 
> For example,
> 
> epicsExportAddress(double,xxxTimeout) generates
> epicsShareExtern double *pvar_double_xxxTimeout;
> epicsShareDef double *pvar_double_Timeout;
> 
> Thus
> 
> For now the only allowed values for typ are: rset,dest,drvet, 
> int, double.
> 
> Unless I hear objections I will make the appropriate changes 
> to epicsExport.h 
> and to registerRecordDeviceDriver.pl
> 
> I will also change iocsh.h and registerRecordDeviceDriver.pl 
> so that the pval in 
>   iocshVarDef is
>      void * const pval;
> 
> 
> Any comments before I start?
> 
> Marty
> 
> 
> 


--- End Message ---
--- Begin Message ---
Subject: Re: [Fwd: initializer is not a constant]
From: Marty Kraimer <[email protected]>
To: Jeff Hill <[email protected]>
Cc: "'Eric Norum'" <[email protected]>, "'Andrew Johnson'" <[email protected]>, "'Ralph Lange'" <[email protected]>
Date: Thu, 12 Feb 2004 08:43:03 -0600
Jeff Hill wrote:
Any comments before I start?


Please see previous message about issues on windows with the linker's
initializing a file scope variable with the address of an exported DLL
symbol which is known only at run time.

Workarounds:

o Let the application create the set / get functions by hand (this allows
application specific range check, locking, change of state processing).

o Computer generate the set and get code (this will work on windows even if
the generated code is not in the exporting DLL because it does not link time
initialize a variable with the address of a symbol exported from a DLL).
This approach allows for compile time knowledge of data type specific range
checking.

o Computer generate a function that returns the symbol's address (this will
work on windows even if the generated code is not in the exporting DLL
because it does not link time initialize a variable with the address of a
symbol exported from a DLL).

o Move the variable to iocsh as Eric suggested (this *will* work, but see my
previous message discussing this).

Jeff

I am still not convinced that what I suggest will not work.

Please note that for rset, dset, registrar, and even with variable it worked with the generated example_registerRecordDeviceDriver.cpp code.


I made and committed changes in src/iocsh and in src/registry so that for pvar the type is "void * const" instead of "void *". Please do a cvs update and see if you can now build.

Thanks,

Marty

--- End Message ---
--- Begin Message ---
Subject: Re: [Fwd: initializer is not a constant]
From: Marty Kraimer <[email protected]>
To: Jeff Hill <[email protected]>
Cc: Marty Kraimer <[email protected]>, "'Eric Norum'" <[email protected]>, "'Andrew Johnson'" <[email protected]>, "'Ralph Lange'" <[email protected]>
Date: Thu, 12 Feb 2004 10:34:27 -0600
Marty Kraimer wrote:

I made and committed changes in src/iocsh and in src/registry so that for pvar the type is "void * const" instead of "void *". Please do a cvs update and see if you can now build.

Thanks,

Marty


I just did another commit to src/iocsh.

I changed {"asCaDebug", iocshArgInt,(void * const )&asCaDebug}

to
{"asCaDebug", iocshArgInt,(void * const )pasCaDebug}

Marty

--- End Message ---

Navigate by Date:
Next: Timestamp (drvTS) progress Korhonen Timo
Index: 2002  2003  <20042005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Next: Timestamp (drvTS) progress Korhonen Timo
Index: 2002  2003  <20042005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 02 Feb 2012 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·