diff options
author | Marco Castelluccio <mcastelluccio@mozilla.com> | 2017-11-08 19:11:54 +0000 |
---|---|---|
committer | Marco Castelluccio <mcastelluccio@mozilla.com> | 2017-11-08 19:11:54 +0000 |
commit | 07e2a968c83c489c5b46efe4973114e78e1804c1 (patch) | |
tree | 5ecc9fe9a721ed2266c2f7773d32385a8c3a1b15 /lib | |
parent | 9a46448f818bd47de8604ec9e0e39ced6a00499e (diff) |
Implement flock for Windows in compiler-rt
Summary:
This patch implements flock for Windows, needed to make gcda writing work in a multiprocessing scenario.
Fixes https://bugs.llvm.org/show_bug.cgi?id=34923.
Reviewers: zturner
Reviewed By: zturner
Subscribers: rnk, zturner, llvm-commits
Differential Revision: https://reviews.llvm.org/D38891
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@317705 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/profile/WindowsMMap.c | 58 |
1 files changed, 55 insertions, 3 deletions
diff --git a/lib/profile/WindowsMMap.c b/lib/profile/WindowsMMap.c index f81d7da53..0c534710b 100644 --- a/lib/profile/WindowsMMap.c +++ b/lib/profile/WindowsMMap.c @@ -120,9 +120,61 @@ int msync(void *addr, size_t length, int flags) } COMPILER_RT_VISIBILITY -int flock(int fd, int operation) -{ - return -1; /* Not supported. */ +int lock(HANDLE handle, DWORD lockType, BOOL blocking) { + DWORD flags = lockType; + if (!blocking) + flags |= LOCKFILE_FAIL_IMMEDIATELY; + + OVERLAPPED overlapped; + ZeroMemory(&overlapped, sizeof(OVERLAPPED)); + overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + BOOL result = LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped); + if (!result) { + DWORD dw = GetLastError(); + + // In non-blocking mode, return an error if the file is locked. + if (!blocking && dw == ERROR_LOCK_VIOLATION) + return -1; // EWOULDBLOCK + + // If the error is ERROR_IO_PENDING, we need to wait until the operation + // finishes. Otherwise, we return an error. + if (dw != ERROR_IO_PENDING) + return -1; + + DWORD dwNumBytes; + if (!GetOverlappedResult(handle, &overlapped, &dwNumBytes, TRUE)) + return -1; + } + + return 0; +} + +COMPILER_RT_VISIBILITY +int flock(int fd, int operation) { + HANDLE handle = (HANDLE)_get_osfhandle(fd); + if (handle == INVALID_HANDLE_VALUE) + return -1; + + BOOL blocking = (operation & LOCK_NB) == 0; + int op = operation & ~LOCK_NB; + + switch (op) { + case LOCK_EX: + return lock(handle, LOCKFILE_EXCLUSIVE_LOCK, blocking); + + case LOCK_SH: + return lock(handle, 0, blocking); + + case LOCK_UN: + if (!UnlockFile(handle, 0, 0, MAXDWORD, MAXDWORD)) + return -1; + break; + + default: + return -1; + } + + return 0; } #undef DWORD_HI |