1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/unix/threadpsx.cpp 
   3 // Purpose:     wxThread (Posix) Implementation 
   4 // Author:      Original from Wolfram Gloger/Guilhem Lavaux 
   5 // Modified by: K. S. Sreeram (2002): POSIXified wxCondition, added wxSemaphore 
   8 // Copyright:   (c) Wolfram Gloger (1996, 1997) 
   9 //                  Guilhem Lavaux (1998) 
  10 //                  Vadim Zeitlin (1999-2002) 
  11 //                  Robert Roebling (1999) 
  12 //                  K. S. Sreeram (2002) 
  13 // Licence:     wxWindows licence 
  14 ///////////////////////////////////////////////////////////////////////////// 
  16 // ============================================================================ 
  18 // ============================================================================ 
  20 // ---------------------------------------------------------------------------- 
  22 // ---------------------------------------------------------------------------- 
  24 // for compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  29 #include "wx/thread.h" 
  32     #include "wx/dynarray.h" 
  37     #include "wx/stopwatch.h" 
  38     #include "wx/module.h" 
  50 #ifdef HAVE_THR_SETCONCURRENCY 
  54 // we use wxFFile under Linux in GetCPUCount() 
  59     #include <sys/resource.h> 
  63     #define THR_ID(thr) ((long long)(thr)->GetId()) 
  65     #define THR_ID(thr) ((long)(thr)->GetId()) 
  68 // ---------------------------------------------------------------------------- 
  70 // ---------------------------------------------------------------------------- 
  72 // the possible states of the thread and transitions from them 
  75     STATE_NEW
,          // didn't start execution yet (=> RUNNING) 
  76     STATE_RUNNING
,      // running (=> PAUSED or EXITED) 
  77     STATE_PAUSED
,       // suspended (=> RUNNING or EXITED) 
  78     STATE_EXITED        
// thread doesn't exist any more 
  81 // the exit value of a thread which has been cancelled 
  82 static const wxThread::ExitCode EXITCODE_CANCELLED 
= (wxThread::ExitCode
)-1; 
  84 // trace mask for wxThread operations 
  85 #define TRACE_THREADS   _T("thread") 
  87 // you can get additional debugging messages for the semaphore operations 
  88 #define TRACE_SEMA      _T("semaphore") 
  90 // ---------------------------------------------------------------------------- 
  92 // ---------------------------------------------------------------------------- 
  94 static void ScheduleThreadForDeletion(); 
  95 static void DeleteThread(wxThread 
*This
); 
  97 // ---------------------------------------------------------------------------- 
  99 // ---------------------------------------------------------------------------- 
 101 // an (non owning) array of pointers to threads 
 102 WX_DEFINE_ARRAY_PTR(wxThread 
*, wxArrayThread
); 
 104 // an entry for a thread we can wait for 
 106 // ----------------------------------------------------------------------------- 
 108 // ----------------------------------------------------------------------------- 
 110 // we keep the list of all threads created by the application to be able to 
 111 // terminate them on exit if there are some left - otherwise the process would 
 113 static wxArrayThread gs_allThreads
; 
 115 // a mutex to protect gs_allThreads 
 116 static wxMutex 
*gs_mutexAllThreads 
= NULL
; 
 118 // the id of the main thread 
 119 static pthread_t gs_tidMain 
= (pthread_t
)-1; 
 121 // the key for the pointer to the associated wxThread object 
 122 static pthread_key_t gs_keySelf
; 
 124 // the number of threads which are being deleted - the program won't exit 
 125 // until there are any left 
 126 static size_t gs_nThreadsBeingDeleted 
= 0; 
 128 // a mutex to protect gs_nThreadsBeingDeleted 
 129 static wxMutex 
*gs_mutexDeleteThread 
= (wxMutex 
*)NULL
; 
 131 // and a condition variable which will be signaled when all 
 132 // gs_nThreadsBeingDeleted will have been deleted 
 133 static wxCondition 
*gs_condAllDeleted 
= (wxCondition 
*)NULL
; 
 135 // this mutex must be acquired before any call to a GUI function 
 136 // (it's not inside #if wxUSE_GUI because this file is compiled as part 
 138 static wxMutex 
*gs_mutexGui 
= NULL
; 
 140 // when we wait for a thread to exit, we're blocking on a condition which the 
 141 // thread signals in its SignalExit() method -- but this condition can't be a 
 142 // member of the thread itself as a detached thread may delete itself at any 
 143 // moment and accessing the condition member of the thread after this would 
 144 // result in a disaster 
 146 // so instead we maintain a global list of the structs below for the threads 
 147 // we're interested in waiting on 
 149 // ============================================================================ 
 150 // wxMutex implementation 
 151 // ============================================================================ 
 153 // ---------------------------------------------------------------------------- 
 155 // ---------------------------------------------------------------------------- 
 157 // this is a simple wrapper around pthread_mutex_t which provides error 
 159 class wxMutexInternal
 
 162     wxMutexInternal(wxMutexType mutexType
); 
 166     wxMutexError 
TryLock(); 
 167     wxMutexError 
Unlock(); 
 169     bool IsOk() const { return m_isOk
; } 
 172     pthread_mutex_t m_mutex
; 
 175     // wxConditionInternal uses our m_mutex 
 176     friend class wxConditionInternal
; 
 179 #if defined(HAVE_PTHREAD_MUTEXATTR_T) && \ 
 180         wxUSE_UNIX && !defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE_DECL) 
 181 // on some systems pthread_mutexattr_settype() is not in the headers (but it is 
 182 // in the library, otherwise we wouldn't compile this code at all) 
 183 extern "C" int pthread_mutexattr_settype(pthread_mutexattr_t 
*, int); 
 186 wxMutexInternal::wxMutexInternal(wxMutexType mutexType
) 
 191         case wxMUTEX_RECURSIVE
: 
 192             // support recursive locks like Win32, i.e. a thread can lock a 
 193             // mutex which it had itself already locked 
 195             // unfortunately initialization of recursive mutexes is non 
 196             // portable, so try several methods 
 197 #ifdef HAVE_PTHREAD_MUTEXATTR_T 
 199                 pthread_mutexattr_t attr
