(file) Return to Thread.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  1 karl  1.89 //%2006////////////////////////////////////////////////////////////////////////
  2 mike  1.2  //
  3 karl  1.71 // 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.56 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.71 // 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.75 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl  1.89 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12            // EMC Corporation; Symantec Corporation; The Open Group.
 13 mike  1.2  //
 14            // Permission is hereby granted, free of charge, to any person obtaining a copy
 15 chip  1.11 // 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 mike  1.2  // 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 karl  1.89 // 
 21 chip  1.11 // 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 chip  1.11 // 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 mike  1.2  // 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            #include "Thread.h"
 35 mike  1.96 #include <errno.h>
 36 kumpf 1.68 #include <exception>
 37 kumpf 1.14 #include <Pegasus/Common/Tracer.h>
 38 mike  1.91 #include "Time.h"
 39 mike  1.2  
 40 mike  1.91 PEGASUS_USING_STD;
 41 mike  1.2  
 42            PEGASUS_NAMESPACE_BEGIN
 43            
 44 mike  1.91 //==============================================================================
 45            //
 46            // POSIX Threads Implementation:
 47            //
 48            //==============================================================================
 49 mday  1.42 
 50 mike  1.91 #if defined(PEGASUS_HAVE_PTHREADS)
 51            
 52            struct StartWrapperArg
 53 chip  1.11 {
 54 mike  1.91     void *(PEGASUS_THREAD_CDECL * start) (void *);
 55                void *arg;
 56            };
 57 mike  1.2  
 58 mike  1.91 extern "C" void *_start_wrapper(void *arg_)
 59 chuck 1.43 {
 60 mike  1.91     StartWrapperArg *arg = (StartWrapperArg *) arg_;
 61 chuck 1.43 
 62 mike  1.91     void *return_value = (*arg->start) (arg->arg);
 63                delete arg;
 64 chuck 1.37 
 65 mike  1.91     return return_value;
 66            }
 67 mike  1.2  
 68 mike  1.91 void Thread::cancel()
 69 mike  1.2  {
 70 mike  1.91     _cancelled = true;
 71 mike  1.94     pthread_cancel(_handle.thid.thread);
 72 mike  1.2  }
 73 kumpf 1.81 
 74 mike  1.91 void Thread::test_cancel()
 75 mike  1.2  {
 76 mike  1.91 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
 77                pthread_testintr();
 78            #else
 79                pthread_testcancel();
 80            #endif
 81 mike  1.2  }
 82 kumpf 1.81 
 83 kumpf 1.98 Boolean Thread::is_cancelled()
 84 chip  1.11 {
 85 mike  1.91     return _cancelled;
 86 mike  1.2  }
 87            
 88 mike  1.91 void Thread::thread_switch()
 89            {
 90            #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
 91                pthread_yield(NULL);
 92            #else
 93                sched_yield();
 94 mike  1.2  #endif
 95 mike  1.91 }
 96 mike  1.2  
 97 mike  1.91 /*
 98            ATTN: why are these missing on other platforms?
 99            */
