1CGLOBALS(3)                     Common      Library     Functions
2CGLOBALS(3)
3
4
5
6[1mNAME[0m
7       [1mCglobals [22m‐ LCG thread‐specific [1mglobal  [22mvari‐
8able[1ms [22minterface
9
10[1mSYNOPSIS[0m
11       [1m#include <Cglobals.h>[0m
12
13       [1mvoid Cglobals_init([0m
14              [1mint         (*[4m[22mgetspec[24m[1m)        (int
15*[4m[22mkey[24m[1m, void **[4m[22maddr[24m[1m),[0m
16              [1mint        (*[4m[22msetspec[24m[1m)         (int
17*[4m[22mkey[24m[1m, void *[4m[22maddr[24m[1m),[0m
18              [1mint (*[4m[22mgetTid[24m[1m) (void)[0m
19       [1m);[0m
20
21       [1mint     Cglobals_get(int    *[4m[22mkey[24m[1m,    void
22**[4m[22maddr[24m[1m, size_t [4m[22msize[24m[1m);[0m
23
24       [1mvoid Cglobals_getTid(int *[4m[22mTid[24m[1m);[0m
25
26       [1mint C__serrno();[0m
27
28       [1mint C__rfio_errno();[0m
29
30       [1mint C__Copterr();[0m
31
32       [1mint C__Coptind();[0m
33
34       [1mint C__Coptopt();[0m
35
36       [1mint C__Coptreset();[0m
37
38       [1mchar *C__Coptarg();[0m
39
40       [1mint C__h_errno();[0m
41
42
43[1mDESCRIPTION[0m
44       [1mCglobals  [22mis  the  interface  where are defined all
45necessary functions
46       that  always  return  a  thread‐specific  value of  global
47variables.  Each
48       package  of  [1mLCG [22mthat needs to externalize  thread‐
49specific global vari‐
50       ables  contains  in  its  header, if compiled with threads
51turned on  (e.g.
52       the default), a set of:
53              an [1mextern [22mdefinition to a function contained
54in Cglobals
55              a [1m#define [22mmacro that replaces all occurences
56of any global vari‐
57              able that needs  to  be  thread‐specific  to   this
58Cglobal’s  func‐
59              tion.
60       In   order  to  satisfy packages not compiled with threads
61turned on, or
62       that do not initialize [1mLCG [22mThread Interface’s [1mC‐
63thread[22m, any such  global
64       variable is also explicitly defined in [1mCglobals[22m.
65
66       For   example,   taking  the global error variable [1mser‐
67rno[22m, [1mCglobals [22msource
68       code contains:
69              an explicit definition  of  this  variable  [1mser‐
70rno[0m
71              an  explicit  definition,  with  source  code, of a
72function  [1mC_ser‐[0m
73              [1mrno() [22mthat does only the following:
74                     if  [1mCglobals_init  [22mwas  not (success‐
75fully) called, return
76                     the  address  of the global variable [1mser‐
77rno[0m
78                     else return the  address  of  a  thread‐safe
79specific memory,
80                     instanciated   at   the  first  call to this
81function, that
82                     holds the content of the current instance of
83the  thread‐
84                     specific value of [1mserrno[0m
85
86       The     following    description    of    [1mCglobals_init
87[22mfunction  is explaining
88       internals of [1mCglobals [22mand [1mCthread[22m. In theory
89no LCG application need to
90       call   [1mCglobals_init[22m,  you can skip if you want the
91following paragraphs,
92       and concentrate only on the other functions descriptions.
93
94       [1mCglobals_init  [22mis  bundled   to   work   with   the
95[1mLCG  [22mThread  Interface’s
96       [1mCthread[22m.  That is, any implicit or explicit call to
97[1mCthread [22malways makes
98       sure that [1mCglobals_init [22mis called, with three argu‐
99ments that are:
100              a  [4mgetspec[24m  function  address that, given  a
101static  [4mkey[24m  address,
102              returns  the  address of a  Thread‐Specific  memory
103into [4maddr[24m con‐
104              tent.  This uses an internal structure inside [1mC‐
105thread[22m,  allocated
106              on  the  heap,  that  is  associated bijectively to
107[4mkey[24m address.
108              [1mCthread [22malways explicitly allocates such in‐
109ternal  structure  to
110              any  [4mkey[24m  address  if it is unknown  at  the
111moment of the call to
112              [4mgetspec.[0m
113              In  such  a  case  it will return a NULL value into
114[4maddr[24m  ,  and  it
115              will be the responsability  of  [1mCglobals  [22mto
116allocate memory on the
117              heap  and  to say to [1mCthread [22mthat this newly
118allocated  memory  is
119              the one to associate with [4mkey[24m address, using
120[4msetspec.[0m
121              If  the  internal structure in [1mCthread [22masso‐
122ciated bijectively to
123              [4mkey[24m yet exists, [4mgetspec[24m only  returns
124what  it  knows  about  the
125              thread‐specific    memory   associated   with   it,
126which is a [1mvoid *[0m
127              member inside  the  same  internal  structure  men‐
128tionned above.
129
130              a  [4msetspec[24m  function address that, given the
131[4mkey[24m address  and  the
132              [4maddr[24m  value,  previously  instanciated  with
133a [4mgetspec[24m call, and
134              possibly  allocated  on  the  heap  by  [1mCglobals
135[22mif  necessary,  will
136              internally  explicitly call  the  Operating  System
137Thread‐Specific
138              functions  that  will   put  the  value  of  [4mad‐
139dress[24m  as  something
140              thread‐specific, bijectively associated to  another
141member of the
142              internal structure of [1mCthread[22m, itself bijec‐
143tive to [4mkey.[0m
144
145              a [4mgetTid[24m function address  that  returns  an
146unique integer identi‐
147              fier associated with any thread.
148
149       [1mCglobals_get   [22mreturns   in [4maddr[24m content the
150address of a thread‐specific
151       memory, e.g. thread‐safe,  that  is  bijectively   associ‐
152ated  with  the
153       address  of  a *static*, e.g. constant, address [4mkey[24m
154, that is automati‐
155       cally created and filled with zeros if  necessary,  up  to
156[4msize[24m bytes.
157       If   the  [4maddr[24m  content,  at  return  of  [1mCglob‐
158als_get[22m, is not  NULL,  you  can
159       safely  fill  this  memory with any  value,  provided  you
160does not exceed
161       the  [4msize[24m  bytes  length specified in your previous
162call to  [1mCglobals_get[22m.
163       Because  of applications that are [1mnot [22mmulti‐thread‐
164ed, the initial value
165       of  [4mkey[24m  has  then an importance, that’s why it  is
166necessary  to  always
167       declare it with an initial value of ‐1.
168
169       Return  code  is  ‐1  on error, 0 on  success  and  [1mnot
170[22mthe first call for
171       this  [4mkey[24m , 1 on success and [1mit is [22mthe first
172call for  this  [4mkey.[24m   This
173       allows  to  distinguish   when  Cglobals_get()  initialize
174the memory with
175       zeros (return code 1) and not (return code 0).
176
177       [1mCglobals_getTid  [22muses  the  third function address,
178[4mgetTid[24m , given  as  an
179       argument  to  [1mCglobals_init[22m,  and  will  return  in
180[4mTid[24m content the value
181       returned by [4mgetTid.[0m
182
183       [1mC__serrno[22m, [1mC__rfio_errno[22m, [1mC__Copterr[22m,
184[1mC__Coptind[22m,  [1mC__Coptopt[22m,  [1mC__Cop‐[0m
185       [1mtreset[22m,    [1mC__Coptarg    [22mand   [1mC__h_errno
186[22mare all the internal functions that
187       return  the  address of the thread‐specific memory hosting
188the  value  of
189       the   ’global’   variables  serrno,  rfio_errno,  Copterr,
190Coptind, Coptopt,
191       Coptreset, Coptarg and h_errno, respectively.
192
193[1mEXAMPLE[0m
194       Any  application  can  create its own instance of  thread‐
195specific  global
196       variable using [1mCglobals[22m. You need only to use [1mC‐
197globals_get[22m. Here is how
198       to proceed.
199
200       /*
201        * The following shows how to define and use a thread‐spe‐
202cific
203        * integer, my_var, inside your package
204        */
205
206       #include <stdlib.h>
207       #include <stdio.h>
208       #include <Cglobals.h>   /* Get [1mCglobals_get  [22mproto‐
209type */
210       static  int  my_key = ‐1; /* Our static key, integer, init
211value ‐1 */
212       #define my_var (*C__my_var())
213
214       static int my_var_static; /* If Cglobals_get error in  or‐
215der not to crash */
216
217
218       int *C__my_var()
219       {
220               int *var;
221               /* Call Cglobals_get */
222               Cglobals_get(&my_key,
223                            (void **) &var,
224                            sizeof(int)
225                           );
226               /* If error, var will be NULL */
227               if (var == NULL)
228               {
229                       fprintf(stderr,"Cglobals_get error0);
230                       return(&my_var_static);
231               }
232               return(var);
233       }
234
235       int main()
236       {
237               fprintf(stdout,  "Current  my_var  value  is: %d0,
238my_var);
239               fprintf(stdout, "Set my_var value to: %d0, 12);
240               my_var = 12;
241               fprintf(stdout, "Current  my_var  value  is:  %d0,
242my_var);
243               return(0);
244       }
245
246       The  following example is the source of the test suite for
247Cglobals_get():
248
249       #include <Cthread_api.h>
250       #include <stdlib.h>
251       #include <stdio.h>
252       #include <Cglobals.h>   /* Get Cglobals_get prototype */
253       #include <serrno.h>
254
255       static int my_key = ‐1; /* Our static key,  integer,  init
256value ‐1 */
257       #define my_var (*C__my_var())
258
259       static  int my_var_static; /* If Cglobals_get error in or‐
260der not to crash */
261       void *doit _PROTO((void *));
262
263       int doit_v = 0;
264       #define NTHREAD 100
265
266       int *C__my_var()
267       {
268         int *var;
269         /* Call Cglobals_get */
270         switch (Cglobals_get(&my_key,
271                              (void **) &var,
272                              sizeof(int)
273                              )) {
274         case ‐1:
275           fprintf(stderr,"[%d]       Cglobals_get        error0,
276Cthread_self());
277           break;
278         case 0:
279           fprintf(stderr,"[%d]         Cglobals_get         OK0,
280Cthread_self());
281           break;
282         case 1:
283           fprintf(stderr,"[%d] Cglobals_get OK and first  call0,
284Cthread_self());
285           break;
286         default:
287           fprintf(stderr,"[%d]   Cglobals_get   unknown   return
288code0, Cthread_self());
289           break;
290         }
291         /* If error, var will be NULL */
292         if (var == NULL) {
293           fprintf(stderr,"[%d] Cglobals_get error : RETURN stat‐
294ic ADDRESS!!!!!!!!!!!!0, Cthread_self());
295           return(&my_var_static);
296         }
297         return(var);
298       }
299
300       int main()
301       {
302         int i;
303
304         fprintf(stdout,  "[%d]  ‐‐‐>  Before  any Cthread call0,
305‐1);
306         fprintf(stdout, "[%d] Current my_var value is: %d0,  ‐1,
307my_var);
308         fprintf(stdout, "[%d] Set my_var value to: %d0, ‐1, 12);
309         my_var = 12;
310         fprintf(stdout,  "[%d] Current my_var value is: %d0, ‐1,
311my_var);
312         fprintf(stdout, "[%d] Testing consistency0, ‐1);
313         if (my_var != 12) {
314           fprintf(stdout, "[%d] Cglobals_get worked ok0, ‐1);
315           exit(1);
316         }
317         sleep(1);
318         for (i = 0; i < NTHREAD; i++) {
319           Cthread_create(&doit, &doit_v);
320           doit_v++;
321         }
322         fprintf(stdout,  "[%d]  ‐‐‐>  After  all  Cthread_create
323calls0, ‐1);
324         fprintf(stdout,  "[%d] Current my_var value is: %d0, ‐1,
325my_var);
326         fprintf(stdout, "[%d] Set  my_var  value  to:  %d0,  ‐1,
327NTHREAD * 10000 + 12);
328         my_var = NTHREAD * 10000 + 12;
329         fprintf(stdout,  "[%d] Current my_var value is: %d0, ‐1,
330my_var);
331         fprintf(stdout, "[%d] Testing consistency0, ‐1);
332         if (my_var != (NTHREAD * 10000 + 12)) {
333           fprintf(stdout, "[%d] Cglobals_get worked ok0, ‐1);
334           exit(1);
335         }
336         sleep(1);
337         exit(0);
338       }
339
340       void *doit(arg)
341            void *arg;
342       {
343         int Tid;
344         int doit = * (int *) arg;
345         Cglobals_getTid(&Tid);
346         my_var = (Tid + 1) * 100 + 12;
347         fprintf(stdout, "[%d] my_var value  is:  %d  (should  be
348%d)0, Cthread_self(), my_var, (Tid + 1) * 100 + 12);
349         fprintf(stdout, "[%d] second call ‐‐ my_var value is: %d
350(should be %d)0, Cthread_self(), my_var, (Tid + 1) * 100 + 12);
351         fprintf(stdout,     "[%d]     Testing      consistency0,
352Cthread_self());
353         if (my_var != ((Tid + 1) * 100 + 12)) {
354           fprintf(stdout,   "[%d]  !!!!!!!!!  ERROR  !!!!!!!!!0,
355Cthread_self());
356           exit(1);
357         } else {
358           fprintf(stdout,   "[%d]   Cglobals_get   worked   ok0,
359Cthread_self());
360         }
361         return(0);
362       }
363
364
365
366
367[1mSEE ALSO[0m
368       [1mCthread[22m(3), [1mserrno[22m(3), [1mCgetopt[22m(3)
369
370
371[1mAUTHOR[0m
372       [1mLCG Grid Deployment [22mTeam
373
374
375
376
377LCG                                                        $Date$
378CGLOBALS(3)
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
Impressum