; 
 200                 pthread_mutexattr_init(&attr
); 
 201                 pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_RECURSIVE
); 
 203                 err 
= pthread_mutex_init(&m_mutex
, &attr
); 
 205 #elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER) 
 206             // we can use this only as initializer so we have to assign it 
 207             // first to a temp var - assigning directly to m_mutex wouldn't 
 210                 pthread_mutex_t mutex 
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
; 
 213 #else // no recursive mutexes 
 215 #endif // HAVE_PTHREAD_MUTEXATTR_T/... 
 219             wxFAIL_MSG( _T("unknown mutex type") ); 
 222         case wxMUTEX_DEFAULT
: 
 223             err 
= pthread_mutex_init(&m_mutex
, NULL
); 
 230         wxLogApiError( wxT("pthread_mutex_init()"), err
); 
 234 wxMutexInternal::~wxMutexInternal() 
 238         int err 
= pthread_mutex_destroy(&m_mutex
); 
 241             wxLogApiError( wxT("pthread_mutex_destroy()"), err
); 
 246 wxMutexError 
wxMutexInternal::Lock() 
 248     int err 
= pthread_mutex_lock(&m_mutex
); 
 252             // only error checking mutexes return this value and so it's an 
 253             // unexpected situation -- hence use assert, not wxLogDebug 
 254             wxFAIL_MSG( _T("mutex deadlock prevented") ); 
 255             return wxMUTEX_DEAD_LOCK
; 
 258             wxLogDebug(_T("pthread_mutex_lock(): mutex not initialized.")); 
 262             return wxMUTEX_NO_ERROR
; 
 265             wxLogApiError(_T("pthread_mutex_lock()"), err
); 
 268     return wxMUTEX_MISC_ERROR
; 
 271 wxMutexError 
wxMutexInternal::TryLock() 
 273     int err 
= pthread_mutex_trylock(&m_mutex
); 
 277             // not an error: mutex is already locked, but we're prepared for 
 282             wxLogDebug(_T("pthread_mutex_trylock(): mutex not initialized.")); 
 286             return wxMUTEX_NO_ERROR
; 
 289             wxLogApiError(_T("pthread_mutex_trylock()"), err
); 
 292     return wxMUTEX_MISC_ERROR
; 
 295 wxMutexError 
wxMutexInternal::Unlock() 
 297     int err 
= pthread_mutex_unlock(&m_mutex
); 
 301             // we don't own the mutex 
 302             return wxMUTEX_UNLOCKED
; 
 305             wxLogDebug(_T("pthread_mutex_unlock(): mutex not initialized.")); 
 309             return wxMUTEX_NO_ERROR
; 
 312             wxLogApiError(_T("pthread_mutex_unlock()"), err
); 
 315     return wxMUTEX_MISC_ERROR
; 
 318 // =========================================================================== 
 319 // wxCondition implementation 
 320 // =========================================================================== 
 322 // --------------------------------------------------------------------------- 
 323 // wxConditionInternal 
 324 // --------------------------------------------------------------------------- 
 326 // this is a wrapper around pthread_cond_t associated with a wxMutex (and hence 
 327 // with a pthread_mutex_t) 
 328 class wxConditionInternal
 
 331     wxConditionInternal(wxMutex
& mutex
); 
 332     ~wxConditionInternal(); 
 334     bool IsOk() const { return m_isOk 
&& m_mutex
.IsOk(); } 
 337     wxCondError 
WaitTimeout(unsigned long milliseconds
); 
 339     wxCondError 
Signal(); 
 340     wxCondError 
Broadcast(); 
 343     // get the POSIX mutex associated with us 
 344     pthread_mutex_t 
*GetPMutex() const { return &m_mutex
.m_internal
->m_mutex
; } 
 347     pthread_cond_t m_cond
; 
 352 wxConditionInternal::wxConditionInternal(wxMutex
& mutex
) 
 355     int err 
= pthread_cond_init(&m_cond
, NULL 
/* default attributes */); 
 361         wxLogApiError(_T("pthread_cond_init()"), err
); 
 365 wxConditionInternal::~wxConditionInternal() 
 369         int err 
= pthread_cond_destroy(&m_cond
); 
 372             wxLogApiError(_T("pthread_cond_destroy()"), err
); 
 377 wxCondError 
wxConditionInternal::Wait() 
 379     int err 
= pthread_cond_wait(&m_cond
, GetPMutex()); 
 382         wxLogApiError(_T("pthread_cond_wait()"), err
); 
 384         return wxCOND_MISC_ERROR
; 
 387     return wxCOND_NO_ERROR
; 
 390 wxCondError 
wxConditionInternal::WaitTimeout(unsigned long milliseconds
) 
 392     wxLongLong curtime 
= wxGetLocalTimeMillis(); 
 393     curtime 
+= milliseconds
; 
 394     wxLongLong temp 
= curtime 
/ 1000; 
 395     int sec 
= temp
.GetLo(); 
 397     temp 
= curtime 
- temp
; 
 398     int millis 
= temp
.GetLo(); 
 403     tspec
.tv_nsec 
= millis 
* 1000L * 1000L; 
 405     int err 
= pthread_cond_timedwait( &m_cond
, GetPMutex(), &tspec 
); 
 409             return wxCOND_TIMEOUT
; 
 412             return wxCOND_NO_ERROR
; 
 415             wxLogApiError(_T("pthread_cond_timedwait()"), err
); 
 418     return wxCOND_MISC_ERROR
; 
 421 wxCondError 
wxConditionInternal::Signal() 
 423     int err 
= pthread_cond_signal(&m_cond
); 
 426         wxLogApiError(_T("pthread_cond_signal()"), err
); 
 428         return wxCOND_MISC_ERROR
; 
 431     return wxCOND_NO_ERROR
; 
 434 wxCondError 
wxConditionInternal::Broadcast() 
 436     int err 
