32 #include "precompiled.h"
62 switch(oflag & (O_RDONLY|O_WRONLY|O_RDWR))
66 return GENERIC_READ|FILE_WRITE_ATTRIBUTES;
70 return GENERIC_READ|GENERIC_WRITE;
79 switch(oflag & (O_RDONLY|O_WRONLY|O_RDWR))
82 return FILE_SHARE_READ;
84 return FILE_SHARE_WRITE;
86 return FILE_SHARE_WRITE;
96 return (oflag & O_EXCL)? CREATE_NEW : CREATE_ALWAYS;
99 return TRUNCATE_EXISTING;
101 return OPEN_EXISTING;
111 const DWORD flags = FILE_FLAG_OVERLAPPED|FILE_FLAG_NO_BUFFERING;
112 const DWORD attributes = FILE_ATTRIBUTE_NORMAL;
113 return flags|attributes;
124 hFile = CreateFileW(
OsString(pathname).c_str(), access, share, 0, create, flags, 0);
125 if(hFile == INVALID_HANDLE_VALUE)
155 InitializeSListHead(&freelist);
159 const size_t size = Align<cacheLineSize>(
sizeof(
Entry));
160 for(uintptr_t offset = 0; offset+size <=
storageSize; offset += size)
164 InterlockedPushEntrySList(&freelist, &entry->
entry);
177 InterlockedFlushSList(&freelist);
193 if(pSetFileIoOverlappedRange)
201 Entry* entry = (
Entry*)InterlockedPopEntrySList(&freelist);
205 OVERLAPPED& ovl = entry->
ovl;
207 ovl.InternalHigh = 0;
208 ovl.Offset =
u64_lo(offset);
209 ovl.OffsetHigh =
u64_hi(offset);
221 const uintptr_t address = uintptr_t(ovl);
223 InterlockedPushEntrySList(&freelist, (PSLIST_ENTRY)(address - offsetof(
Entry, ovl)));
232 # pragma warning(push)
233 # pragma warning(disable:4324) // structure was padded due to __declspec(align())
235 __declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) SLIST_HEADER freelist;
237 # pragma warning(pop)
256 hFile = INVALID_HANDLE_VALUE;
276 if(pSetFileCompletionNotificationModes)
280 (void)pSetFileCompletionNotificationModes(
hFile, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
289 hFile = INVALID_HANDLE_VALUE;
314 for(
size_t i = 0; i <
maxFiles; i++)
323 for(
size_t i = 0; i <
maxFiles; i++)
332 for(
size_t i = 0; i <
maxFiles; i++)
343 const size_t index = fcb - &
fcbs[0];
349 const size_t index = fcb - &
fcbs[0];
375 fileControlBlocks.
Init();
395 if(waio_initState == 0)
412 ENSURE(!(oflag & O_APPEND));
448 hFile = (
HANDLE)_get_osfhandle(fd);
449 if(hFile == INVALID_HANDLE_VALUE)
458 LARGE_INTEGER size64; size64.QuadPart = alignedSize;
459 WARN_IF_FALSE(SetFilePointerEx(hFile, size64, 0, FILE_BEGIN));
460 if(!SetEndOfFile(hFile))
462 if(GetLastError() == ERROR_DISK_FULL)
465 debug_printf(L
"waio_Preallocate(%lld) failed: %d\n", size, GetLastError());
470 if(pSetFileValidData)
480 (void)pSetFileValidData(hFile, alignedSize);
481 ENSURE(GetLastError() == 0);
520 void*
const buf = (
void*)cb->
aio_buf;
523 OVERLAPPED* ovl = (OVERLAPPED*)cb->
ovl;
528 if(ok || GetLastError() == ERROR_IO_PENDING)
540 for(
int i = 0; i < n; i++)
545 if(HasOverlappedIoCompleted((OVERLAPPED*)cbs[i]->ovl))
575 for(
int i = 0; i < n; i++)
577 if(cbs[i] == 0 || cbs[i]->aio_lio_opcode ==
LIO_NOP)
580 if(
Issue(cbs[i]) == -1)
595 DWORD bytesTransferred; ULONG_PTR
key; OVERLAPPED* ovl;
615 const DWORD milliseconds = 1;
636 const OVERLAPPED* ovl = (
const OVERLAPPED*)cb->
ovl;
639 if(!HasOverlappedIoCompleted(ovl))
641 if(ovl->Internal != ERROR_SUCCESS)
650 OVERLAPPED* ovl = (OVERLAPPED*)cb->
ovl;
657 const ULONG_PTR status = ovl->Internal;
658 const ULONG_PTR bytesTransferred = ovl->InternalHigh;
664 return (status == ERROR_SUCCESS)? bytesTransferred : -1;
static Status OpenFile(const OsPath &pathname, int oflag, HANDLE &hFile)
static bool AreAnyComplete(const struct aiocb *const cbs[], int n)
int aio_error(const struct aiocb *cb)
int aio_suspend(const struct aiocb *const cbs[], int n, const struct timespec *timeout)
static const size_t pageSize
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
#define WARN_IF_ERR(expression)
#define COMPILER_FENCE
prevent the compiler from reordering loads or stores across this point.
Status waio_Preallocate(int fd, off_t size)
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) SLIST_HEADER freelist
some WinAPI functions SetLastError(0) on success, which is bad because it can hide previous errors...
FileControlBlock * Allocate()
int aio_write(struct aiocb *cb)
void Deallocate(OVERLAPPED *ovl)
#define WUTIL_FUNC(varName, ret, params)
static const uintptr_t maxSectorSize
static ModuleInitState waio_initState
T round_up(T n, T multiple)
round number up/down to the next given multiple.
#define ASSERT(expr)
same as ENSURE in debug mode, does nothing in release mode.
intptr_t cpu_AtomicAdd(volatile intptr_t *location, intptr_t increment)
add a signed value to a variable without the possibility of interference from other threads/CPUs...
u32 u64_lo(u64 x)
return upper 32-bits
int aio_fsync(int, struct aiocb *)
#define WINIT_REGISTER_MAIN_SHUTDOWN(func)
const Status INVALID_HANDLE
void AttachToCompletionPort(HANDLE hFile, HANDLE &hIOCP, ULONG_PTR key, DWORD numConcurrentThreads)
CACHE_ALIGNED(volatile intptr_t) inUse[maxFiles]
bool IsAligned(T t, uintptr_t multiple)
void Deallocate(FileControlBlock *fcb)
const Status NOT_SUPPORTED
void Associate(HANDLE hFile)
int ErrnoFromStatus(Status status)
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
#define UNUSED2(param)
mark a function local variable or parameter as unused and avoid the corresponding compiler warning...
intptr_t ModuleInitState
initialization state of a module (class, source file, etc.) must be initialized to zero (e...
bool WriteFile(void *cbdata, std::wstring cfgNsString, Path path)
ssize_t aio_return(struct aiocb *cb)
int aio_cancel(int fd, struct aiocb *cb)
Status PollCompletionPort(HANDLE hIOCP, DWORD timeout, DWORD &bytesTransferred, ULONG_PTR &key, OVERLAPPED *&ovl)
const Status INVALID_PARAM
static DWORD FlagsAndAttributes()
i64 Status
Error handling system.
static DWORD CreationDisposition(int oflag)
FileControlBlock fcbs[maxFiles]
static const size_t storageSize
Status wutil_SetPrivilege(const wchar_t *privilege, bool enable)
int Descriptor(FileControlBlock *fcb) const
#define DEBUG_WARN_ERR(status)
display the error dialog with text corresponding to the given error code.
OVERLAPPED * Allocate(off_t offset)
JSBool ReadFile(JSContext *cx, uintN argc, jsval *vp)
static const size_t maxFiles
Status waio_open(const OsPath &pathname, int oflag,...)
bool cpu_CAS(volatile intptr_t *location, intptr_t expected, intptr_t newValue)
atomic "compare and swap".
#define WARN_IF_FALSE(expression)
static DWORD ShareMode(int oflag)
int lio_listio(int mode, struct aiocb *const cbs[], int n, struct sigevent *se)
static FileControlBlocks fileControlBlocks
#define WARN_RETURN(status)
static const int firstDescriptor
Status Open(const OsPath &pathname, int oflag)
static DWORD DesiredAccess(int oflag)
static int Issue(aiocb *cb)
Status ModuleInit(volatile ModuleInitState *initState, Status(*init)())
calls a user-defined init function if initState is zero.
int aio_read(struct aiocb *cb)
#define WUTIL_IMPORT_KERNEL32(procName, varName)
static Status waio_Shutdown()
static Status waio_Init()
Status waio_close(int fd)
void debug_printf(const wchar_t *fmt,...)
write a formatted string to the debug channel, subject to filtering (see below).
static std::string OsString(const OsPath &path)
#define RETURN_STATUS_IF_ERR(expression)
FileControlBlock * FromDescriptor(int descriptor)