source: trunk/src/wsock32/asyncthread.cpp@ 7041

Last change on this file since 7041 was 7041, checked in by sandervl, 24 years ago

several updates + fixes

File size: 9.0 KB
Line 
1/* $Id: asyncthread.cpp,v 1.12 2001-10-13 18:51:07 sandervl Exp $ */
2
3/*
4 * Async thread help functions
5 *
6 * Copyright 2000 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * TODO: Not everything is 100% thread safe (i.e. async parameter updates)
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 */
13#define INCL_BASE
14#include <os2wrap.h>
15#include <os2sel.h>
16#include <stdlib.h>
17#include <wprocess.h>
18#include <win32api.h>
19#include <misc.h>
20#include <string.h>
21#include <vmutex.h>
22#include "wsock32.h"
23#include "asyncthread.h"
24
25static PASYNCTHREADPARM threadList = NULL;
26VMutex asyncThreadMutex;
27
28static void AddToQueue(PASYNCTHREADPARM pThreadParm);
29
30//******************************************************************************
31//******************************************************************************
32static void _Optlink AsyncThread(void *arg)
33{
34 PASYNCTHREADPARM pThreadParm = (PASYNCTHREADPARM)arg;
35
36 pThreadParm->asyncProc((PVOID)arg);
37
38//only for blocking hooks (currently not implemented)
39//// if(pThreadParm->request == ASYNC_BLOCKHOOK)
40//// WSASetBlocking(FALSE, pThreadParm->hThread);
41
42 dprintf(("AsyncThread %x exit", pThreadParm->hAsyncTaskHandle));
43 free((PVOID)pThreadParm);
44}
45//******************************************************************************
46//******************************************************************************
47ULONG QueueAsyncJob(ASYNCTHREADPROC asyncproc, PASYNCTHREADPARM pThreadParm, BOOL fSetBlocking)
48{
49 TID tid;
50
51 pThreadParm->asyncProc = asyncproc;
52 pThreadParm->fActive = TRUE;
53 pThreadParm->fCancelled = FALSE;
54 pThreadParm->next = NULL;
55 pThreadParm->hAsyncTaskHandle = 0;
56
57 pThreadParm->hThread = GetCurrentThread();
58 AddToQueue(pThreadParm);
59
60 if(fSetBlocking) WSASetBlocking(TRUE);
61
62 USHORT sel = GetFS();
63 tid = _beginthread(AsyncThread, NULL, 16384, (PVOID)pThreadParm);
64 SetFS(sel);
65 if (tid == -1) {
66 dprintf(("QueueAsyncJob: _beginthread failed"));
67 if(fSetBlocking) WSASetBlocking(FALSE);
68 RemoveFromQueue(pThreadParm);
69 WSASetLastError(WSAEFAULT);
70 return 0;
71 }
72 pThreadParm->hAsyncTaskHandle = tid;
73 WSASetLastError(NO_ERROR);
74 return pThreadParm->hAsyncTaskHandle;
75}
76//******************************************************************************
77//******************************************************************************
78void AddToQueue(PASYNCTHREADPARM pThreadParm)
79{
80 asyncThreadMutex.enter();
81 pThreadParm->next = threadList;
82 threadList = pThreadParm;
83 asyncThreadMutex.leave();
84}
85//******************************************************************************
86//******************************************************************************
87void RemoveFromQueue(PASYNCTHREADPARM pThreadParm)
88{
89 PASYNCTHREADPARM pThreadInfo;
90
91 asyncThreadMutex.enter();
92 pThreadInfo = threadList;
93
94 if(pThreadInfo == pThreadParm) {
95 threadList = pThreadParm->next;
96 }
97 else {
98 while(pThreadInfo->next) {
99 if(pThreadInfo->next == pThreadParm) {
100 pThreadInfo->next = pThreadParm->next;
101 break;
102 }
103 pThreadInfo = pThreadInfo->next;
104 }
105 if(pThreadInfo == NULL) {
106 dprintf(("RemoveFromQueue: parm %x not found!!", pThreadParm));
107 DebugInt3();
108 }
109 }
110 memset(pThreadParm, 0, sizeof(*pThreadParm));
111 asyncThreadMutex.leave();
112}
113//******************************************************************************
114//******************************************************************************
115void WSACancelAllAsyncRequests()
116{
117 PASYNCTHREADPARM pThreadInfo;
118 BOOL found = FALSE;
119
120 dprintf(("WSACancelAllAsyncRequests"));
121 asyncThreadMutex.enter();
122 pThreadInfo = threadList;
123
124 while(pThreadInfo) {
125 dprintf(("WSACancelAllAsyncRequests %x", pThreadInfo->hAsyncTaskHandle));
126 pThreadInfo->fCancelled = TRUE;
127 pThreadInfo->u.asyncselect.asyncSem->post();
128 pThreadInfo = pThreadInfo->next;
129 }
130 asyncThreadMutex.leave();
131 //TODO: not the right way to wait for the async threads to die
132 DosSleep(250);
133}
134//******************************************************************************
135//******************************************************************************
136int WIN32API WSACancelAsyncRequest(LHANDLE hAsyncTaskHandle)
137{
138 PASYNCTHREADPARM pThreadInfo;
139 BOOL found = FALSE;
140
141 dprintf(("WSACancelAsyncRequest: cancel task %x", hAsyncTaskHandle));
142 asyncThreadMutex.enter();
143 pThreadInfo = threadList;
144
145 while(pThreadInfo) {
146 if(pThreadInfo->hAsyncTaskHandle == hAsyncTaskHandle) {
147 pThreadInfo->fCancelled = TRUE;
148 found = TRUE;
149 break;
150 }
151 pThreadInfo = pThreadInfo->next;
152 }
153 asyncThreadMutex.leave();
154 if(found == FALSE) {
155 WSASetLastError(WSAEINVAL);
156 dprintf(("WSACancelAsyncRequest: task not found!!"));
157 }
158 return (found) ? NO_ERROR : SOCKET_ERROR;
159}
160//******************************************************************************
161//Only to cancel blocking hooks
162//******************************************************************************
163int WIN32API WSACancelBlockingCall()
164{
165 HANDLE hThread = GetCurrentThread();
166
167 dprintf(("WSACancelBlockingCall"));
168#if 0
169 asyncThreadMutex.enter();
170 pThreadInfo = threadList;
171
172 while(pThreadInfo) {
173 if(pThreadInfo->hThread == hThread) {
174 pThreadInfo->fCancelled = TRUE;
175
176 if(pThreadInfo->request == ASYNC_BLOCKHOOK) {
177 ret = so_cancel(pThreadInfo->blockedsocket);
178 }
179
180 found = TRUE;
181 break;
182 }
183 pThreadInfo = pThreadInfo->next;
184 }
185 asyncThreadMutex.leave();
186#endif
187 return SOCKET_ERROR;
188}
189//******************************************************************************
190//dump queue
191//******************************************************************************
192void DumpQueue(void)
193{
194 HANDLE hThread = GetCurrentThread();
195 PASYNCTHREADPARM pThreadInfo;
196
197 dprintf(("DumpQueue"));
198
199 asyncThreadMutex.enter();
200 pThreadInfo = threadList;
201
202 while(pThreadInfo) {
203 dprintf(( "SOCKET %08xh thread#%d events %xh pending %xh, select %d",
204 pThreadInfo->u.asyncselect.s,
205 pThreadInfo->hAsyncTaskHandle,
206 pThreadInfo->u.asyncselect.lEvents,
207 pThreadInfo->u.asyncselect.lEventsPending,
208 pThreadInfo->fWaitSelect));
209 pThreadInfo = pThreadInfo->next;
210 }
211 asyncThreadMutex.leave();
212 dprintf(("DumpQueue done"));
213}
214//******************************************************************************
215//Assumes caller owns async thread mutex!
216//******************************************************************************
217PASYNCTHREADPARM FindAsyncEvent(SOCKET s)
218{
219 PASYNCTHREADPARM pThreadInfo;
220
221 pThreadInfo = threadList;
222 while(pThreadInfo) {
223 if(pThreadInfo->u.asyncselect.s == s && !pThreadInfo->fRemoved) {
224 return pThreadInfo;
225 }
226 pThreadInfo = pThreadInfo->next;
227 }
228 return NULL;
229}
230//******************************************************************************
231//******************************************************************************
232BOOL FindAndSetAsyncEvent(SOCKET s, int mode, int notifyHandle, int notifyData, ULONG lEventMask)
233{
234 PASYNCTHREADPARM pThreadInfo;
235
236 asyncThreadMutex.enter();
237 pThreadInfo = FindAsyncEvent(s);
238 if(pThreadInfo) {
239 pThreadInfo->u.asyncselect.mode = mode;
240 pThreadInfo->u.asyncselect.lEvents = lEventMask;
241 pThreadInfo->u.asyncselect.lEventsPending = lEventMask;
242 pThreadInfo->notifyHandle = notifyHandle;
243 pThreadInfo->notifyData = notifyData;
244 if(lEventMask == 0) {
245 //make sure this thread isn't used anymore
246 pThreadInfo->fRemoved = TRUE;
247 }
248 if(pThreadInfo->fWaitSelect) {
249 //cancel pending select in async select thread (if any)
250 so_cancel(s);
251 }
252
253 //unblock async thread if it was waiting
254 pThreadInfo->u.asyncselect.asyncSem->post();
255 }
256 asyncThreadMutex.leave();
257 return(pThreadInfo != NULL);
258}
259//******************************************************************************
260//******************************************************************************
261void EnableAsyncEvent(SOCKET s, ULONG flags)
262{
263 PASYNCTHREADPARM pThreadInfo;
264
265 asyncThreadMutex.enter();
266 pThreadInfo = FindAsyncEvent(s);
267 if(pThreadInfo) {
268 pThreadInfo->u.asyncselect.lEventsPending |= (pThreadInfo->u.asyncselect.lEvents & flags);
269 //unblock async thread if it was waiting
270 pThreadInfo->u.asyncselect.asyncSem->post();
271
272 //cancel pending select in async select thread (if any)
273 if(pThreadInfo->fWaitSelect) {
274 so_cancel(s);
275 }
276 }
277 asyncThreadMutex.leave();
278}
279//******************************************************************************
280//******************************************************************************
281BOOL QueryAsyncEvent(SOCKET s, HWND *pHwnd, int *pMsg, ULONG *plEvent)
282{
283 PASYNCTHREADPARM pThreadInfo;
284
285 asyncThreadMutex.enter();
286 pThreadInfo = FindAsyncEvent(s);
287 if(pThreadInfo) {
288 *pHwnd = (HWND)pThreadInfo->notifyHandle;
289 *pMsg = pThreadInfo->notifyData;
290 *plEvent = pThreadInfo->u.asyncselect.lEvents;
291 }
292 asyncThreadMutex.leave();
293 return(pThreadInfo != NULL);
294}
295//******************************************************************************
296//******************************************************************************
Note: See TracBrowser for help on using the repository browser.