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