source: trunk/testapp/threads/threads.c@ 21916

Last change on this file since 21916 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

  • Property svn:eol-style set to native
File size: 6.3 KB
Line 
1/*
2 * Taken from here http://msdn.microsoft.com/en-us/library/ms682516%28v=VS.85%29.aspx
3 * and modified for the needs of the testcase
4 */
5
6//#define USE_TRY
7
8#if !defined(_MSC_VER) && 1
9#define INCL_DOS
10#include <os2wrap2.h>
11#endif
12
13#include <windows.h>
14#include <tchar.h>
15#include <excpt.h>
16
17#define MAX_THREADS 10
18#define BUF_SIZE 255
19
20#ifdef _MSC_VER
21#include <strsafe.h>
22#else
23#include <stdio.h>
24#include <stdarg.h>
25void StringCchPrintf(LPTSTR pszDest, size_t cchDest,
26 LPCTSTR pszFormat, ...);
27void StringCchLength(LPCTSTR psz, size_t cchMax, size_t *pcch);
28#endif
29
30DWORD WINAPI MyThreadFunction( LPVOID lpParam );
31void ErrorHandler(LPTSTR lpszFunction);
32
33// Sample custom data structure for threads to use.
34// This is passed by void pointer so it can be any data type
35// that can be passed using a single void pointer (LPVOID).
36typedef struct MyData {
37 int val1;
38 int val2;
39} MYDATA, *PMYDATA;
40
41#ifndef _MSC_VER
42
43// register the EXE to cause the OS/2 exception handler setup around
44// the entry point
45
46#include <odinlx.h>
47
48#undef _tmain
49int _tmain();
50
51int APIENTRY WinMain(HINSTANCE hInstance,
52 HINSTANCE hPrevInstance,
53 LPTSTR lpCmdLine,
54 int nCmdShow)
55{
56 return _tmain();
57}
58
59int main(int argc, char **argv)
60{
61 EnableSEH();
62 RegisterLxExe((WINMAIN)WinMain, NULL);
63 return _tmain();
64}
65
66void StringCchPrintf(LPTSTR pszDest, size_t cchDest,
67 LPCTSTR pszFormat, ...)
68{
69 va_list ap;
70
71 va_start(ap, pszFormat);
72 vsnprintf(pszDest, cchDest, pszFormat, ap);
73 va_end(ap);
74}
75
76void StringCchLength(LPCTSTR psz, size_t cchMax, size_t *pcch)
77{
78 *pcch = strnlen(psz, cchMax);
79}
80
81#endif // !_MSC_VER
82
83int _tmain()
84{
85 PMYDATA pDataArray[MAX_THREADS];
86 DWORD dwThreadIdArray[MAX_THREADS];
87 HANDLE hThreadArray[MAX_THREADS];
88
89 // Create MAX_THREADS worker threads.
90
91 int i;
92 for( i=0; i<MAX_THREADS; i++ )
93 {
94 // Allocate memory for thread data.
95
96 pDataArray[i] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
97 sizeof(MYDATA));
98
99 if( pDataArray[i] == NULL )
100 {
101 // If the array allocation fails, the system is out of memory
102 // so there is no point in trying to print an error message.
103 // Just terminate execution.
104 ExitProcess(2);
105 }
106
107 // Generate unique data for each thread to work with.
108
109 pDataArray[i]->val1 = i;
110 pDataArray[i]->val2 = i+100;
111
112 // Create the thread to begin execution on its own.
113
114 hThreadArray[i] = CreateThread(
115 NULL, // default security attributes
116 0, // use default stack size
117 MyThreadFunction, // thread function name
118 pDataArray[i], // argument to thread function
119 0, // use default creation flags
120 &dwThreadIdArray[i]); // returns the thread identifier
121
122
123 // Check the return value for success.
124 // If CreateThread fails, terminate execution.
125 // This will automatically clean up threads and memory.
126
127 if (hThreadArray[i] == NULL)
128 {
129 ErrorHandler(TEXT("CreateThread"));
130 ExitProcess(3);
131 }
132 } // End of main thread creation loop.
133
134 _tprintf(TEXT("Started %d threads. Waiting for them to terminate...\n"),
135 MAX_THREADS);
136
137 // Wait until some threads have terminated.
138
139 WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, 2000);
140
141 _tprintf(TEXT("Finished waiting.\n"));
142
143 // Close all thread handles and free memory allocations.
144
145 for(i=0; i<MAX_THREADS; i++)
146 {
147 CloseHandle(hThreadArray[i]);
148 if(pDataArray[i] != NULL)
149 {
150 HeapFree(GetProcessHeap(), 0, pDataArray[i]);
151 pDataArray[i] = NULL; // Ensure address is not reused.
152 }
153 }
154
155#if !defined(_MSC_VER) && 1
156 DosExit(1, 0);
157#endif
158
159 return 0;
160}
161
162#ifdef USE_TRY
163int exc_filter(DWORD code, PEXCEPTION_POINTERS pPtrs)
164{
165 PEXCEPTION_RECORD pRec = pPtrs->ExceptionRecord;
166
167#ifndef _MSC_VER
168 os2_PPIB pPib;
169 os2_PTIB pTib;
170 DosGetInfoBlocks(&pTib, &pPib);
171 printf("TID: %d\n", pTib->tib_ptib2->tib2_ultid);
172#endif
173
174 _tprintf(TEXT("Filter: code %08lx\n"), code);
175 _tprintf(TEXT("ExceptionCode %p\n"), pRec->ExceptionCode);
176 _tprintf(TEXT("ExceptionAddress %p\n"), pRec->ExceptionAddress);
177 _tprintf(TEXT("NumberParameters %d\n"), pRec->NumberParameters);
178
179 return EXCEPTION_CONTINUE_SEARCH;
180}
181#endif
182
183DWORD WINAPI MyThreadFunction( LPVOID lpParam )
184{
185 PMYDATA pDataArray;
186
187 TCHAR msgBuf[BUF_SIZE];
188 size_t cchStringSize;
189 DWORD dwChars;
190
191#ifdef USE_TRY
192 __try
193 {
194#endif
195 // Cast the parameter to the correct data type.
196 // The pointer is known to be valid because
197 // it was checked for NULL before the thread was created.
198
199 pDataArray = (PMYDATA)lpParam;
200
201 // Print the parameter values using thread-safe functions.
202
203 Sleep(1000 * pDataArray->val1 / 2);
204
205#if 0
206 StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"),
207 pDataArray->val1, pDataArray->val2);
208 _tprintf("%s", msgBuf);
209#endif
210
211#ifdef USE_TRY
212 }
213 __except(exc_filter(exception_code(), exception_info()))
214 {
215 }
216#endif
217
218 return 0;
219}
220
221void ErrorHandler(LPTSTR lpszFunction)
222{
223 // Retrieve the system error message for the last-error code.
224
225 LPVOID lpMsgBuf;
226 LPVOID lpDisplayBuf;
227 DWORD dw = GetLastError();
228
229 FormatMessage(
230 FORMAT_MESSAGE_ALLOCATE_BUFFER |
231 FORMAT_MESSAGE_FROM_SYSTEM |
232 FORMAT_MESSAGE_IGNORE_INSERTS,
233 NULL,
234 dw,
235 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
236 (LPTSTR) &lpMsgBuf,
237 0, NULL );
238
239 // Display the error message.
240
241 lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
242 (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR));
243 StringCchPrintf((LPTSTR)lpDisplayBuf,
244 LocalSize((HLOCAL)lpDisplayBuf) / sizeof(TCHAR),
245 TEXT("%s failed with error %d: %s"),
246 lpszFunction, dw, lpMsgBuf);
247 MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK);
248
249 // Free error-handling buffer allocations.
250
251 LocalFree((HLOCAL)lpMsgBuf);
252 LocalFree((HLOCAL)lpDisplayBuf);
253}
254
Note: See TracBrowser for help on using the repository browser.