aio_win32.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 81 aio_xxx() POSIX emulation on Windows */
10 
11 #include "squid.h"
12 #include "comm.h"
13 #include "DiskIO/AIO/aio_win32.h"
14 #include "fd.h"
15 #include "StatCounters.h"
16 #include "win32.h"
17 
18 #include <cerrno>
19 
20 #if _SQUID_WINDOWS_
21 VOID CALLBACK IoCompletionRoutine(DWORD dwErrorCode,
22  DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
23 {
24 
25  struct aiocb *aiocbp = (struct aiocb *) lpOverlapped->hEvent;
26 
27  aiocbp->aio_sigevent.sigev_notify = dwErrorCode;
28  aiocbp->aio_sigevent.sigev_signo = dwNumberOfBytesTransfered;
29  debugs(81, 7, "AIO operation complete: errorcode=" << dwErrorCode << " nbytes=" << dwNumberOfBytesTransfered);
30  xfree(lpOverlapped);
31 }
32 
33 int aio_read(struct aiocb *aiocbp)
34 {
35  LPOVERLAPPED Overlapped;
36  BOOL IoOperationStatus;
37 
38  /* Allocate an overlapped structure. */
39  Overlapped = (LPOVERLAPPED) xcalloc(1, sizeof(OVERLAPPED));
40 
41  if (!Overlapped) {
42  errno = ENOMEM;
43  return -1;
44  }
45 
46 #if _FILE_OFFSET_BITS==64
47 #ifdef __GNUC__
48  Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000LL);
49 
50  Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000LL);
51 
52 #else
53 
54  Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000);
55 
56  Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000);
57 
58 #endif
59 #else
60 
61  Overlapped->Offset = aiocbp->aio_offset;
62 
63  Overlapped->OffsetHigh = 0;
64 
65 #endif
66 
67  Overlapped->hEvent = aiocbp;
68 
69  aiocbp->aio_sigevent.sigev_notify = EINPROGRESS;
70 
71  aiocbp->aio_sigevent.sigev_signo = -1;
72 
73  IoOperationStatus = ReadFileEx((HANDLE)_get_osfhandle(aiocbp->aio_fildes),
74  aiocbp->aio_buf,
75  aiocbp->aio_nbytes,
76  Overlapped,
77  IoCompletionRoutine);
78 
79  /* Test to see if the I/O was queued successfully. */
80  if (!IoOperationStatus) {
81  errno = GetLastError();
82  debugs(81, DBG_IMPORTANT, "aio_read: GetLastError=" << errno );
83  return -1;
84  }
85 
86  /* The I/O queued successfully. Go back into the
87  alertable wait for I/O completion or for
88  more I/O requests. */
89  return 0;
90 }
91 
92 int aio_read64(struct aiocb64 *aiocbp)
93 {
94  LPOVERLAPPED Overlapped;
95  BOOL IoOperationStatus;
96 
97  /* Allocate an overlapped structure. */
98  Overlapped = (LPOVERLAPPED) xcalloc(1, sizeof(OVERLAPPED));
99 
100  if (!Overlapped) {
101  errno = ENOMEM;
102  return -1;
103  }
104 
105 #ifdef __GNUC__
106  Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000LL);
107 
108  Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000LL);
109 
110 #else
111 
112  Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000);
113 
114  Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000);
115 
116 #endif
117 
118  Overlapped->hEvent = aiocbp;
119 
120  aiocbp->aio_sigevent.sigev_notify = EINPROGRESS;
121 
122  aiocbp->aio_sigevent.sigev_signo = -1;
123 
124  IoOperationStatus = ReadFileEx((HANDLE)_get_osfhandle(aiocbp->aio_fildes),
125  aiocbp->aio_buf,
126  aiocbp->aio_nbytes,
127  Overlapped,
128  IoCompletionRoutine);
129 
130  /* Test to see if the I/O was queued successfully. */
131  if (!IoOperationStatus) {
132  errno = GetLastError();
133  debugs(81, DBG_IMPORTANT, "aio_read: GetLastError=" << errno );
134  return -1;
135  }
136 
137  /* The I/O queued successfully. Go back into the
138  alertable wait for I/O completion or for
139  more I/O requests. */
140  return 0;
141 }
142 
143 int aio_write(struct aiocb *aiocbp)
144 {
145  LPOVERLAPPED Overlapped;
146  BOOL IoOperationStatus;
147 
148  /* Allocate an overlapped structure. */
149  Overlapped = (LPOVERLAPPED) xcalloc(1, sizeof(OVERLAPPED));
150 
151  if (!Overlapped) {
152  errno = ENOMEM;
153  return -1;
154  }
155 
156 #if _FILE_OFFSET_BITS==64
157 #ifdef __GNUC__
158  Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000LL);
159 
160  Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000LL);
161 
162 #else
163 
164  Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000);
165 
166  Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000);
167 
168 #endif
169 #else
170 
171  Overlapped->Offset = aiocbp->aio_offset;
172 
173  Overlapped->OffsetHigh = 0;
174 
175 #endif
176 
177  Overlapped->hEvent = aiocbp;
178 
179  aiocbp->aio_sigevent.sigev_notify = EINPROGRESS;
180 
181  aiocbp->aio_sigevent.sigev_signo = -1;
182 
183  IoOperationStatus = WriteFileEx((HANDLE)_get_osfhandle(aiocbp->aio_fildes),
184  aiocbp->aio_buf,
185  aiocbp->aio_nbytes,
186  Overlapped,
187  IoCompletionRoutine);
188 
189  /* Test to see if the I/O was queued successfully. */
190  if (!IoOperationStatus) {
191  errno = GetLastError();
192  debugs(81, DBG_IMPORTANT, "aio_write: GetLastError=" << errno );
193  return -1;
194  }
195 
196  /* The I/O queued successfully. Go back into the
197  alertable wait for I/O completion or for
198  more I/O requests. */
199  return 0;
200 }
201 
202 int aio_write64(struct aiocb64 *aiocbp)
203 {
204  LPOVERLAPPED Overlapped;
205  BOOL IoOperationStatus;
206 
207  /* Allocate an overlapped structure. */
208  Overlapped = (LPOVERLAPPED) xcalloc(1, sizeof(OVERLAPPED));
209 
210  if (!Overlapped) {
211  errno = ENOMEM;
212  return -1;
213  }
214 
215 #ifdef __GNUC__
216  Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000LL);
217 
218  Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000LL);
219 
220 #else
221 
222  Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000);
223 
224  Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000);
225 
226 #endif
227 
228  Overlapped->hEvent = aiocbp;
229 
230  aiocbp->aio_sigevent.sigev_notify = EINPROGRESS;
231 
232  aiocbp->aio_sigevent.sigev_signo = -1;
233 
234  IoOperationStatus = WriteFileEx((HANDLE)_get_osfhandle(aiocbp->aio_fildes),
235  aiocbp->aio_buf,
236  aiocbp->aio_nbytes,
237  Overlapped,
238  IoCompletionRoutine);
239 
240  /* Test to see if the I/O was queued successfully. */
241  if (!IoOperationStatus) {
242  errno = GetLastError();
243  debugs(81, DBG_IMPORTANT, "aio_write: GetLastError=" << errno );
244  return -1;
245  }
246 
247  /* The I/O queued successfully. Go back into the
248  alertable wait for I/O completion or for
249  more I/O requests. */
250  return 0;
251 }
252 
253 int aio_error(const struct aiocb * aiocbp)
254 {
255  return aiocbp->aio_sigevent.sigev_notify;
256 }
257 
258 int aio_error64(const struct aiocb64 * aiocbp)
259 {
260  return aiocbp->aio_sigevent.sigev_notify;
261 }
262 
263 int aio_open(const char *path, int mode)
264 {
265  HANDLE hndl;
266  DWORD dwCreationDisposition;
267  DWORD dwDesiredAccess;
268  int fd;
269 
270  if (mode & O_WRONLY)
271  mode |= O_APPEND;
272 
273  mode |= O_BINARY;
274 
275  errno = 0;
276 
277  if (mode & O_WRONLY)
278  dwDesiredAccess = GENERIC_WRITE;
279  else
280  dwDesiredAccess = (mode & O_RDONLY) ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE;
281 
282  if (mode & O_TRUNC)
283  dwCreationDisposition = CREATE_ALWAYS;
284  else
285  dwCreationDisposition = (mode & O_CREAT) ? OPEN_ALWAYS : OPEN_EXISTING;
286 
287  if ((hndl = CreateFile(path, /* file name */
288  dwDesiredAccess, /* access mode */
289  0, /* share mode */
290  nullptr, /* SD */
291  dwCreationDisposition, /* how to create */
292  FILE_FLAG_OVERLAPPED, /* file attributes */
293  NULL /* handle to template file */
294  )) != INVALID_HANDLE_VALUE) {
295  ++ statCounter.syscalls.disk.opens;
296  fd = _open_osfhandle((long) hndl, 0);
297  commSetCloseOnExec(fd);
298  fd_open(fd, FD_FILE, path);
299  } else {
300  errno = GetLastError();
301  fd = DISK_ERROR;
302  }
303 
304  return fd;
305 }
306 
307 void aio_close(int fd)
308 {
309  CloseHandle((HANDLE)_get_osfhandle(fd));
310  fd_close(fd);
311  ++ statCounter.syscalls.disk.closes;
312 }
313 
314 ssize_t aio_return(struct aiocb * aiocbp)
315 {
316  return aiocbp->aio_sigevent.sigev_signo;
317 }
318 
319 ssize_t aio_return64(struct aiocb64 * aiocbp)
320 
321 {
322  return aiocbp->aio_sigevent.sigev_signo;
323 }
324 #endif /* _SQUID_WINDOWS_ */
325 
void * xcalloc(size_t n, size_t sz)
Definition: xalloc.cc:71
void commSetCloseOnExec(int)
Definition: minimal.cc:27
struct StatCounters::@119::@123 disk
void fd_open(const int fd, unsigned int, const char *description)
Definition: minimal.cc:15
struct StatCounters::@119 syscalls
#define O_BINARY
Definition: defines.h:134
#define NULL
Definition: types.h:145
#define xfree
#define DBG_IMPORTANT
Definition: Stream.h:38
void fd_close(const int fd)
Definition: minimal.cc:21
#define DISK_ERROR
Definition: defines.h:28
#define BOOL
Definition: std-includes.h:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
@ FD_FILE
Definition: enums.h:15
StatCounters statCounter
Definition: StatCounters.cc:12

 

Introduction

Documentation

Support

Miscellaneous