Skip to content

Commit 261ca25

Browse files
committed
Centralize on Errno for errors, and work around lifetime compiler crash. There's a second compiler crash still to work around though.
1 parent 014f8b7 commit 261ca25

File tree

1 file changed

+52
-107
lines changed

1 file changed

+52
-107
lines changed

Sources/System/IORing.swift

Lines changed: 52 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ internal func _enter(
118118
numEvents: UInt32,
119119
minCompletions: UInt32,
120120
flags: UInt32
121-
) throws(IORing.OperationError) -> Int32 {
121+
) throws(Errno) -> Int32 {
122122
// Ring always needs enter right now;
123123
// TODO: support SQPOLL here
124124
while true {
@@ -133,14 +133,14 @@ internal func _enter(
133133
//TODO: should we wait a bit on AGAIN?
134134
continue
135135
} else if ret < 0 {
136-
throw(IORing.OperationError(result: -ret))
136+
throw(Errno(rawValue: -ret))
137137
} else {
138138
return ret
139139
}
140140
}
141141
}
142142

143-
internal func _submitRequests(ring: borrowing SQRing, ringDescriptor: Int32) throws(IORing.OperationError) {
143+
internal func _submitRequests(ring: borrowing SQRing, ringDescriptor: Int32) throws(Errno) {
144144
let flushedEvents = _flushQueue(ring: ring)
145145
_ = try _enter(
146146
ringDescriptor: ringDescriptor, numEvents: flushedEvents, minCompletions: 0, flags: 0)
@@ -193,7 +193,7 @@ internal func _getSubmissionEntry(
193193

194194
private func setUpRing(
195195
queueDepth: UInt32, flags: IORing.SetupFlags, submissionRing: inout SQRing
196-
) throws(IORing.SetupError) ->
196+
) throws(Errno) ->
197197
(params: io_uring_params, ringDescriptor: Int32, ringPtr: UnsafeMutableRawPointer, ringSize: Int, sqes: UnsafeMutableRawPointer) {
198198
var params = io_uring_params()
199199
params.flags = flags.rawValue
@@ -208,15 +208,15 @@ private func setUpRing(
208208
}
209209

210210
if let err {
211-
throw IORing.SetupError(setupResult: err.rawValue)
211+
throw err
212212
}
213213

214214
if params.features & IORING_FEAT_SINGLE_MMAP == 0
215215
|| params.features & IORING_FEAT_NODROP == 0
216216
{
217217
close(ringDescriptor)
218218
// TODO: error handling
219-
throw .missingRequiredFeatures
219+
throw Errno.invalidArgument
220220
}
221221

222222
let submitRingSize =
@@ -239,9 +239,10 @@ private func setUpRing(
239239
)
240240

241241
if ringPtr == MAP_FAILED {
242+
let errno = Errno.current
242243
perror("mmap")
243244
close(ringDescriptor)
244-
throw .mapFailed
245+
throw errno
245246
}
246247

247248
let submissionRing = SQRing(
@@ -285,52 +286,17 @@ private func setUpRing(
285286
)
286287

287288
if sqes == MAP_FAILED {
289+
let errno = Errno.current
288290
perror("mmap")
289291
munmap(ringPtr, ringSize)
290292
close(ringDescriptor)
291-
throw .mapFailed
293+
throw errno
292294
}
293295

294296
return (params: params, ringDescriptor: ringDescriptor, ringPtr: ringPtr!, ringSize: ringSize, sqes: sqes!)
295297
}
296298

297299
public struct IORing: ~Copyable {
298-
299-
/// Errors in either submitting operations or receiving operation completions
300-
@frozen
301-
public struct OperationError: Error, Hashable {
302-
private var errorCode: Int
303-
public static var operationCanceled: OperationError { .init(result: ECANCELED) }
304-
305-
internal init(result: Int32) {
306-
errorCode = Int(result) //TODO, flesh this out
307-
}
308-
}
309-
310-
@frozen
311-
public struct SetupError: Error, Hashable {
312-
private var errorCode: Int
313-
314-
public static var missingRequiredFeatures: SetupError {
315-
.init(setupResult: -1) /* TODO: numeric value */
316-
}
317-
318-
public static var mapFailed: SetupError { .init(setupResult: -2) }
319-
320-
internal init(setupResult: Int32) {
321-
errorCode = Int(setupResult) //TODO, flesh this out
322-
}
323-
}
324-
325-
@frozen
326-
public struct RegistrationError: Error, Hashable {
327-
private var errorCode: Int
328-
329-
internal init(registrationResult: Int32) {
330-
errorCode = Int(registrationResult) //TODO, flesh this out
331-
}
332-
}
333-
334300
let ringFlags: UInt32
335301
let ringDescriptor: Int32
336302

@@ -346,8 +312,8 @@ public struct IORing: ~Copyable {
346312
let ringSize: Int
347313
let ringPtr: UnsafeMutableRawPointer
348314

349-
var _registeredFiles: [UInt32] = []
350-
var _registeredBuffers: [iovec] = []
315+
var _registeredFiles: [UInt32]
316+
var _registeredBuffers: [iovec]
351317

352318
var features = Features(rawValue: 0)
353319

@@ -375,7 +341,7 @@ public struct IORing: ~Copyable {
375341
//TODO: should IORING_SETUP_NO_SQARRAY be the default? do we need to adapt anything to it?
376342
}
377343

378-
public init(queueDepth: UInt32, flags: SetupFlags) throws(SetupError) {
344+
public init(queueDepth: UInt32, flags: SetupFlags) throws(Errno) {
379345
let (params, tmpRingDescriptor, tmpRingPtr, tmpRingSize, sqes) = try setUpRing(queueDepth: queueDepth, flags: flags, submissionRing: &submissionRing)
380346
// All throws need to be before initializing ivars here to avoid
381347
// "error: conditional initialization or destruction of noncopyable types is not supported;
@@ -384,6 +350,8 @@ public struct IORing: ~Copyable {
384350
ringDescriptor = tmpRingDescriptor
385351
ringPtr = tmpRingPtr
386352
ringSize = tmpRingSize
353+
_registeredFiles = []
354+
_registeredBuffers = []
387355

388356
submissionQueueEntries = UnsafeMutableBufferPointer(
389357
start: sqes.assumingMemoryBound(to: io_uring_sqe.self),
@@ -417,13 +385,13 @@ public struct IORing: ~Copyable {
417385
minimumCount: UInt32,
418386
maximumCount: UInt32,
419387
extraArgs: UnsafeMutablePointer<io_uring_getevents_arg>? = nil,
420-
consumer: (consuming IOCompletion?, OperationError?, Bool) throws(Err) -> Void
388+
consumer: (consuming IOCompletion?, Errno?, Bool) throws(Err) -> Void
421389
) throws(Err) {
422390
var count = 0
423391
while let completion = _tryConsumeCompletion(ring: completionRing) {
424392
count += 1
425393
if completion.result < 0 {
426-
try consumer(nil, OperationError(result: completion.result), false)
394+
try consumer(nil, Errno(rawValue: -completion.result), false)
427395
} else {
428396
try consumer(completion, nil, false)
429397
}
@@ -469,7 +437,7 @@ public struct IORing: ~Copyable {
469437
while let completion = _tryConsumeCompletion(ring: completionRing) {
470438
count += 1
471439
if completion.result < 0 {
472-
try consumer(nil, OperationError(result: completion.result), false)
440+
try consumer(nil, Errno(rawValue: -completion.result), false)
473441
} else {
474442
try consumer(completion, nil, false)
475443
}
@@ -483,52 +451,37 @@ public struct IORing: ~Copyable {
483451

484452
internal func _blockingConsumeOneCompletion(
485453
extraArgs: UnsafeMutablePointer<io_uring_getevents_arg>? = nil
486-
) throws(OperationError) -> IOCompletion {
454+
) throws(Errno) -> IOCompletion {
487455
var result: IOCompletion? = nil
488-
do {
489-
try _blockingConsumeCompletionGuts(minimumCount: 1, maximumCount: 1, extraArgs: extraArgs) {
490-
(completion: consuming IOCompletion?, error, done) in
491-
if let error {
492-
throw error
493-
}
494-
if let completion {
495-
result = consume completion
496-
}
456+
try _blockingConsumeCompletionGuts(minimumCount: 1, maximumCount: 1, extraArgs: extraArgs) {
457+
(completion: consuming IOCompletion?, error, done) throws(Errno) in
458+
if let error {
459+
throw error
460+
}
461+
if let completion {
462+
result = consume completion
497463
}
498-
} catch (let e) {
499-
throw e as! OperationError //TODO: why is this needed?
500464
}
501465
return result.take()!
502466
}
503467

504468
public func blockingConsumeCompletion(
505469
timeout: Duration? = nil
506-
) throws(OperationError) -> IOCompletion {
470+
) throws(Errno) -> IOCompletion {
507471
if let timeout {
508472
var ts = __kernel_timespec(
509473
tv_sec: timeout.components.seconds,
510474
tv_nsec: timeout.components.attoseconds / 1_000_000_000
511475
)
512-
var err: OperationError? = nil
513-
var result: IOCompletion? = nil
514-
result = withUnsafePointer(to: &ts) { tsPtr in
476+
return try withUnsafePointer(to: &ts) { (tsPtr) throws(Errno) -> IOCompletion in
515477
var args = io_uring_getevents_arg(
516478
sigmask: 0,
517479
sigmask_sz: 0,
518480
pad: 0,
519481
ts: UInt64(UInt(bitPattern: tsPtr))
520482
)
521-
do {
522-
return try _blockingConsumeOneCompletion(extraArgs: &args)
523-
} catch (let e) {
524-
err = (e as! OperationError)
525-
return nil
526-
}
527-
}
528-
guard let result else {
529-
throw(err!)
483+
return try _blockingConsumeOneCompletion(extraArgs: &args)
530484
}
531-
return result
532485
} else {
533486
return try _blockingConsumeOneCompletion()
534487
}
@@ -537,31 +490,23 @@ public struct IORing: ~Copyable {
537490
public func blockingConsumeCompletions<Err: Error>(
538491
minimumCount: UInt32 = 1,
539492
timeout: Duration? = nil,
540-
consumer: (consuming IOCompletion?, OperationError?, Bool) throws(Err) -> Void
493+
consumer: (consuming IOCompletion?, Errno?, Bool) throws(Err) -> Void
541494
) throws(Err) {
542495
if let timeout {
543496
var ts = __kernel_timespec(
544497
tv_sec: timeout.components.seconds,
545498
tv_nsec: timeout.components.attoseconds / 1_000_000_000
546499
)
547-
var err: Err? = nil
548-
withUnsafePointer(to: &ts) { tsPtr in
500+
try withUnsafePointer(to: &ts) { (tsPtr) throws(Err) in
549501
var args = io_uring_getevents_arg(
550502
sigmask: 0,
551503
sigmask_sz: 0,
552504
pad: 0,
553505
ts: UInt64(UInt(bitPattern: tsPtr))
554506
)
555-
do {
556-
try _blockingConsumeCompletionGuts(
557-
minimumCount: minimumCount, maximumCount: UInt32.max, extraArgs: &args,
558-
consumer: consumer)
559-
} catch (let e) {
560-
err = (e as! Err) //TODO: why is `e` coming in as `any Error`? That seems wrong
561-
}
562-
}
563-
if let err {
564-
throw(err)
507+
try _blockingConsumeCompletionGuts(
508+
minimumCount: minimumCount, maximumCount: UInt32.max, extraArgs: &args,
509+
consumer: consumer)
565510
}
566511
} else {
567512
try _blockingConsumeCompletionGuts(
@@ -591,7 +536,7 @@ public struct IORing: ~Copyable {
591536
return nil
592537
}
593538

594-
public mutating func registerEventFD(_ descriptor: FileDescriptor) throws(RegistrationError) {
539+
public mutating func registerEventFD(_ descriptor: FileDescriptor) throws(Errno) {
595540
var rawfd = descriptor.rawValue
596541
let result = withUnsafePointer(to: &rawfd) { fdptr in
597542
let result = io_uring_register(
@@ -600,26 +545,26 @@ public struct IORing: ~Copyable {
600545
UnsafeMutableRawPointer(mutating: fdptr),
601546
1
602547
)
603-
return result >= 0 ? nil : Errno.current
548+
return result >= 0 ? nil : Errno(rawValue: -result)
604549
}
605550
if let result {
606-
throw(RegistrationError(registrationResult: result.rawValue))
551+
throw result
607552
}
608553
}
609554

610-
public mutating func unregisterEventFD() throws(RegistrationError) {
555+
public mutating func unregisterEventFD() throws(Errno) {
611556
let result = io_uring_register(
612557
ringDescriptor,
613558
IORING_UNREGISTER_EVENTFD,
614559
nil,
615560
0
616561
)
617562
if result < 0 {
618-
throw(RegistrationError(registrationResult: result))
563+
throw Errno(rawValue: -result)
619564
}
620565
}
621566

622-
public mutating func registerFileSlots(count: Int) throws(RegistrationError) -> RegisteredResources<
567+
public mutating func registerFileSlots(count: Int) throws(Errno) -> RegisteredResources<
623568
IORingFileSlot.Resource
624569
> {
625570
precondition(_registeredFiles.isEmpty)
@@ -633,11 +578,11 @@ public struct IORing: ~Copyable {
633578
UnsafeMutableRawPointer(mutating: bPtr.baseAddress!),
634579
UInt32(truncatingIfNeeded: count)
635580
)
636-
return result >= 0 ? nil : Errno.current
581+
return result >= 0 ? nil : Errno(rawValue: -result)
637582
}
638-
639-
guard regResult == nil else {
640-
throw RegistrationError(registrationResult: regResult!.rawValue)
583+
584+
if let regResult {
585+
throw regResult
641586
}
642587

643588
_registeredFiles = files
@@ -652,7 +597,7 @@ public struct IORing: ~Copyable {
652597
RegisteredResources(resources: _registeredFiles)
653598
}
654599

655-
public mutating func registerBuffers(_ buffers: some Collection<UnsafeMutableRawBufferPointer>) throws(RegistrationError)
600+
public mutating func registerBuffers(_ buffers: some Collection<UnsafeMutableRawBufferPointer>) throws(Errno)
656601
-> RegisteredResources<IORingBuffer.Resource>
657602
{
658603
precondition(buffers.count < UInt32.max)
@@ -666,19 +611,19 @@ public struct IORing: ~Copyable {
666611
UnsafeMutableRawPointer(mutating: bPtr.baseAddress!),
667612
UInt32(truncatingIfNeeded: buffers.count)
668613
)
669-
return result >= 0 ? nil : Errno.current
614+
return result >= 0 ? nil : Errno(rawValue: -result)
670615
}
671616

672-
guard regResult == nil else {
673-
throw RegistrationError(registrationResult: regResult!.rawValue)
617+
if let regResult {
618+
throw regResult
674619
}
675620

676621
// TODO: error handling
677622
_registeredBuffers = iovecs
678623
return registeredBuffers
679624
}
680625

681-
public mutating func registerBuffers(_ buffers: UnsafeMutableRawBufferPointer...) throws(RegistrationError)
626+
public mutating func registerBuffers(_ buffers: UnsafeMutableRawBufferPointer...) throws(Errno)
682627
-> RegisteredResources<IORingBuffer.Resource>
683628
{
684629
try registerBuffers(buffers)
@@ -708,14 +653,14 @@ public struct IORing: ~Copyable {
708653
fatalError("failed to unregister buffers: TODO")
709654
}
710655

711-
public func submitPreparedRequests() throws(OperationError) {
656+
public func submitPreparedRequests() throws(Errno) {
712657
try _submitRequests(ring: submissionRing, ringDescriptor: ringDescriptor)
713658
}
714659

715660
public func submitPreparedRequestsAndConsumeCompletions<Err: Error>(
716661
minimumCount: UInt32 = 1,
717662
timeout: Duration? = nil,
718-
consumer: (consuming IOCompletion?, OperationError?, Bool) throws(Err) -> Void
663+
consumer: (consuming IOCompletion?, Errno?, Bool) throws(Err) -> Void
719664
) throws(Err) {
720665
//TODO: optimize this to one uring_enter
721666
do {
@@ -757,7 +702,7 @@ public struct IORing: ~Copyable {
757702
prepare(linkedRequests: linkedRequests)
758703
}
759704

760-
public mutating func submit(linkedRequests: IORequest...) throws(OperationError) {
705+
public mutating func submit(linkedRequests: IORequest...) throws(Errno) {
761706
prepare(linkedRequests: linkedRequests)
762707
try submitPreparedRequests()
763708
}

0 commit comments

Comments
 (0)