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