Mercurial > flash_v2
diff host/tools/Utils/common/eCosThreadUtils.cpp @ 76:435cced73e2f ecos-v1_3_1-release
eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST
| author | jlarmour |
|---|---|
| date | Tue, 28 Mar 2000 14:10:45 +0000 |
| parents | |
| children | 6736c52df507 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/host/tools/Utils/common/eCosThreadUtils.cpp @@ -0,0 +1,247 @@ +//####COPYRIGHTBEGIN#### +// +// ---------------------------------------------------------------------------- +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// +// This program is part of the eCos host tools. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// ---------------------------------------------------------------------------- +// +//####COPYRIGHTEND#### +#include "eCosThreadUtils.h" +#include "eCosTrace.h" + +CeCosThreadUtils::THREAD_ID CeCosThreadUtils::CS::nCSOwner=(CeCosThreadUtils::THREAD_ID)-1; +int CeCosThreadUtils::CS::m_nCriticalSectionLock=0; +#ifdef _WIN32 + CRITICAL_SECTION CeCosThreadUtils::CS::cs; + bool CeCosThreadUtils::CS::bCSInitialized=false; +#else // UNIX + // Static recursive mutex for unix critical section + #ifndef NO_THREADS + pthread_mutex_t CeCosThreadUtils::CS::cs = PTHREAD_MUTEX_INITIALIZER; + #endif +#endif + + +CeCosThreadUtils::THREAD_ID CeCosThreadUtils::GetThreadId() +{ + return + #ifdef _WIN32 + GetCurrentThreadId(); + #else // UNIX + #ifdef NO_THREADS + 42; + #else + pthread_self(); + #endif + #endif +} + +// Wait for the specified Boolean to turn true or the timeout to occur +// The value of the Boolean is returned as result +bool CeCosThreadUtils::WaitFor (bool &b, Duration dTimeout) +{ + Time t=Now(); + do { + if(b){ + break; + } + Sleep(250); + } while (Now()-t<dTimeout); + return b; +} + +// This function spawns a thread and causes it to run asynchrously. +// The callback may be +// A function, which is called when the thread completes +// A boolean, which is set when the thread completes +// Null, in which case no notification is received of thread completion +// pParam is passed to the thread function pThreadFunc on thread initiation. + +bool CeCosThreadUtils::RunThread(CallbackProc *pThreadFunc, void *pParam, CallbackProc *pCompletionFunc, void *pCompletionParam, LPCTSTR pszName) +{ + TRACE(_T("RunThread %s\n"),pszName); + // Do not spawn a thread while in possession of a mutex + // ENTERCRITICAL; + // VTRACE(_T("csl=%d\n"),CS::m_nCriticalSectionLock); + // assert(1==CS::m_nCriticalSectionLock); + // LEAVECRITICAL; + + ThreadInfo *pInfo=new ThreadInfo(pThreadFunc,pParam,pCompletionFunc,pCompletionParam,pszName); // SThreadFunc will delete + bool rc=false; + +#ifdef _WIN32 + // FIXME: CreateThread incompatible with C runtime calls? + DWORD dwID; + HANDLE hThread=CreateThread(NULL,0,SThreadFunc, pInfo, 0, &dwID); + if(hThread){ + TRACE(_T("RunThread: - new thread=%x\n"),dwID); + ::CloseHandle(hThread); + rc=true; + } else { + ERROR(_T("Failed to create thread\n")); + } +#else // UNIX + #ifdef NO_THREADS + assert(false); + #else + VTRACE(_T("RunThread():Calling pthread_create()\n")); + pthread_t hThread; + int n=pthread_create(&hThread, NULL, SThreadFunc, pInfo); + TRACE( _T("RunThread: - non-blocking call (new thread=%x)\n"),hThread); + VTRACE(_T("RunThread(): pthread_create() returned <%d>\n"), n); + if (n != 0) { + ERROR(_T("RunThread(): pthread_create failed - %s\n"),strerror(errno)); + } else { + + VTRACE(_T("RunThread(): Calling pthread_detach\n")); + int n = pthread_detach(hThread); + + if (0==n) { + rc=true; + } else { + ERROR(_T("RunThread(): pthread_detach failed - %s\n"),strerror(errno)); + hThread=0; + } + } + VTRACE(_T("RunThread(): returned from pthread calls - exiting RunThread()\n")); + #endif +#endif + if(!rc){ + delete pInfo; + } + return rc; + +} + +#ifdef _WIN32 +int CALLBACK CeCosThreadUtils::FilterFunction(EXCEPTION_POINTERS *p) +{ + EXCEPTION_RECORD *pRec =p->ExceptionRecord; + TRACE(_T("!!!Exception!!! address=%08x code=%08x\n"),pRec->ExceptionAddress,pRec->ExceptionCode); + /* + CONTEXT *pContext=p->ContextRecord; + const unsigned char *ESP=(const unsigned char *)pContext->Esp; + for(int i=0;i<16;i++){ + TRACE(_T("%08X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n"),ESP, + ESP[0],ESP[1],ESP[2],ESP[3],ESP[4],ESP[5],ESP[6],ESP[7],ESP[8],ESP[9],ESP[10],ESP[11],ESP[12],ESP[13],ESP[14],ESP[15]); + ESP+=16; + } + */ + return EXCEPTION_EXECUTE_HANDLER; +} +#endif + +CeCosThreadUtils::THREADFUNC CALLBACK CeCosThreadUtils::SThreadFunc (void *pParam) +{ + VTRACE(_T("SThreadFunc()\n")); + ThreadInfo *pInfo=(ThreadInfo*)pParam; +#ifdef _WIN32 + __try { + // Call what we are instructed to (e.g. LocalThreadFunc): + pInfo->pThreadFunc(pInfo->pThreadParam); + } + __except ( CeCosThreadUtils::FilterFunction(GetExceptionInformation() )) + { + TRACE(_T("Handling exception!!!...\n")); + } +#else // UNIX + try { + // Call what we are instructed to (e.g. LocalThreadFunc): + pInfo->pThreadFunc(pInfo->pThreadParam); + } + catch (...){ + TRACE(_T("Exception caught in SThreadFunc!!!\n")); + } +#endif + + // Call the Callback: + TRACE(_T("SThreadFunc - invoking callback\n")); + if(pInfo->pCompletionFunc){ + pInfo->pCompletionFunc (pInfo->pCompletionParam); + } else if (pInfo->pCompletionParam) { + // No function - just a flag: + *(bool *)pInfo->pCompletionParam=true; + } + // No more references to pInfo->pTest from now on... + VTRACE(_T("SThreadFunc(): deleting (ThreadInfo)pInfo\n")); + delete pInfo; + TRACE(_T("SThreadFunc exiting\n")); + return 0; +} + +int CeCosThreadUtils::CS::AtomicIncrement (int &n) +{ + int rc; + ENTERCRITICAL; + rc=n++; + LEAVECRITICAL; + return rc; +} + +int CeCosThreadUtils::CS::AtomicDecrement (int &n) +{ + int rc; + ENTERCRITICAL; + rc=n--; + LEAVECRITICAL; + return rc; +} + +CeCosThreadUtils::CS::CS() +{ + // Get mutex lock; block until available unless current + // thread already owns the mutex. + if(GetThreadId()!=nCSOwner){ + VTRACE(_T("%x try CS\n"),GetThreadId()); +#ifdef _WIN32 + if(!bCSInitialized){ + InitializeCriticalSection(&cs); + bCSInitialized=true; + } + ::EnterCriticalSection(&cs); +#else // UNIX + #ifndef NO_THREADS + pthread_mutex_lock(&cs); + #endif +#endif + nCSOwner=GetThreadId(); + VTRACE(_T("%x has CS count=%d\n"),GetThreadId(),m_nCriticalSectionLock);//sdf + } + m_nCriticalSectionLock++; +} + +CeCosThreadUtils::CS::~CS() +{ + m_nCriticalSectionLock--; + assert(m_nCriticalSectionLock>=0); + if(0==m_nCriticalSectionLock){ + nCSOwner=(THREAD_ID)-1; + VTRACE(_T("%x leaves CS count=%d\n"),GetThreadId(),m_nCriticalSectionLock); + + // Release mutex lock. +#ifdef _WIN32 + ::LeaveCriticalSection(&cs); +#else // UNIX + #ifndef NO_THREADS + pthread_mutex_unlock(&cs); + #endif +#endif + } +} +
