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 //-----------------------------------------------------------------
106 /// Conditionals to support native or generic Conditional Semaphore
107 chuck 1.1 //-----------------------------------------------------------------
108
109 #define PEGASUS_CONDITIONAL_NATIVE = 1
110
111 typedef pthread_cond_t PEGASUS_COND_TYPE;
112
113 typedef struct {
114 pthread_cond_t cond;
115 PEGASUS_THREAD_TYPE owner;
116 } PEGASUS_COND_HANDLE;
117
118 //-----------------------------------------------------------------
119 /// Conditionals to support native or generic atomic variables
120 //-----------------------------------------------------------------
121
122
123 //-----------------------------------------------------------------
124 /// Conditionals to support native or generic read/write semaphores
125 //-----------------------------------------------------------------
126
|
127 gerarda 1.4 /* Gerarda - commented out the following code */
128 /*
|
129 chuck 1.1 #define PEGASUS_READWRITE_NATIVE = 1
130
131 typedef struct {
132 pthread_rwlock_t rwlock;
133 PEGASUS_THREAD_TYPE owner;
134 } PEGASUS_RWLOCK_HANDLE;
|
135 gerarda 1.4 */
|
136 chuck 1.1
137
138 inline void pegasus_yield(void)
139 {
140 sched_yield();
141 }
142
143 // pthreads cancellation calls
144 inline void disable_cancel(void)
145 {
146 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
147 }
148
149 inline void enable_cancel(void)
150 {
151 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
152 }
153
154
155 inline void pegasus_sleep(int msec)
156 {
|
157 gerarda 1.4 /* Gerarda - redid the sleep routine */
158 int loop;
159 int microsecs = msec * 1000; /* convert from milliseconds to microseconds */
160
161 if (microsecs < 1000000)
162 usleep(microsecs);
163 else
164 {
165 loop = microsecs / 1000000;
166 for(int i = 0; i < loop; i++)
167 usleep(1000000);
168 if ((loop*1000000) < microsecs)
169 usleep(microsecs - (loop*1000000));
170 }
171
172 /* Turns out the following code does not induce sleep on OS400 */
173 /*
|
174 chuck 1.1 struct timespec wait;
175 pthread_mutex_t sleep_mut = PTHREAD_MUTEX_INITIALIZER;
176 pthread_cond_t sleep_cond;
177 pthread_cond_init (&sleep_cond, NULL);
178 pthread_mutex_lock(&sleep_mut);
179 wait.tv_sec = msec / 1000;
|
180 kumpf 1.6 wait.tv_nsec = (msec % 1000) * 1000000;
|
181 chuck 1.1 pthread_cond_timedwait(&sleep_cond,&sleep_mut,&wait);
182 pthread_mutex_unlock(&sleep_mut);
183 pthread_cond_destroy(&sleep_cond);
|
184 gerarda 1.4 */
|
185 chuck 1.1 }
186
187 inline void init_crit(PEGASUS_CRIT_TYPE *crit)
188 {
189 pthread_mutex_init(&(crit->mut), NULL);
190 }
191
192 inline void enter_crit(PEGASUS_CRIT_TYPE *crit)
193 {
194 pthread_mutex_lock(&(crit->mut));
195 }
196
197 inline void try_crit(PEGASUS_CRIT_TYPE *crit)
198 {
199 pthread_mutex_trylock(&(crit->mut));
200 }
201
202 inline void exit_crit(PEGASUS_CRIT_TYPE *crit)
203 {
204 pthread_mutex_unlock(&(crit->mut));
205 }
206 chuck 1.1
207 inline void destroy_crit(PEGASUS_CRIT_TYPE *crit)
208 {
209 pthread_mutexattr_destroy(&(crit->mutatt));
210 }
211
212 inline static int pegasus_gettimeofday(struct timeval *tv)
213 {
214 return gettimeofday(tv,NULL);
215 }
216
217 inline void exit_thread(PEGASUS_THREAD_RETURN rc)
218 {
219 pthread_exit(rc);
220 }
221
|
222 chuck 1.3 // Overload pegasus_thread_self to construct our
223 // PEGASUS_THREAD_TYPE with all the variables set.
|
224 chuck 1.1 inline PEGASUS_THREAD_TYPE pegasus_thread_self(void)
225 {
|
226 chuck 1.3 // Construct a PEGASUS_THREAD_TYPE with the
227 // pegasusValue initialized to 1 (ie. the thread
228 // is 'alive')
229 PEGASUS_THREAD_TYPE thrd = {pthread_self(),1};
|
230 chuck 1.1 return thrd;
231 }
232
233 inline void destroy_thread(PEGASUS_THREAD_TYPE th, PEGASUS_THREAD_RETURN rc)
234 {
235 pthread_cancel(th.thid);
236
237 }
238
239 // Need to overload some operators because Pegasus does compares,
240 // and assignments using the thread type, but pthread_t is a structure
241 // on OS/400
242 inline int operator==(const PEGASUS_THREAD_TYPE & lval,
243 const PEGASUS_THREAD_TYPE & rval)
244 {
245 return pthread_equal(lval.thid, rval.thid);
246 }
247
248 inline int operator==(const PEGASUS_THREAD_TYPE & lval,
249 const PEGASUS_UINT64 & rval)
250 {
|
251 chuck 1.3 return ( lval.pegasusValue == rval);
|
252 chuck 1.1 }
253
254
255 inline int operator!=(const PEGASUS_THREAD_TYPE & lval,
256 const PEGASUS_THREAD_TYPE & rval)
257 {
258 return !operator==(lval,rval);
259 }
260
261
262 inline int operator!=(const PEGASUS_THREAD_TYPE & lval,
263 const PEGASUS_UINT64 & rval)
264 {
265 return !operator==(lval,rval);
266 }
267
268 inline int operator!=(const PEGASUS_THREAD_TYPE & lval,
269 const int & rval)
270 {
271 return !operator==(lval,(PEGASUS_UINT64)rval);
272 }
273 chuck 1.1
274 inline int operator==(const PEGASUS_THREAD_TYPE & lval,
275 const int & rval)
276 {
277 return operator==(lval,(PEGASUS_UINT64)rval);
278 }
279
280 inline __pegasus_os400_thread_type& __pegasus_os400_thread_type::operator=(const PEGASUS_UINT64 & rval)
281 {
|
282 chuck 1.3 pegasusValue = rval;
|
283 chuck 1.1 return *this;
284 }
285
286 inline __pegasus_os400_thread_type::operator pthread_t *()
287 {
288 return &thid;
289 }
290
291 inline __pegasus_os400_thread_type::operator pthread_t ()
292 {
293 return thid;
294 }
295
296 inline __pegasus_os400_thread_type::operator Uint32 ()
297 {
|
298 chuck 1.5 pthread_id_np_t tid;
299 pthread_getunique_np(&thid, &tid);
300 return (Uint32)(tid.intId.lo);
|
301 chuck 1.1 }
302
303 PEGASUS_NAMESPACE_END
304
305 #endif // IPCOS400Include
|