= pthread_cond_broadcast(&m_cond
); 
 439         wxLogApiError(_T("pthread_cond_broadcast()"), err
); 
 441         return wxCOND_MISC_ERROR
; 
 444     return wxCOND_NO_ERROR
; 
 447 // =========================================================================== 
 448 // wxSemaphore implementation 
 449 // =========================================================================== 
 451 // --------------------------------------------------------------------------- 
 452 // wxSemaphoreInternal 
 453 // --------------------------------------------------------------------------- 
 455 // we implement the semaphores using mutexes and conditions instead of using 
 456 // the sem_xxx() POSIX functions because they're not widely available and also 
 457 // because it's impossible to implement WaitTimeout() using them 
 458 class wxSemaphoreInternal
 
 461     wxSemaphoreInternal(int initialcount
, int maxcount
); 
 463     bool IsOk() const { return m_isOk
; } 
 466     wxSemaError 
TryWait(); 
 467     wxSemaError 
WaitTimeout(unsigned long milliseconds
); 
 481 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
) 
 485     if ( (initialcount 
< 0 || maxcount 
< 0) || 
 486             ((maxcount 
> 0) && (initialcount 
> maxcount
)) ) 
 488         wxFAIL_MSG( _T("wxSemaphore: invalid initial or maximal count") ); 
 494         m_maxcount 
= (size_t)maxcount
; 
 495         m_count 
= (size_t)initialcount
; 
 498     m_isOk 
= m_mutex
.IsOk() && m_cond
.IsOk(); 
 501 wxSemaError 
wxSemaphoreInternal::Wait() 
 503     wxMutexLocker 
locker(m_mutex
); 
 505     while ( m_count 
== 0 ) 
 507         wxLogTrace(TRACE_SEMA
, 
 508                    _T("Thread %ld waiting for semaphore to become signalled"), 
 509                    wxThread::GetCurrentId()); 
 511         if ( m_cond
.Wait() != wxCOND_NO_ERROR 
) 
 512             return wxSEMA_MISC_ERROR
; 
 514         wxLogTrace(TRACE_SEMA
, 
 515                    _T("Thread %ld finished waiting for semaphore, count = %lu"), 
 516                    wxThread::GetCurrentId(), (unsigned long)m_count
); 
 521     return wxSEMA_NO_ERROR
; 
 524 wxSemaError 
wxSemaphoreInternal::TryWait() 
 526     wxMutexLocker 
locker(m_mutex
); 
 533     return wxSEMA_NO_ERROR
; 
 536 wxSemaError 
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
) 
 538     wxMutexLocker 
locker(m_mutex
); 
 540     wxLongLong startTime 
= wxGetLocalTimeMillis(); 
 542     while ( m_count 
== 0 ) 
 544         wxLongLong elapsed 
= wxGetLocalTimeMillis() - startTime
; 
 545         long remainingTime 
= (long)milliseconds 
- (long)elapsed
.GetLo(); 
 546         if ( remainingTime 
<= 0 ) 
 549             return wxSEMA_TIMEOUT
; 
 552         switch ( m_cond
.WaitTimeout(remainingTime
) ) 
 555                 return wxSEMA_TIMEOUT
; 
 558                 return wxSEMA_MISC_ERROR
; 
 560             case wxCOND_NO_ERROR
: 
 567     return wxSEMA_NO_ERROR
; 
 570 wxSemaError 
wxSemaphoreInternal::Post() 
 572     wxMutexLocker 
locker(m_mutex
); 
 574     if ( m_maxcount 
> 0 && m_count 
== m_maxcount 
) 
 576         return wxSEMA_OVERFLOW
; 
 581     wxLogTrace(TRACE_SEMA
, 
 582                _T("Thread %ld about to signal semaphore, count = %lu"), 
 583                wxThread::GetCurrentId(), (unsigned long)m_count
); 
 585     return m_cond
.Signal() == wxCOND_NO_ERROR 
? wxSEMA_NO_ERROR
 
 589 // =========================================================================== 
 590 // wxThread implementation 
 591 // =========================================================================== 
 593 // the thread callback functions must have the C linkage 
 597 #ifdef wxHAVE_PTHREAD_CLEANUP 
 598     // thread exit function 
 599     void wxPthreadCleanup(void *ptr
); 
 600 #endif // wxHAVE_PTHREAD_CLEANUP 
 602 void *wxPthreadStart(void *ptr
); 
 606 // ---------------------------------------------------------------------------- 
 608 // ---------------------------------------------------------------------------- 
 610 class wxThreadInternal
 
 616     // thread entry function 
 617     static void *PthreadStart(wxThread 
*thread
); 
 622         // unblock the thread allowing it to run 
 623     void SignalRun() { m_semRun
.Post(); } 
 624         // ask the thread to terminate 
 626         // go to sleep until Resume() is called 
 633     int GetPriority() const { return m_prio
; } 
 634     void SetPriority(int prio
) { m_prio 
= prio
; } 
 636     wxThreadState 
GetState() const { return m_state
; } 
 637     void SetState(wxThreadState state
) 
 640         static const wxChar 
*stateNames
[] = 
 648         wxLogTrace(TRACE_THREADS
, _T("Thread %ld: %s => %s."), 
 649                    (long)GetId(), stateNames
[m_state
], stateNames
[state
]); 
 650 #endif // __WXDEBUG__ 
 655     pthread_t 
GetId() const { return m_threadId
; } 
 656     pthread_t 
*GetIdPtr() { return &m_threadId
; } 
 658     void SetCancelFlag() { m_cancelled 
= true; } 
 659     bool WasCancelled() const { return m_cancelled
; } 
 661     void SetExitCode(wxThread::ExitCode exitcode
) { m_exitcode 
= exitcode
; } 
 662     wxThread::ExitCode 
GetExitCode() const { return m_exitcode
; } 
 665     void SetReallyPaused(bool paused
) { m_isPaused 
= paused
; } 
 666     bool IsReallyPaused() const { return m_isPaused
; } 
 668         // tell the thread that it is a detached one 
 671         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 673         m_shouldBeJoined 