100            #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)
101            void Thread::suspend()
102 chuck 1.39 {
103 mike  1.94     pthread_kill(_handle.thid.thread, SIGSTOP);
104 chuck 1.39 }
105            
106 mike  1.91 void Thread::resume()
107 chuck 1.37 {
108 mike  1.94     pthread_kill(_handle.thid.thread, SIGCONT);
109 chuck 1.39 }
110 mike  1.91 #endif
111 chuck 1.39 
112 mike  1.91 void Thread::sleep(Uint32 msec)
113 chuck 1.39 {
114 mike  1.91     Threads::sleep(msec);
115 chuck 1.37 }
116            
117 kumpf 1.98 void Thread::join()
118 chuck 1.37 {
119 mike  1.94     if (!_is_detached && !Threads::null(_handle.thid))
120                    pthread_join(_handle.thid.thread, &_exit_code);
121 kumpf 1.81 
122 mike  1.91     Threads::clear(_handle.thid);
123 chuck 1.37 }
124            
125 kumpf 1.98 void Thread::thread_init()
126 chuck 1.37 {
127 mike  1.91 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
128                pthread_setintr(PTHREAD_INTR_ENABLE);
129                pthread_setintrtype(PTHREAD_INTR_ASYNCHRONOUS);
130            #else
131                pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
132                pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
133            #endif
134                _cancel_enabled = true;
135 chuck 1.37 }
136            
137 kumpf 1.98 void Thread::detach()
138 chuck 1.37 {
139 mike  1.91     _is_detached = true;
140            #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
141 mike  1.94     pthread_t  thread_id=_handle.thid.thread;
142 mike  1.91     pthread_detach(&thread_id);
143            #else
144 mike  1.94     pthread_detach(_handle.thid.thread);
145 mike  1.91 #endif
146 chuck 1.37 }
147            
148 mike  1.91 ThreadStatus Thread::run()
149            {
150                StartWrapperArg *arg = new StartWrapperArg;
151                arg->start = _start;
152                arg->arg = this;
153 mday  1.52 
154 mike  1.91     Threads::Type type = _is_detached ? Threads::DETACHED : Threads::JOINABLE;
155                int rc = Threads::create(_handle.thid, type, _start_wrapper, arg);
156 kumpf 1.81 
157 kumpf 1.98     // On Linux distributions released prior 2005, the implementation of
158 mike  1.91     // Native POSIX Thread Library returns ENOMEM instead of EAGAIN when
159 kumpf 1.98     // there
160 mike  1.91     // are no insufficient memory.  Hence we are checking for both.  See bug
161                // 386.
162 mday  1.58 
163 marek 1.93     if (rc == -1)
164                    rc = errno;
165 mike  1.91     if ((rc == EAGAIN) || (rc == ENOMEM))
166 kumpf 1.81     {
167 mike  1.91         Threads::clear(_handle.thid);
168                    delete arg;
169                    return PEGASUS_THREAD_INSUFFICIENT_RESOURCES;
170 kumpf 1.81     }
171 mike  1.91     else if (rc != 0)
172 kumpf 1.81     {
173 mike  1.91         Threads::clear(_handle.thid);
174                    delete arg;
175                    return PEGASUS_THREAD_SETUP_FAILURE;
176 kumpf 1.81     }
177 mike  1.91     return PEGASUS_THREAD_OK;
178            }
179 mday  1.58 
180 mike  1.91 static sigset_t *block_signal_mask(sigset_t * sig)
181            {
182                sigemptyset(sig);
183                // should not be used for main()
184                sigaddset(sig, SIGHUP);
185                sigaddset(sig, SIGINT);
186                // maybe useless, since KILL can't be blocked according to POSIX
187                sigaddset(sig, SIGKILL);
188            
189                sigaddset(sig, SIGABRT);
190                sigaddset(sig, SIGALRM);
191                sigaddset(sig, SIGPIPE);
192            
193            
194            // Note: older versions of the linux pthreads library use SIGUSR1 and SIGUSR2
195            // internally to stop and start threads that are blocking, the newer ones
196            // implement this through the kernel's real time signals
197            // since SIGSTOP/CONT can handle suspend()/resume() on Linux
198            // block them
199            // #if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU)
200            //     sigaddset(sig, SIGUSR1);
201 mike  1.91 //     sigaddset(sig, SIGUSR2);
202            // #endif
203 carson.hovey 1.92 #if defined (PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) || defined (PEGASUS_OS_VMS)
204                       sigprocmask(SIG_BLOCK, sig, NULL);
205                   #else
206 mike         1.91     pthread_sigmask(SIG_BLOCK, sig, NULL);
207                   #endif
208                       return sig;
209                   }
210 mday         1.52 
211 kumpf        1.98 Thread::Thread(
212                       ThreadReturnType(PEGASUS_THREAD_CDECL* start) (void*),
213                       void* parameter,
214                       Boolean detached)
215                       : _is_detached(detached),
216                         _cancel_enabled(true),
217                         _cancelled(false),
218                         _start(start),
219                         _cleanup(),
220                         _tsd(),
221                         _thread_parm(parameter),
222                         _exit_code(0)
223 mike         1.91 {
224                       Threads::clear(_handle.thid);
225 kumpf        1.81 }
226 mday         1.20 
227 mike         1.91 Thread::~Thread()
228 mday         1.20 {
229 kumpf        1.81     try
230                       {
231 mike         1.91         join();
232                           empty_tsd();
233 kumpf        1.81     }
234 kumpf        1.98     catch (...)
235 kumpf        1.81     {
236 mike         1.91         // Do not allow the destructor to throw an exception
237 kumpf        1.81     }
238 mday         1.20 }
239                   
240 mike         1.91 #endif /* PEGASUS_HAVE_PTHREADS */
241                   
242                   //==============================================================================
243                   //
244                   // Windows Threads Implementation:
245                   //
246                   //==============================================================================
247 kumpf        1.81 
248 mike         1.91 #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
249 kumpf        1.81 
250 kumpf        1.98 ThreadStatus Thread::run()
251 mike         1.91 {
252                       // Note: A Win32 thread ID is not the same thing as a pthread ID.
253                       // Win32 threads have both a thread ID and a handle.  The handle
254                       // is used in the wait functions, etc.
255                       // So _handle.thid is actually the thread handle.
256 kumpf        1.81 
257 mike         1.91     unsigned threadid = 0;
258 mike         1.2  
259 mike         1.91     ThreadType tt;
260                       tt.handle = (HANDLE) _beginthreadex(NULL, 0, _start, this, 0, &threadid);
261                       _handle.thid = tt;
262 chuck        1.39 
263 mike         1.95     if (Threads::null(_handle.thid))
264 mike         1.91     {
265                           if (errno == EAGAIN)
266 kumpf        1.81         {
267 mike         1.91             return PEGASUS_THREAD_INSUFFICIENT_RESOURCES;
268 kumpf        1.81         }
269 mike         1.91         else
270 kumpf        1.81         {
271 mike         1.91             return PEGASUS_THREAD_SETUP_FAILURE;
272 kumpf        1.81         }
273 mike         1.91     }
274                       return PEGASUS_THREAD_OK;
275                   }
276 mday         1.52 
277 kumpf        1.98 void Thread::cancel()
278 mike         1.91 {
279                       _cancelled = true;
280                   }
281 kumpf        1.82 
282 kumpf        1.98 void Thread::test_cancel()
283 mike         1.91 {
284                       if (_cancel_enabled && _cancelled)
285                       {
286                           exit_self(0);
287                       }
288                   }
289 kumpf        1.82 
290 kumpf        1.98 Boolean Thread::is_cancelled()
291 mike         1.91 {
292                       return _cancelled;
293                   }
294 kumpf        1.82 
295 kumpf        1.98 void Thread::thread_switch()
296 mike         1.91 {
297                       Sleep(0);
298                   }
299 kumpf        1.82 
300 mike         1.91 void Thread::sleep(Uint32 milliseconds)
301                   {
302                       Sleep(milliseconds);
303                   }
304 mike         1.2  
305 kumpf        1.98 void Thread::join()
306 mike         1.91 {
307 mike         1.95     if (!Threads::null(_handle.thid))
308 mike         1.91     {
309                           if (!_is_detached)
310                           {
311                               if (!_cancelled)
312 kumpf        1.82             {
313 mike         1.91                 // Emulate the unix join api. Caller sleeps until thread is
314                                   // done.
315                                   WaitForSingleObject(_handle.thid.handle, INFINITE);
316 kumpf        1.82             }
317 mike         1.91             else
318 kumpf        1.82             {
319 mike         1.91                 // Currently this is the only way to ensure this code does
320 kumpf        1.98                 // not
321 mike         1.91                 // hang forever.
322                                   if (WaitForSingleObject(_handle.thid.handle, 10000) ==
323                                       WAIT_TIMEOUT)
324 kumpf        1.82                 {
325 mike         1.91                     TerminateThread(_handle.thid.handle, 0);
326 kumpf        1.82                 }
327 mike         1.91             }
328 s.hills      1.49 
329 mike         1.91             DWORD exit_code = 0;
330                               GetExitCodeThread(_handle.thid.handle, &exit_code);
331                               _exit_code = (ThreadReturnType) exit_code;
332 kumpf        1.81         }
333 mike         1.91 
334                           CloseHandle(_handle.thid.handle);
335                           Threads::clear(_handle.thid);
336 kumpf        1.82     }
337 mike         1.91 }
338 kumpf        1.14 
339 kumpf        1.98 void Thread::thread_init()
340 mike         1.91 {
341                       _cancel_enabled = true;
342 mike         1.2  }
343                   
344 kumpf        1.98 void Thread::detach()
345 mike         1.2  {
346 mike         1.91     _is_detached = true;
347                   }
348 kumpf        1.81 
349 mike         1.91 Thread::Thread(ThreadReturnType(PEGASUS_THREAD_CDECL * start) (void *),
350                                  void *parameter,
351                                  Boolean detached):_is_detached(detached),
352                   _cancel_enabled(true),
353                   _cancelled(false),
354                   _start(start), _cleanup(), _tsd(), _thread_parm(parameter), _exit_code(0)
355                   {
356                       Threads::clear(_handle.thid);
357                   }
358 kumpf        1.81 
359 mike         1.91 Thread::~Thread()
360                   {
361 kumpf        1.81     try
362                       {
363 mike         1.91         join();
364                           empty_tsd();
365                       }
366 kumpf        1.98     catch (...)
367 mike         1.91     {
368                       }
369                   }
370 kumpf        1.81 
371 mike         1.91 #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
372 kumpf        1.57 
373 mike         1.91 //==============================================================================
374                   //
375                   // Common implementation:
376                   //
377                   //==============================================================================
378 kumpf        1.81 
379 mike         1.91 void thread_data::default_delete(void *data)
380                   {
381                       if (data != NULL)
382                           ::operator  delete(data);
383                   }
384 mike         1.2  
385 mike         1.91 void language_delete(void *data)
386                   {
387                       if (data != NULL)
388                       {
389                           AutoPtr < AcceptLanguageList > al(static_cast <
390                                                             AcceptLanguageList * >(data));
391 kumpf        1.57     }
392 mike         1.2  }
393                   
394 mike         1.91 Boolean Thread::_signals_blocked = false;
395                   #ifndef PEGASUS_OS_ZOS
396                   TSDKeyType Thread::_platform_thread_key = TSDKeyType(-1);
397                   #else
398                   TSDKeyType Thread::_platform_thread_key;
399                   #endif
400                   Boolean Thread::_key_initialized = false;
401                   Boolean Thread::_key_error = false;
402 mday         1.12 
403 mike         1.91 void Thread::cleanup_push(void (*routine) (void *), void *parm)
404 mike         1.2  {
405 mike         1.91     AutoPtr < cleanup_handler > cu(new cleanup_handler(routine, parm));
406                       _cleanup.insert_front(cu.get());
407                       cu.release();
408                       return;
409                   }
410 kumpf        1.81 
411 mike         1.91 void Thread::cleanup_pop(Boolean execute)
412                   {
413                       AutoPtr < cleanup_handler > cu;
414                       try
415                       {
416                           cu.reset(_cleanup.remove_front());
417                       }
418 kumpf        1.98     catch (IPCException &)
419 mike         1.91     {
420                           PEGASUS_ASSERT(0);
421                       }
422                       if (execute == true)
423                           cu->execute();
424                   }
425 kumpf        1.81 
426                   
427 mike         1.91 void Thread::exit_self(ThreadReturnType exit_code)
428                   {
429 marek        1.97 #ifndef PEGASUS_PLATFORM_AIX_RS_IBMCXX
430                       Threads::exit(exit_code);
431 mike         1.91 #else
432                       // execute the cleanup stack and then return
433                       while (_cleanup.size())
434                       {
435 kumpf        1.81         try
436                           {
437 mike         1.91             cleanup_pop(true);
438 kumpf        1.81         }
439 kumpf        1.98         catch (IPCException &)
440 kumpf        1.81         {
441 mike         1.91             PEGASUS_ASSERT(0);
442 kumpf        1.81             break;
443                           }
444 mike         1.91     }
445                       _exit_code = exit_code;
446                       Threads::exit(exit_code);
447                       Threads::clear(_handle.thid);
448                   #endif
449                   }
450 kumpf        1.81 
451 mike         1.91 Sint8 Thread::initializeKey()
452                   {
453                       PEG_METHOD_ENTER(TRC_THREAD, "Thread::initializeKey");
454                       if (!Thread::_key_initialized)
455                       {
456                           if (Thread::_key_error)
457                           {
458                               Tracer::trace(TRC_THREAD, Tracer::LEVEL4,
459                                             "Thread: ERROR - thread key error");
460                               return -1;
461                           }
462 kumpf        1.81 
463 mike         1.91         if (TSDKey::create(&Thread::_platform_thread_key) == 0)
464 kumpf        1.81         {
465 mike         1.91             Tracer::trace(TRC_THREAD, Tracer::LEVEL4,
466                                             "Thread: able to create a thread key");
467                               Thread::_key_initialized = true;
468 kumpf        1.81         }
469                           else
470                           {
471 mike         1.91             Tracer::trace(TRC_THREAD, Tracer::LEVEL4,
472                                             "Thread: ERROR - unable to create a thread key");
473                               Thread::_key_error = true;
474                               return -1;
475 kumpf        1.81         }
476 konrad.r     1.67     }
477 kumpf        1.81 
478                       PEG_METHOD_EXIT();
479 mike         1.91     return 0;
480 konrad.r     1.67 }
481 mday         1.19 
482 mike         1.91 Thread *Thread::getCurrent()
483 mday         1.19 {
484 mike         1.91     PEG_METHOD_ENTER(TRC_THREAD, "Thread::getCurrent");
485                       if (Thread::initializeKey() != 0)
486                       {
487                           return NULL;
488                       }
489 kumpf        1.81     PEG_METHOD_EXIT();
490 mike         1.91     return (Thread *) TSDKey::get_thread_specific(_platform_thread_key);
491 mday         1.19 }
492                   
493 mike         1.91 void Thread::setCurrent(Thread * thrd)
494 mday         1.19 {
495 mike         1.91     PEG_METHOD_ENTER(TRC_THREAD, "Thread::setCurrent");
496                       if (Thread::initializeKey() == 0)
497 kumpf        1.81     {
498 mike         1.91         if (TSDKey::
499                               set_thread_specific(Thread::_platform_thread_key,
500                                                   (void *) thrd) == 0)
501                           {
502                               Tracer::trace(TRC_THREAD, Tracer::LEVEL4,
503                                   "Successful set Thread * into thread specific storage");
504                           }
505                           else
506                           {
507                               Tracer::trace(TRC_THREAD, Tracer::LEVEL4,
508                                   "ERROR: error setting Thread * into thread specific storage");
509                           }
510 kumpf        1.81     }
511 mike         1.91     PEG_METHOD_EXIT();
512 mday         1.19 }
513                   
514 mike         1.91 AcceptLanguageList *Thread::getLanguages()
515 mday         1.19 {
516 mike         1.91     PEG_METHOD_ENTER(TRC_THREAD, "Thread::getLanguages");
517                   
518                       Thread *curThrd = Thread::getCurrent();
519                       if (curThrd == NULL)
520                           return NULL;
521                       AcceptLanguageList *acceptLangs =
522                           (AcceptLanguageList *) curThrd->reference_tsd("acceptLanguages");
523                       curThrd->dereference_tsd();
524                       PEG_METHOD_EXIT();
525                       return acceptLangs;
526 mday         1.19 }
527                   
528 kumpf        1.98 void Thread::setLanguages(AcceptLanguageList * langs)
529 mday         1.19 {
530 mike         1.91     PEG_METHOD_ENTER(TRC_THREAD, "Thread::setLanguages");
531 kumpf        1.81 
532 mike         1.91     Thread *currentThrd = Thread::getCurrent();
533                       if (currentThrd != NULL)
534 kumpf        1.81     {
535 mike         1.91         // deletes the old tsd and creates a new one
536                           currentThrd->put_tsd("acceptLanguages",
537                                                language_delete,
538                                                sizeof (AcceptLanguageList *), langs);
539 kumpf        1.81     }
540                   
541                       PEG_METHOD_EXIT();
542 mday         1.19 }
543 mike         1.2  
544 kumpf        1.98 void Thread::clearLanguages()
545 kumpf        1.81 {
546 mike         1.91     PEG_METHOD_ENTER(TRC_THREAD, "Thread::clearLanguages");
547                   
548                       Thread *currentThrd = Thread::getCurrent();
549                       if (currentThrd != NULL)
550 kumpf        1.81     {
551 mike         1.91         // deletes the old tsd
552                           currentThrd->delete_tsd("acceptLanguages");
553 kumpf        1.81     }
554                   
555 mike         1.91     PEG_METHOD_EXIT();
556 kumpf        1.81 }
557 mike         1.2  
558 mike         1.91 // ATTN: not sure where to put this!
559                   #ifdef PEGASUS_ZOS_SECURITY
560                   bool isEnhancedSecurity = 99;
561                   #endif
562                   
563 mike         1.2  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2