Exports.swift 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /*
  2. This source file is part of the Swift System open source project
  3. Copyright (c) 2020 - 2026 Apple Inc. and the Swift System project authors
  4. Licensed under Apache License v2.0 with Runtime Library Exception
  5. See https://swift.org/LICENSE.txt for license information
  6. */
  7. // Internal wrappers and typedefs which help reduce #if littering in System's
  8. // code base.
  9. // TODO: Should CSystem just include all the header files we need?
  10. #if SYSTEM_PACKAGE_DARWIN
  11. import Darwin
  12. #elseif os(Windows)
  13. import CSystem
  14. import ucrt
  15. #elseif canImport(Glibc)
  16. import CSystem
  17. import Glibc
  18. #elseif canImport(Musl)
  19. import CSystem
  20. import Musl
  21. #elseif canImport(WASILibc)
  22. import WASILibc
  23. #elseif canImport(Android)
  24. import CSystem
  25. import Android
  26. #else
  27. #error("Unsupported Platform")
  28. #endif
  29. internal typealias _COffT = off_t
  30. // MARK: syscalls and variables
  31. #if SYSTEM_PACKAGE_DARWIN
  32. internal var system_errno: CInt {
  33. get { Darwin.errno }
  34. set { Darwin.errno = newValue }
  35. }
  36. #elseif os(Windows)
  37. internal var system_errno: CInt {
  38. get {
  39. var value: CInt = 0
  40. // TODO(compnerd) handle the error?
  41. _ = ucrt._get_errno(&value)
  42. return value
  43. }
  44. set {
  45. _ = ucrt._set_errno(newValue)
  46. }
  47. }
  48. #elseif canImport(Glibc)
  49. internal var system_errno: CInt {
  50. get { Glibc.errno }
  51. set { Glibc.errno = newValue }
  52. }
  53. #elseif canImport(Musl)
  54. internal var system_errno: CInt {
  55. get { Musl.errno }
  56. set { Musl.errno = newValue }
  57. }
  58. #elseif canImport(WASILibc)
  59. internal var system_errno: CInt {
  60. get { WASILibc.errno }
  61. set { WASILibc.errno = newValue }
  62. }
  63. #elseif canImport(Android)
  64. internal var system_errno: CInt {
  65. get { Android.errno }
  66. set { Android.errno = newValue }
  67. }
  68. #endif
  69. // MARK: C stdlib decls
  70. // Convention: `system_foo` is system's wrapper for `foo`.
  71. internal func system_strerror(_ __errnum: Int32) -> UnsafeMutablePointer<Int8>! {
  72. strerror(__errnum)
  73. }
  74. internal func system_strlen(_ s: UnsafePointer<CChar>) -> Int {
  75. strlen(s)
  76. }
  77. internal func system_strlen(_ s: UnsafeMutablePointer<CChar>) -> Int {
  78. strlen(s)
  79. }
  80. #if !os(Windows)
  81. @available(System 0.0.2, *)
  82. @_alwaysEmitIntoClient
  83. internal func system_stat(_ p: UnsafePointer<CChar>, _ s: inout CInterop.Stat) -> Int32 {
  84. stat(p, &s)
  85. }
  86. @available(System 1.7.0, *)
  87. internal func system_lstat(_ p: UnsafePointer<CChar>, _ s: inout CInterop.Stat) -> Int32 {
  88. lstat(p, &s)
  89. }
  90. @available(System 1.7.0, *)
  91. internal func system_fstat(_ fd: CInt, _ s: inout CInterop.Stat) -> Int32 {
  92. fstat(fd, &s)
  93. }
  94. @available(System 1.7.0, *)
  95. internal func system_fstatat(_ fd: CInt, _ p: UnsafePointer<CChar>, _ s: inout CInterop.Stat, _ flags: CInt) -> Int32 {
  96. fstatat(fd, p, &s, flags)
  97. }
  98. #endif
  99. // Convention: `system_platform_foo` is a
  100. // platform-representation-abstracted wrapper around `foo`-like functionality.
  101. // Type and layout differences such as the `char` vs `wchar` are abstracted.
  102. //
  103. // strlen for the platform string
  104. internal func system_platform_strlen(_ s: UnsafePointer<CInterop.PlatformChar>) -> Int {
  105. #if os(Windows)
  106. return wcslen(s)
  107. #else
  108. return strlen(s)
  109. #endif
  110. }
  111. // memset for raw buffers
  112. // FIXME: Do we really not have something like this in the stdlib already?
  113. internal func system_memset(
  114. _ buffer: UnsafeMutableRawBufferPointer,
  115. to byte: UInt8
  116. ) {
  117. guard buffer.count > 0 else { return }
  118. memset(buffer.baseAddress!, CInt(byte), buffer.count)
  119. }
  120. // Interop between String and platfrom string
  121. extension String {
  122. internal func _withPlatformString<Result>(
  123. _ body: (UnsafePointer<CInterop.PlatformChar>) throws -> Result
  124. ) rethrows -> Result {
  125. // Need to #if because CChar may be signed
  126. #if os(Windows)
  127. return try withCString(encodedAs: CInterop.PlatformUnicodeEncoding.self, body)
  128. #else
  129. return try withCString(body)
  130. #endif
  131. }
  132. internal init?(_platformString platformString: UnsafePointer<CInterop.PlatformChar>) {
  133. // Need to #if because CChar may be signed
  134. #if os(Windows)
  135. guard let strRes = String.decodeCString(
  136. platformString,
  137. as: CInterop.PlatformUnicodeEncoding.self,
  138. repairingInvalidCodeUnits: false
  139. ) else { return nil }
  140. assert(strRes.repairsMade == false)
  141. self = strRes.result
  142. return
  143. #else
  144. self.init(validatingCString: platformString)
  145. #endif
  146. }
  147. internal init(
  148. _errorCorrectingPlatformString platformString: UnsafePointer<CInterop.PlatformChar>
  149. ) {
  150. // Need to #if because CChar may be signed
  151. #if os(Windows)
  152. let strRes = String.decodeCString(
  153. platformString,
  154. as: CInterop.PlatformUnicodeEncoding.self,
  155. repairingInvalidCodeUnits: true)
  156. self = strRes!.result
  157. return
  158. #else
  159. self.init(cString: platformString)
  160. #endif
  161. }
  162. }
  163. // TLS
  164. #if os(Windows)
  165. internal typealias _PlatformTLSKey = DWORD
  166. #elseif os(WASI) && !_runtime(_multithreaded)
  167. // Mock TLS storage for single-threaded WASI.
  168. // Carries no state of its own, and only used to index `sharedTLSStorage`.
  169. internal final class _PlatformTLSKey: @unchecked Sendable {
  170. fileprivate init() {}
  171. }
  172. private final class TLSStorage: @unchecked Sendable {
  173. var storage = [ObjectIdentifier: UnsafeMutableRawPointer]()
  174. }
  175. private let sharedTLSStorage = TLSStorage()
  176. func pthread_setspecific(_ key: _PlatformTLSKey, _ p: UnsafeMutableRawPointer?) -> Int {
  177. sharedTLSStorage.storage[ObjectIdentifier(key)] = p
  178. return 0
  179. }
  180. func pthread_getspecific(_ key: _PlatformTLSKey) -> UnsafeMutableRawPointer? {
  181. sharedTLSStorage.storage[ObjectIdentifier(key)]
  182. }
  183. #else
  184. internal typealias _PlatformTLSKey = pthread_key_t
  185. #endif
  186. internal func makeTLSKey() -> _PlatformTLSKey {
  187. #if os(Windows)
  188. let raw: DWORD = FlsAlloc(nil)
  189. if raw == FLS_OUT_OF_INDEXES {
  190. fatalError("Unable to create key")
  191. }
  192. return raw
  193. #elseif os(WASI) && !_runtime(_multithreaded)
  194. return _PlatformTLSKey()
  195. #else
  196. var raw = pthread_key_t()
  197. guard 0 == pthread_key_create(&raw, nil) else {
  198. fatalError("Unable to create key")
  199. }
  200. return raw
  201. #endif
  202. }
  203. internal func setTLS(_ key: _PlatformTLSKey, _ p: UnsafeMutableRawPointer?) {
  204. #if os(Windows)
  205. guard FlsSetValue(key, p) else {
  206. fatalError("Unable to set TLS")
  207. }
  208. #else
  209. guard 0 == pthread_setspecific(key, p) else {
  210. fatalError("Unable to set TLS")
  211. }
  212. #endif
  213. }
  214. internal func getTLS(_ key: _PlatformTLSKey) -> UnsafeMutableRawPointer? {
  215. #if os(Windows)
  216. return FlsGetValue(key)
  217. #else
  218. return pthread_getspecific(key)
  219. #endif
  220. }