= false; 
 677 #ifdef wxHAVE_PTHREAD_CLEANUP 
 678     // this is used by wxPthreadCleanup() only 
 679     static void Cleanup(wxThread 
*thread
); 
 680 #endif // wxHAVE_PTHREAD_CLEANUP 
 683     pthread_t     m_threadId
;   // id of the thread 
 684     wxThreadState m_state
;      // see wxThreadState enum 
 685     int           m_prio
;       // in wxWidgets units: from 0 to 100 
 687     // this flag is set when the thread should terminate 
 690     // this flag is set when the thread is blocking on m_semSuspend 
 693     // the thread exit code - only used for joinable (!detached) threads and 
 694     // is only valid after the thread termination 
 695     wxThread::ExitCode m_exitcode
; 
 697     // many threads may call Wait(), but only one of them should call 
 698     // pthread_join(), so we have to keep track of this 
 699     wxCriticalSection m_csJoinFlag
; 
 700     bool m_shouldBeJoined
; 
 703     // this semaphore is posted by Run() and the threads Entry() is not 
 704     // called before it is done 
 705     wxSemaphore m_semRun
; 
 707     // this one is signaled when the thread should resume after having been 
 709     wxSemaphore m_semSuspend
; 
 712 // ---------------------------------------------------------------------------- 
 713 // thread startup and exit functions 
 714 // ---------------------------------------------------------------------------- 
 716 void *wxPthreadStart(void *ptr
) 
 718     return wxThreadInternal::PthreadStart((wxThread 
*)ptr
); 
 721 void *wxThreadInternal::PthreadStart(wxThread 
*thread
) 
 723     wxThreadInternal 
*pthread 
= thread
->m_internal
; 
 725     wxLogTrace(TRACE_THREADS
, _T("Thread %ld started."), THR_ID(pthread
)); 
 727     // associate the thread pointer with the newly created thread so that 
 728     // wxThread::This() will work 
 729     int rc 
= pthread_setspecific(gs_keySelf
, thread
); 
 732         wxLogSysError(rc
, _("Cannot start thread: error writing TLS")); 
 737     // have to declare this before pthread_cleanup_push() which defines a 
 741 #ifdef wxHAVE_PTHREAD_CLEANUP 
 742     // install the cleanup handler which will be called if the thread is 
 744     pthread_cleanup_push(wxPthreadCleanup
, thread
); 
 745 #endif // wxHAVE_PTHREAD_CLEANUP 
 747     // wait for the semaphore to be posted from Run() 
 748     pthread
->m_semRun
.Wait(); 
 750     // test whether we should run the run at all - may be it was deleted 
 751     // before it started to Run()? 
 753         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 755         dontRunAtAll 
= pthread
->GetState() == STATE_NEW 
&& 
 756                        pthread
