1CGLOBALS(3)                Common Library Functions                CGLOBALS(3)
2
3
4

NAME

6       Cglobals - LCG thread-specific global variables interface
7

SYNOPSIS

9       #include <Cglobals.h>
10
11       void Cglobals_init(
12              int (*getspec) (int *key, void **addr),
13              int (*setspec) (int *key, void *addr),
14              int (*getTid) (void)
15       );
16
17       int Cglobals_get(int *key, void **addr, size_t size);
18
19       void Cglobals_getTid(int *Tid);
20
21       int C__serrno();
22
23       int C__rfio_errno();
24
25       int C__Copterr();
26
27       int C__Coptind();
28
29       int C__Coptopt();
30
31       int C__Coptreset();
32
33       char *C__Coptarg();
34
35       int C__h_errno();
36
37

DESCRIPTION

39       Cglobals  is  the  interface  where are defined all necessary functions
40       that always return a thread-specific value of  global  variables.  Each
41       package  of  LCG that needs to externalize thread-specific global vari‐
42       ables contains in its header, if compiled with threads turned on  (e.g.
43       the default), a set of:
44              an extern definition to a function contained in Cglobals
45              a #define macro that replaces all occurences of any global vari‐
46              able that needs to be thread-specific to  this  Cglobal's  func‐
47              tion.
48       In  order  to  satisfy packages not compiled with threads turned on, or
49       that do not initialize LCG Thread Interface's Cthread, any such  global
50       variable is also explicitly defined in Cglobals.
51
52       For  example,  taking the global error variable serrno, Cglobals source
53       code contains:
54              an explicit definition of this variable serrno
55              an explicit definition, with source code, of a  function  C_ser‐
56              rno() that does only the following:
57                     if  Cglobals_init  was  not (successfully) called, return
58                     the address of the global variable serrno
59                     else return the address of a thread-safe specific memory,
60                     instanciated  at  the  first  call to this function, that
61                     holds the content of the current instance of the  thread-
62                     specific value of serrno
63
64       The  following  description  of  Cglobals_init  function  is explaining
65       internals of Cglobals and Cthread. In theory no LCG application need to
66       call  Cglobals_init, you can skip if you want the following paragraphs,
67       and concentrate only on the other functions descriptions.
68
69       Cglobals_init is bundled  to  work  with  the  LCG  Thread  Interface's
70       Cthread. That is, any implicit or explicit call to Cthread always makes
71       sure that Cglobals_init is called, with three arguments that are:
72              a getspec function address that, given  a  static  key  address,
73              returns  the  address of a Thread-Specific memory into addr con‐
74              tent. This uses an internal structure inside Cthread,  allocated
75              on  the  heap,  that  is  associated bijectively to key address.
76              Cthread always explicitly allocates such internal  structure  to
77              any  key  address  if it is unknown at the moment of the call to
78              getspec.
79              In such a case it will return a NULL value into addr  ,  and  it
80              will be the responsability of Cglobals to allocate memory on the
81              heap and to say to Cthread that this newly allocated  memory  is
82              the one to associate with key address, using setspec.
83              If  the  internal structure in Cthread associated bijectively to
84              key yet exists, getspec only returns what  it  knows  about  the
85              thread-specific  memory  associated  with  it, which is a void *
86              member inside the same internal structure mentionned above.
87
88              a setspec function address that, given the key address  and  the
89              addr  value,  previously  instanciated  with a getspec call, and
90              possibly allocated on the heap by Cglobals  if  necessary,  will
91              internally  explicitly call the Operating System Thread-Specific
92              functions that will  put  the  value  of  address  as  something
93              thread-specific, bijectively associated to another member of the
94              internal structure of Cthread, itself bijective to key.
95
96              a getTid function address that returns an unique integer identi‐
97              fier associated with any thread.
98
99       Cglobals_get  returns  in addr content the address of a thread-specific
100       memory, e.g. thread-safe,  that  is  bijectively  associated  with  the
101       address  of  a *static*, e.g. constant, address key , that is automati‐
102       cally created and filled with zeros if necessary, up to size bytes.
103       If the addr content, at return of Cglobals_get, is not  NULL,  you  can
104       safely  fill  this  memory with any value, provided you does not exceed
105       the size bytes length specified in your previous call to  Cglobals_get.
106       Because  of applications that are not multi-threaded, the initial value
107       of key has then an importance, that's why it  is  necessary  to  always
108       declare it with an initial value of -1.
109
110       Return  code  is  -1  on error, 0 on success and not the first call for
111       this key , 1 on success and it is the first call for  this  key.   This
112       allows  to  distinguish  when Cglobals_get() initialize the memory with
113       zeros (return code 1) and not (return code 0).
114
115       Cglobals_getTid uses the third function address, getTid , given  as  an
116       argument  to  Cglobals_init,  and  will return in Tid content the value
117       returned by getTid.
118
119       C__serrno, C__rfio_errno, C__Copterr, C__Coptind,  C__Coptopt,  C__Cop‐
120       treset,  C__Coptarg  and C__h_errno are all the internal functions that
121       return the address of the thread-specific memory hosting the  value  of
122       the  'global'  variables serrno, rfio_errno, Copterr, Coptind, Coptopt,
123       Coptreset, Coptarg and h_errno, respectively.
124

EXAMPLE

