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

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

accept bugfix for changing async request

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