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