Mercurial > ecos
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 75:41bf073c0c32 | 76:435cced73e2f |
|---|---|
| 1 //####COPYRIGHTBEGIN#### | |
| 2 // | |
| 3 // ---------------------------------------------------------------------------- | |
| 4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. | |
| 5 // | |
| 6 // This program is part of the eCos host tools. | |
| 7 // | |
| 8 // This program is free software; you can redistribute it and/or modify it | |
| 9 // under the terms of the GNU General Public License as published by the Free | |
| 10 // Software Foundation; either version 2 of the License, or (at your option) | |
| 11 // any later version. | |
| 12 // | |
| 13 // This program is distributed in the hope that it will be useful, but WITHOUT | |
| 14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
| 16 // more details. | |
| 17 // | |
| 18 // You should have received a copy of the GNU General Public License along with | |
| 19 // this program; if not, write to the Free Software Foundation, Inc., | |
| 20 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
| 21 // | |
| 22 // ---------------------------------------------------------------------------- | |
| 23 // | |
| 24 //####COPYRIGHTEND#### | |
| 25 #include "eCosThreadUtils.h" | |
| 26 #include "eCosTrace.h" | |
| 27 | |
| 28 CeCosThreadUtils::THREAD_ID CeCosThreadUtils::CS::nCSOwner=(CeCosThreadUtils::THREAD_ID)-1; | |
| 29 int CeCosThreadUtils::CS::m_nCriticalSectionLock=0; | |
| 30 #ifdef _WIN32 | |
| 31 CRITICAL_SECTION CeCosThreadUtils::CS::cs; | |
| 32 bool CeCosThreadUtils::CS::bCSInitialized=false; | |
| 33 #else // UNIX | |
| 34 // Static recursive mutex for unix critical section | |
| 35 #ifndef NO_THREADS | |
| 36 pthread_mutex_t CeCosThreadUtils::CS::cs = PTHREAD_MUTEX_INITIALIZER; | |
| 37 #endif | |
| 38 #endif | |
| 39 | |
| 40 | |
| 41 CeCosThreadUtils::THREAD_ID CeCosThreadUtils::GetThreadId() | |
| 42 { | |
| 43 return | |
| 44 #ifdef _WIN32 | |
| 45 GetCurrentThreadId(); | |
| 46 #else // UNIX | |
| 47 #ifdef NO_THREADS | |
| 48 42; | |
| 49 #else | |
| 50 pthread_self(); | |
| 51 #endif | |
| 52 #endif | |
| 53 } | |
| 54 | |
| 55 // Wait for the specified Boolean to turn true or the timeout to occur | |
| 56 // The value of the Boolean is returned as result | |
| 57 bool CeCosThreadUtils::WaitFor (bool &b, Duration dTimeout) | |
| 58 { | |
| 59 Time t=Now(); | |
| 60 do { | |
| 61 if(b){ | |
| 62 break; | |
| 63 } | |
| 64 Sleep(250); | |
| 65 } while (Now()-t<dTimeout); | |
| 66 return b; | |
| 67 } | |
| 68 | |
| 69 // This function spawns a thread and causes it to run asynchrously. | |
| 70 // The callback may be | |
| 71 // A function, which is called when the thread completes | |
| 72 // A boolean, which is set when the thread completes | |
| 73 // Null, in which case no notification is received of thread completion | |
| 74 // pParam is passed to the thread function pThreadFunc on thread initiation. | |
| 75 | |
| 76 bool CeCosThreadUtils::RunThread(CallbackProc *pThreadFunc, void *pParam, CallbackProc *pCompletionFunc, void *pCompletionParam, LPCTSTR pszName) | |
| 77 { | |
| 78 TRACE(_T("RunThread %s\n"),pszName); | |
| 79 // Do not spawn a thread while in possession of a mutex | |
| 80 // ENTERCRITICAL; | |
| 81 // VTRACE(_T("csl=%d\n"),CS::m_nCriticalSectionLock); | |
| 82 // assert(1==CS::m_nCriticalSectionLock); | |
| 83 // LEAVECRITICAL; | |
| 84 | |
| 85 ThreadInfo *pInfo=new ThreadInfo(pThreadFunc,pParam,pCompletionFunc,pCompletionParam,pszName); // SThreadFunc will delete | |
| 86 bool rc=false; | |
| 87 | |
| 88 #ifdef _WIN32 | |
| 89 // FIXME: CreateThread incompatible with C runtime calls? | |
| 90 DWORD dwID; | |
| 91 HANDLE hThread=CreateThread(NULL,0,SThreadFunc, pInfo, 0, &dwID); | |
| 92 if(hThread){ | |
| 93 TRACE(_T("RunThread: - new thread=%x\n"),dwID); | |
| 94 ::CloseHandle(hThread); | |
| 95 rc=true; | |
| 96 } else { | |
| 97 ERROR(_T("Failed to create thread\n")); | |
| 98 } | |
| 99 #else // UNIX | |
| 100 #ifdef NO_THREADS | |
| 101 assert(false); | |
| 102 #else | |
| 103 VTRACE(_T("RunThread():Calling pthread_create()\n")); | |
| 104 pthread_t hThread; | |
| 105 int n=pthread_create(&hThread, NULL, SThreadFunc, pInfo); | |
| 106 TRACE( _T("RunThread: - non-blocking call (new thread=%x)\n"),hThread); | |
| 107 VTRACE(_T("RunThread(): pthread_create() returned <%d>\n"), n); | |
| 108 if (n != 0) { | |
| 109 ERROR(_T("RunThread(): pthread_create failed - %s\n"),strerror(errno)); | |
| 110 } else { | |
| 111 | |
| 112 VTRACE(_T("RunThread(): Calling pthread_detach\n")); | |
| 113 int n = pthread_detach(hThread); | |
| 114 | |
| 115 if (0==n) { | |
| 116 rc=true; | |
| 117 } else { | |
| 118 ERROR(_T("RunThread(): pthread_detach failed - %s\n"),strerror(errno)); | |
| 119 hThread=0; | |
| 120 } | |
| 121 } | |
| 122 VTRACE(_T("RunThread(): returned from pthread calls - exiting RunThread()\n")); | |
| 123 #endif | |
| 124 #endif | |
| 125 if(!rc){ | |
| 126 delete pInfo; | |
| 127 } | |
| 128 return rc; | |
| 129 | |
| 130 } | |
| 131 | |
| 132 #ifdef _WIN32 | |
| 133 int CALLBACK CeCosThreadUtils::FilterFunction(EXCEPTION_POINTERS *p) | |
| 134 { | |
| 135 EXCEPTION_RECORD *pRec =p->ExceptionRecord; | |
| 136 TRACE(_T("!!!Exception!!! address=%08x code=%08x\n"),pRec->ExceptionAddress,pRec->ExceptionCode); | |
| 137 /* | |
| 138 CONTEXT *pContext=p->ContextRecord; | |
| 139 const unsigned char *ESP=(const unsigned char *)pContext->Esp; | |
| 140 for(int i=0;i<16;i++){ | |
| 141 TRACE(_T("%08X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n"),ESP, | |
| 142 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]); | |
| 143 ESP+=16; | |
| 144 } | |
| 145 */ | |
| 146 return EXCEPTION_EXECUTE_HANDLER; | |
| 147 } | |
| 148 #endif | |
| 149 | |
| 150 CeCosThreadUtils::THREADFUNC CALLBACK CeCosThreadUtils::SThreadFunc (void *pParam) | |
| 151 { | |
| 152 VTRACE(_T("SThreadFunc()\n")); | |
| 153 ThreadInfo *pInfo=(ThreadInfo*)pParam; | |
| 154 #ifdef _WIN32 | |
| 155 __try { | |
| 156 // Call what we are instructed to (e.g. LocalThreadFunc): | |
| 157 pInfo->pThreadFunc(pInfo->pThreadParam); | |
| 158 } | |
| 159 __except ( CeCosThreadUtils::FilterFunction(GetExceptionInformation() )) | |
| 160 { | |
| 161 TRACE(_T("Handling exception!!!...\n")); | |
| 162 } | |
| 163 #else // UNIX | |
| 164 try { | |
| 165 // Call what we are instructed to (e.g. LocalThreadFunc): | |
| 166 pInfo->pThreadFunc(pInfo->pThreadParam); | |
| 167 } | |
| 168 catch (...){ | |
| 169 TRACE(_T("Exception caught in SThreadFunc!!!\n")); | |
| 170 } | |
| 171 #endif | |
| 172 | |
| 173 // Call the Callback: | |
| 174 TRACE(_T("SThreadFunc - invoking callback\n")); | |
| 175 if(pInfo->pCompletionFunc){ | |
| 176 pInfo->pCompletionFunc (pInfo->pCompletionParam); | |
| 177 } else if (pInfo->pCompletionParam) { | |
| 178 // No function - just a flag: | |
| 179 *(bool *)pInfo->pCompletionParam=true; | |
| 180 } | |
| 181 // No more references to pInfo->pTest from now on... | |
| 182 VTRACE(_T("SThreadFunc(): deleting (ThreadInfo)pInfo\n")); | |
| 183 delete pInfo; | |
| 184 TRACE(_T("SThreadFunc exiting\n")); | |
| 185 return 0; | |
| 186 } | |
| 187 | |
| 188 int CeCosThreadUtils::CS::AtomicIncrement (int &n) | |
| 189 { | |
| 190 int rc; | |
| 191 ENTERCRITICAL; | |
| 192 rc=n++; | |
| 193 LEAVECRITICAL; | |
| 194 return rc; | |
| 195 } | |
| 196 | |
| 197 int CeCosThreadUtils::CS::AtomicDecrement (int &n) | |
| 198 { | |
| 199 int rc; | |
| 200 ENTERCRITICAL; | |
| 201 rc=n--; | |
| 202 LEAVECRITICAL; | |
| 203 return rc; | |
| 204 } | |
| 205 | |
| 206 CeCosThreadUtils::CS::CS() | |
| 207 { | |
| 208 // Get mutex lock; block until available unless current | |
| 209 // thread already owns the mutex. | |
| 210 if(GetThreadId()!=nCSOwner){ | |
| 211 VTRACE(_T("%x try CS\n"),GetThreadId()); | |
| 212 #ifdef _WIN32 | |
| 213 if(!bCSInitialized){ | |
| 214 InitializeCriticalSection(&cs); | |
| 215 bCSInitialized=true; | |
| 216 } | |
| 217 ::EnterCriticalSection(&cs); | |
| 218 #else // UNIX | |
| 219 #ifndef NO_THREADS | |
| 220 pthread_mutex_lock(&cs); | |
| 221 #endif | |
| 222 #endif | |
| 223 nCSOwner=GetThreadId(); | |
| 224 VTRACE(_T("%x has CS count=%d\n"),GetThreadId(),m_nCriticalSectionLock);//sdf | |
| 225 } | |
| 226 m_nCriticalSectionLock++; | |
| 227 } | |
| 228 | |
| 229 CeCosThreadUtils::CS::~CS() | |
| 230 { | |
| 231 m_nCriticalSectionLock--; | |
| 232 assert(m_nCriticalSectionLock>=0); | |
| 233 if(0==m_nCriticalSectionLock){ | |
| 234 nCSOwner=(THREAD_ID)-1; | |
| 235 VTRACE(_T("%x leaves CS count=%d\n"),GetThreadId(),m_nCriticalSectionLock); | |
| 236 | |
| 237 // Release mutex lock. | |
| 238 #ifdef _WIN32 | |
| 239 ::LeaveCriticalSection(&cs); | |
| 240 #else // UNIX | |
| 241 #ifndef NO_THREADS | |
| 242 pthread_mutex_unlock(&cs); | |
| 243 #endif | |
| 244 #endif | |
| 245 } | |
| 246 } | |
| 247 |
