1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % TTTTT H H RRRR EEEEE AAA DDDD %
6 % T H H R R E A A D D %
7 % T HHHHH RRRR EEE AAAAA D D %
8 % T H H R R E A A D D %
9 % T H H R R EEEEE A A DDDD %
10 % %
11 % %
12 % MagickCore Thread Methods %
13 % %
14 % Software Design %
15 % Cristy %
16 % March 2003 %
17 % %
18 % %
19 % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %
20 % dedicated to making software imaging solutions freely available. %
21 % %
22 % You may not use this file except in compliance with the License. You may %
23 % obtain a copy of the License at %
24 % %
25 % https://imagemagick.org/script/license.php %
26 % %
27 % Unless required by applicable law or agreed to in writing, software %
28 % distributed under the License is distributed on an "AS IS" BASIS, %
29 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
30 % See the License for the specific language governing permissions and %
31 % limitations under the License. %
32 % %
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 %
35 %
36 */
37
38 /*
39 Include declarations.
40 */
41 #include "MagickCore/studio.h"
42 #include "MagickCore/memory_.h"
43 #include "MagickCore/thread_.h"
44 #include "MagickCore/thread-private.h"
45
46 /*
47 Typedef declarations.
48 */
49 typedef struct _MagickThreadValue
50 {
51 size_t
52 number_threads;
53
54 void
55 **values,
56 (*destructor)(void *);
57 } MagickThreadValue;
58
59 /*
60 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
61 % %
62 % %
63 % %
64 % C r e a t e M a g i c k T h r e a d K e y %
65 % %
66 % %
67 % %
68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 %
70 % CreateMagickThreadKey() creates a thread-specific data key visible to all
71 % threads in the process.
72 %
73 % The format of the CreateMagickThreadKey method is:
74 %
75 % MagickThreadKey CreateMagickThreadKey(MagickThreadKey *key)
76 %
77 % A description of each parameter follows:
78 %
79 % o key: opaque objects used to locate thread-specific data.
80 %
81 % o destructor: associate an optional destructor with each key value.
82 %
83 */
CreateMagickThreadKey(MagickThreadKey * key,void (* destructor)(void *))84 MagickExport MagickBooleanType CreateMagickThreadKey(MagickThreadKey *key,
85 void (*destructor)(void *))
86 {
87 #if defined(MAGICKCORE_THREAD_SUPPORT)
88 return(pthread_key_create(key,destructor) == 0 ? MagickTrue : MagickFalse);
89 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
90 magick_unreferenced(destructor);
91 *key=TlsAlloc();
92 return(*key != TLS_OUT_OF_INDEXES ? MagickTrue : MagickFalse);
93 #else
94 {
95 MagickThreadValue
96 **keys;
97
98 keys=(MagickThreadValue **) key;
99 *keys=(MagickThreadValue *) AcquireQuantumMemory(1,sizeof(**keys));
100 if (*keys != (MagickThreadValue *) NULL)
101 {
102 (*keys)->number_threads=GetOpenMPMaximumThreads();
103 (*keys)->values=AcquireQuantumMemory((*keys)->number_threads,
104 sizeof(void *));
105 if ((*keys)->values == (void *) NULL)
106 *keys=RelinquishMagickMemory(*keys);
107 else
108 (void) memset((*keys)->values,0,(*keys)->number_threads*
109 sizeof(void *));
110 (*keys)->destructor=destructor;
111 }
112 return((*keys != (MagickThreadValue *) NULL) ? MagickTrue : MagickFalse);
113 }
114 #endif
115 }
116
117 /*
118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119 % %
120 % %
121 % %
122 % D e l e t e M a g i c k T h r e a d K e y %
123 % %
124 % %
125 % %
126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
127 %
128 % DeleteMagickThreadKey() deletes a thread-specific data key.
129 %
130 % The format of the DeleteMagickThreadKey method is:
131 %
132 % MagickBooleanType DeleteMagickThreadKey(MagickThreadKey key)
133 %
134 % A description of each parameter follows:
135 %
136 % o key: the thread key.
137 %
138 */
DeleteMagickThreadKey(MagickThreadKey key)139 MagickExport MagickBooleanType DeleteMagickThreadKey(MagickThreadKey key)
140 {
141 #if defined(MAGICKCORE_THREAD_SUPPORT)
142 return(pthread_key_delete(key) == 0 ? MagickTrue : MagickFalse);
143 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
144 return(TlsFree(key) != 0 ? MagickTrue : MagickFalse);
145 #else
146 {
147 MagickThreadValue
148 *keys;
149
150 register ssize_t
151 i;
152
153 keys=(MagickThreadValue *) key;
154 for (i=0; i < (ssize_t) keys->number_threads; i++)
155 if ((keys->destructor != (void *) NULL) &&
156 (keys->values[i] != (void *) NULL))
157 {
158 keys->destructor(keys->values[i]);
159 keys->values[i]=(void *) NULL;
160 }
161 keys=(MagickThreadValue *) RelinquishMagickMemory(keys);
162 }
163 return(MagickTrue);
164 #endif
165 }
166
167 /*
168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
169 % %
170 % %
171 % %
172 % G e t M a g i c k T h r e a d V a l u e %
173 % %
174 % %
175 % %
176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
177 %
178 % GetMagickThreadValue() returns the value currently bound to the specified
179 % key on behalf of the calling thread.
180 %
181 % The format of the GetMagickThreadValue method is:
182 %
183 % void *GetMagickThreadValue(MagickThreadKey key)
184 %
185 % A description of each parameter follows:
186 %
187 % o key: the thread key.
188 %
189 */
GetMagickThreadValue(MagickThreadKey key)190 MagickExport void *GetMagickThreadValue(MagickThreadKey key)
191 {
192 #if defined(MAGICKCORE_THREAD_SUPPORT)
193 return(pthread_getspecific(key));
194 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
195 return(TlsGetValue(key));
196 #else
197 {
198 MagickThreadValue
199 *keys;
200
201 keys=(MagickThreadValue *) key;
202 return(keys->values[GetOpenMPThreadId()]);
203 }
204 #endif
205 }
206
207 /*
208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
209 % %
210 % %
211 % %
212 % S e t M a g i c k T h r e a d V a l u e %
213 % %
214 % %
215 % %
216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
217 %
218 % SetMagickThreadValue() binds a value to the specified key on behalf of the
219 % calling thread.
220 %
221 % The format of the SetMagickThreadValue method is:
222 %
223 % MagickBooleanType SetMagickThreadValue(MagickThreadKey key,
224 % const void *value)
225 %
226 % A description of each parameter follows:
227 %
228 % o key: the thread key.
229 %
230 % o value: the value.
231 %
232 */
SetMagickThreadValue(MagickThreadKey key,const void * value)233 MagickExport MagickBooleanType SetMagickThreadValue(MagickThreadKey key,
234 const void *value)
235 {
236 #if defined(MAGICKCORE_THREAD_SUPPORT)
237 return(pthread_setspecific(key,value) == 0 ? MagickTrue : MagickFalse);
238 #elif defined(MAGICKCORE_WINDOWS_SUPPORT)
239 return(TlsSetValue(key,(void *) value) != 0 ? MagickTrue : MagickFalse);
240 #else
241 {
242 MagickThreadValue
243 *keys;
244
245 keys=(MagickThreadValue *) key;
246 keys->values[GetOpenMPThreadId()]=(void *) value;
247 }
248 return(MagickTrue);
249 #endif
250 }
251