1 #if defined( THREAD_SAFE )
2 
3 #define astCLASS
4 
5 #include "globals.h"
6 #include "error.h"
7 #include <pthread.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 
11 /* Configuration results. */
12 /* ---------------------- */
13 #if HAVE_CONFIG_H
14 #include <config.h>
15 #endif
16 
17 /* Select the appropriate memory management functions. These will be the
18    system's malloc, free and realloc unless AST was configured with the
19    "--with-starmem" option, in which case they will be the starmem
20    malloc, free and realloc. */
21 #ifdef HAVE_STAR_MEM_H
22 #  include <star/mem.h>
23 #  define MALLOC starMalloc
24 #  define FREE starFree
25 #  define REALLOC starRealloc
26 #else
27 #  define MALLOC malloc
28 #  define FREE free
29 #  define REALLOC realloc
30 #endif
31 
32 /* Module variables */
33 /* ================ */
34 
35 /* A count of the number of thread-specific data structures created so
36    far. Create a mutex to serialise access to this static variable. */
37 static int nthread = 0;
38 static pthread_mutex_t nthread_mutex = PTHREAD_MUTEX_INITIALIZER;
39 
40 /* External variables visible throughout AST */
41 /* ========================================= */
42 
43 /* Set a flag indicating that the thread-specific data key has not yet
44    been created. */
45 pthread_once_t starlink_ast_globals_initialised = PTHREAD_ONCE_INIT;
46 
47 /* Declare the pthreads key that will be associated with the thread-specific
48    data for each thread. */
49 pthread_key_t starlink_ast_globals_key;
50 
51 /* Declare the pthreads key that will be associated with the thread-specific
52    status value for each thread. */
53 pthread_key_t starlink_ast_status_key;
54 
55 
56 /* Function definitions: */
57 /* ===================== */
58 
59 
astGlobalsCreateKey_(void)60 void astGlobalsCreateKey_( void ) {
61 /*
62 *+
63 *  Name:
64 *     astGlobalsCreateKey_
65 
66 *  Purpose:
67 *     Create the thread specific data key used for accessing global data.
68 
69 *  Type:
70 *     Protected function.
71 
72 *  Synopsis:
73 *     #include "globals.h"
74 *     astGlobalsCreateKey_()
75 
76 *  Description:
77 *     This function creates the thread-specific data key. It is called
78 *     once only by the pthread_once function, which is invoked via the
79 *     astGET_GLOBALS(this) macro by each AST function that requires access to
80 *     global data.
81 
82 *  Returned Value:
83 *     Zero for success.
84 
85 *-
86 */
87 
88 /* Create the key used to access thread-specific global data values.
89    Report an error if it fails. */
90    if( pthread_key_create( &starlink_ast_globals_key, NULL ) ) {
91       fprintf( stderr, "ast: Failed to create Thread-Specific Data key" );
92 
93 /* If succesful, create the key used to access the thread-specific status
94    value. Report an error if it fails. */
95    } else if( pthread_key_create( &starlink_ast_status_key, NULL ) ) {
96       fprintf( stderr, "ast: Failed to create Thread-Specific Status key" );
97 
98    }
99 
100 }
101 
astGlobalsInit_(void)102 AstGlobals *astGlobalsInit_( void ) {
103 /*
104 *+
105 *  Name:
106 *     astGlobalsInit
107 
108 *  Purpose:
109 *     Create and initialise a structure holding thread-specific global
110 *     data values.
111 
112 *  Type:
113 *     Protected function.
114 
115 *  Synopsis:
116 *     #include "globals.h"
117 *     AstGlobals *astGlobalsInit;
118 
119 *  Description:
120 *     This function allocates memory to hold thread-specific global data
121 *     for use throughout AST, and initialises it.
122 
123 *  Returned Value:
124 *     Pointer to the structure holding global data values for the
125 *     currently executing thread.
126 
127 *-
128 */
129 
130 /* Local Variables: */
131    AstGlobals *globals;
132    AstStatusBlock *status;
133 
134 /* Allocate memory to hold the global data values for the currently
135    executing thread. Use malloc rather than astMalloc (the AST memory
136    module uses global data managed by this module and so using astMalloc
137    could put us into an infinite loop). */
138    globals = MALLOC( sizeof( AstGlobals ) );
139 
140    if ( !globals ){
141       fprintf( stderr, "ast: Failed to allocate memory to hold AST "
142                "global data values" );
143 
144 /* Initialise the global data values. */
145    } else {
146 
147 /* Each thread has a unique integer identifier. */
148       pthread_mutex_lock( &nthread_mutex );
149       globals->thread_identifier = nthread++;
150       pthread_mutex_unlock( &nthread_mutex );
151 
152 #define INIT(class) astInit##class##Globals_( &(globals->class) );
153       INIT( Error );
154       INIT( Memory );
155       INIT( Object );
156       INIT( Axis );
157       INIT( Mapping );
158       INIT( Frame );
159       INIT( Channel );
160       INIT( CmpMap );
161       INIT( KeyMap );
162       INIT( FitsChan );
163       INIT( FitsTable );
164       INIT( CmpFrame );
165       INIT( DSBSpecFrame );
166       INIT( FrameSet );
167       INIT( LutMap );
168       INIT( MathMap );
169       INIT( PcdMap );
170       INIT( PointSet );
171       INIT( SkyAxis );
172       INIT( SkyFrame );
173       INIT( SlaMap );
174       INIT( SpecFrame );
175       INIT( SphMap );
176       INIT( TimeFrame );
177       INIT( WcsMap );
178       INIT( ZoomMap );
179       INIT( FluxFrame );
180       INIT( SpecFluxFrame );
181       INIT( GrismMap );
182       INIT( IntraMap );
183       INIT( Plot );
184       INIT( Plot3D );
185       INIT( Region );
186       INIT( Xml );
187       INIT( XmlChan );
188       INIT( Box );
189       INIT( Circle );
190       INIT( CmpRegion );
191       INIT( DssMap );
192       INIT( Ellipse );
193       INIT( Interval );
194       INIT( MatrixMap );
195       INIT( NormMap );
196       INIT( NullRegion );
197       INIT( PermMap );
198       INIT( PointList );
199       INIT( PolyMap );
200       INIT( Polygon );
201       INIT( Prism );
202       INIT( RateMap );
203       INIT( SelectorMap );
204       INIT( ShiftMap );
205       INIT( SpecMap );
206       INIT( Stc );
207       INIT( StcCatalogEntryLocation );
208       INIT( StcObsDataLocation );
209       INIT( SwitchMap );
210       INIT( Table );
211       INIT( TimeMap );
212       INIT( TranMap );
213       INIT( UnitMap );
214       INIT( WinMap );
215       INIT( StcResourceProfile );
216       INIT( StcSearchLocation );
217       INIT( StcsChan );
218 #undef INIT
219 
220 /* Save the pointer as the value of the starlink_ast_globals_key
221    thread-specific data key. */
222       if( pthread_setspecific( starlink_ast_globals_key, globals ) ) {
223          fprintf( stderr, "ast: Failed to store Thread-Specific Data pointer." );
224 
225 /* We also take this opportunity to allocate and initialise the
226    thread-specific status value. */
227       } else {
228          status = MALLOC( sizeof( AstStatusBlock ) );
229          if( status ) {
230             status->internal_status = 0;
231             status->status_ptr = &( status->internal_status );
232 
233 /* If succesful, store the pointer to this memory as the value of the
234    status key for the currently executing thread. Report an error if
235    this fails. */
236             if( pthread_setspecific( starlink_ast_status_key, status ) ) {
237                fprintf( stderr, "ast: Failed to store Thread-Specific Status pointer." );
238             }
239 
240          } else {
241             fprintf( stderr, "ast: Failed to allocate memory for Thread-Specific Status pointer." );
242          }
243       }
244    }
245 
246 /* Return a pointer to the data structure holding the global data values. */
247    return globals;
248 }
249 
250 #endif
251 
252