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 mike 1.5 #include <errno.h>
|
35 mike 1.2 #include "Threads.h"
36 #include "IDFactory.h"
37 #include "TSDKey.h"
38 #include "Once.h"
39
40 #if defined(PEGASUS_PLATFORM_WIN32_IX86_MSVC)
41 # include <sys/timeb.h>
42 #endif
43
44 PEGASUS_NAMESPACE_BEGIN
45
46 void Threads::sleep(int msec)
47 {
48 #if defined(PEGASUS_HAVE_NANOSLEEP)
49
50 struct timespec wait;
51 wait.tv_sec = msec / 1000;
52 wait.tv_nsec = (msec % 1000) * 1000000;
53 nanosleep(&wait, NULL);
54
55 #elif defined(PEGASUS_PLATFORM_OS400_ISERIES_IBM)
56 mike 1.2
57 int loop;
58 int microsecs = msec * 1000; /* convert from milliseconds to microseconds */
59
60 if (microsecs < 1000000)
61 usleep(microsecs);
62 else
63 {
64 loop = microsecs / 1000000;
|
65 kumpf 1.6 for (int i = 0; i < loop; i++)
|
66 mike 1.2 usleep(1000000);
67 if ((loop*1000000) < microsecs)
68 usleep(microsecs - (loop*1000000));
69 }
70
71 #elif defined(PEGASUS_PLATFORM_WIN32_IX86_MSVC)
72
73 if (msec == 0)
|
74 kumpf 1.6 {
|
75 mike 1.2 Sleep(0);
76 return;
77 }
78
79 struct _timeb end, now;
80 _ftime( &end );
81 end.time += (msec / 1000);
82 msec -= (msec / 1000);
83 end.millitm += msec;
84
85 do
86 {
87 Sleep(0);
88 _ftime(&now);
|
89 kumpf 1.6 }
90 while (end.millitm > now.millitm && end.time >= now.time);
|
91 mike 1.2
92 #elif defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
93 int seconds;
94 if (msec < 1000)
95 {
96 usleep(msec*1000);
97 }
98 else
99 {
100 // sleep for loop seconds
|
101 mike 1.3 ::sleep(msec / 1000);
|
102 mike 1.2 // Usleep the remaining micro seconds
103 usleep( (msec*1000) % 1000000 );
104 }
105 #elif defined(PEGASUS_OS_VMS)
106
|
107 mike 1.3 ::sleep(msec / 1000);
|
108 mike 1.2
109 #endif
110 }
111
112 //==============================================================================
113 //
114 // Thread id TSD:
115 //
116 //==============================================================================
117
118 static Once _once = PEGASUS_ONCE_INITIALIZER;
119 static TSDKeyType _key;
120
121 static void _create_key()
122 {
123 TSDKey::create(&_key);
124 }
125
126 static inline void _set_id_tsd(Uint32 id)
127 {
128 once(&_once, _create_key);
129 mike 1.2 TSDKey::set_thread_specific(_key, (void*)(long)id);
130 }
131
132 static inline Uint32 _get_id_tsd()
133 {
134 once(&_once, _create_key);
135 void* ptr = TSDKey::get_thread_specific(_key);
136
137 if (!ptr)
138 {
139 // Main thread's id is 1!
140 return 1;
141 }
142
143 return (Uint32)(long)ptr;
144 }
145
146 //==============================================================================
147 //
148 // _get_stack_multiplier()
149 //
150 mike 1.2 //==============================================================================
151
152 static inline int _get_stack_multiplier()
153 {
154 #if defined(PEGASUS_OS_VMS)
155
156 static int _multiplier = 0;
157 static MutexType _multiplier_mutex = PEGASUS_MUTEX_INITIALIZER;
158
|
159 kumpf 1.6 //
160 // This code uses a, 'hidden' (non-documented), VMS only, logical
|
161 mike 1.2 // name (environment variable), PEGASUS_VMS_THREAD_STACK_MULTIPLIER,
162 // to allow in the field adjustment of the thread stack size.
163 //
164 // We only check for the logical name once to not have an
165 // impact on performance.
|
166 kumpf 1.6 //
|
167 mike 1.2 // Note: This code may have problems in a multithreaded environment
168 // with the setting of doneOnce to true.
|
169 kumpf 1.6 //
|
170 mike 1.2 // Current code in Cimserver and the clients do some serial thread
171 // creations first so this is not a problem now.
|
172 kumpf 1.6 //
|
173 mike 1.2
174 if (_multiplier == 0)
175 {
176 mutex_lock(&_multiplier_mutex);
177
178 if (_multiplier == 0)
179 {
180 const char *env = getenv("PEGASUS_VMS_THREAD_STACK_MULTIPLIER");
181
182 if (env)
183 _multiplier = atoi(env);
184
185 if (_multiplier == 0)
186 _multiplier = 2;
187 }
188
189 mutex_unlock(&_multiplier_mutex);
190 }
191
192 return _multiplier;
193 #else
194 mike 1.2 return 2;
195 #endif
196 }
197
198 //==============================================================================
199 //
200 // PEGASUS_HAVE_PTHREADS
201 //
202 //==============================================================================
203
204 #if defined(PEGASUS_HAVE_PTHREADS)
205
206 int Threads::create(
|
207 kumpf 1.6 ThreadType& thread,
|
208 mike 1.2 Type type,
|
209 kumpf 1.6 void* (*start)(void*),
|
210 mike 1.2 void* arg)
211 {
212 // Initialize thread attributes:
213
214 pthread_attr_t attr;
215 pthread_attr_init(&attr);
216
217 // Detached:
218
219 if (type == DETACHED)
220 {
221 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
222 int ds = 1;
223 pthread_attr_setdetachstate(&attr, &ds);
224 #else
225 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
226 #endif
227 }
228
229 // Stack size:
230
231 mike 1.2 #if defined(PEGASUS_PLATFORM_HPUX_PARISC_ACC) || defined(PEGASUS_OS_VMS)
232 {
233 size_t stacksize;
234
235 if (pthread_attr_getstacksize(&attr, &stacksize) == 0)
236 {
237 int m = _get_stack_multiplier();
238 int rc = pthread_attr_setstacksize(&attr, stacksize * m);
239 PEGASUS_ASSERT(rc == 0);
240 }
241 }
242 #endif
243
244 // Scheduling policy:
245
246 #if defined(PEGASUS_PLATFORM_SOLARIS_SPARC_GNU) || \
247 defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC)
248 # if defined SUNOS_5_7
249 pthread_attr_setschedpolicy(&attr, SCHED_RR);
250 # else
251 pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
252 mike 1.2 # endif
253 #endif // PEGASUS_PLATFORM_SOLARIS_SPARC_GNU
254
255 // Create thread:
256
|
257 mike 1.4 int rc = pthread_create(&thread.thread, &attr, start, arg);
|
258 mike 1.2
259 if (rc != 0)
260 {
261 thread = ThreadType();
262 return rc;
263 }
264
265 // Destroy attributes now.
266
267 pthread_attr_destroy(&attr);
268
269 // Return:
270
271 return 0;
272 }
273
|
274 kumpf 1.6 ThreadType Threads::self()
|
275 mike 1.2 {
|
276 mike 1.4 ThreadType tt;
277 tt.thread = pthread_self();
278 return tt;
|
279 mike 1.2 }
280
281 #endif /* PEGASUS_HAVE_PTHREADS */
282
283 PEGASUS_NAMESPACE_END
|