Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows syscall adapters #11

Merged
merged 2 commits into from
Oct 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions Sources/SystemInternals/Mocking.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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() }()
Expand Down
4 changes: 2 additions & 2 deletions Sources/SystemInternals/Syscalls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
102 changes: 102 additions & 0 deletions Sources/SystemInternals/WindowsSyscallAdapters.swift
Original file line number Diff line number Diff line change
@@ -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<CChar>, _ 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<CChar>, _ 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