->WasCancelled(); 
 761         // call the main entry 
 762         wxLogTrace(TRACE_THREADS
, 
 763                    _T("Thread %ld about to enter its Entry()."), 
 766         pthread
->m_exitcode 
= thread
->Entry(); 
 768         wxLogTrace(TRACE_THREADS
, 
 769                    _T("Thread %ld Entry() returned %lu."), 
 770                    THR_ID(pthread
), wxPtrToUInt(pthread
->m_exitcode
)); 
 773             wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 775             // change the state of the thread to "exited" so that 
 776             // wxPthreadCleanup handler won't do anything from now (if it's 
 777             // called before we do pthread_cleanup_pop below) 
 778             pthread
->SetState(STATE_EXITED
); 
 782     // NB: pthread_cleanup_push/pop() are macros and pop contains the matching 
 783     //     '}' for the '{' in push, so they must be used in the same block! 
 784 #ifdef wxHAVE_PTHREAD_CLEANUP 
 786         // under Tru64 we get a warning from macro expansion 
 788         #pragma message disable(declbutnotref) 
 791     // remove the cleanup handler without executing it 
 792     pthread_cleanup_pop(FALSE
); 
 795         #pragma message restore 
 797 #endif // wxHAVE_PTHREAD_CLEANUP 
 801         // FIXME: deleting a possibly joinable thread here??? 
 804         return EXITCODE_CANCELLED
; 
 808         // terminate the thread 
 809         thread
->Exit(pthread
->m_exitcode
); 
 811         wxFAIL_MSG(wxT("wxThread::Exit() can't return.")); 
 817 #ifdef wxHAVE_PTHREAD_CLEANUP 
 819 // this handler is called when the thread is cancelled 
 820 extern "C" void wxPthreadCleanup(void *ptr
) 
 822     wxThreadInternal::Cleanup((wxThread 
*)ptr
); 
 825 void wxThreadInternal::Cleanup(wxThread 
*thread
) 
 827     if (pthread_getspecific(gs_keySelf
) == 0) return; 
 829         wxCriticalSectionLocker 
lock(thread
->m_critsect
); 
 830         if ( thread
->m_internal
->GetState() == STATE_EXITED 
) 
 832             // thread is already considered as finished. 
 837     // exit the thread gracefully 
 838     thread
->Exit(EXITCODE_CANCELLED
); 
 841 #endif // wxHAVE_PTHREAD_CLEANUP 
 843 // ---------------------------------------------------------------------------- 
 845 // ---------------------------------------------------------------------------- 
 847 wxThreadInternal::wxThreadInternal() 
 851     m_prio 
= WXTHREAD_DEFAULT_PRIORITY
; 
 855     // set to true only when the thread starts waiting on m_semSuspend 
 858     // defaults for joinable threads 
 859     m_shouldBeJoined 
= true; 
 860     m_isDetached 
= false; 
 863 wxThreadInternal::~wxThreadInternal() 
 867 wxThreadError 
wxThreadInternal::Run() 
 869     wxCHECK_MSG( GetState() == STATE_NEW
, wxTHREAD_RUNNING
, 
 870                  wxT("thread may only be started once after Create()") ); 
 872     SetState(STATE_RUNNING
); 
 874     // wake up threads waiting for our start 
 877     return wxTHREAD_NO_ERROR
; 
 880 void wxThreadInternal::Wait() 
 882     wxCHECK_RET( !m_isDetached
, _T("can't wait for a detached thread") ); 
 884     // if the thread we're waiting for is waiting for the GUI mutex, we will 
 885     // deadlock so make sure we release it temporarily 
 886     if ( wxThread::IsMain() ) 
 889     wxLogTrace(TRACE_THREADS
, 
 890                _T("Starting to wait for thread %ld to exit."), 
 893     // to avoid memory leaks we should call pthread_join(), but it must only be 
 894     // done once so use a critical section to serialize the code below 
 896         wxCriticalSectionLocker 
lock(m_csJoinFlag
); 
 898         if ( m_shouldBeJoined 
) 
 900             // FIXME shouldn't we set cancellation type to DISABLED here? If 
 901             //       we're cancelled inside pthread_join(), things will almost 
 902             //       certainly break - but if we disable the cancellation, we 
 904             if ( pthread_join(GetId(), &m_exitcode
) != 0 ) 
 906                 // this is a serious problem, so use wxLogError and not 
 907                 // wxLogDebug: it is possible to bring the system to its knees 
 908                 // by creating too many threads and not joining them quite 
 910                 wxLogError(_("Failed to join a thread, potential memory leak detected - please restart the program")); 
 913             m_shouldBeJoined 
= false; 
 917     // reacquire GUI mutex 
 918     if ( wxThread::IsMain() ) 
 922 void wxThreadInternal::Pause() 
 924     // the state is set from the thread which pauses us first, this function 
 925     // is called later so the state should have been already set 
 926     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
 927                  wxT("thread must first be paused with wxThread::Pause().") ); 
 929    wxLogTrace(TRACE_THREADS
, 
 930               _T("Thread %ld goes to sleep."), THR_ID(this)); 
 932     // wait until the semaphore is Post()ed from Resume() 
 936 void wxThreadInternal::Resume() 
 938     wxCHECK_RET( m_state 
== STATE_PAUSED
, 
 939                  wxT("can't resume thread which is not suspended.") ); 
 941     // the thread might be not actually paused yet - if there were no call to 
 942     // TestDestroy() since the last call to Pause() for example 
 943     if ( IsReallyPaused() ) 
 945        wxLogTrace(TRACE_THREADS
, 
 946                   _T("Waking up thread %ld"), THR_ID(this)); 
 952         SetReallyPaused(false); 
 956         wxLogTrace(TRACE_THREADS
, 
 957                    _T("Thread %ld is not yet really paused"), THR_ID(this)); 
 960     SetState(STATE_RUNNING
); 
 963 // ----------------------------------------------------------------------------- 
 964 // wxThread static functions 
 965 // ----------------------------------------------------------------------------- 
 967 wxThread 
*wxThread::This() 
 969     return (wxThread 
*)pthread_getspecific(gs_keySelf
); 
 972 bool wxThread::IsMain() 
 974     return (bool)pthread_equal(pthread_self(), gs_tidMain
) || gs_tidMain 
== (pthread_t
)-1; 
 977 void wxThread::Yield() 
 979 #ifdef HAVE_SCHED_YIELD 
 984 void wxThread::Sleep(unsigned long milliseconds
) 
 986     wxMilliSleep(milliseconds
); 
 989 int wxThread::GetCPUCount() 
 991 #if defined(__LINUX__) && wxUSE_FFILE 
 992     // read from proc (can't use wxTextFile here because it's a special file: 
 993     // it has 0 size but still can be read from) 
 996     wxFFile 
file(_T("/proc/cpuinfo")); 
 997     if ( file
.IsOpened() ) 
 999         // slurp the whole file 
1001         if ( file
.ReadAll(&s
) ) 
1003             // (ab)use Replace() to find the number of "processor: num" strings 
1004             size_t count 
= s
.Replace(_T("processor\t:"), _T("")); 
1010             wxLogDebug(_T("failed to parse /proc/cpuinfo")); 
1014             wxLogDebug(_T("failed to read /proc/cpuinfo")); 
1017 #elif defined(_SC_NPROCESSORS_ONLN) 
1018     // this works for Solaris 
1019     int rc 
= sysconf(_SC_NPROCESSORS_ONLN
); 
1024 #endif // different ways to get number of CPUs 
1030 // VMS is a 64 bit system and threads have 64 bit pointers. 
1031 // FIXME: also needed for other systems???? 
1033 unsigned long long wxThread::GetCurrentId() 
1035     return (unsigned long long)pthread_self(); 
1040 unsigned long wxThread::GetCurrentId() 
1042     return (unsigned long)pthread_self(); 
1045 #endif // __VMS/!__VMS 
1048 bool wxThread::SetConcurrency(size_t level
) 
1050 #ifdef HAVE_THR_SETCONCURRENCY 
1051     int rc 
= thr_setconcurrency(level
); 
1054         wxLogSysError(rc
, _T("thr_setconcurrency() failed")); 
1058 #else // !HAVE_THR_SETCONCURRENCY 
1059     // ok only for the default value 
1061 #endif // HAVE_THR_SETCONCURRENCY/!HAVE_THR_SETCONCURRENCY 
1064 // ----------------------------------------------------------------------------- 
1066 // ----------------------------------------------------------------------------- 
1068 wxThread::wxThread(wxThreadKind kind
) 
1070     // add this thread to the global list of all threads 
1072         wxMutexLocker 
lock(*gs_mutexAllThreads
); 
1074         gs_allThreads
.Add(this); 
1077     m_internal 
= new wxThreadInternal(); 
1079     m_isDetached 
= kind 
== wxTHREAD_DETACHED
; 
1082 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE 
1083     #define WXUNUSED_STACKSIZE(identifier)  identifier 
1085     #define WXUNUSED_STACKSIZE(identifier)  WXUNUSED(identifier) 
1088 wxThreadError 
wxThread::Create(unsigned int WXUNUSED_STACKSIZE(stackSize
)) 
1090     if ( m_internal
->GetState() != STATE_NEW 
) 
1092         // don't recreate thread 
1093         return wxTHREAD_RUNNING
; 
1096     // set up the thread attribute: right now, we only set thread priority 
1097     pthread_attr_t attr
; 
1098     pthread_attr_init(&attr
); 
1100 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE 
1102       pthread_attr_setstacksize(&attr
, stackSize
); 
1105 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS 
1107     if ( pthread_attr_getschedpolicy(&attr
, &policy
) != 0 ) 
1109         wxLogError(_("Cannot retrieve thread scheduling policy.")); 
1113    /* the pthread.h contains too many spaces. This is a work-around */ 
1114 # undef sched_get_priority_max 
1115 #undef sched_get_priority_min 
1116 #define sched_get_priority_max(_pol_) \ 
1117      (_pol_ == SCHED_OTHER ? PRI_FG_MAX_NP : PRI_FIFO_MAX) 
1118 #define sched_get_priority_min(_pol_) \ 
1119      (_pol_ == SCHED_OTHER ? PRI_FG_MIN_NP : PRI_FIFO_MIN) 
1122     int max_prio 
= sched_get_priority_max(policy
), 
1123         min_prio 
= sched_get_priority_min(policy
), 
1124         prio 
= m_internal
->GetPriority(); 
1126     if ( min_prio 
== -1 || max_prio 
== -1 ) 
1128         wxLogError(_("Cannot get priority range for scheduling policy %d."), 
1131     else if ( max_prio 
== min_prio 
) 
1133         if ( prio 
!= WXTHREAD_DEFAULT_PRIORITY 
) 
1135             // notify the programmer that this doesn't work here 
1136             wxLogWarning(_("Thread priority setting is ignored.")); 
1138         //else: we have default priority, so don't complain 
1140         // anyhow, don't do anything because priority is just ignored 
1144         struct sched_param sp
; 
1145         if ( pthread_attr_getschedparam(&attr
, &sp
) != 0 ) 
1147             wxFAIL_MSG(_T("pthread_attr_getschedparam() failed")); 
1150         sp
.sched_priority 
= min_prio 
+ (prio
*(max_prio 
- min_prio
))/100; 
1152         if ( pthread_attr_setschedparam(&attr
, &sp
) != 0 ) 
1154             wxFAIL_MSG(_T("pthread_attr_setschedparam(priority) failed")); 
1157 #endif // HAVE_THREAD_PRIORITY_FUNCTIONS 
1159 #ifdef HAVE_PTHREAD_ATTR_SETSCOPE 
1160     // this will make the threads created by this process really concurrent 
1161     if ( pthread_attr_setscope(&attr
, PTHREAD_SCOPE_SYSTEM
) != 0 ) 
1163         wxFAIL_MSG(_T("pthread_attr_setscope(PTHREAD_SCOPE_SYSTEM) failed")); 
1165 #endif // HAVE_PTHREAD_ATTR_SETSCOPE 
1167     // VZ: assume that this one is always available (it's rather fundamental), 
1168     //     if this function is ever missing we should try to use 
1169     //     pthread_detach() instead (after thread creation) 
1172         if ( pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
) != 0 ) 
1174             wxFAIL_MSG(_T("pthread_attr_setdetachstate(DETACHED) failed")); 
1177         // never try to join detached threads 
1178         m_internal
->Detach(); 
1180     //else: threads are created joinable by default, it's ok 
1182     // create the new OS thread object 
1183     int rc 
= pthread_create
 
1185                 m_internal
->GetIdPtr(), 
1191     if ( pthread_attr_destroy(&attr
) != 0 ) 
1193         wxFAIL_MSG(_T("pthread_attr_destroy() failed")); 
1198         m_internal
->SetState(STATE_EXITED
); 
1200         return wxTHREAD_NO_RESOURCE
; 
1203     return wxTHREAD_NO_ERROR
; 
1206 wxThreadError 
wxThread::Run() 
1208     wxCriticalSectionLocker 
lock(m_critsect
); 
1210     wxCHECK_MSG( m_internal
->GetId(), wxTHREAD_MISC_ERROR
, 
1211                  wxT("must call wxThread::Create() first") ); 
1213     return m_internal
->Run(); 
1216 // ----------------------------------------------------------------------------- 
1218 // ----------------------------------------------------------------------------- 
1220 void wxThread::SetPriority(unsigned int prio
) 
1222     wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY 
<= (int)prio
) && 
1223                  ((int)prio 
<= (int)WXTHREAD_MAX_PRIORITY
), 
1224                  wxT("invalid thread priority") ); 
1226     wxCriticalSectionLocker 
lock(m_critsect
); 
1228     switch ( m_internal
->GetState() ) 
1231             // thread not yet started, priority will be set when it is 
1232             m_internal
->SetPriority(prio
); 
1237 #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS 
1238 #if defined(__LINUX__) 
1239             // On Linux, pthread_setschedparam with SCHED_OTHER does not allow 
1240             // a priority other than 0.  Instead, we use the BSD setpriority 
1241             // which alllows us to set a 'nice' value between 20 to -20.  Only 
1242             // super user can set a value less than zero (more negative yields 
1243             // higher priority).  setpriority set the static priority of a 
1244             // process, but this is OK since Linux is configured as a thread 
1247             // FIXME this is not true for 2.6!! 
1249             // map wx priorites WXTHREAD_MIN_PRIORITY..WXTHREAD_MAX_PRIORITY 
1250             // to Unix priorities 20..-20 
1251             if ( setpriority(PRIO_PROCESS
, 0, -(2*prio
)/5 + 20) == -1 ) 
1253                 wxLogError(_("Failed to set thread priority %d."), prio
); 
1257                 struct sched_param sparam
; 
1258                 sparam
.sched_priority 
= prio
; 
1260                 if ( pthread_setschedparam(m_internal
->GetId(), 
1261                                            SCHED_OTHER
, &sparam
) != 0 ) 
1263                     wxLogError(_("Failed to set thread priority %d."), prio
); 
1267 #endif // HAVE_THREAD_PRIORITY_FUNCTIONS 
1272             wxFAIL_MSG(wxT("impossible to set thread priority in this state")); 
1276 unsigned int wxThread::GetPriority() const 
1278     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1280     return m_internal
->GetPriority(); 
1283 wxThreadIdType 
wxThread::GetId() const 
1285     return (wxThreadIdType
) m_internal
->GetId(); 
1288 // ----------------------------------------------------------------------------- 
1290 // ----------------------------------------------------------------------------- 
1292 wxThreadError 
wxThread::Pause() 
1294     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1295                  _T("a thread can't pause itself") ); 
1297     wxCriticalSectionLocker 
lock(m_critsect
); 
1299     if ( m_internal
->GetState() != STATE_RUNNING 
) 
1301         wxLogDebug(wxT("Can't pause thread which is not running.")); 
1303         return wxTHREAD_NOT_RUNNING
; 
1306     // just set a flag, the thread will be really paused only during the next 
1307     // call to TestDestroy() 
1308     m_internal
->SetState(STATE_PAUSED
); 
1310     return wxTHREAD_NO_ERROR
; 
1313 wxThreadError 
wxThread::Resume() 
1315     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1316                  _T("a thread can't resume itself") ); 
1318     wxCriticalSectionLocker 
lock(m_critsect
); 
1320     wxThreadState state 
= m_internal
->GetState(); 
1325             wxLogTrace(TRACE_THREADS
, _T("Thread %ld suspended, resuming."), 
1328             m_internal
->Resume(); 
1330             return wxTHREAD_NO_ERROR
; 
1333             wxLogTrace(TRACE_THREADS
, _T("Thread %ld exited, won't resume."), 
1335             return wxTHREAD_NO_ERROR
; 
1338             wxLogDebug(_T("Attempt to resume a thread which is not paused.")); 
1340             return wxTHREAD_MISC_ERROR
; 
1344 // ----------------------------------------------------------------------------- 
1346 // ----------------------------------------------------------------------------- 
1348 wxThread::ExitCode 
wxThread::Wait() 
1350     wxCHECK_MSG( This() != this, (ExitCode
)-1, 
1351                  _T("a thread can't wait for itself") ); 
1353     wxCHECK_MSG( !m_isDetached
, (ExitCode
)-1, 
1354                  _T("can't wait for detached thread") ); 
1358     return m_internal
->GetExitCode(); 
1361 wxThreadError 
wxThread::Delete(ExitCode 
*rc
) 
1363     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1364                  _T("a thread can't delete itself") ); 
1366     bool isDetached 
= m_isDetached
; 
1369     wxThreadState state 
= m_internal
->GetState(); 
1371     // ask the thread to stop 
1372     m_internal
->SetCancelFlag(); 
1379             // we need to wake up the thread so that PthreadStart() will 
1380             // terminate - right now it's blocking on run semaphore in 
1382             m_internal
->SignalRun(); 
1391             // resume the thread first 
1392             m_internal
->Resume(); 
1399                 // wait until the thread stops 
1404                     // return the exit code of the thread 
1405                     *rc 
= m_internal
->GetExitCode(); 
1408             //else: can't wait for detached threads 
1411     return wxTHREAD_NO_ERROR
; 
1414 wxThreadError 
wxThread::Kill() 
1416     wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR
, 
1417                  _T("a thread can't kill itself") ); 
1419     switch ( m_internal
->GetState() ) 
1423             return wxTHREAD_NOT_RUNNING
; 
1426             // resume the thread first 
1432 #ifdef HAVE_PTHREAD_CANCEL 
1433             if ( pthread_cancel(m_internal
->GetId()) != 0 ) 
1434 #endif // HAVE_PTHREAD_CANCEL 
1436                 wxLogError(_("Failed to terminate a thread.")); 
1438                 return wxTHREAD_MISC_ERROR
; 
1441 #ifdef HAVE_PTHREAD_CANCEL 
1444                 // if we use cleanup function, this will be done from 
1445                 // wxPthreadCleanup() 
1446 #ifndef wxHAVE_PTHREAD_CLEANUP 
1447                 ScheduleThreadForDeletion(); 
1449                 // don't call OnExit() here, it can only be called in the 
1450                 // threads context and we're in the context of another thread 
1453 #endif // wxHAVE_PTHREAD_CLEANUP 
1457                 m_internal
->SetExitCode(EXITCODE_CANCELLED
); 
1460             return wxTHREAD_NO_ERROR
; 
1461 #endif // HAVE_PTHREAD_CANCEL 
1465 void wxThread::Exit(ExitCode status
) 
1467     wxASSERT_MSG( This() == this, 
1468                   _T("wxThread::Exit() can only be called in the context of the same thread") ); 
1472         // from the moment we call OnExit(), the main program may terminate at 
1473         // any moment, so mark this thread as being already in process of being 
1474         // deleted or wxThreadModule::OnExit() will try to delete it again 
1475         ScheduleThreadForDeletion(); 
1478     // don't enter m_critsect before calling OnExit() because the user code 
1479     // might deadlock if, for example, it signals a condition in OnExit() (a 
1480     // common case) while the main thread calls any of functions entering 
1481     // m_critsect on us (almost all of them do) 
1484     // delete C++ thread object if this is a detached thread - user is 
1485     // responsible for doing this for joinable ones 
1488         // FIXME I'm feeling bad about it - what if another thread function is 
1489         //       called (in another thread context) now? It will try to access 
1490         //       half destroyed object which will probably result in something 
1491         //       very bad - but we can't protect this by a crit section unless 
1492         //       we make it a global object, but this would mean that we can 
1493         //       only call one thread function at a time :-( 
1495         pthread_setspecific(gs_keySelf
, 0); 
1500         m_internal
->SetState(STATE_EXITED
); 
1504     // terminate the thread (pthread_exit() never returns) 
1505     pthread_exit(status
); 
1507     wxFAIL_MSG(_T("pthread_exit() failed")); 
1510 // also test whether we were paused 
1511 bool wxThread::TestDestroy() 
1513     wxASSERT_MSG( This() == this, 
1514                   _T("wxThread::TestDestroy() can only be called in the context of the same thread") ); 
1518     if ( m_internal
->GetState() == STATE_PAUSED 
) 
1520         m_internal
->SetReallyPaused(true); 
1522         // leave the crit section or the other threads will stop too if they 
1523         // try to call any of (seemingly harmless) IsXXX() functions while we 
1527         m_internal
->Pause(); 
1531         // thread wasn't requested to pause, nothing to do 
1535     return m_internal
->WasCancelled(); 
1538 wxThread::~wxThread() 
1543     // check that the thread either exited or couldn't be created 
1544     if ( m_internal
->GetState() != STATE_EXITED 
&& 
1545          m_internal
->GetState() != STATE_NEW 
) 
1547         wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), 
1552 #endif // __WXDEBUG__ 
1556     // remove this thread from the global array 
1558         wxMutexLocker 
lock(*gs_mutexAllThreads
); 
1560         gs_allThreads
.Remove(this); 
1564 // ----------------------------------------------------------------------------- 
1566 // ----------------------------------------------------------------------------- 
1568 bool wxThread::IsRunning() const 
1570     wxCriticalSectionLocker 
lock((wxCriticalSection 
&)m_critsect
); 
1572     return m_internal
->GetState() == STATE_RUNNING
; 
1575 bool wxThread::IsAlive() const 
1577     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1579     switch ( m_internal
->GetState() ) 
1590 bool wxThread::IsPaused() const 
1592     wxCriticalSectionLocker 
lock((wxCriticalSection
&)m_critsect
); 
1594     return (m_internal
->GetState() == STATE_PAUSED
); 
1597 //-------------------------------------------------------------------- 
1599 //-------------------------------------------------------------------- 
1601 class wxThreadModule 
: public wxModule
 