126       Any application can create its own instance of  thread-specific  global
127       variable using Cglobals. You need only to use Cglobals_get. Here is how
128       to proceed.
129
130       /*
131        * The following shows how to define and use a thread-specific
132        * integer, my_var, inside your package
133        */
134
135       #include <stdlib.h>
136       #include <stdio.h>
137       #include <Cglobals.h>   /* Get Cglobals_get prototype */
138       static int my_key = -1; /* Our static key, integer, init value -1 */
139       #define my_var (*C__my_var())
140
141       static int my_var_static; /* If Cglobals_get error in order not to crash */
142
143
144       int *C__my_var()
145       {
146               int *var;
147               /* Call Cglobals_get */
148               Cglobals_get(&my_key,
149                            (void **) &var,
150                            sizeof(int)
151                           );
152               /* If error, var will be NULL */
153               if (var == NULL)
154               {
155                       fprintf(stderr,"Cglobals_get error0);
156                       return(&my_var_static);
157               }
158               return(var);
159       }
160
161       int main()
162       {
163               fprintf(stdout, "Current my_var value is: %d0, my_var);
164               fprintf(stdout, "Set my_var value to: %d0, 12);
165               my_var = 12;
166               fprintf(stdout, "Current my_var value is: %d0, my_var);
167               return(0);
168       }
169
170       The following example is the source of the test suite for Cglobals_get():
171
172       #include <Cthread_api.h>
173       #include <stdlib.h>
174       #include <stdio.h>
175       #include <Cglobals.h>   /* Get Cglobals_get prototype */
176       #include <serrno.h>
177
178       static int my_key = -1; /* Our static key, integer, init value -1 */
179       #define my_var (*C__my_var())
180
181       static int my_var_static; /* If Cglobals_get error in order not to crash */
182       void *doit _PROTO((void *));
183
184       int doit_v = 0;
185       #define NTHREAD 100
186
187       int *C__my_var()
188       {
189         int *var;
190         /* Call Cglobals_get */
191         switch (Cglobals_get(&my_key,
192                              (void **) &var,
193                              sizeof(int)
194                              )) {
195         case -1:
196           fprintf(stderr,"[%d] Cglobals_get error0, Cthread_self());
197           break;
198         case 0:
199           fprintf(stderr,"[%d] Cglobals_get OK0, Cthread_self());
200           break;
201         case 1:
202           fprintf(stderr,"[%d] Cglobals_get OK and first call0, Cthread_self());
203           break;
204         default:
205           fprintf(stderr,"[%d] Cglobals_get unknown return code0, Cthread_self());
206           break;
207         }
208         /* If error, var will be NULL */
209         if (var == NULL) {
210           fprintf(stderr,"[%d] Cglobals_get error : RETURN static ADDRESS!!!!!!!!!!!!0, Cthread_self());
211           return(&my_var_static);
212         }
213         return(var);
214       }
215
216       int main()
217       {
218         int i;
219
220         fprintf(stdout, "[%d] ---> Before any Cthread call0, -1);
221         fprintf(stdout, "[%d] Current my_var value is: %d0, -1, my_var);
222         fprintf(stdout, "[%d] Set my_var value to: %d0, -1, 12);
223         my_var = 12;
224         fprintf(stdout, "[%d] Current my_var value is: %d0, -1, my_var);
225         fprintf(stdout, "[%d] Testing consistency0, -1);
226         if (my_var != 12) {
227           fprintf(stdout, "[%d] Cglobals_get worked ok0, -1);
228           exit(1);
229         }
230         sleep(1);
231         for (i = 0; i < NTHREAD; i++) {
232           Cthread_create(&doit, &doit_v);
233           doit_v++;
234         }
235         fprintf(stdout, "[%d] ---> After all Cthread_create calls0, -1);
236         fprintf(stdout, "[%d] Current my_var value is: %d0, -1, my_var);
237         fprintf(stdout, "[%d] Set my_var value to: %d0, -1, NTHREAD * 10000 + 12);
238         my_var = NTHREAD * 10000 + 12;
239         fprintf(stdout, "[%d] Current my_var value is: %d0, -1, my_var);
240         fprintf(stdout, "[%d] Testing consistency0, -1);
241         if (my_var != (NTHREAD * 10000 + 12)) {
242           fprintf(stdout, "[%d] Cglobals_get worked ok0, -1);
243           exit(1);
244         }
245         sleep(1);
246         exit(0);
247       }
248
249       void *doit(arg)
250            void *arg;
251       {
252         int Tid;
253         int doit = * (int *) arg;
254         Cglobals_getTid(&Tid);
255         my_var = (Tid + 1) * 100 + 12;
256         fprintf(stdout, "[%d] my_var value is: %d (should be %d)0, Cthread_self(), my_var, (Tid + 1) * 100 + 12);
257         fprintf(stdout, "[%d] second call -- my_var value is: %d (should be %d)0, Cthread_self(), my_var, (Tid + 1) * 100 + 12);
258         fprintf(stdout, "[%d] Testing consistency0, Cthread_self());
259         if (my_var != ((Tid + 1) * 100 + 12)) {
260           fprintf(stdout, "[%d] !!!!!!!!! ERROR !!!!!!!!!0, Cthread_self());
261           exit(1);
262         } else {
263           fprintf(stdout, "[%d] Cglobals_get worked ok0, Cthread_self());
264         }
265         return(0);
266       }
267
268
269
270

SEE ALSO

272       Cthread(3), serrno(3), Cgetopt(3)
273
274

AUTHOR

276       LCG Grid Deployment Team
277
278
279
280
281LCG          $Date: 2010-04-05 09:51:26 +0200 (Mon, 05 Apr 2010) $ CGLOBALS(3)
Impressum