summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMarco Castelluccio <mcastelluccio@mozilla.com>2017-11-08 19:11:54 +0000
committerMarco Castelluccio <mcastelluccio@mozilla.com>2017-11-08 19:11:54 +0000
commit07e2a968c83c489c5b46efe4973114e78e1804c1 (patch)
tree5ecc9fe9a721ed2266c2f7773d32385a8c3a1b15 /lib
parent9a46448f818bd47de8604ec9e0e39ced6a00499e (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.c58
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