00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041
00042 #include "OSGConfig.h"
00043
00044 #include <iostream>
00045
00046 #include "OSGBaseThread.h"
00047 #include "OSGBaseFunctions.h"
00048 #include "OSGThreadManager.h"
00049 #include "OSGLog.h"
00050
00051 #if ! defined (OSG_USE_PTHREADS) && ! defined (OSG_USE_WINTHREADS)
00052 #define _SGI_MP_SOURCE
00053 #include <sys/types.h>
00054 #include <sys/prctl.h>
00055 #include <errno.h>
00056
00057 #include <sys/types.h>
00058 #include <sys/wait.h>
00059 #include <unistd.h>
00060 #include <signal.h>
00061 #endif
00062
00063 #if defined (OSG_USE_PTHREADS)
00064 #include <signal.h>
00065 #endif
00066
00067 OSG_USING_NAMESPACE
00068
00069
00070
00071
00072
00073 bool BaseThreadCommonBase::isInitialized(void)
00074 {
00075 return _bInitialized;
00076 }
00077
00078
00079
00080
00081 BaseThreadCommonBase::BaseThreadCommonBase(const Char8 *szName,
00082 UInt32 uiId ) :
00083
00084 Inherited (szName),
00085 _uiThreadId (uiId ),
00086 _bInitialized(false )
00087 {
00088 }
00089
00090
00091
00092 BaseThreadCommonBase::~BaseThreadCommonBase(void)
00093 {
00094 }
00095
00096
00097
00098 #if defined (OSG_USE_PTHREADS)
00099
00100
00101
00102
00103
00104 #if defined(OSG_PTHREAD_ELF_TLS)
00105 __thread BaseThread *BasePThreadBase::_pLocalThread = NULL;
00106 #else
00107 pthread_key_t BasePThreadBase::_threadKey;
00108 #endif
00109
00110
00111
00112
00113
00114 void *BasePThreadBase::threadFunc(void *pThreadArg)
00115 {
00116 void **pArgs = (void **) pThreadArg;
00117
00118 if(pArgs != NULL)
00119 {
00120 if(pArgs[2] != NULL)
00121 {
00122 ((BaseThread *) pArgs[2])->init();
00123
00124 if(pArgs[0] != NULL)
00125 {
00126 ThreadFuncF fThreadFunc = (ThreadFuncF) pArgs[0];
00127
00128 fThreadFunc(pArgs[1]);
00129 }
00130 }
00131 }
00132
00133 return NULL;
00134 }
00135
00136 #if !defined(OSG_PTHREAD_ELF_TLS)
00137 void BasePThreadBase::freeThread(void *pThread)
00138 {
00139 BaseThread **pT = static_cast<BaseThread **>(pThread);
00140
00141 delete pT;
00142 }
00143 #endif
00144
00145
00146
00147 BasePThreadBase::BasePThreadBase(const Char8 *szName,
00148 UInt32 uiId ) :
00149 Inherited (szName, uiId),
00150
00151 _pThreadDesc(NULL),
00152 _pBlockCond (NULL),
00153 _pBlockMutex(NULL)
00154 {
00155 _pThreadData[0] = NULL;
00156 _pThreadData[1] = NULL;
00157 _pThreadData[2] = NULL;
00158 }
00159
00160
00161
00162
00163 BasePThreadBase::~BasePThreadBase(void)
00164 {
00165 delete _pThreadDesc;
00166 }
00167
00168
00169
00170
00171 void BasePThreadBase::setupThread(void)
00172 {
00173 #ifdef OSG_PTHREAD_ELF_TLS
00174 _pLocalThread = static_cast<BaseThread *>(this);
00175 #else
00176 BaseThread **pThread = new BaseThread *;
00177
00178 *pThread = (BaseThread *) this;
00179
00180 pthread_setspecific(_threadKey, (void *) pThread);
00181 #endif
00182 }
00183
00184 void BasePThreadBase::setupBlockCond(void)
00185 {
00186 _pBlockCond = new pthread_cond_t;
00187 _pBlockMutex = new pthread_mutex_t;
00188
00189 pthread_cond_init (_pBlockCond, NULL);
00190 pthread_mutex_init(_pBlockMutex, NULL);
00191 }
00192
00193 void BasePThreadBase::init(void)
00194 {
00195 if(_bInitialized == true)
00196 return;
00197
00198 setupThread ();
00199 setupBlockCond ();
00200
00201 _bInitialized = true;
00202 }
00203
00204
00205
00206 BaseThread *BasePThreadBase::getCurrent(void)
00207 {
00208 #ifdef OSG_PTHREAD_ELF_TLS
00209 return _pLocalThread;
00210 #else
00211 BaseThread **pThread;
00212
00213 pThread = (BaseThread **) pthread_getspecific(_threadKey);
00214
00215 return *pThread;
00216 #endif
00217 }
00218
00219
00220
00221 void BasePThreadBase::join(BasePThreadBase *pThread)
00222 {
00223 if(pThread != NULL && pThread->_pThreadDesc != NULL)
00224 {
00225 pthread_join(*(pThread->_pThreadDesc), NULL);
00226 }
00227 }
00228
00229
00230
00231
00232
00233 bool BasePThreadBase::runFunction(ThreadFuncF fThreadFunc,
00234 void *pThreadArg)
00235 {
00236 bool returnValue = true;
00237 Int32 rc = 0;
00238
00239 _bInitialized = false;
00240
00241 if(fThreadFunc != NULL)
00242 {
00243 if(_pThreadDesc == NULL)
00244 _pThreadDesc = new pthread_t;
00245
00246 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &rc);
00247
00248 _pThreadData[0] = (void *) fThreadFunc;
00249 _pThreadData[1] = pThreadArg;
00250 _pThreadData[2] = (void *) this;
00251
00252 pthread_attr_t threadAttr;
00253 pthread_attr_setscope(&threadAttr, PTHREAD_SCOPE_SYSTEM);
00254
00255 rc = pthread_create(_pThreadDesc,
00256 #if 0
00257 &threadAttr,
00258 #else
00259 NULL,
00260 #endif
00261 BasePThreadBase::threadFunc,
00262 (void *) &_pThreadData);
00263
00264 if(rc != 0)
00265 {
00266 SFATAL << "OSGPTB : pthread_create failed" << std::endl;
00267 returnValue = false;
00268 }
00269 }
00270 else
00271 {
00272 SFATAL << "OSGPTB : no thread function given";
00273 returnValue = false;
00274 }
00275
00276 return returnValue;
00277 }
00278
00279
00280
00281 void BasePThreadBase::block(void)
00282 {
00283 pthread_mutex_lock (_pBlockMutex);
00284 pthread_cond_wait (_pBlockCond, _pBlockMutex);
00285 pthread_mutex_unlock(_pBlockMutex);
00286 }
00287
00288 void BasePThreadBase::unblock(void)
00289 {
00290 pthread_cond_broadcast(_pBlockCond);
00291 }
00292
00293
00294
00295 bool BasePThreadBase::exists(void)
00296 {
00297 return true;
00298 }
00299
00300 void BasePThreadBase::terminate(void)
00301 {
00302 if(_pThreadDesc != NULL)
00303 pthread_cancel(*_pThreadDesc);
00304 }
00305
00306 void BasePThreadBase::kill(void)
00307 {
00308 if(_pThreadDesc != NULL)
00309 pthread_cancel(*_pThreadDesc);
00310 }
00311
00312
00313
00314 void BasePThreadBase::print(void)
00315 {
00316 fprintf(stderr, "OSGPThreadBase -%s-%d-\n", _szName, _uiThreadId);
00317 }
00318
00319 #endif
00320
00321
00322
00323
00324 #if defined (OSG_USE_SPROC)
00325
00326
00327
00328
00329
00330
00331
00332 void BaseSprocBase::threadFunc(void *pThreadArg)
00333 {
00334 void **pArgs = (void **) pThreadArg;
00335
00336 if(pArgs != NULL)
00337 {
00338 if(pArgs[2] != NULL)
00339 {
00340 ((BaseThread *) pArgs[2])->init();
00341
00342 ((BaseThread *) pArgs[2])->setPid();
00343
00344 if(pArgs[0] != NULL)
00345 {
00346 ThreadFuncF threadFuncF = (ThreadFuncF) pArgs[0];
00347
00348 threadFuncF(pArgs[1]);
00349 }
00350 }
00351 }
00352 }
00353
00354
00355
00356 BaseSprocBase::BaseSprocBase(const Char8 *szName,
00357 UInt32 uiId ) :
00358 Inherited(szName, uiId),
00359
00360 _pid (NULL)
00361 {
00362 _pThreadData[0] = NULL;
00363 _pThreadData[1] = NULL;
00364 _pThreadData[2] = NULL;
00365 }
00366
00367
00368
00369 BaseSprocBase::~BaseSprocBase(void)
00370 {
00371 }
00372
00373
00374
00375 void BaseSprocBase::init(void)
00376 {
00377 if(_bInitialized == true)
00378 return;
00379
00380 setCurrentInternal((BaseThread *) this);
00381
00382 _bInitialized = true;
00383 }
00384
00385 void BaseSprocBase::setPid(void)
00386 {
00387 _pid = getpid();
00388 }
00389
00390 void BaseSprocBase::setCurrentInternal(BaseThread *pThread)
00391 {
00392 ((ProcessData *) PRDA->usr_prda.fill)->_pThread = pThread;
00393 }
00394
00395
00396
00397 BaseThread *BaseSprocBase::getCurrent(void)
00398 {
00399 return ((ProcessData *) PRDA->usr_prda.fill)->_pThread;
00400 }
00401
00402
00403
00404 void BaseSprocBase::join(BaseSprocBase *pThread)
00405 {
00406 if(pThread != NULL)
00407 waitpid(pThread->_pid, NULL, 0);
00408 }
00409
00410
00411
00412
00413
00414 bool BaseSprocBase::runFunction(ThreadFuncF fThreadFunc,
00415 void *pThreadArg)
00416 {
00417 bool returnValue = true;
00418 Int32 rc = 0;
00419
00420 _bInitialized = false;
00421
00422 if(fThreadFunc != NULL)
00423 {
00424 _pThreadData[0] = (void *) fThreadFunc;
00425 _pThreadData[1] = pThreadArg;
00426 _pThreadData[2] = (void *) this;
00427
00428 rc = sproc(BaseSprocBase::threadFunc, PR_SALL, (void *) _pThreadData);
00429
00430 if(rc == -1)
00431 {
00432 SFATAL << "OSGSPB : sproc thread failed. Reason: "
00433 << strerror(errno) << std::endl;
00434 returnValue = false;
00435 }
00436 }
00437 else
00438 {
00439 SFATAL << "OSGSPB : no thread function given";
00440 returnValue = false;
00441 }
00442
00443 return returnValue;
00444 }
00445
00446
00447
00448 void BaseSprocBase::block(void)
00449 {
00450 blockproc(_pid);
00451 }
00452
00453 void BaseSprocBase::unblock(void)
00454 {
00455 unblockproc(_pid);
00456 }
00457
00458
00459
00460 bool BaseSprocBase::exists(void)
00461 {
00462 bool returnValue = false;
00463
00464 returnValue = (prctl(PR_ISBLOCKED, _pid) != -1);
00465
00466 return returnValue;
00467 }
00468
00469
00470 void BaseSprocBase::terminate(void)
00471 {
00472 ::kill(_pid, SIGTERM);
00473 }
00474
00475 void BaseSprocBase::kill(void)
00476 {
00477 ::kill(_pid, SIGKILL);
00478 }
00479
00480
00481
00482 void BaseSprocBase::print(void)
00483 {
00484 fprintf(stderr, "OSGSprocBase -%s-%d-\n", _szName, _uiThreadId);
00485 }
00486
00487 #endif
00488
00489
00490
00491
00492 #if defined (OSG_USE_WINTHREADS)
00493
00494
00495
00496
00497
00498 #if defined(OSG_ASPECT_USE_LOCALSTORAGE)
00499 UInt32 BaseWinThreadBase::_threadKey = 0;
00500 #endif
00501
00502 #if defined(OSG_ASPECT_USE_DECLSPEC)
00503 __declspec (thread) BaseThread *BaseWinThreadBase::_pThreadLocal = NULL;
00504 #endif
00505
00506
00507
00508 void BaseWinThreadBase::threadFunc(void *pThreadArg)
00509 {
00510 void **pArgs = (void **) pThreadArg;
00511
00512 if(pArgs != NULL)
00513 {
00514 if(pArgs[2] != NULL)
00515 {
00516 ((BaseThread *) pArgs[2])->init();
00517
00518 ((BaseWinThreadBase *) pArgs[2])->setPid();
00519 }
00520
00521 if(pArgs[0] != NULL)
00522 {
00523 ThreadFuncF threadFuncF = (ThreadFuncF) pArgs[0];
00524
00525 threadFuncF(pArgs[1]);
00526 }
00527 }
00528 }
00529
00530 #if defined (OSG_ASPECT_USE_LOCALSTORAGE)
00531 void BaseWinThreadBase::freeThread(void)
00532 {
00533 BaseThread **pThread;
00534
00535 pThread = (BaseThread **) TlsGetValue(_threadKey);
00536
00537 delete pThread;
00538 }
00539 #endif
00540
00541
00542
00543 BaseWinThreadBase::BaseWinThreadBase(const Char8 *szName,
00544 UInt32 uiId) :
00545 Inherited (szName, uiId),
00546
00547 _pThreadHandle (NULL),
00548 _pExternalHandle (NULL),
00549 _uiNativeThreadId(0 )
00550 {
00551 _pThreadData[0] = NULL;
00552 _pThreadData[1] = NULL;
00553 _pThreadData[2] = NULL;
00554 }
00555
00556
00557
00558 BaseWinThreadBase::~BaseWinThreadBase(void)
00559 {
00560 }
00561
00562
00563
00564 void BaseWinThreadBase::init(void)
00565 {
00566 if(_bInitialized == true)
00567 return;
00568
00569 setupThread();
00570
00571 _bInitialized = true;
00572 }
00573
00574 void BaseWinThreadBase::setPid(void)
00575 {
00576 _pThreadHandle = GetCurrentThread ();
00577 _uiNativeThreadId = GetCurrentThreadId();
00578 }
00579
00580 void BaseWinThreadBase::setExternalHandle(Handle pExternalHandle)
00581 {
00582 _pExternalHandle = pExternalHandle;
00583 }
00584
00585
00586 void BaseWinThreadBase::setupThread(void)
00587 {
00588 #if defined (OSG_ASPECT_USE_LOCALSTORAGE)
00589 BaseThread **pThread = new BaseThread *;
00590
00591 *pThread = (BaseThread *) this;
00592
00593 TlsSetValue(_threadKey, pThread);
00594 #endif
00595
00596 #if defined (OSG_ASPECT_USE_DECLSPEC)
00597 _pThreadLocal = (BaseThread *) this;
00598 #endif
00599 }
00600
00601
00602
00603 BaseThread *BaseWinThreadBase::getCurrent(void)
00604 {
00605 #ifdef OSG_ASPECT_USE_LOCALSTORAGE
00606 BaseThread **pThread;
00607
00608 pThread = (BaseThread **) TlsGetValue(_threadKey);
00609
00610 return *pThread;
00611 #endif
00612 #ifdef OSG_ASPECT_USE_DECLSPEC
00613 return _pThreadLocal;
00614 #endif
00615 }
00616
00617
00618
00619 void BaseWinThreadBase::join(BaseWinThreadBase *pThread)
00620 {
00621 if(pThread != NULL)
00622 WaitForSingleObject(pThread->_pExternalHandle, INFINITE);
00623 }
00624
00625
00626
00627
00628
00629 bool BaseWinThreadBase::runFunction(ThreadFuncF fThreadFunc,
00630 void *pThreadArg)
00631 {
00632 bool returnValue = true;
00633 Handle rc = 0;
00634 DWord tmp;
00635
00636 _bInitialized = false;
00637
00638 if(fThreadFunc != NULL)
00639 {
00640 _pThreadData[0] = (void *) fThreadFunc;
00641 _pThreadData[1] = pThreadArg;
00642 _pThreadData[2] = (void *) this;
00643
00644 rc = CreateThread(NULL,
00645 0,
00646 (LPTHREAD_START_ROUTINE) BaseThreadBase::threadFunc,
00647 _pThreadData,
00648 0,
00649 &tmp);
00650
00651 this->setExternalHandle(rc);
00652
00653 if(rc == NULL)
00654 {
00655 SFATAL << "OSGWTB : sproc thread failed. Reason: "
00656 << strerror(errno) << std::endl;
00657 returnValue = false;
00658 }
00659 }
00660 else
00661 {
00662 SFATAL << "OSGWTB : no thread function given";
00663 returnValue = false;
00664 }
00665
00666 return returnValue;
00667 }
00668
00669
00670
00671 void BaseWinThreadBase::block(void)
00672 {
00673 SuspendThread(_pThreadHandle);
00674 }
00675
00676 void BaseWinThreadBase::unblock(void)
00677 {
00678 ResumeThread(_pExternalHandle);
00679 }
00680
00681
00682
00683 bool BaseWinThreadBase::exists(void)
00684 {
00685 bool returnValue = false;
00686 DWORD rc = 0;
00687
00688 if(BaseThread::getCurrent() == this)
00689 {
00690 GetExitCodeThread( _pThreadHandle,
00691 &rc );
00692 }
00693 else
00694 {
00695 GetExitCodeThread( _pExternalHandle,
00696 &rc );
00697 }
00698
00699 returnValue = (rc == STILL_ACTIVE);
00700
00701 return returnValue;
00702 }
00703
00704
00705 void BaseWinThreadBase::terminate(void)
00706 {
00707 if(BaseThread::getCurrent() == this)
00708 {
00709 TerminateThread(_pThreadHandle, 0);
00710 }
00711 else
00712 {
00713 TerminateThread(_pExternalHandle, 0);
00714 }
00715 }
00716
00717 void BaseWinThreadBase::kill(void)
00718 {
00719 if(BaseThread::getCurrent() == this)
00720 {
00721 TerminateThread(_pThreadHandle, 0);
00722 }
00723 else
00724 {
00725 TerminateThread(_pExternalHandle, 0);
00726 }
00727 }
00728
00729
00730
00731 void BaseWinThreadBase::print(void)
00732 {
00733 fprintf(stderr, "OSGWinThreadBase -%s-%u-\n", _szName, _uiThreadId);
00734 }
00735
00736 #endif
00737
00738
00739
00740
00741
00742
00743
00744
00745 MPThreadType BaseThread::_type("OSGBaseThread",
00746 "OSGMPBase",
00747 &BaseThread::create,
00748 BaseThread::initThreading);
00749
00750
00751
00752 BaseThread *BaseThread::get(const Char8 *szName)
00753 {
00754 return ThreadManager::the()->getThread(szName, "OSGBaseThread");
00755 }
00756
00757 BaseThread *BaseThread::find(const Char8 *szName)
00758 {
00759 return ThreadManager::the()->findThread(szName);
00760 }
00761
00762 BaseThread *BaseThread::create(void)
00763 {
00764 return BaseThread::get(NULL);
00765 }
00766
00767 const MPThreadType &BaseThread::getClassType(void)
00768 {
00769 return _type;
00770 }
00771
00772
00773
00774 BaseThread *BaseThread::getCurrent(void)
00775 {
00776 return Inherited::getCurrent();
00777 }
00778
00779
00780
00781 void BaseThread::join(BaseThread *pThread)
00782 {
00783 Inherited::join(pThread);
00784 }
00785
00786
00787
00788
00789 void BaseThread::run(void)
00790 {
00791 Inherited::runFunction(runWorkProc, this);
00792 }
00793
00794 bool BaseThread::runFunction(ThreadFuncF fThreadFunc,
00795 void *pThreadArg)
00796 {
00797 return Inherited::runFunction(fThreadFunc, pThreadArg);
00798 }
00799
00800
00801
00802 void BaseThread::block(void)
00803 {
00804 Inherited::block();
00805 }
00806
00807 void BaseThread::unblock(void)
00808 {
00809 Inherited::unblock();
00810 }
00811
00812
00813
00814 bool BaseThread::exists(void)
00815 {
00816 return Inherited::exists();
00817 }
00818
00819
00820 void BaseThread::terminate(void)
00821 {
00822 Inherited::terminate();
00823 }
00824
00825 void BaseThread::kill(void)
00826 {
00827 Inherited::kill();
00828 }
00829
00830
00831
00832 void BaseThread::print(void)
00833 {
00834 Inherited::print();
00835 }
00836
00837
00838
00839 BaseThread *BaseThread::create(const Char8 *szName, UInt32 uiId)
00840 {
00841 return new BaseThread(szName, uiId);
00842 }
00843
00844 void BaseThread::initThreading(void)
00845 {
00846 FINFO(("BaseThread::initThreading\n"))
00847
00848 #if defined(OSG_USE_PTHREADS) && !defined(OSG_PTHREAD_ELF_TLS)
00849 int rc;
00850
00851 rc = pthread_key_create(&(BaseThread::_threadKey),
00852 BaseThread::freeThread);
00853
00854 FFASSERT((rc == 0), 1, ("Failed to create pthread thread key\n");)
00855 #endif
00856
00857 #if defined(OSG_USE_WINTHREADS) && defined (OSG_ASPECT_USE_LOCALSTORAGE)
00858 BaseThread::_threadKey = TlsAlloc();
00859
00860 FFASSERT((BaseThread::_threadKey != 0xFFFFFFFF), 1,
00861 ("Failed to alloc thread key local storage\n");)
00862 #endif
00863 }
00864
00865 void BaseThread::runWorkProc(void *pThread)
00866 {
00867 if(pThread != NULL)
00868 {
00869 static_cast<BaseThread *>(pThread)->workProc();
00870 }
00871 }
00872
00873
00874
00875
00876 BaseThread::BaseThread(const Char8 *szName, UInt32 uiId) :
00877 Inherited(szName, uiId)
00878 {
00879 }
00880
00881
00882
00883 BaseThread::~BaseThread(void)
00884 {
00885 ThreadManager::the()->removeThread(this);
00886
00887 if(this != ThreadManager::getAppThread())
00888 terminate();
00889 }
00890
00891
00892
00893 void BaseThread::workProc(void)
00894 {
00895 }
00896
00897
00898
00899
00900 #ifdef __sgi
00901 #pragma set woff 1174
00902 #endif
00903
00904 #ifdef OSG_LINUX_ICC
00905 #pragma warning( disable : 177 )
00906 #endif
00907
00908 namespace
00909 {
00910 static Char8 cvsid_cpp[] = "@(#)$Id: $";
00911 static Char8 cvsid_hpp[] = OSGBASETHREAD_HEADER_CVSID;
00912 }