X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ef4f69ec32a1562734222d3839122a496411fce2..fcdbeefa4e1f033a8c1d0e2a0d4fb521e5e47450:/src/unix/threadpsx.cpp diff --git a/src/unix/threadpsx.cpp b/src/unix/threadpsx.cpp index 2c68b71db9..2eb63474f9 100644 --- a/src/unix/threadpsx.cpp +++ b/src/unix/threadpsx.cpp @@ -21,10 +21,6 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "thread.h" -#endif - // for compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -37,13 +33,14 @@ #include "wx/intl.h" #include "wx/dynarray.h" #include "wx/timer.h" +#include "wx/stopwatch.h" #include #include #include #include #include -#if HAVE_SCHED_H +#ifdef HAVE_SCHED_H #include #endif @@ -99,7 +96,7 @@ static void DeleteThread(wxThread *This); // ---------------------------------------------------------------------------- // an (non owning) array of pointers to threads -WX_DEFINE_ARRAY(wxThread *, wxArrayThread); +WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread); // an entry for a thread we can wait for @@ -113,7 +110,7 @@ WX_DEFINE_ARRAY(wxThread *, wxArrayThread); static wxArrayThread gs_allThreads; // the id of the main thread -static pthread_t gs_tidMain; +static pthread_t gs_tidMain = (pthread_t)-1; // the key for the pointer to the associated wxThread object static pthread_key_t gs_keySelf; @@ -173,7 +170,8 @@ private: friend class wxConditionInternal; }; -#ifdef HAVE_PTHREAD_MUTEXATTR_T +#if defined(HAVE_PTHREAD_MUTEXATTR_T) && \ + wxUSE_UNIX && !defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE_DECL) // on some systems pthread_mutexattr_settype() is not in the headers (but it is // in the library, otherwise we wouldn't compile this code at all) extern "C" int pthread_mutexattr_settype(pthread_mutexattr_t *, int); @@ -501,14 +499,14 @@ wxSemaError wxSemaphoreInternal::Wait() while ( m_count == 0 ) { wxLogTrace(TRACE_SEMA, - "Thread %ld waiting for semaphore to become signalled", + _T("Thread %ld waiting for semaphore to become signalled"), wxThread::GetCurrentId()); if ( m_cond.Wait() != wxCOND_NO_ERROR ) return wxSEMA_MISC_ERROR; wxLogTrace(TRACE_SEMA, - "Thread %ld finished waiting for semaphore, count = %lu", + _T("Thread %ld finished waiting for semaphore, count = %lu"), wxThread::GetCurrentId(), (unsigned long)m_count); } @@ -575,7 +573,7 @@ wxSemaError wxSemaphoreInternal::Post() m_count++; wxLogTrace(TRACE_SEMA, - "Thread %ld about to signal semaphore, count = %lu", + _T("Thread %ld about to signal semaphore, count = %lu"), wxThread::GetCurrentId(), (unsigned long)m_count); return m_cond.Signal() == wxCOND_NO_ERROR ? wxSEMA_NO_ERROR @@ -590,10 +588,10 @@ wxSemaError wxSemaphoreInternal::Post() extern "C" { -#if HAVE_THREAD_CLEANUP_FUNCTIONS +#ifdef wxHAVE_PTHREAD_CLEANUP // thread exit function void wxPthreadCleanup(void *ptr); -#endif // HAVE_THREAD_CLEANUP_FUNCTIONS +#endif // wxHAVE_PTHREAD_CLEANUP void *wxPthreadStart(void *ptr); @@ -670,15 +668,15 @@ public: m_isDetached = TRUE; } -#if HAVE_THREAD_CLEANUP_FUNCTIONS +#ifdef wxHAVE_PTHREAD_CLEANUP // this is used by wxPthreadCleanup() only static void Cleanup(wxThread *thread); -#endif // HAVE_THREAD_CLEANUP_FUNCTIONS +#endif // wxHAVE_PTHREAD_CLEANUP private: pthread_t m_threadId; // id of the thread wxThreadState m_state; // see wxThreadState enum - int m_prio; // in wxWindows units: from 0 to 100 + int m_prio; // in wxWidgets units: from 0 to 100 // this flag is set when the thread should terminate bool m_cancelled; @@ -734,11 +732,11 @@ void *wxThreadInternal::PthreadStart(wxThread *thread) // block! bool dontRunAtAll; -#if HAVE_THREAD_CLEANUP_FUNCTIONS +#ifdef wxHAVE_PTHREAD_CLEANUP // install the cleanup handler which will be called if the thread is // cancelled pthread_cleanup_push(wxPthreadCleanup, thread); -#endif // HAVE_THREAD_CLEANUP_FUNCTIONS +#endif // wxHAVE_PTHREAD_CLEANUP // wait for the semaphore to be posted from Run() pthread->m_semRun.Wait(); @@ -763,7 +761,7 @@ void *wxThreadInternal::PthreadStart(wxThread *thread) wxLogTrace(TRACE_THREADS, _T("Thread %ld Entry() returned %lu."), - THR_ID(pthread), (unsigned long)pthread->m_exitcode); + THR_ID(pthread), wxPtrToUInt(pthread->m_exitcode)); { wxCriticalSectionLocker lock(thread->m_critsect); @@ -775,13 +773,22 @@ void *wxThreadInternal::PthreadStart(wxThread *thread) } } - // NB: at least under Linux, pthread_cleanup_push/pop are macros and pop - // contains the matching '}' for the '{' in push, so they must be used - // in the same block! -#if HAVE_THREAD_CLEANUP_FUNCTIONS + // NB: pthread_cleanup_push/pop() are macros and pop contains the matching + // '}' for the '{' in push, so they must be used in the same block! +#ifdef wxHAVE_PTHREAD_CLEANUP + #ifdef __DECCXX + // under Tru64 we get a warning from macro expansion + #pragma message save + #pragma message disable(declbutnotref) + #endif + // remove the cleanup handler without executing it pthread_cleanup_pop(FALSE); -#endif // HAVE_THREAD_CLEANUP_FUNCTIONS + + #ifdef __DECCXX + #pragma message restore + #endif +#endif // wxHAVE_PTHREAD_CLEANUP if ( dontRunAtAll ) { @@ -801,7 +808,7 @@ void *wxThreadInternal::PthreadStart(wxThread *thread) } } -#if HAVE_THREAD_CLEANUP_FUNCTIONS +#ifdef wxHAVE_PTHREAD_CLEANUP // this handler is called when the thread is cancelled extern "C" void wxPthreadCleanup(void *ptr) @@ -824,7 +831,7 @@ void wxThreadInternal::Cleanup(wxThread *thread) thread->Exit(EXITCODE_CANCELLED); } -#endif // HAVE_THREAD_CLEANUP_FUNCTIONS +#endif // wxHAVE_PTHREAD_CLEANUP // ---------------------------------------------------------------------------- // wxThreadInternal @@ -893,8 +900,7 @@ void wxThreadInternal::Wait() // wxLogDebug: it is possible to bring the system to its knees // by creating too many threads and not joining them quite // easily - wxLogError(_("Failed to join a thread, potential memory leak " - "detected - please restart the program")); + wxLogError(_("Failed to join a thread, potential memory leak detected - please restart the program")); } m_shouldBeJoined = FALSE; @@ -958,7 +964,7 @@ wxThread *wxThread::This() bool wxThread::IsMain() { - return (bool)pthread_equal(pthread_self(), gs_tidMain); + return (bool)pthread_equal(pthread_self(), gs_tidMain) || gs_tidMain == (pthread_t)-1; } void wxThread::Yield() @@ -970,7 +976,7 @@ void wxThread::Yield() void wxThread::Sleep(unsigned long milliseconds) { - wxUsleep(milliseconds); + wxMilliSleep(milliseconds); } int wxThread::GetCPUCount() @@ -1062,7 +1068,13 @@ wxThread::wxThread(wxThreadKind kind) m_isDetached = kind == wxTHREAD_DETACHED; } -wxThreadError wxThread::Create(unsigned int WXUNUSED(stackSize)) +#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE + #define WXUNUSED_STACKSIZE(identifier) identifier +#else + #define WXUNUSED_STACKSIZE(identifier) WXUNUSED(identifier) +#endif + +wxThreadError wxThread::Create(unsigned int WXUNUSED_STACKSIZE(stackSize)) { if ( m_internal->GetState() != STATE_NEW ) { @@ -1074,6 +1086,11 @@ wxThreadError wxThread::Create(unsigned int WXUNUSED(stackSize)) pthread_attr_t attr; pthread_attr_init(&attr); +#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE + if (stackSize) + pthread_attr_setstacksize(&attr, stackSize); +#endif + #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS int policy; if ( pthread_attr_getschedpolicy(&attr, &policy) != 0 ) @@ -1208,42 +1225,21 @@ void wxThread::SetPriority(unsigned int prio) case STATE_PAUSED: #ifdef HAVE_THREAD_PRIORITY_FUNCTIONS #if defined(__LINUX__) -// On Linux, pthread_setschedparam with SCHED_OTHER does not allow -// a priority other than 0. Instead, we use the BSD setpriority -// which alllows us to set a 'nice' value between 20 to -20. Only -// super user can set a value less than zero (more negative yields -// higher priority). setpriority set the static priority of a process, -// but this is OK since Linux is configured as a thread per process. - { - float fPrio; - float pSpan; - int iPrio; - - // Map Wx priorites (WXTHREAD_MIN_PRIORITY - - // WXTHREAD_MAX_PRIORITY) into BSD priorities (20 - -20). - // Do calculation of values instead of hard coding them - // to make maintenance easier. - - pSpan = ((float)(WXTHREAD_MAX_PRIORITY - WXTHREAD_MIN_PRIORITY)) / 2.0; - - // prio starts as ................... // value => (0) >= p <= (n) - - fPrio = ((float)prio) - pSpan; // value => (-n) >= p <= (+n) - - fPrio = 0.0 - fPrio; // value => (+n) <= p >= (-n) - - fPrio = fPrio * (20. / pSpan) + .5; // value => (20) <= p >= (-20) - - iPrio = (int)fPrio; - - // Clamp prio from 20 - -20; - iPrio = (iPrio > 20) ? 20 : iPrio; - iPrio = (iPrio < -20) ? -20 : iPrio; + // On Linux, pthread_setschedparam with SCHED_OTHER does not allow + // a priority other than 0. Instead, we use the BSD setpriority + // which alllows us to set a 'nice' value between 20 to -20. Only + // super user can set a value less than zero (more negative yields + // higher priority). setpriority set the static priority of a + // process, but this is OK since Linux is configured as a thread + // per process. + // + // FIXME this is not true for 2.6!! - if (setpriority(PRIO_PROCESS, 0, iPrio) == -1) - { - wxLogError(_("Failed to set thread priority %d."), prio); - } + // map wx priorites WXTHREAD_MIN_PRIORITY..WXTHREAD_MAX_PRIORITY + // to Unix priorities 20..-20 + if ( setpriority(PRIO_PROCESS, 0, -(2*prio)/5 + 20) == -1 ) + { + wxLogError(_("Failed to set thread priority %d."), prio); } #else // __LINUX__ { @@ -1424,25 +1420,26 @@ wxThreadError wxThread::Kill() default: #ifdef HAVE_PTHREAD_CANCEL if ( pthread_cancel(m_internal->GetId()) != 0 ) -#endif +#endif // HAVE_PTHREAD_CANCEL { wxLogError(_("Failed to terminate a thread.")); return wxTHREAD_MISC_ERROR; } +#ifdef HAVE_PTHREAD_CANCEL if ( m_isDetached ) { // if we use cleanup function, this will be done from // wxPthreadCleanup() -#if !HAVE_THREAD_CLEANUP_FUNCTIONS +#ifndef wxHAVE_PTHREAD_CLEANUP ScheduleThreadForDeletion(); // don't call OnExit() here, it can only be called in the // threads context and we're in the context of another thread DeleteThread(this); -#endif // HAVE_THREAD_CLEANUP_FUNCTIONS +#endif // wxHAVE_PTHREAD_CLEANUP } else { @@ -1450,14 +1447,14 @@ wxThreadError wxThread::Kill() } return wxTHREAD_NO_ERROR; +#endif // HAVE_PTHREAD_CANCEL } } void wxThread::Exit(ExitCode status) { wxASSERT_MSG( This() == this, - _T("wxThread::Exit() can only be called in the " - "context of the same thread") ); + _T("wxThread::Exit() can only be called in the context of the same thread") ); if ( m_isDetached ) { @@ -1485,6 +1482,12 @@ void wxThread::Exit(ExitCode status) // only call one thread function at a time :-( DeleteThread(this); } + else + { + m_critsect.Enter(); + m_internal->SetState(STATE_EXITED); + m_critsect.Leave(); + } // terminate the thread (pthread_exit() never returns) pthread_exit(status); @@ -1496,8 +1499,7 @@ void wxThread::Exit(ExitCode status) bool wxThread::TestDestroy() { wxASSERT_MSG( This() == this, - _T("wxThread::TestDestroy() can only be called in the " - "context of the same thread") ); + _T("wxThread::TestDestroy() can only be called in the context of the same thread") ); m_critsect.Enter(); @@ -1530,8 +1532,8 @@ wxThread::~wxThread() if ( m_internal->GetState() != STATE_EXITED && m_internal->GetState() != STATE_NEW ) { - wxLogDebug(_T("The thread %ld is being destroyed although it is still " - "running! The application may crash."), GetId()); + wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), + (long)GetId()); } m_critsect.Leave(); @@ -1597,8 +1599,7 @@ bool wxThreadModule::OnInit() int rc = pthread_key_create(&gs_keySelf, NULL /* dtor function */); if ( rc != 0 ) { - wxLogSysError(rc, _("Thread module initialization failed: " - "failed to create thread key")); + wxLogSysError(rc, _("Thread module initialization failed: failed to create thread key")); return FALSE; }