1 karl 1.25 //%2005////////////////////////////////////////////////////////////////////////
|
2 mike 1.2 //
|
3 karl 1.23 // 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 karl 1.18 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.23 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.25 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 mike 1.2 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
13 kumpf 1.10 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
16 mike 1.2 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
18 //
|
19 kumpf 1.10 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
20 mike 1.2 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
22 kumpf 1.10 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
25 mike 1.2 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
29 //
30 // Author: Markus Mueller (sedgewick_de@yahoo.de)
31 //
32 // Modified By: Mike Day (mdday@us.ibm.com)
33 //
34 //%/////////////////////////////////////////////////////////////////////////////
35
36 #ifndef IPC_UNIX_include
37 #define IPC_UNIX_include
38
39 #include <sched.h>
40 #include <semaphore.h>
41 #include <pthread.h>
42 #include <signal.h>
43 #include <errno.h>
44 #include <sys/time.h>
45 #include <time.h>
|
46 dudhe.girish 1.21 #if !defined(PEGASUS_PLATFORM_DARWIN_PPC_GNU)
|
47 mike 1.2 #include <sys/timex.h>
|
48 dudhe.girish 1.21 #endif
|
49 mike 1.2
|
50 konrad.r 1.26 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)
51 #if GCC_VERSION > 30202
52 #define USE_PTHREAD_COND_IN_SEMAPHORE
53 #endif
54 #endif
55
|
56 mike 1.2 PEGASUS_NAMESPACE_BEGIN
57
|
58 mday 1.5 int timeval_subtract (struct timeval *result,
59 struct timeval *x,
60 struct timeval *y);
61
62
|
63 mike 1.3 #ifdef PEGASUS_NEED_CRITICAL_TYPE
|
64 konrad.r 1.22 #if !defined(PEGASUS_PLATFORM_DARWIN_PPC_GNU)
|
65 mike 1.2 typedef pthread_spinlock_t PEGASUS_CRIT_TYPE;
|
66 dudhe.girish 1.21 #else
67 typedef pthread_mutex_t PEGASUS_CRIT_TYPE;
68 #endif
|
69 mike 1.3 #endif
70
|
71 mike 1.2 typedef sem_t PEGASUS_SEMAPHORE_TYPE;
72 typedef pthread_t PEGASUS_THREAD_TYPE;
73 typedef pthread_mutex_t PEGASUS_MUTEX_TYPE;
74
|
75 konrad.r 1.26 #if !defined(PEGASUS_OS_ZOS_ZSERIES_IBM) && !defined(PEGASUS_OS_DARWIN) && !defined(USE_PTHREAD_COND_IN_SEMAPHORE)
|
76 mike 1.2 typedef struct {
77 sem_t sem;
78 pthread_t owner;
79 } PEGASUS_SEM_HANDLE ;
|
80 dudhe.girish 1.21 #elif defined(PEGASUS_OS_DARWIN)
81 typedef struct {
82 sem_t * sem;
83 pthread_t owner;
84 Uint32 waiters;
85 } PEGASUS_SEM_HANDLE ;
|
86 mike 1.2 #else
87 typedef struct {
|
88 konrad.r 1.24 Uint32 waiters;
|
89 mike 1.2 pthread_mutex_t mutex;
90 pthread_cond_t cond;
91 pthread_t owner;
92 } PEGASUS_SEM_HANDLE ;
93 #endif
94
95 typedef struct {
96 pthread_mutex_t mut;
97 pthread_mutexattr_t mutatt;
98 pthread_t owner;
99 } PEGASUS_MUTEX_HANDLE ;
100
|
101 keith.petley 1.17 #ifdef PEGASUS_OS_SOLARIS
|
102 mike 1.3 typedef _cleanup_t PEGASUS_CLEANUP_HANDLE;
|
103 dudhe.girish 1.21 #elif defined(PEGASUS_OS_DARWIN)
104 typedef void * PEGASUS_CLEANUP_HANDLE;
|
105 mike 1.3 #else
106 typedef struct _pthread_cleanup_buffer PEGASUS_CLEANUP_HANDLE;
107 #endif
|
108 mike 1.2
109 typedef void *PEGASUS_THREAD_RETURN;
110
111 #define PEGASUS_THREAD_CDECL
112
113 typedef struct {
114 pthread_t thid;
115 pthread_attr_t thatt;
116 } PEGASUS_THREAD_HANDLE ;
117
118 //-----------------------------------------------------------------
119 /// Conditionals to support native or generic Conditional Semaphore
120 //-----------------------------------------------------------------
121
|
122 david.eger 1.15 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)
|
123 kumpf 1.19 #define PEGASUS_CONDITIONAL_NATIVE
|
124 mike 1.2
125 typedef pthread_cond_t PEGASUS_COND_TYPE;
126
127 typedef struct {
128 pthread_cond_t cond;
129 pthread_t owner;
130 } PEGASUS_COND_HANDLE;
131
132 #endif // linux platform conditional type
133
134 //-----------------------------------------------------------------
135 /// Conditionals to support native or generic atomic variables
136 //-----------------------------------------------------------------
137
|
138 kumpf 1.20 // Linux IA32 offers a built-in integer type for atomic access.
139 // Linux IA64 does not allow for built-in atomic access.
140 // Spinlock on some Linux IA64 distributions does not work.
141 // Other unix platforms HPUX, AIX, may have different types
|
142 mike 1.2 // implementors should use the native type for faster operations
143
|
144 konrad.r 1.22 #if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU) && !defined(PEGASUS_OS_LSB)
|
145 kumpf 1.19 #define PEGASUS_ATOMIC_INT_NATIVE
|
146 konrad.r 1.22 typedef pthread_spinlock_t PEGASUS_ATOMIC_TYPE;
|
147 kumpf 1.12 #endif
|
148 mike 1.2
149 //-----------------------------------------------------------------
150 /// Conditionals to support native or generic read/write semaphores
151 //-----------------------------------------------------------------
152
153
154 //-----------------------------------------------------------------
155 // NOTE: Tue Oct 9 13:36:53 2001 mdday
156 //
157 // I put some read/write counting into the Thread test program to see
158 // how native r/w performance compares to generic r/w on linux.
159 // For RH linux 7.1, the generic r/w lock in IPC.cpp performs
160 // much better than the pthreads native implementation.
161 //
162 // Here are the data (remember that there are 4 readers for every one
163 // writer):
164 //
165 // Generic read operations 6538 <- 4:1 ratio of reads to writes
166 // write operations 1422
167 //
168 // Native read operations 2060 <- 1:1 even though there are
169 mike 1.2 // write operations 2033 4 readers for every writer
170 //
171 //
172 // Comments -
173 //
174 // The native implementation prefers writers, which slows the entire
175 // test down because write operations take longer than read operations.
176 // Moreover, as soon as one writer gains the lock, the next owner will
177 // always be a writer until there are no further writers. Readers are
178 // blocked out until all writers are sleeping.
179 //
180 // In the test there are 4 readers for every writer. However, the
181 // native r/w lock severely skews resources toward writers.
182 //
183 // The generic implementation has no preference among readers and writers.
184 // Therefore whichever thread is ready to read or write will gain the lock
185 // with no dependence on whether the predecessor is a reader or writer.
186 // This results in higher throughput in the test program for linux.
187 //
188 // I would encourage all the platform maintainers to run their own tests
189 // so we can decide which implementation to use for production builds.
190 mike 1.2 //
191 //-----------------------------------------------------------------
192
193
194 //#if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU)
|
195 kumpf 1.19 // #define PEGASUS_READWRITE_NATIVE
|
196 mike 1.2
197 // typedef struct {
198 // pthread_rwlock_t rwlock;
199 // pthread_t owner;
200 // } PEGASUS_RWLOCK_HANDLE;
201
202 //#endif // linux platform read/write type
203
204 inline void pegasus_yield(void)
205 {
|
206 mike 1.3 #ifdef PEGASUS_NEED_CRITICAL_TYPE
|
207 dudhe.girish 1.21 #if !defined(PEGASUS_PLATFORM_DARWIN_PPC_GNU)
|
208 mike 1.2 pthread_yield();
|
209 dudhe.girish 1.21 #else
210 pthread_yield_np();
211 #endif
|
212 mike 1.3 #else
213 sched_yield();
214 #endif
|
215 mike 1.2 }
216
217 // pthreads cancellation calls
218 inline void disable_cancel(void)
219 {
|
220 kumpf 1.27 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
221 mike 1.2 }
222
223 inline void enable_cancel(void)
224 {
|
225 kumpf 1.27 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
226 mike 1.2 }
227
228 inline void pegasus_sleep(int msec)
229 {
230 struct timespec wait;
231 wait.tv_sec = msec / 1000;
|
232 kumpf 1.14 wait.tv_nsec = (msec % 1000) * 1000000;
|
233 mike 1.2 nanosleep(&wait, NULL);
234 }
235
|
236 mike 1.3 #ifdef PEGASUS_NEED_CRITICAL_TYPE
|
237 dudhe.girish 1.21 #if !defined(PEGASUS_PLATFORM_DARWIN_PPC_GNU)
|
238 mike 1.3
|
239 mike 1.2 inline void init_crit(PEGASUS_CRIT_TYPE *crit)
240 {
241 pthread_spin_init(crit, 0);
242 }
243
244 inline void enter_crit(PEGASUS_CRIT_TYPE *crit)
245 {
246 pthread_spin_lock(crit);
247 }
248
249 inline void try_crit(PEGASUS_CRIT_TYPE *crit)
250 {
251 pthread_spin_trylock(crit);
252 }
253
254 inline void exit_crit(PEGASUS_CRIT_TYPE *crit)
255 {
256 pthread_spin_unlock(crit);
257 }
258
259 inline void destroy_crit(PEGASUS_CRIT_TYPE *crit)
260 mike 1.2 {
261 pthread_spin_destroy(crit);
262 }
|
263 dudhe.girish 1.21 #else
264
265 inline void init_crit(PEGASUS_CRIT_TYPE *crit)
266 {
267 pthread_mutex_init(crit, 0);
268 }
|
269 mike 1.2
|
270 dudhe.girish 1.21 inline void enter_crit(PEGASUS_CRIT_TYPE *crit)
271 {
272 pthread_mutex_lock(crit);
273 }
274
275 inline void try_crit(PEGASUS_CRIT_TYPE *crit)
276 {
277 pthread_mutex_trylock(crit);
278 }
279
280 inline void exit_crit(PEGASUS_CRIT_TYPE *crit)
281 {
282 pthread_mutex_unlock(crit);
283 }
284
285 inline void destroy_crit(PEGASUS_CRIT_TYPE *crit)
286 {
287 pthread_mutex_destroy(crit);
288 }
289
290 #endif
|
291 mike 1.3 #endif /* PEGASUS_NEED_CRITICAL_TYPE */
|
292 mike 1.2
293 //-----------------------------------------------------------------
294 /// accurate version of gettimeofday for unix systems
295 // posix glibc implementation does not return microseconds.
296 // mdday Wed Aug 1 16:05:26 2001
297 //-----------------------------------------------------------------
|
298 konrad.r 1.22 #if !defined(PEGASUS_PLATFORM_DARWIN_PPC_GNU) && !defined(PEGASUS_OS_LSB)
|
299 mike 1.2 inline static int pegasus_gettimeofday(struct timeval *tv)
300 {
301 struct ntptimeval ntp;
302 int err;
303 if(tv == NULL)
304 return(EINVAL);
305 err = ntp_gettime(&ntp);
306 tv->tv_sec = ntp.time.tv_sec;
307 tv->tv_usec = ntp.time.tv_usec;
308 return(err);
309 }
|
310 dudhe.girish 1.21 #else
311 inline static int pegasus_gettimeofday(struct timeval *tv)
312 {
313 int err;
314 if(tv == NULL)
315 return(EINVAL);
316 err = gettimeofday(tv,NULL);
317 return err;
318 }
319 #endif
|
320 mike 1.2
321 inline void exit_thread(PEGASUS_THREAD_RETURN rc)
322 {
323 pthread_exit(rc);
324 }
325
326 inline PEGASUS_THREAD_TYPE pegasus_thread_self(void)
327 {
328 return(pthread_self());
329 }
330
|
331 chuck 1.16 // l10n start
332 typedef pthread_key_t PEGASUS_THREAD_KEY_TYPE;
333
334 inline Uint32 pegasus_key_create(PEGASUS_THREAD_KEY_TYPE * key)
335 {
336 // Note: a destructor is not supported
337 // (because not supported on Windows (?))
338 return pthread_key_create(key, NULL);
339 }
340
341 inline Uint32 pegasus_key_delete(PEGASUS_THREAD_KEY_TYPE key)
342 {
343 return pthread_key_delete(key);
344 }
345
346 inline void * pegasus_get_thread_specific(PEGASUS_THREAD_KEY_TYPE key)
347 {
348 return pthread_getspecific(key);
349 }
350
351 inline Uint32 pegasus_set_thread_specific(PEGASUS_THREAD_KEY_TYPE key,
352 chuck 1.16 void * value)
353 {
354 return pthread_setspecific(key, value);
355 }
356 // l10n end
357
358
|
359 mike 1.2 inline void destroy_thread(PEGASUS_THREAD_TYPE th, PEGASUS_THREAD_RETURN rc)
360 {
361 pthread_cancel(th);
362
363 }
364
365 PEGASUS_NAMESPACE_END
366
367 #endif // IPCUNIXInclude
|