develooper Front page | perl.perl5.porters | Postings from January 2014

[perl #20609] MY_CXT macros and modules with multiple object files

Thread Next
bulk88 via RT
January 26, 2014 01:22
[perl #20609] MY_CXT macros and modules with multiple object files
Message ID:
On Fri Jan 20 09:46:08 2012, salva wrote:
> I cared because I wanted my module to support both threaded and non-
> threaded perls.
> Under threaded perls, MY_CTX becomes a function call that gets the
> context from local thread storage and so it is accesible from any
> compilation unit (.xs and .c files).

Wrong, threaded MY_CXT STILL uses static data. 2 different compilation units will wind up with different my_cxt_index values which will translate to 2 different "my_cxt_t *" at the end. The compilation unit WITHOUT the "MY_CXT_INIT;" (also means the compilation unit without BOOT:), will probably SEGV due to the -1.

from perl.h
#    define START_MY_CXT static int my_cxt_index = -1;

> On the other hand, under non-threaded perls, MY_CTX becomes an alias
> for the C structure declared as static by the START_MY_CXT macro, and
> so it is not accesible outside the compilation unit where it is
> declared (usually the .xs file).
> % ./perl -Ilib Porting/ dMY_CXT
> > `sh  cflags "optimize='-O3'" try.c` -E try.c > try.i
> >       CCCMD =  cc -DPERL_CORE -c -fno-common -DPERL_DARWIN
> > -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include
> > -I/opt/local/include  -std=c89 -O3  -Wall -ansi -W -Wextra
> > -Wdeclaration-after-statement -Wendif-labels -Wc++-compat
> > -Wwrite-strings
> > # 4 "dMY_CXT expands to"
> > extern int Perl___notused(void)
> >
> > which I certainly hope returns the same answer when called from two
> > different C or XS files.  It's actually in a perl built with threads
> > that these docs in perlxs.pod would be applicable:
> >
> > "Note that these macros will only work together within the same
> > source
> > file; that is, a dMY_CTX in one source file will access a different
> > structure than a dMY_CTX in another source file."
> >
> > I believe it might be possible to pass thread context around with
> > aMY_CXT/pMY_CXT between different source files but I've never tried
> > it.  Interested parties might want to also look at what
> >
> I don't think so.
> Under non-threaded perls, aMY_CXT and pMY_CXT are defined as...
> #  define pMY_CXT               void
> #  define pMY_CXT_
> #  define _pMY_CXT
> #  define aMY_CXT
> #  define aMY_CXT_
> #  define _aMY_CXT
> so the non visibility issue of the static structure remains.

You will have to declare an extern getter C function that does "dMY_CXT; return MY_CXT;" defined in the compilation unit with BOOT:. If your compiler is advanced enough, ( ) it might get auto-inlined. If on threaded MY_CXT, and if my_cxt_index is NOT declared static, there will be a disaster on ELF platforms due to my_cxt_index being an extern symbol and all XS modules, static linked or SO, that use MY_CXT, will be broken. The only solution would be for my_cxt_index to have a C symbol name compatible prefix unique to each XSPP based on "PACKAGE = " (or "MODULE = ", on a per binary/SO basis). A long long time ago (< ~5.9.3) before the more efficient current implementation ( as of ), MY_CXT_KEY that each module defined (and still defines to this day because of docs), was used as the unique pe
 r module element, instead of my_cxt_index. But we never told anything that MY_CXT_KEY has to be a valid C identifier without double quotes (it has double quotes already and you can't de-stringify), so MY_CXT_KEY can't be used as the following invalid proposal
#    define START_MY_CXT int MY_CXT_KEY##_my_cxt_index = -1;

After reading the old MY_CXT implementation that used a HV with MY_CXT_KEY, I think your feature request was a "bug" that the new MY_CXT implementation fixed (maybe davem can chime in since he wrote it and I dont have time to search the ML archives), since on old MY_CXT, the non-threaded was static, the thread was global to module due to the HV and MY_CXT_KEY (assuming you declared MY_CXT_KEY in a compilation unit, that didn't have BOOT:). In new MY_CXT both the threaded and non-threaded, are compilation unit static. I'm leaning towards this ticket being rejected, unless someone (not me) wants to write a new GMY_CXT api (G for global) that uses symbol name unique my_cxt_index declared as extern, this GMY_CXT will still use PL_my_cxt_list as the new MY_CXT does.

I was going to bring up another API design question but the theory is impossible due to a check of my_cxt_index is -1 in Perl_my_cxt_init() and my_cxt_index isn't assigned to if its !=  -1. Will GMY_CXT have protection against multiple runs of GMY_CXT_INIT or is that nearly impossible to create such a scenario? The only scenario I see is if someone does a "require" inside an ithread, then BOOT: of the DLL will run again and set my_cxt_index to a new value.

bulk88 ~ bulk88 at

via perlbug:  queue: perl5 status: open

Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About