+ULONG wxThreadInternal::OS2ThreadStart(
+  wxThread*                         pThread
+)
+{
+    m_pThread = pThread;
+
+    DWORD                           dwRet = (DWORD)pThread->Entry();
+
+    // enter m_critsect before changing the thread state
+    pThread->m_critsect.Enter();
+
+    bool                            bWasCancelled = pThread->m_internal->GetState() == STATE_CANCELED;
+
+    pThread->m_internal->SetState(STATE_EXITED);
+    pThread->m_critsect.Leave();
+
+    pThread->OnExit();
+
+    // if the thread was cancelled (from Delete()), then it the handle is still
+    // needed there
+    if (pThread->IsDetached() && !bWasCancelled)
+    {
+        // auto delete
+        delete pThread;
+    }
+    //else: the joinable threads handle will be closed when Wait() is done
+    return dwRet;
+}
+
+void wxThreadInternal::SetPriority(
+  unsigned int                      nPriority
+)
+{
+    // translate wxWindows priority to the PM one
+    ULONG                           ulOS2_Priority;
+    ULONG                           ulrc;
+
+    m_nPriority = nPriority;
+
+    if (m_nPriority <= 20)
+        ulOS2_Priority = PRTYC_NOCHANGE;
+    else if (m_nPriority <= 40)
+        ulOS2_Priority = PRTYC_IDLETIME;
+    else if (m_nPriority <= 60)
+        ulOS2_Priority = PRTYC_REGULAR;
+    else if (m_nPriority <= 80)
+        ulOS2_Priority = PRTYC_TIMECRITICAL;
+    else if (m_nPriority <= 100)
+        ulOS2_Priority = PRTYC_FOREGROUNDSERVER;
+    else
+    {
+        wxFAIL_MSG(wxT("invalid value of thread priority parameter"));
+        ulOS2_Priority = PRTYC_REGULAR;
+    }
+    ulrc = ::DosSetPriority( PRTYS_THREAD
+                            ,ulOS2_Priority
+                            ,0
+                            ,(ULONG)m_hThread
+                           );
+    if (ulrc != 0)
+    {
+        wxLogSysError(_("Can't set thread priority"));
+    }
+}
+
+bool wxThreadInternal::Create(
+  wxThread*                         pThread
+)
+{
+    APIRET                          ulrc;
+
+    ulrc = ::DosCreateThread( &m_hThread
+                             ,(PFNTHREAD)wxThreadInternal::OS2ThreadStart
+                             ,(ULONG)pThread
+                             ,CREATE_SUSPENDED | STACK_SPARSE
+                             ,8192L
+                            );
+    if(ulrc != 0)
+    {
+        wxLogSysError(_("Can't create thread"));
+
+        return FALSE;
+    }
+    if (m_nPriority != WXTHREAD_DEFAULT_PRIORITY)
+    {
+        SetPriority(m_nPriority);
+    }
+    return(TRUE);
+}
+
+bool wxThreadInternal::Suspend()
+{
+    ULONG                           ulrc = ::DosSuspendThread(m_hThread);
+
+    if (ulrc != 0)
+    {
+        wxLogSysError(_("Can not suspend thread %lu"), m_hThread);
+        return FALSE;
+    }
+    m_eState = STATE_PAUSED;
+    return TRUE;
+}
+
+bool wxThreadInternal::Resume()
+{
+    ULONG                           ulrc = ::DosResumeThread(m_hThread);
+
+    if (ulrc != 0)
+    {
+        wxLogSysError(_("Can not suspend thread %lu"), m_hThread);
+        return FALSE;
+    }
+    m_eState = STATE_PAUSED;
+    return TRUE;
+}
+
+// static functions
+// ----------------
+
+wxThread *wxThread::This()
+{
+    wxThread*                       pThread = m_pThread;
+    return pThread;
+}
+
+bool wxThread::IsMain()
+{
+    PTIB                            ptib;
+    PPIB                            ppib;
+
+    ::DosGetInfoBlocks(&ptib, &ppib);
+
+    if (ptib->tib_ptib2->tib2_ultid == s_ulIdMainThread)
+        return TRUE;
+    return FALSE;
+}
+
+#ifdef Yield
+    #undef Yield
+#endif
+
+void wxThread::Yield()
+{
+    ::DosSleep(0);
+}
+
+void wxThread::Sleep(
+  unsigned long                     ulMilliseconds
+)
+{
+    ::DosSleep(ulMilliseconds);
+}
+
+// ctor and dtor
+// -------------
+
+wxThread::wxThread(wxThreadKind kind)
+{
+    m_internal = new wxThreadInternal();
+
+    m_isDetached = kind == wxTHREAD_DETACHED;
+}
+
+wxThread::~wxThread()
+{
+    delete m_internal;
+}
+
+// create/start thread
+// -------------------
+