1 martin 1.19 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.20 //
|
3 martin 1.19 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.20 //
|
10 martin 1.19 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.20 //
|
17 martin 1.19 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.20 //
|
20 martin 1.19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.20 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.20 //
|
28 martin 1.19 //////////////////////////////////////////////////////////////////////////
|
29 mike 1.2 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #ifndef Pegasus_Threads_h
33 #define Pegasus_Threads_h
34
35 #include <cstring>
|
36 mike 1.5 #include <cstdio>
37 #include <cstring>
|
38 mike 1.2 #include <Pegasus/Common/Config.h>
39 #include <Pegasus/Common/Linkage.h>
40
41 // ATTN: can we consolidate these someplace?
42
|
43 marek 1.15 #ifdef PEGASUS_OS_ZOS
44 # include <sched.h>
45 #endif
|
46 mike 1.2 #if defined(PEGASUS_HAVE_PTHREADS)
47 # include <pthread.h>
48 # include <errno.h>
49 # include <sys/time.h>
50 #elif defined(PEGASUS_HAVE_WINDOWS_THREADS)
51 # include <windows.h>
52 # include <process.h>
53 #else
54 # error "<Pegasus/Common/Threads.h>: not implemented"
55 #endif
56
|
57 karl 1.17 #if defined(PEGASUS_OS_SOLARIS)
58 # include <string.h>
59 # include <stdio.h>
60 #endif
61
|
62 mike 1.2 PEGASUS_NAMESPACE_BEGIN
63
64 //==============================================================================
65 //
66 // PEGASUS_THREAD_CDECL
67 //
68 //==============================================================================
69
|
70 a.dunfey 1.12 #if defined(PEGASUS_OS_TYPE_WINDOWS)
|
71 mike 1.2 # define PEGASUS_THREAD_CDECL __stdcall
72 #else
73 # define PEGASUS_THREAD_CDECL /* empty */
74 #endif
75
76 //==============================================================================
77 //
|
78 mike 1.4 // ThreadId
79 //
80 //==============================================================================
81
82 struct ThreadId
83 {
|
84 kumpf 1.10 // The character representation of a uint64 requires 22 bytes including the
|
85 mike 1.4 // null terminator.
86 char buffer[22];
87 };
88
89 //==============================================================================
90 //
|
91 mike 1.2 // ThreadType
92 //
93 //==============================================================================
94
95 #if defined(PEGASUS_HAVE_PTHREADS)
96 struct ThreadType
97 {
98 ThreadType()
99 {
|
100 mike 1.3 memset(&thread, 0, sizeof(thread));
|
101 mike 1.2 }
102
|
103 mike 1.3 ThreadType(pthread_t thread_) : thread(thread_)
|
104 mike 1.2 {
105 }
106
|
107 mike 1.3 pthread_t thread;
108 };
|
109 mike 1.2 #endif /* PEGASUS_HAVE_PTHREADS */
110
111 #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
112 struct ThreadType
113 {
|
114 kumpf 1.10 ThreadType() : handle(NULL)
115 {
|
116 mike 1.3 }
117
|
118 mike 1.2 HANDLE handle;
119 };
120 #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
121
122 //==============================================================================
123 //
124 // ThreadReturnType
125 //
126 //==============================================================================
127
128 #if defined(PEGASUS_HAVE_PTHREADS)
129 typedef void* ThreadReturnType;
130 #endif
131
132 #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
133 typedef unsigned ThreadReturnType;
134 #endif
135
136 //==============================================================================
137 //
138 // ThreadHandle
139 mike 1.2 //
140 //==============================================================================
141
142 #if defined(PEGASUS_HAVE_PTHREADS)
143 struct ThreadHandle
144 {
145 ThreadType thid;
146 };
147 #elif defined(PEGASUS_HAVE_WINDOWS_THREADS)
148 struct ThreadHandle
149 {
150 ThreadType thid;
151 };
152 #endif
153
154 //==============================================================================
155 //
156 // Threads
157 //
158 //==============================================================================
159
160 mike 1.2 class PEGASUS_COMMON_LINKAGE Threads
161 {
162 public:
163
164 enum Type { DETACHED, JOINABLE };
165
166 static int create(
|
167 kumpf 1.10 ThreadType& thread,
|
168 mike 1.2 Type type,
|
169 kumpf 1.10 void* (*start)(void*),
|
170 mike 1.2 void* arg);
171
172 static ThreadType self();
173
174 static bool equal(ThreadType x, ThreadType y);
175
176 static void exit(ThreadReturnType rc);
177
178 static void cancel(ThreadType th, ThreadReturnType rc);
179
180 static void yield();
181
182 static void sleep(int msec);
183
184 static void cleanup_push(void (*start)(void*), void* arg);
185
186 static void cleanup_pop(int execute);
187
|
188 mike 1.3 static ThreadId id(const ThreadType& x = Threads::self());
189
190 static bool null(const ThreadType& x = Threads::self());
|
191 mike 1.2
192 static void clear(ThreadType& x);
193 };
194
195 //==============================================================================
196 //
197 // POSIX Threads Implementation
198 //
199 //==============================================================================
200
201 #if defined(PEGASUS_HAVE_PTHREADS)
202
|
203 kumpf 1.10 inline bool Threads::equal(ThreadType x, ThreadType y)
204 {
|
205 mike 1.3 return pthread_equal(x.thread, y.thread);
|
206 mike 1.2 }
207
208 inline void Threads::exit(ThreadReturnType rc)
209 {
|
210 marek 1.9 // NOTE: pthread_exit exhibits unusual behavior on RHEL 3 U2, as
211 // documented in Bugzilla 3836. Where feasible, it may be advantageous
212 // to avoid using this function.
|
213 mike 1.2 pthread_exit(rc);
214 }
215
216 inline void Threads::cancel(ThreadType th, ThreadReturnType rc)
217 {
|
218 mike 1.3 pthread_cancel(th.thread);
|
219 mike 1.2 }
220
221 inline void Threads::yield()
222 {
|
223 marek 1.16 #ifdef PEGASUS_OS_LINUX
224 pthread_yield();
225 #else
|
226 mike 1.2 sched_yield();
227 #endif
228 }
229
230 inline void Threads::cleanup_push(void (*func)(void*), void* arg)
231 {
232 // ATTN: it is doubtful whether cleanup handlers ever really worked.
233 // They are only used in two places and not used in many other
234 // places where mutexes are obtained. Further, they are only
235 // implemented correctly on one or two platforms. For now, we
236 // will defer their implementation until we can find a way to
237 // implement them on all platforms (using thread local storage).
238 }
239
240 inline void Threads::cleanup_pop(int execute)
241 {
242 // ATTN: not implemented.
243 }
244
|
245 mike 1.3 inline ThreadId Threads::id(const ThreadType& x)
|
246 mike 1.2 {
|
247 karl 1.17 ThreadId tid = { { 0 } };
|
248 mike 1.3
|
249 r.kieninger 1.18 #if defined(PEGASUS_OS_ZOS)
|
250 mike 1.3 const char* s = x.thread.__;
|
251 kumpf 1.10 sprintf(tid.buffer, "%X%X%X%X%X%X%X%X",
|
252 mike 1.3 s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]);
253 #else
|
254 kumpf 1.10 sprintf(tid.buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u",
|
255 mike 1.6 Uint64(x.thread));
|
256 mike 1.3 #endif
257
258 return tid;
259 }
260
261 inline bool Threads::null(const ThreadType& x)
262 {
|
263 r.kieninger 1.18 #if defined(PEGASUS_OS_ZOS)
|
264 mike 1.3 Uint64 tmp;
|
265 marek 1.7 memcpy(&tmp, x.thread.__, sizeof(Uint64));
|
266 mike 1.3 return tmp == 0;
267 #else
268 return x.thread == 0;
269 #endif
|
270 mike 1.2 }
271
272 inline void Threads::clear(ThreadType& x)
273 {
274 memset(&x, 0, sizeof(x));
275 }
276
277 #endif /* defined(PEGASUS_HAVE_PTHREADS) */
278
279 //==============================================================================
280 //
281 // Windows Threads Implementation
282 //
283 //==============================================================================
284
285 #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
286
|
287 kumpf 1.10 inline ThreadType Threads::self()
|
288 mike 1.2 {
289 ThreadType tt;
|
290 mike 1.5 tt.handle = GetCurrentThread();
|
291 mike 1.2 return tt;
292 }
293
|
294 kumpf 1.10 inline bool Threads::equal(ThreadType x, ThreadType y)
|
295 mike 1.2 {
296 return x.handle == y.handle;
297 }
298
299 inline void Threads::exit(ThreadReturnType rc)
300 {
301 _endthreadex(rc);
302 }
303
304 inline void Threads::cancel(ThreadType th, ThreadReturnType rc)
305 {
306 TerminateThread(th.handle, rc);
307 }
308
309 inline void Threads::yield()
310 {
311 Sleep(0);
312 }
313
314 inline void Threads::cleanup_push(void (*func)(void*), void* arg)
315 {
316 mike 1.2 // ATTN: Not implemented on Windows.
317 }
318
319 inline void Threads::cleanup_pop(int execute)
320 {
321 // ATTN: Not implemented on Windows.
322 }
323
|
324 mike 1.3 inline ThreadId Threads::id(const ThreadType& x)
325 {
326 ThreadId tmp;
327
|
328 kumpf 1.10 sprintf(tmp.buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u",
|
329 mike 1.5 Uint64(x.handle));
|
330 mike 1.3
331 return tmp;
332 }
333
334 inline bool Threads::null(const ThreadType& x)
|
335 mike 1.2 {
|
336 mike 1.3 return x.handle == NULL;
|
337 mike 1.2 }
338
339 inline void Threads::clear(ThreadType& x)
340 {
341 x.handle = NULL;
342 }
343
344 #endif /* defined(PEGASUS_HAVE_WINDOWS_THREADS) */
345
346 PEGASUS_NAMESPACE_END
347
348 #endif /* Pegasus_Threads_h */
|