Line data Source code
1 : /* Copyright (C) 2011 Wildfire Games.
2 : *
3 : * Permission is hereby granted, free of charge, to any person obtaining
4 : * a copy of this software and associated documentation files (the
5 : * "Software"), to deal in the Software without restriction, including
6 : * without limitation the rights to use, copy, modify, merge, publish,
7 : * distribute, sublicense, and/or sell copies of the Software, and to
8 : * permit persons to whom the Software is furnished to do so, subject to
9 : * the following conditions:
10 : *
11 : * The above copyright notice and this permission notice shall be included
12 : * in all copies or substantial portions of the Software.
13 : *
14 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 : * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 : * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 : * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 : * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 : */
22 :
23 : #include "precompiled.h"
24 : #include "lib/file/io/io.h"
25 :
26 : #include "lib/sysdep/rtl.h"
27 :
28 : static const StatusDefinition ioStatusDefinitions[] = {
29 : { ERR::IO, L"Error during IO", EIO }
30 : };
31 1 : STATUS_ADD_DEFINITIONS(ioStatusDefinitions);
32 :
33 : namespace io {
34 :
35 : // this is just a thin wrapper on top of lowio and POSIX aio.
36 : // note that the Windows aio implementation requires buffers, sizes and
37 : // offsets to be sector-aligned.
38 :
39 2935 : Status Issue(aiocb& cb, size_t queueDepth)
40 : {
41 : #if CONFIG2_FILE_ENABLE_AIO
42 : if(queueDepth > 1)
43 : {
44 : const int ret = (cb.aio_lio_opcode == LIO_WRITE)? aio_write(&cb): aio_read(&cb);
45 : if(ret != 0)
46 : WARN_RETURN(StatusFromErrno());
47 : }
48 : else
49 : #else
50 : UNUSED2(queueDepth);
51 : #endif
52 : {
53 2935 : ENSURE(lseek(cb.aio_fildes, cb.aio_offset, SEEK_SET) == cb.aio_offset);
54 :
55 2935 : void* buf = (void*)cb.aio_buf; // cast from volatile void*
56 2935 : const ssize_t bytesTransferred = (cb.aio_lio_opcode == LIO_WRITE)? write(cb.aio_fildes, buf, cb.aio_nbytes) : read(cb.aio_fildes, buf, cb.aio_nbytes);
57 2935 : if(bytesTransferred < 0)
58 0 : WARN_RETURN(StatusFromErrno());
59 :
60 2935 : cb.aio_nbytes = (size_t)bytesTransferred;
61 : }
62 :
63 2935 : return INFO::OK;
64 : }
65 :
66 :
67 2935 : Status WaitUntilComplete(aiocb& cb, size_t queueDepth)
68 : {
69 : #if CONFIG2_FILE_ENABLE_AIO
70 : if(queueDepth > 1)
71 : {
72 : aiocb* const cbs = &cb;
73 : timespec* const timeout = 0; // infinite
74 : SUSPEND_AGAIN:
75 : errno = 0;
76 : const int ret = aio_suspend(&cbs, 1, timeout);
77 : if(ret != 0)
78 : {
79 : if(errno == EINTR) // interrupted by signal
80 : goto SUSPEND_AGAIN;
81 : WARN_RETURN(StatusFromErrno());
82 : }
83 :
84 : const int err = aio_error(&cb);
85 : ENSURE(err != EINPROGRESS); // else aio_return is undefined
86 : ssize_t bytesTransferred = aio_return(&cb);
87 : if(bytesTransferred == -1) // transfer failed
88 : {
89 : errno = err;
90 : WARN_RETURN(StatusFromErrno());
91 : }
92 : cb.aio_nbytes = (size_t)bytesTransferred;
93 : }
94 : #else
95 : UNUSED2(cb);
96 : UNUSED2(queueDepth);
97 : #endif
98 :
99 2935 : return INFO::OK;
100 : }
101 :
102 3 : } // namespace io
|