1 //####COPYRIGHTBEGIN####
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
6 // This program is part of the eCos host tools.
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)
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
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.
22 // ----------------------------------------------------------------------------
24 //####COPYRIGHTEND####
25 #include "eCosThreadUtils.h"
26 #include "eCosTrace.h"
28 CeCosThreadUtils::THREAD_ID CeCosThreadUtils::CS::nCSOwner=(CeCosThreadUtils::THREAD_ID)-1;
29 int CeCosThreadUtils::CS::m_nCriticalSectionLock=0;
31 CRITICAL_SECTION CeCosThreadUtils::CS::cs;
32 bool CeCosThreadUtils::CS::bCSInitialized=false;
34 // Static recursive mutex for unix critical section
36 pthread_mutex_t CeCosThreadUtils::CS::cs = PTHREAD_MUTEX_INITIALIZER;
41 CeCosThreadUtils::THREAD_ID CeCosThreadUtils::GetThreadId()
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)
65 } while (Now()-t<dTimeout);
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.
76 bool CeCosThreadUtils::RunThread(CallbackProc *pThreadFunc, void *pParam, CallbackProc *pCompletionFunc, void *pCompletionParam, LPCTSTR pszName)
78 TRACE(_T("RunThread %s\n"),pszName);
79 // Do not spawn a thread while in possession of a mutex
81 // VTRACE(_T("csl=%d\n"),CS::m_nCriticalSectionLock);
82 // assert(1==CS::m_nCriticalSectionLock);
85 ThreadInfo *pInfo=new ThreadInfo(pThreadFunc,pParam,pCompletionFunc,pCompletionParam,pszName); // SThreadFunc will delete
89 // FIXME: CreateThread incompatible with C runtime calls?
91 HANDLE hThread=CreateThread(NULL,0,SThreadFunc, pInfo, 0, &dwID);
93 ::CloseHandle(hThread);
96 ERROR(_T("Failed to create thread\n"));
103 int n=pthread_create(&hThread, NULL, SThreadFunc, pInfo);
104 TRACE( _T("RunThread: - non-blocking call (new thread=%x)\n"),hThread);
106 ERROR(_T("RunThread(): pthread_create failed - %s\n"),strerror(errno));
109 int n = pthread_detach(hThread);
114 ERROR(_T("RunThread(): pthread_detach failed - %s\n"),strerror(errno));
128 int CALLBACK CeCosThreadUtils::FilterFunction(EXCEPTION_POINTERS *p)
130 EXCEPTION_RECORD *pRec =p->ExceptionRecord;
131 TRACE(_T("!!!Exception!!! address=%08x code=%08x\n"),pRec->ExceptionAddress,pRec->ExceptionCode);
133 CONTEXT *pContext=p->ContextRecord;
134 const unsigned char *ESP=(const unsigned char *)pContext->Esp;
135 for(int i=0;i<16;i++){
136 TRACE(_T("%08X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n"),ESP,
137 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]);
141 return EXCEPTION_EXECUTE_HANDLER;
145 CeCosThreadUtils::THREADFUNC CALLBACK CeCosThreadUtils::SThreadFunc (void *pParam)
147 THREAD_ID id=GetThreadId();
148 ThreadInfo *pInfo=(ThreadInfo*)pParam;
149 TRACE(_T("Thread %x [%s] created\n"),id,(LPCTSTR)pInfo->strName);
150 #if defined(_WIN32) && !defined(__CYGWIN__)
152 // Call what we are instructed to (e.g. LocalThreadFunc):
153 pInfo->pThreadFunc(pInfo->pThreadParam);
155 __except ( CeCosThreadUtils::FilterFunction(GetExceptionInformation() ))
157 TRACE(_T("Handling exception!!!...\n"));
161 // Call what we are instructed to (e.g. LocalThreadFunc):
162 pInfo->pThreadFunc(pInfo->pThreadParam);
165 TRACE(_T("Exception caught in SThreadFunc!!!\n"));
169 // Call the Callback:
170 if(pInfo->pCompletionFunc){
171 pInfo->pCompletionFunc (pInfo->pCompletionParam);
172 } else if (pInfo->pCompletionParam) {
173 // No function - just a flag:
174 *(bool *)pInfo->pCompletionParam=true;
176 // No more references to pInfo->pTest from now on...
177 TRACE(_T("Thread %x [%s] terminated\n"),id,(LPCTSTR)pInfo->strName);
182 bool CeCosThreadUtils::CS::InCriticalSection()
184 return GetThreadId()==nCSOwner;
187 int CeCosThreadUtils::AtomicIncrement (int &n)
196 int CeCosThreadUtils::AtomicDecrement (int &n)
205 CeCosThreadUtils::CS::CS()
207 // Get mutex lock; block until available unless current
208 // thread already owns the mutex.
209 if(!InCriticalSection()){
212 InitializeCriticalSection(&cs);
215 ::EnterCriticalSection(&cs);
218 pthread_mutex_lock(&cs);
221 // As we now own the CS it is safe to perform the following assignment:
222 nCSOwner=GetThreadId();
224 // As we now own the CS it is safe to perform the following increment:
225 m_nCriticalSectionLock++;
228 CeCosThreadUtils::CS::~CS()
230 assert(InCriticalSection());
231 // As we own the CS we can safely manipulate variables:
232 m_nCriticalSectionLock--;
233 assert(m_nCriticalSectionLock>=0);
234 if(0==m_nCriticalSectionLock){
235 // Last lock is being released - let go of the mutex
236 nCSOwner=(THREAD_ID)-1;
238 // Release mutex lock.
240 ::LeaveCriticalSection(&cs);
243 pthread_mutex_unlock(&cs);
249 void CeCosThreadUtils::Sleep(int nMsec)
255 usleep((int)nMsec * 1000);