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