1604     virtual bool OnInit(); 
1605     virtual void OnExit(); 
1608     DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
1611 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
) 
1613 bool wxThreadModule::OnInit() 
1615     int rc 
= pthread_key_create(&gs_keySelf
, NULL 
/* dtor function */); 
1618         wxLogSysError(rc
, _("Thread module initialization failed: failed to create thread key")); 
1623     gs_tidMain 
= pthread_self(); 
1625     gs_mutexAllThreads 
= new wxMutex(); 
1627     gs_mutexGui 
= new wxMutex(); 
1628     gs_mutexGui
->Lock(); 
1630     gs_mutexDeleteThread 
= new wxMutex(); 
1631     gs_condAllDeleted 
= new wxCondition(*gs_mutexDeleteThread
); 
1636 void wxThreadModule::OnExit() 
1638     wxASSERT_MSG( wxThread::IsMain(), wxT("only main thread can be here") ); 
1640     // are there any threads left which are being deleted right now? 
1641     size_t nThreadsBeingDeleted
; 
1644         wxMutexLocker 
lock( *gs_mutexDeleteThread 
); 
1645         nThreadsBeingDeleted 
= gs_nThreadsBeingDeleted
; 
1647         if ( nThreadsBeingDeleted 
> 0 ) 
1649             wxLogTrace(TRACE_THREADS
, 
1650                        _T("Waiting for %lu threads to disappear"), 
1651                        (unsigned long)nThreadsBeingDeleted
); 
1653             // have to wait until all of them disappear 
1654             gs_condAllDeleted
->Wait(); 
1661         wxMutexLocker 
lock(*gs_mutexAllThreads
); 
1663         // terminate any threads left 
1664         count 
= gs_allThreads
.GetCount(); 
1667             wxLogDebug(wxT("%lu threads were not terminated by the application."), 
1668                        (unsigned long)count
); 
1670     } // unlock mutex before deleting the threads as they lock it in their dtor 
1672     for ( size_t n 
= 0u; n 
< count
; n
++ ) 
1674         // Delete calls the destructor which removes the current entry. We 
1675         // should only delete the first one each time. 
1676         gs_allThreads
[0]->Delete(); 
1679     delete gs_mutexAllThreads
; 
1681     // destroy GUI mutex 
1682     gs_mutexGui
->Unlock(); 
1685     // and free TLD slot 
1686     (void)pthread_key_delete(gs_keySelf
); 
1688     delete gs_condAllDeleted
; 
1689     delete gs_mutexDeleteThread
; 
1692 // ---------------------------------------------------------------------------- 
1694 // ---------------------------------------------------------------------------- 
1696 static void ScheduleThreadForDeletion() 
1698     wxMutexLocker 
lock( *gs_mutexDeleteThread 
); 
1700     gs_nThreadsBeingDeleted
++; 
1702     wxLogTrace(TRACE_THREADS
, _T("%lu thread%s waiting to be deleted"), 
1703                (unsigned long)gs_nThreadsBeingDeleted
, 
1704                gs_nThreadsBeingDeleted 
== 1 ? "" : "s"); 
1707 static void DeleteThread(wxThread 
*This
) 
1709     // gs_mutexDeleteThread should be unlocked before signalling the condition 
1710     // or wxThreadModule::OnExit() would deadlock 
1711     wxMutexLocker 
locker( *gs_mutexDeleteThread 
); 
1713     wxLogTrace(TRACE_THREADS
, _T("Thread %ld auto deletes."), This
->GetId()); 
1717     wxCHECK_RET( gs_nThreadsBeingDeleted 
> 0, 
1718                  _T("no threads scheduled for deletion, yet we delete one?") ); 
1720     wxLogTrace(TRACE_THREADS
, _T("%lu scheduled for deletion threads left."), 
1721                (unsigned long)gs_nThreadsBeingDeleted 
- 1); 
1723     if ( !--gs_nThreadsBeingDeleted 
) 
1725         // no more threads left, signal it 
1726         gs_condAllDeleted
->Signal(); 
1730 void wxMutexGuiEnter() 
1732     gs_mutexGui
->Lock(); 
1735 void wxMutexGuiLeave() 
1737     gs_mutexGui
->Unlock(); 
1740 // ---------------------------------------------------------------------------- 
1741 // include common implementation code 
1742 // ---------------------------------------------------------------------------- 
1744 #include "wx/thrimpl.cpp" 
1746 #endif // wxUSE_THREADS