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 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)