(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 kumpf 1.98.4.2 #include <Pegasus/Common/AutoPtr.h>
 39 mike  1.91     #include "Time.h"
 40 mike  1.2      
 41 mike  1.91     PEGASUS_USING_STD;
 42 mike  1.2      
 43                PEGASUS_NAMESPACE_BEGIN
 44                
 45 mike  1.91     //==============================================================================
 46                //
 47                // POSIX Threads Implementation:
 48                //
 49                //==============================================================================
 50 mday  1.42     
 51 mike  1.91     #if defined(PEGASUS_HAVE_PTHREADS)
 52                
 53                struct StartWrapperArg
 54 chip  1.11     {
 55 mike  1.91         void *(PEGASUS_THREAD_CDECL * start) (void *);
 56                    void *arg;
 57                };
 58 mike  1.2      
 59 mike  1.91     extern "C" void *_start_wrapper(void *arg_)
 60 chuck 1.43     {
 61 kumpf 1.98.4.2     AutoPtr<StartWrapperArg> arg((StartWrapperArg *) arg_);
 62 chuck 1.43     
 63 mike  1.91         void *return_value = (*arg->start) (arg->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 marek        1.98.4.1             PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
459 mike         1.91                               "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 marek        1.98.4.1             PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
466 mike         1.91                               "Thread: able to create a thread key");
467                                   Thread::_key_initialized = true;
468 kumpf        1.81             }
469                               else
470                               {
471 marek        1.98.4.1             PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
472 mike         1.91                               "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 marek        1.98.4.1             PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
503 mike         1.91                     "Successful set Thread * into thread specific storage");
504                               }
505                               else
506                               {
507 marek        1.98.4.1             PEG_TRACE_CSTRING(TRC_THREAD, Tracer::LEVEL4,
508 mike         1.91                     "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