From 5712a283775e86ec6f2393c3ad853a5709bc3960 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Thu, 22 Oct 2020 17:24:51 -0700 Subject: [PATCH 1/2] Windows TLS mocking support --- Sources/SystemInternals/Mocking.swift | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/Sources/SystemInternals/Mocking.swift b/Sources/SystemInternals/Mocking.swift index 725feef1..343372d7 100644 --- a/Sources/SystemInternals/Mocking.swift +++ b/Sources/SystemInternals/Mocking.swift @@ -92,7 +92,26 @@ import Glibc #endif // TLS helper functions -#if !os(Windows) +#if os(Windows) +internal typealias TLSKey = DWORD +internal func makeTLSKey() -> TLSKey { + var raw: DWORD = FlsAlloc(nil) + if raw == FLS_OUT_OF_INDEXES { + fatalError("Unable to create key") + } + return raw +} +internal func setTLS(_ key: TLSKey, _ p: UnsafeMutableRawPointer?) { + guard 0 != FlsSetValue(key, p) else { + fatalError("Unable to set TLS") + } +} +internal func getTLS(_ key: TLSKey) -> UnsafeMutableRawPointer? { + FlsGetValue(key) +} + +#else + internal typealias TLSKey = pthread_key_t internal func makeTLSKey() -> TLSKey { var raw = pthread_key_t() @@ -109,9 +128,6 @@ internal func setTLS(_ key: TLSKey, _ p: UnsafeMutableRawPointer?) { internal func getTLS(_ key: TLSKey) -> UnsafeMutableRawPointer? { pthread_getspecific(key) } -#else -// TODO: Windows version... -#error("Unsupported Platform") #endif private let driverKey: TLSKey = { makeTLSKey() }() From 1eeeaf72009e4af41b61ee3484db76d156a43018 Mon Sep 17 00:00:00 2001 From: Michael Ilseman Date: Thu, 22 Oct 2020 17:17:39 -0700 Subject: [PATCH 2/2] Initial Windows syscall adapters --- Sources/SystemInternals/Syscalls.swift | 4 +- .../WindowsSyscallAdapters.swift | 102 ++++++++++++++++++ 2 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 Sources/SystemInternals/WindowsSyscallAdapters.swift diff --git a/Sources/SystemInternals/Syscalls.swift b/Sources/SystemInternals/Syscalls.swift index 2deea86f..a78760da 100644 --- a/Sources/SystemInternals/Syscalls.swift +++ b/Sources/SystemInternals/Syscalls.swift @@ -35,11 +35,11 @@ private func mockImpl( switch driver.forceErrno { case .none: break case .always(let e): - errno = e + system_errno = e return -1 case .counted(let e, let count): assert(count >= 1) - errno = e + system_errno = e driver.forceErrno = count > 1 ? .counted(errno: e, count: count-1) : .none return -1 } diff --git a/Sources/SystemInternals/WindowsSyscallAdapters.swift b/Sources/SystemInternals/WindowsSyscallAdapters.swift new file mode 100644 index 00000000..7a97695f --- /dev/null +++ b/Sources/SystemInternals/WindowsSyscallAdapters.swift @@ -0,0 +1,102 @@ +/* + This source file is part of the Swift System open source project + + Copyright (c) 2020 Apple Inc. and the Swift System project authors + Licensed under Apache License v2.0 with Runtime Library Exception + + See https://swift.org/LICENSE.txt for license information +*/ + +#if os(Windows) + +@inline(__always) +internal func open(_ path: UnsafePointer, _ oflag: Int32) { + var fh: CInt = -1 + _ = _sopen_s(&fh, path, oflag, _SH_DENYNO, _S_IREAD | _S_IWRITE) + return fh +} + +@inline(__always) +internal func open( + _ path: UnsafePointer, _ oflag: Int32, _ mode: mode_t +) -> CInt { + // TODO(compnerd): Apply read/write permissions + var fh: CInt = -1 + _ = _sopen_s(&fh, path, oflag, _SH_DENYNO, _S_IREAD | _S_IWRITE) + return fh +} + +@inline(__always) +internal func close(_ fd: Int32) -> Int32 { + _close(fd) +} + +@inline(__always) +internal func lseek( + _ fd: Int32, _ off: off_t, _ whence: Int32 +) -> off_t { + _lseek(fd, off, whence) +} + +@inline(__always) +internal func read( + _ fd: Int32, _ buf: UnsafeMutableRawPointer!, _ nbyte: Int +) -> Int { + Int(_read(fd, buf, numericCast(nbyte))) +} + +@inline(__always) +internal func write( + _ fd: Int32, _ buf: UnsafeRawPointer!, _ nbyte: Int +) -> Int { + Int(_write(fd, buf, numericCast(nbyte))) +} + +@inline(__always) +internal func pread( + _ fd: Int32, _ buf: UnsafeMutableRawPointer!, _ nbyte: Int, _ offset: off_t +) -> Int { + let handle: intptr_t = _get_osfhandle(fd) + if handle == /* INVALID_HANDLE_VALUE */ -1 { return Int(EBADF) } + + // NOTE: this is a non-owning handle, do *not* call CloseHandle on it + let hFile: HANDLE = HANDLE(bitPattern: handle)! + + var ovlOverlapped: OVERLAPPED = OVERLAPPED() + ovlOverlapped.OffsetHigh = DWORD(UInt32(offset >> 32) & 0xffffffff) + ovlOverlapped.Offset = DWORD(UInt32(offset >> 0) & 0xffffffff) + + var nNumberOfBytesRead: DWORD = 0 + if !ReadFile(hFile, buf, DWORD(nbyte), &nNumberOfBytesRead, &ovlOverlapped) { + let _ = GetLastError() + // TODO(compnerd) map windows error to errno + return Int(-1) + } + return Int(nNumberOfBytesRead) +} + +@inline(__always) +internal func pwrite( + _ fd: Int32, _ buf: UnsafeRawPointer!, _ nbyte: Int, _ offset: off_t +) -> Int { + let handle: intptr_t = _get_osfhandle(fd) + if handle == /* INVALID_HANDLE_VALUE */ -1 { return Int(EBADF) } + + // NOTE: this is a non-owning handle, do *not* call CloseHandle on it + let hFile: HANDLE = HANDLE(bitPattern: handle)! + + var ovlOverlapped: OVERLAPPED = OVERLAPPED() + ovlOverlapped.OffsetHigh = DWORD(UInt32(offset >> 32) & 0xffffffff) + ovlOverlapped.Offset = DWORD(UInt32(offset >> 0) & 0xffffffff) + + var nNumberOfBytesWritten: DWORD = 0 + if !WriteFile(hFile, buf, DWORD(nbyte), &nNumberOfBytesWritten, + &ovlOverlapped) { + let _ = GetLastError() + // TODO(compnerd) map windows error to errno + return Int(-1) + } + return Int(nNumberOfBytesWritten) +} + +#endif