Mercurial > trustbridge > nss-cmake-static
comparison nspr/pr/src/md/windows/w32poll.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | |
2 /* This Source Code Form is subject to the terms of the Mozilla Public | |
3 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
5 | |
6 /* | |
7 * This file implements _PR_MD_PR_POLL for Win32. | |
8 */ | |
9 | |
10 /* The default value of FD_SETSIZE is 64. */ | |
11 #define FD_SETSIZE 1024 | |
12 | |
13 #include "primpl.h" | |
14 | |
15 #if !defined(_PR_GLOBAL_THREADS_ONLY) | |
16 | |
17 struct select_data_s { | |
18 PRInt32 status; | |
19 PRInt32 error; | |
20 fd_set *rd, *wt, *ex; | |
21 const struct timeval *tv; | |
22 }; | |
23 | |
24 static void | |
25 _PR_MD_select_thread(void *cdata) | |
26 { | |
27 struct select_data_s *cd = (struct select_data_s *)cdata; | |
28 | |
29 cd->status = select(0, cd->rd, cd->wt, cd->ex, cd->tv); | |
30 | |
31 if (cd->status == SOCKET_ERROR) { | |
32 cd->error = WSAGetLastError(); | |
33 } | |
34 } | |
35 | |
36 int _PR_NTFiberSafeSelect( | |
37 int nfds, | |
38 fd_set *readfds, | |
39 fd_set *writefds, | |
40 fd_set *exceptfds, | |
41 const struct timeval *timeout) | |
42 { | |
43 PRThread *me = _PR_MD_CURRENT_THREAD(); | |
44 int ready; | |
45 | |
46 if (_PR_IS_NATIVE_THREAD(me)) { | |
47 ready = _MD_SELECT(nfds, readfds, writefds, exceptfds, timeout); | |
48 } | |
49 else | |
50 { | |
51 /* | |
52 ** Creating a new thread on each call!! | |
53 ** I guess web server doesn't use non-block I/O. | |
54 */ | |
55 PRThread *selectThread; | |
56 struct select_data_s data; | |
57 data.status = 0; | |
58 data.error = 0; | |
59 data.rd = readfds; | |
60 data.wt = writefds; | |
61 data.ex = exceptfds; | |
62 data.tv = timeout; | |
63 | |
64 selectThread = PR_CreateThread( | |
65 PR_USER_THREAD, _PR_MD_select_thread, &data, | |
66 PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); | |
67 if (selectThread == NULL) return -1; | |
68 | |
69 PR_JoinThread(selectThread); | |
70 ready = data.status; | |
71 if (ready == SOCKET_ERROR) WSASetLastError(data.error); | |
72 } | |
73 return ready; | |
74 } | |
75 | |
76 #endif /* !defined(_PR_GLOBAL_THREADS_ONLY) */ | |
77 | |
78 PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) | |
79 { | |
80 int ready, err; | |
81 fd_set rd, wt, ex; | |
82 fd_set *rdp, *wtp, *exp; | |
83 int nrd, nwt, nex; | |
84 PRFileDesc *bottom; | |
85 PRPollDesc *pd, *epd; | |
86 PRThread *me = _PR_MD_CURRENT_THREAD(); | |
87 | |
88 struct timeval tv, *tvp = NULL; | |
89 | |
90 if (_PR_PENDING_INTERRUPT(me)) | |
91 { | |
92 me->flags &= ~_PR_INTERRUPT; | |
93 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); | |
94 return -1; | |
95 } | |
96 | |
97 /* | |
98 ** Is it an empty set? If so, just sleep for the timeout and return | |
99 */ | |
100 if (0 == npds) | |
101 { | |
102 PR_Sleep(timeout); | |
103 return 0; | |
104 } | |
105 | |
106 nrd = nwt = nex = 0; | |
107 FD_ZERO(&rd); | |
108 FD_ZERO(&wt); | |
109 FD_ZERO(&ex); | |
110 | |
111 ready = 0; | |
112 for (pd = pds, epd = pd + npds; pd < epd; pd++) | |
113 { | |
114 SOCKET osfd; | |
115 PRInt16 in_flags_read = 0, in_flags_write = 0; | |
116 PRInt16 out_flags_read = 0, out_flags_write = 0; | |
117 | |
118 if ((NULL != pd->fd) && (0 != pd->in_flags)) | |
119 { | |
120 if (pd->in_flags & PR_POLL_READ) | |
121 { | |
122 in_flags_read = (pd->fd->methods->poll)( | |
123 pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_WRITE), | |
124 &out_flags_read); | |
125 } | |
126 if (pd->in_flags & PR_POLL_WRITE) | |
127 { | |
128 in_flags_write = (pd->fd->methods->poll)( | |
129 pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_READ), | |
130 &out_flags_write); | |
131 } | |
132 if ((0 != (in_flags_read & out_flags_read)) | |
133 || (0 != (in_flags_write & out_flags_write))) | |
134 { | |
135 /* this one's ready right now (buffered input) */ | |
136 if (0 == ready) | |
137 { | |
138 /* | |
139 * We will have to return without calling the | |
140 * system poll/select function. So zero the | |
141 * out_flags fields of all the poll descriptors | |
142 * before this one. | |
143 */ | |
144 PRPollDesc *prev; | |
145 for (prev = pds; prev < pd; prev++) | |
146 { | |
147 prev->out_flags = 0; | |
148 } | |
149 } | |
150 ready += 1; | |
151 pd->out_flags = out_flags_read | out_flags_write; | |
152 } | |
153 else | |
154 { | |
155 pd->out_flags = 0; /* pre-condition */ | |
156 /* make sure this is an NSPR supported stack */ | |
157 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); | |
158 PR_ASSERT(NULL != bottom); /* what to do about that? */ | |
159 if ((NULL != bottom) | |
160 && (_PR_FILEDESC_OPEN == bottom->secret->state)) | |
161 { | |
162 if (0 == ready) | |
163 { | |
164 osfd = (SOCKET) bottom->secret->md.osfd; | |
165 if (in_flags_read & PR_POLL_READ) | |
166 { | |
167 pd->out_flags |= _PR_POLL_READ_SYS_READ; | |
168 FD_SET(osfd, &rd); | |
169 nrd++; | |
170 } | |
171 if (in_flags_read & PR_POLL_WRITE) | |
172 { | |
173 pd->out_flags |= _PR_POLL_READ_SYS_WRITE; | |
174 FD_SET(osfd, &wt); | |
175 nwt++; | |
176 } | |
177 if (in_flags_write & PR_POLL_READ) | |
178 { | |
179 pd->out_flags |= _PR_POLL_WRITE_SYS_READ; | |
180 FD_SET(osfd, &rd); | |
181 nrd++; | |
182 } | |
183 if (in_flags_write & PR_POLL_WRITE) | |
184 { | |
185 pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE; | |
186 FD_SET(osfd, &wt); | |
187 nwt++; | |
188 } | |
189 if (pd->in_flags & PR_POLL_EXCEPT) { | |
190 FD_SET(osfd, &ex); | |
191 nex++; | |
192 } | |
193 } | |
194 } | |
195 else | |
196 { | |
197 if (0 == ready) | |
198 { | |
199 PRPollDesc *prev; | |
200 for (prev = pds; prev < pd; prev++) | |
201 { | |
202 prev->out_flags = 0; | |
203 } | |
204 } | |
205 ready += 1; /* this will cause an abrupt return */ | |
206 pd->out_flags = PR_POLL_NVAL; /* bogii */ | |
207 } | |
208 } | |
209 } | |
210 else | |
211 { | |
212 pd->out_flags = 0; | |
213 } | |
214 } | |
215 | |
216 if (0 != ready) return ready; /* no need to block */ | |
217 | |
218 /* | |
219 * FD_SET does nothing if the fd_set's internal fd_array is full. If | |
220 * nrd, nwt, or nex is greater than FD_SETSIZE, we know FD_SET must | |
221 * have failed to insert an osfd into the corresponding fd_set, and | |
222 * therefore we should fail. | |
223 */ | |
224 if ((nrd > FD_SETSIZE) || (nwt > FD_SETSIZE) || (nex > FD_SETSIZE)) { | |
225 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); | |
226 return -1; | |
227 } | |
228 | |
229 rdp = (0 == nrd) ? NULL : &rd; | |
230 wtp = (0 == nwt) ? NULL : &wt; | |
231 exp = (0 == nex) ? NULL : &ex; | |
232 | |
233 if ((NULL == rdp) && (NULL == wtp) && (NULL == exp)) { | |
234 PR_Sleep(timeout); | |
235 return 0; | |
236 } | |
237 | |
238 if (timeout != PR_INTERVAL_NO_TIMEOUT) | |
239 { | |
240 PRInt32 ticksPerSecond = PR_TicksPerSecond(); | |
241 tv.tv_sec = timeout / ticksPerSecond; | |
242 tv.tv_usec = PR_IntervalToMicroseconds( timeout % ticksPerSecond ); | |
243 tvp = &tv; | |
244 } | |
245 | |
246 #if defined(_PR_GLOBAL_THREADS_ONLY) | |
247 ready = _MD_SELECT(0, rdp, wtp, exp, tvp); | |
248 #else | |
249 ready = _PR_NTFiberSafeSelect(0, rdp, wtp, exp, tvp); | |
250 #endif | |
251 | |
252 /* | |
253 ** Now to unravel the select sets back into the client's poll | |
254 ** descriptor list. Is this possibly an area for pissing away | |
255 ** a few cycles or what? | |
256 */ | |
257 if (ready > 0) | |
258 { | |
259 ready = 0; | |
260 for (pd = pds, epd = pd + npds; pd < epd; pd++) | |
261 { | |
262 PRInt16 out_flags = 0; | |
263 if ((NULL != pd->fd) && (0 != pd->in_flags)) | |
264 { | |
265 SOCKET osfd; | |
266 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); | |
267 PR_ASSERT(NULL != bottom); | |
268 | |
269 osfd = (SOCKET) bottom->secret->md.osfd; | |
270 | |
271 if (FD_ISSET(osfd, &rd)) | |
272 { | |
273 if (pd->out_flags & _PR_POLL_READ_SYS_READ) | |
274 out_flags |= PR_POLL_READ; | |
275 if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) | |
276 out_flags |= PR_POLL_WRITE; | |
277 } | |
278 if (FD_ISSET(osfd, &wt)) | |
279 { | |
280 if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) | |
281 out_flags |= PR_POLL_READ; | |
282 if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) | |
283 out_flags |= PR_POLL_WRITE; | |
284 } | |
285 if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT; | |
286 } | |
287 pd->out_flags = out_flags; | |
288 if (out_flags) ready++; | |
289 } | |
290 PR_ASSERT(ready > 0); | |
291 } | |
292 else if (ready == SOCKET_ERROR) | |
293 { | |
294 err = WSAGetLastError(); | |
295 if (err == WSAENOTSOCK) | |
296 { | |
297 /* Find the bad fds */ | |
298 int optval; | |
299 int optlen = sizeof(optval); | |
300 ready = 0; | |
301 for (pd = pds, epd = pd + npds; pd < epd; pd++) | |
302 { | |
303 pd->out_flags = 0; | |
304 if ((NULL != pd->fd) && (0 != pd->in_flags)) | |
305 { | |
306 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); | |
307 if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET, | |
308 SO_TYPE, (char *) &optval, &optlen) == -1) | |
309 { | |
310 PR_ASSERT(WSAGetLastError() == WSAENOTSOCK); | |
311 if (WSAGetLastError() == WSAENOTSOCK) | |
312 { | |
313 pd->out_flags = PR_POLL_NVAL; | |
314 ready++; | |
315 } | |
316 } | |
317 } | |
318 } | |
319 PR_ASSERT(ready > 0); | |
320 } | |
321 else _PR_MD_MAP_SELECT_ERROR(err); | |
322 } | |
323 | |
324 return ready; | |
325 } |