Cglobals man page

CGLOBALS(3) Common Library Functions CGLOBALS(3)

[1mNAME[0m
[1mCglobals [22m- LCG thread-specific [1mglobal [22mvariable[1ms [22minterface

[1mSYNOPSIS[0m
[1m#include <Cglobals.h>[0m

[1mvoid Cglobals_init([0m
[1mint (*[4m[22mgetspec[24m[1m) (int *[4m[22mkey[24m[1m, void **[4m[22maddr[24m[1m),[0m
[1mint (*[4m[22msetspec[24m[1m) (int *[4m[22mkey[24m[1m, void *[4m[22maddr[24m[1m),[0m
[1mint (*[4m[22mgetTid[24m[1m) (void)[0m
[1m);[0m

[1mint Cglobals_get(int *[4m[22mkey[24m[1m, void **[4m[22maddr[24m[1m, size_t [4m[22msize[24m[1m);[0m

[1mvoid Cglobals_getTid(int *[4m[22mTid[24m[1m);[0m

[1mint C__serrno();[0m

[1mint C__rfio_errno();[0m

[1mint C__Copterr();[0m

[1mint C__Coptind();[0m

[1mint C__Coptopt();[0m

[1mint C__Coptreset();[0m

[1mchar *C__Coptarg();[0m

[1mint C__h_errno();[0m

[1mDESCRIPTION[0m
[1mCglobals [22mis the interface where are defined all necessary functions
that always return a thread-specific value of global variables. Each
package of [1mLCG [22mthat needs to externalize thread-specific global vari-
ables contains in its header, if compiled with threads turned on (e.g.
the default), a set of:
an [1mextern [22mdefinition to a function contained in Cglobals
a [1m#define [22mmacro that replaces all occurences of any global vari-
able that needs to be thread-specific to this Cglobal's func-
tion.
In order to satisfy packages not compiled with threads turned on, or
that do not initialize [1mLCG [22mThread Interface's [1mCthread[22m, any such global
variable is also explicitly defined in [1mCglobals[22m.

For example, taking the global error variable [1mserrno[22m, [1mCglobals [22msource
code contains:
an explicit definition of this variable [1mserrno[0m
an explicit definition, with source code, of a function [1mC_ser-[0m
[1mrno() [22mthat does only the following:
if [1mCglobals_init [22mwas not (successfully) called, return
the address of the global variable [1mserrno[0m
else return the address of a thread-safe specific memory,
instanciated at the first call to this function, that
holds the content of the current instance of the thread-
specific value of [1mserrno[0m

The following description of [1mCglobals_init [22mfunction is explaining
internals of [1mCglobals [22mand [1mCthread[22m. In theory no LCG application need to
call [1mCglobals_init[22m, you can skip if you want the following paragraphs,
and concentrate only on the other functions descriptions.

[1mCglobals_init [22mis bundled to work with the [1mLCG [22mThread Interface's
[1mCthread[22m. That is, any implicit or explicit call to [1mCthread [22malways makes
sure that [1mCglobals_init [22mis called, with three arguments that are:
a [4mgetspec[24m function address that, given a static [4mkey[24m address,
returns the address of a Thread-Specific memory into [4maddr[24m con-
tent. This uses an internal structure inside [1mCthread[22m, allocated
on the heap, that is associated bijectively to [4mkey[24m address.
[1mCthread [22malways explicitly allocates such internal structure to
any [4mkey[24m address if it is unknown at the moment of the call to
[4mgetspec.[0m
In such a case it will return a NULL value into [4maddr[24m , and it
will be the responsability of [1mCglobals [22mto allocate memory on the
heap and to say to [1mCthread [22mthat this newly allocated memory is
the one to associate with [4mkey[24m address, using [4msetspec.[0m
If the internal structure in [1mCthread [22massociated bijectively to
[4mkey[24m yet exists, [4mgetspec[24m only returns what it knows about the
thread-specific memory associated with it, which is a [1mvoid *[0m
member inside the same internal structure mentionned above.

a [4msetspec[24m function address that, given the [4mkey[24m address and the
[4maddr[24m value, previously instanciated with a [4mgetspec[24m call, and
possibly allocated on the heap by [1mCglobals [22mif necessary, will
internally explicitly call the Operating System Thread-Specific
functions that will put the value of [4maddress[24m as something
thread-specific, bijectively associated to another member of the
internal structure of [1mCthread[22m, itself bijective to [4mkey.[0m

a [4mgetTid[24m function address that returns an unique integer identi-
fier associated with any thread.

[1mCglobals_get [22mreturns in [4maddr[24m content the address of a thread-specific
memory, e.g. thread-safe, that is bijectively associated with the
address of a *static*, e.g. constant, address [4mkey[24m , that is automati-
cally created and filled with zeros if necessary, up to [4msize[24m bytes.
If the [4maddr[24m content, at return of [1mCglobals_get[22m, is not NULL, you can
safely fill this memory with any value, provided you does not exceed
the [4msize[24m bytes length specified in your previous call to [1mCglobals_get[22m.
Because of applications that are [1mnot [22mmulti-threaded, the initial value
of [4mkey[24m has then an importance, that's why it is necessary to always
declare it with an initial value of -1.

Return code is -1 on error, 0 on success and [1mnot [22mthe first call for
this [4mkey[24m , 1 on success and [1mit is [22mthe first call for this [4mkey.[24m This
allows to distinguish when Cglobals_get() initialize the memory with
zeros (return code 1) and not (return code 0).

[1mCglobals_getTid [22muses the third function address, [4mgetTid[24m , given as an
argument to [1mCglobals_init[22m, and will return in [4mTid[24m content the value
returned by [4mgetTid.[0m

[1mC__serrno[22m, [1mC__rfio_errno[22m, [1mC__Copterr[22m, [1mC__Coptind[22m, [1mC__Coptopt[22m, [1mC__Cop-[0m
[1mtreset[22m, [1mC__Coptarg [22mand [1mC__h_errno [22mare all the internal functions that
return the address of the thread-specific memory hosting the value of
the 'global' variables serrno, rfio_errno, Copterr, Coptind, Coptopt,
Coptreset, Coptarg and h_errno, respectively.

[1mEXAMPLE[0m
Any application can create its own instance of thread-specific global
variable using [1mCglobals[22m. You need only to use [1mCglobals_get[22m. Here is how
to proceed.

/*
* The following shows how to define and use a thread-specific
* integer, my_var, inside your package
*/

#include <stdlib.h>
#include <stdio.h>
#include <Cglobals.h> /* Get [1mCglobals_get [22mprototype */
static int my_key = -1; /* Our static key, integer, init value -1 */
#define my_var (*C__my_var())

static int my_var_static; /* If Cglobals_get error in order not to crash */

int *C__my_var()
{
int *var;
/* Call Cglobals_get */
Cglobals_get(&my_key,
(void **) &var,
sizeof(int)
);
/* If error, var will be NULL */
if (var == NULL)
{
fprintf(stderr,"Cglobals_get error0);
return(&my_var_static);
}
return(var);
}

int main()
{
fprintf(stdout, "Current my_var value is: %d0, my_var);
fprintf(stdout, "Set my_var value to: %d0, 12);
my_var = 12;
fprintf(stdout, "Current my_var value is: %d0, my_var);
return(0);
}

The following example is the source of the test suite for Cglobals_get():

#include <Cthread_api.h>
#include <stdlib.h>
#include <stdio.h>
#include <Cglobals.h> /* Get Cglobals_get prototype */
#include <serrno.h>

static int my_key = -1; /* Our static key, integer, init value -1 */
#define my_var (*C__my_var())

static int my_var_static; /* If Cglobals_get error in order not to crash */
void *doit _PROTO((void *));

int doit_v = 0;
#define NTHREAD 100

int *C__my_var()
{
int *var;
/* Call Cglobals_get */
switch (Cglobals_get(&my_key,
(void **) &var,
sizeof(int)
)) {
case -1:
fprintf(stderr,"[%d] Cglobals_get error0, Cthread_self());
break;
case 0:
fprintf(stderr,"[%d] Cglobals_get OK0, Cthread_self());
break;
case 1:
fprintf(stderr,"[%d] Cglobals_get OK and first call0, Cthread_self());
break;
default:
fprintf(stderr,"[%d] Cglobals_get unknown return code0, Cthread_self());
break;
}
/* If error, var will be NULL */
if (var == NULL) {
fprintf(stderr,"[%d] Cglobals_get error : RETURN static ADDRESS!!!!!!!!!!!!0, Cthread_self());
return(&my_var_static);
}
return(var);
}

int main()
{
int i;

fprintf(stdout, "[%d] ---> Before any Cthread call0, -1);
fprintf(stdout, "[%d] Current my_var value is: %d0, -1, my_var);
fprintf(stdout, "[%d] Set my_var value to: %d0, -1, 12);
my_var = 12;
fprintf(stdout, "[%d] Current my_var value is: %d0, -1, my_var);
fprintf(stdout, "[%d] Testing consistency0, -1);
if (my_var != 12) {
fprintf(stdout, "[%d] Cglobals_get worked ok0, -1);
exit(1);
}
sleep(1);
for (i = 0; i < NTHREAD; i++) {
Cthread_create(&doit, &doit_v);
doit_v++;
}
fprintf(stdout, "[%d] ---> After all Cthread_create calls0, -1);
fprintf(stdout, "[%d] Current my_var value is: %d0, -1, my_var);
fprintf(stdout, "[%d] Set my_var value to: %d0, -1, NTHREAD * 10000 + 12);
my_var = NTHREAD * 10000 + 12;
fprintf(stdout, "[%d] Current my_var value is: %d0, -1, my_var);
fprintf(stdout, "[%d] Testing consistency0, -1);
if (my_var != (NTHREAD * 10000 + 12)) {
fprintf(stdout, "[%d] Cglobals_get worked ok0, -1);
exit(1);
}
sleep(1);
exit(0);
}

void *doit(arg)
void *arg;
{
int Tid;
int doit = * (int *) arg;
Cglobals_getTid(&Tid);
my_var = (Tid + 1) * 100 + 12;
fprintf(stdout, "[%d] my_var value is: %d (should be %d)0, Cthread_self(), my_var, (Tid + 1) * 100 + 12);
fprintf(stdout, "[%d] second call -- my_var value is: %d (should be %d)0, Cthread_self(), my_var, (Tid + 1) * 100 + 12);
fprintf(stdout, "[%d] Testing consistency0, Cthread_self());
if (my_var != ((Tid + 1) * 100 + 12)) {
fprintf(stdout, "[%d] !!!!!!!!! ERROR !!!!!!!!!0, Cthread_self());
exit(1);
} else {
fprintf(stdout, "[%d] Cglobals_get worked ok0, Cthread_self());
}
return(0);
}

[1mSEE ALSO[0m
[1mCthread[22m(3), [1mserrno[22m(3), [1mCgetopt[22m(3)

[1mAUTHOR[0m
[1mLCG Grid Deployment [22mTeam

LCG $Date: 2010-04-05 09:51:26 +0200 (Mon, 05 Apr 2010) $ CGLOBALS(3)

Info