1 chuck 1.1 //%/////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
4 // The Open Group, Tivoli Systems
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to
8 // deal in the Software without restriction, including without limitation the
9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 // sell copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
13 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
14 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
15 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 chuck 1.1 //==============================================================================
23 //
24 // Author: Chuck Carmack (carmack@us.ibm.com)
25 //
26 //%/////////////////////////////////////////////////////////////////////////////
27
28 #ifndef IPC_OS400_include
29 #define IPC_OS400_include
30
31 #define _MULTI_THREADED // must be before pthread.h
32
|
33 chuck 1.2 #include <limits.h> // has SEM_VALUE_MAX
|
34 chuck 1.1 #include <sched.h>
35 #include <semaphore.h>
36 #include <pthread.h>
37 #include <signal.h>
38 #include <errno.h>
39 #include <sys/time.h>
40 #include <time.h>
41 //#include <sys/timex.h>
42 #include <unistd.h>
43
|
44 chuck 1.2 //#define SEM_VALUE_MAX 0xffffffff - defined in limits.h
|
45 chuck 1.1
46 PEGASUS_NAMESPACE_BEGIN
47
48 //typedef sem_t PEGASUS_SEMAPHORE_TYPE;
49
50 //typedef pthread_t PEGASUS_THREAD_TYPE;
51
|
52 chuck 1.3 // Redefine PEGASUS_THREAD_TYPE as a class on OS/400. On other platforms
53 // this is an int and Pegasus sets this to 0 to indicate
54 // that the thread is 'dead'. Also, we cannot use == operator
55 // on pthread_t, but need to call pthread_equal( ), so the ==
56 // operation is overloaded. Other operators are overloaded in this file.
|
57 chuck 1.1 typedef class __pegasus_os400_thread_type {
58 public:
59 pthread_t thid; // An opaque struct on OS/400
|
60 chuck 1.5 PEGASUS_UINT64 pegasusValue; // Needed because Pegasus sets PEGASUS_THREAD_TYPEs to 0
61 // to indicate the thread is dead, but
|
62 chuck 1.3 // pthread_t structs cannot be changed on OS/400.
|
63 chuck 1.1
|
64 chuck 1.3 // Overloaded operators.
|
65 chuck 1.1 __pegasus_os400_thread_type& operator=(const PEGASUS_UINT64 & rval);
66 operator pthread_t*();
67 operator pthread_t();
68 operator Uint32 ();
69 } PEGASUS_THREAD_TYPE;
70
71 typedef pthread_mutex_t PEGASUS_MUTEX_TYPE;
72
73 typedef struct {
74 sem_t sem;
75 PEGASUS_THREAD_TYPE owner;
76 } PEGASUS_SEM_HANDLE ;
77
78 typedef struct {
79 pthread_mutex_t mut;
80 pthread_mutexattr_t mutatt;
81 PEGASUS_THREAD_TYPE owner;
82 } PEGASUS_MUTEX_HANDLE ;
83
84 typedef PEGASUS_MUTEX_HANDLE PEGASUS_CRIT_TYPE;
85
86 chuck 1.1
87 struct _pthread_cleanup_buffer {
88 void (*__routine) (void *); /* Function to call. */
89 void *__arg; /* Its argument. */
90 int __canceltype; /* Saved cancellation type. */
91 struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions.*/
92 };
93 typedef struct _pthread_cleanup_buffer PEGASUS_CLEANUP_HANDLE;
94
95 //#define PEGASUS_THREAD_CDECL __cdecl
96 #define PEGASUS_THREAD_CDECL
97
98 typedef void *PEGASUS_THREAD_RETURN;
99
100 typedef struct {
101 PEGASUS_THREAD_TYPE thid;
102 pthread_attr_t thatt;
103 } PEGASUS_THREAD_HANDLE ;
104
|
105 chuck 1.7
|
106 chuck 1.1 //-----------------------------------------------------------------
107 /// Conditionals to support native or generic Conditional Semaphore
108 //-----------------------------------------------------------------
109
110 #define PEGASUS_CONDITIONAL_NATIVE = 1
111
112 typedef pthread_cond_t PEGASUS_COND_TYPE;
113
114 typedef struct {
115 pthread_cond_t cond;
116 PEGASUS_THREAD_TYPE owner;
117 } PEGASUS_COND_HANDLE;
118
119 //-----------------------------------------------------------------
120 /// Conditionals to support native or generic atomic variables
121 //-----------------------------------------------------------------
122
123
124 //-----------------------------------------------------------------
125 /// Conditionals to support native or generic read/write semaphores
126 //-----------------------------------------------------------------
127 chuck 1.1
|
128 gerarda 1.4 /* Gerarda - commented out the following code */
129 /*
|
130 chuck 1.1 #define PEGASUS_READWRITE_NATIVE = 1
131
132 typedef struct {
133 pthread_rwlock_t rwlock;
134 PEGASUS_THREAD_TYPE owner;
135 } PEGASUS_RWLOCK_HANDLE;
|
136 gerarda 1.4 */
|
137 chuck 1.1
138
139 inline void pegasus_yield(void)
140 {
141 sched_yield();
142 }
143
144 // pthreads cancellation calls
145 inline void disable_cancel(void)
146 {
147 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
148 }
149
150 inline void enable_cancel(void)
151 {
152 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
153 }
154
155
156 inline void pegasus_sleep(int msec)
157 {
|
158 gerarda 1.4 /* Gerarda - redid the sleep routine */
159 int loop;
160 int microsecs = msec * 1000; /* convert from milliseconds to microseconds */
161
162 if (microsecs < 1000000)
163 usleep(microsecs);
164 else
165 {
166 loop = microsecs / 1000000;
167 for(int i = 0; i < loop; i++)
168 usleep(1000000);
169 if ((loop*1000000) < microsecs)
170 usleep(microsecs - (loop*1000000));
171 }
172
173 /* Turns out the following code does not induce sleep on OS400 */
174 /*
|
175 chuck 1.1 struct timespec wait;
176 pthread_mutex_t sleep_mut = PTHREAD_MUTEX_INITIALIZER;
177 pthread_cond_t sleep_cond;
178 pthread_cond_init (&sleep_cond, NULL);
179 pthread_mutex_lock(&sleep_mut);
180 wait.tv_sec = msec / 1000;
|
181 kumpf 1.6 wait.tv_nsec = (msec % 1000) * 1000000;
|
182 chuck 1.1 pthread_cond_timedwait(&sleep_cond,&sleep_mut,&wait);
183 pthread_mutex_unlock(&sleep_mut);
184 pthread_cond_destroy(&sleep_cond);
|
185 gerarda 1.4 */
|
186 chuck 1.1 }
187
188 inline void init_crit(PEGASUS_CRIT_TYPE *crit)
189 {
190 pthread_mutex_init(&(crit->mut), NULL);
191 }
192
193 inline void enter_crit(PEGASUS_CRIT_TYPE *crit)
194 {
195 pthread_mutex_lock(&(crit->mut));
196 }
197
198 inline void try_crit(PEGASUS_CRIT_TYPE *crit)
199 {
200 pthread_mutex_trylock(&(crit->mut));
201 }
202
203 inline void exit_crit(PEGASUS_CRIT_TYPE *crit)
204 {
205 pthread_mutex_unlock(&(crit->mut));
206 }
207 chuck 1.1
208 inline void destroy_crit(PEGASUS_CRIT_TYPE *crit)
209 {
210 pthread_mutexattr_destroy(&(crit->mutatt));
211 }
212
213 inline static int pegasus_gettimeofday(struct timeval *tv)
214 {
215 return gettimeofday(tv,NULL);
216 }
217
218 inline void exit_thread(PEGASUS_THREAD_RETURN rc)
219 {
220 pthread_exit(rc);
221 }
222
|
223 chuck 1.3 // Overload pegasus_thread_self to construct our
224 // PEGASUS_THREAD_TYPE with all the variables set.
|
225 chuck 1.1 inline PEGASUS_THREAD_TYPE pegasus_thread_self(void)
226 {
|
227 chuck 1.3 // Construct a PEGASUS_THREAD_TYPE with the
228 // pegasusValue initialized to 1 (ie. the thread
229 // is 'alive')
230 PEGASUS_THREAD_TYPE thrd = {pthread_self(),1};
|
231 chuck 1.1 return thrd;
232 }
|
233 chuck 1.7
234 // l10n start
235 typedef pthread_key_t PEGASUS_THREAD_KEY_TYPE;
236
237 inline Uint32 pegasus_key_create(PEGASUS_THREAD_KEY_TYPE * key)
238 {
239 // Note: a destructor is not supported
240 // (because not supported on Windows (?))
241 return pthread_key_create(key, NULL);
242 }
243
244 inline Uint32 pegasus_key_delete(PEGASUS_THREAD_KEY_TYPE key)
245 {
246 return pthread_key_delete(key);
247 }
248
249 inline void * pegasus_get_thread_specific(PEGASUS_THREAD_KEY_TYPE key)
250 {
251 return pthread_getspecific(key);
252 }
253
254 chuck 1.7 inline Uint32 pegasus_set_thread_specific(PEGASUS_THREAD_KEY_TYPE key,
255 void * value)
256 {
257 return pthread_setspecific(key, value);
258 }
259 // l10n end
|
260 chuck 1.1
261 inline void destroy_thread(PEGASUS_THREAD_TYPE th, PEGASUS_THREAD_RETURN rc)
262 {
263 pthread_cancel(th.thid);
264
265 }
266
267 // Need to overload some operators because Pegasus does compares,
268 // and assignments using the thread type, but pthread_t is a structure
269 // on OS/400
270 inline int operator==(const PEGASUS_THREAD_TYPE & lval,
271 const PEGASUS_THREAD_TYPE & rval)
272 {
273 return pthread_equal(lval.thid, rval.thid);
274 }
275
276 inline int operator==(const PEGASUS_THREAD_TYPE & lval,
277 const PEGASUS_UINT64 & rval)
278 {
|
279 chuck 1.3 return ( lval.pegasusValue == rval);
|
280 chuck 1.1 }
281
282
283 inline int operator!=(const PEGASUS_THREAD_TYPE & lval,
284 const PEGASUS_THREAD_TYPE & rval)
285 {
286 return !operator==(lval,rval);
287 }
288
289
290 inline int operator!=(const PEGASUS_THREAD_TYPE & lval,
291 const PEGASUS_UINT64 & rval)
292 {
293 return !operator==(lval,rval);
294 }
295
296 inline int operator!=(const PEGASUS_THREAD_TYPE & lval,
297 const int & rval)
298 {
299 return !operator==(lval,(PEGASUS_UINT64)rval);
300 }
301 chuck 1.1
302 inline int operator==(const PEGASUS_THREAD_TYPE & lval,
303 const int & rval)
304 {
305 return operator==(lval,(PEGASUS_UINT64)rval);
306 }
307
308 inline __pegasus_os400_thread_type& __pegasus_os400_thread_type::operator=(const PEGASUS_UINT64 & rval)
309 {
|
310 chuck 1.3 pegasusValue = rval;
|
311 chuck 1.1 return *this;
312 }
313
314 inline __pegasus_os400_thread_type::operator pthread_t *()
315 {
316 return &thid;
317 }
318
319 inline __pegasus_os400_thread_type::operator pthread_t ()
320 {
321 return thid;
322 }
323
324 inline __pegasus_os400_thread_type::operator Uint32 ()
325 {
|
326 chuck 1.5 pthread_id_np_t tid;
327 pthread_getunique_np(&thid, &tid);
328 return (Uint32)(tid.intId.lo);
|
329 chuck 1.1 }
330
331 PEGASUS_NAMESPACE_END
332
333 #endif // IPCOS400Include
|