… | |
… | |
22 | } aio_thread; |
22 | } aio_thread; |
23 | |
23 | |
24 | typedef struct { |
24 | typedef struct { |
25 | int type; |
25 | int type; |
26 | aio_thread *thread; |
26 | aio_thread *thread; |
27 | |
|
|
28 | SV *savesv; |
|
|
29 | |
27 | |
30 | int fd; |
28 | int fd; |
31 | off_t offset; |
29 | off_t offset; |
32 | size_t length; |
30 | size_t length; |
33 | ssize_t result; |
31 | ssize_t result; |
… | |
… | |
110 | } |
108 | } |
111 | |
109 | |
112 | if (length < 0) |
110 | if (length < 0) |
113 | croak ("length must not be negative"); |
111 | croak ("length must not be negative"); |
114 | |
112 | |
115 | New (0, req, 1, aio_cb); |
113 | Newz (0, req, 1, aio_cb); |
116 | |
114 | |
117 | if (!req) |
115 | if (!req) |
118 | croak ("out of memory during aio_req allocation"); |
116 | croak ("out of memory during aio_req allocation"); |
119 | |
117 | |
120 | req->type = dowrite ? REQ_WRITE : REQ_READ; |
118 | req->type = dowrite ? REQ_WRITE : REQ_READ; |
… | |
… | |
145 | else |
143 | else |
146 | { |
144 | { |
147 | int errorno = errno; |
145 | int errorno = errno; |
148 | errno = req->errorno; |
146 | errno = req->errorno; |
149 | |
147 | |
150 | if (req->savesv) |
|
|
151 | SvREFCNT_dec (req->savesv); |
|
|
152 | |
|
|
153 | if (req->type == REQ_READ) |
148 | if (req->type == REQ_READ) |
154 | SvCUR_set (req->data, req->dataoffset |
149 | SvCUR_set (req->data, req->dataoffset |
155 | + req->result > 0 ? req->result : 0); |
150 | + req->result > 0 ? req->result : 0); |
|
|
151 | |
|
|
152 | if (req->data) |
|
|
153 | SvREFCNT_dec (req->data); |
156 | |
154 | |
157 | if (req->type == REQ_STAT || req->type == REQ_LSTAT || req->type == REQ_FSTAT) |
155 | if (req->type == REQ_STAT || req->type == REQ_LSTAT || req->type == REQ_FSTAT) |
158 | { |
156 | { |
159 | PL_laststype = req->type == REQ_LSTAT ? OP_LSTAT : OP_STAT; |
157 | PL_laststype = req->type == REQ_LSTAT ? OP_LSTAT : OP_STAT; |
160 | PL_laststatval = req->result; |
158 | PL_laststatval = req->result; |
… | |
… | |
179 | XPUSHs (sv_2mortal (newSViv (req->result))); |
177 | XPUSHs (sv_2mortal (newSViv (req->result))); |
180 | PUTBACK; |
178 | PUTBACK; |
181 | call_sv (req->callback, G_VOID); |
179 | call_sv (req->callback, G_VOID); |
182 | SPAGAIN; |
180 | SPAGAIN; |
183 | |
181 | |
184 | SvREFCNT_dec (req->data); |
182 | if (req->callback) |
185 | SvREFCNT_dec (req->callback); |
183 | SvREFCNT_dec (req->callback); |
186 | |
184 | |
187 | errno = errorno; |
185 | errno = errorno; |
188 | nreqs--; |
186 | nreqs--; |
189 | count++; |
187 | count++; |
190 | } |
188 | } |
… | |
… | |
225 | |
223 | |
226 | /* then loop */ |
224 | /* then loop */ |
227 | while (read (reqpipe[0], (void *)&req, sizeof (req)) == sizeof (req)) |
225 | while (read (reqpipe[0], (void *)&req, sizeof (req)) == sizeof (req)) |
228 | { |
226 | { |
229 | req->thread = thr; |
227 | req->thread = thr; |
230 | errno = 0; |
228 | errno = 0; /* strictly unnecessary */ |
231 | |
229 | |
232 | if (req->type == REQ_READ) |
230 | if (req->type == REQ_READ) |
233 | req->result = pread (req->fd, req->dataptr, req->length, req->offset); |
231 | req->result = pread (req->fd, req->dataptr, req->length, req->offset); |
234 | else if (req->type == REQ_WRITE) |
232 | else if (req->type == REQ_WRITE) |
235 | req->result = pwrite (req->fd, req->dataptr, req->length, req->offset); |
233 | req->result = pwrite (req->fd, req->dataptr, req->length, req->offset); |
… | |
… | |
291 | { |
289 | { |
292 | end_thread (); |
290 | end_thread (); |
293 | cur--; |
291 | cur--; |
294 | } |
292 | } |
295 | |
293 | |
296 | poll_cb (); |
|
|
297 | while (started > nthreads) |
294 | while (started > nthreads) |
298 | { |
295 | { |
299 | sched_yield (); |
296 | fd_set rfd; |
300 | fcntl (respipe[0], F_SETFL, 0); |
297 | FD_ZERO(&rfd); |
|
|
298 | FD_SET(respipe[0], &rfd); |
|
|
299 | |
|
|
300 | select (respipe[0] + 1, &rfd, 0, 0, 0); |
301 | poll_cb (); |
301 | poll_cb (); |
302 | fcntl (respipe[0], F_SETFL, O_NONBLOCK); |
|
|
303 | } |
302 | } |
304 | |
303 | |
305 | void |
304 | void |
306 | aio_open(pathname,flags,mode,callback) |
305 | aio_open(pathname,flags,mode,callback) |
307 | SV * pathname |
306 | SV * pathname |
… | |
… | |
310 | SV * callback |
309 | SV * callback |
311 | PROTOTYPE: $$$$ |
310 | PROTOTYPE: $$$$ |
312 | CODE: |
311 | CODE: |
313 | aio_req req; |
312 | aio_req req; |
314 | |
313 | |
315 | New (0, req, 1, aio_cb); |
314 | Newz (0, req, 1, aio_cb); |
316 | |
315 | |
317 | if (!req) |
316 | if (!req) |
318 | croak ("out of memory during aio_req allocation"); |
317 | croak ("out of memory during aio_req allocation"); |
319 | |
318 | |
320 | req->type = REQ_OPEN; |
319 | req->type = REQ_OPEN; |
321 | req->savesv = newSVsv (pathname); |
320 | req->data = newSVsv (pathname); |
322 | req->dataptr = SvPV_nolen (req->savesv); |
321 | req->dataptr = SvPV_nolen (req->data); |
323 | req->fd = flags; |
322 | req->fd = flags; |
324 | req->mode = mode; |
323 | req->mode = mode; |
325 | req->callback = SvREFCNT_inc (callback); |
324 | req->callback = SvREFCNT_inc (callback); |
326 | |
325 | |
327 | send_req (req); |
326 | send_req (req); |
328 | |
327 | |
329 | void |
328 | void |
330 | aio_close(fh,callback) |
329 | aio_close(fh,callback) |
331 | InputStream fh |
330 | InputStream fh |
332 | SV * callback |
331 | SV * callback |
333 | PROTOTYPE: $ |
332 | PROTOTYPE: $$ |
334 | CODE: |
333 | CODE: |
335 | aio_req req; |
334 | aio_req req; |
336 | |
335 | |
337 | New (0, req, 1, aio_cb); |
336 | Newz (0, req, 1, aio_cb); |
338 | |
337 | |
339 | if (!req) |
338 | if (!req) |
340 | croak ("out of memory during aio_req allocation"); |
339 | croak ("out of memory during aio_req allocation"); |
341 | |
340 | |
342 | req->type = REQ_CLOSE; |
341 | req->type = REQ_CLOSE; |
… | |
… | |
377 | ALIAS: |
376 | ALIAS: |
378 | aio_lstat = 1 |
377 | aio_lstat = 1 |
379 | CODE: |
378 | CODE: |
380 | aio_req req; |
379 | aio_req req; |
381 | |
380 | |
382 | New (0, req, 1, aio_cb); |
381 | Newz (0, req, 1, aio_cb); |
383 | |
382 | |
384 | if (!req) |
383 | if (!req) |
385 | croak ("out of memory during aio_req allocation"); |
384 | croak ("out of memory during aio_req allocation"); |
386 | |
385 | |
387 | New (0, req->statdata, 1, struct stat64); |
386 | New (0, req->statdata, 1, struct stat64); |
… | |
… | |
390 | croak ("out of memory during aio_req->statdata allocation"); |
389 | croak ("out of memory during aio_req->statdata allocation"); |
391 | |
390 | |
392 | if (SvPOK (fh_or_path)) |
391 | if (SvPOK (fh_or_path)) |
393 | { |
392 | { |
394 | req->type = ix ? REQ_LSTAT : REQ_STAT; |
393 | req->type = ix ? REQ_LSTAT : REQ_STAT; |
395 | req->savesv = newSVsv (fh_or_path); |
394 | req->data = newSVsv (fh_or_path); |
396 | req->dataptr = SvPV_nolen (req->savesv); |
395 | req->dataptr = SvPV_nolen (req->data); |
397 | } |
396 | } |
398 | else |
397 | else |
399 | { |
398 | { |
400 | req->type = REQ_FSTAT; |
399 | req->type = REQ_FSTAT; |
401 | req->fd = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); |
400 | req->fd = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); |