| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | | const Pool = @This(); |
| 1 | const Threaded = @This(); |
| 2 | 2 | |
| 3 | 3 | const builtin = @import("builtin"); |
| 4 | 4 | const native_os = builtin.os.tag; |
| ... | ... | @@ -76,18 +76,18 @@ pub fn init( |
| 76 | 76 | /// If these functions are avoided, then `Allocator.failing` may be passed |
| 77 | 77 | /// here. |
| 78 | 78 | gpa: Allocator, |
| 79 | | ) Pool { |
| 80 | | var pool: Pool = .{ |
| 79 | ) Threaded { |
| 80 | var t: Threaded = .{ |
| 81 | 81 | .allocator = gpa, |
| 82 | 82 | .threads = .empty, |
| 83 | 83 | .stack_size = std.Thread.SpawnConfig.default_stack_size, |
| 84 | 84 | .cpu_count = std.Thread.getCpuCount(), |
| 85 | 85 | .concurrent_count = 0, |
| 86 | 86 | }; |
| 87 | | if (pool.cpu_count) |n| { |
| 88 | | pool.threads.ensureTotalCapacityPrecise(gpa, n - 1) catch {}; |
| 87 | if (t.cpu_count) |n| { |
| 88 | t.threads.ensureTotalCapacityPrecise(gpa, n - 1) catch {}; |
| 89 | 89 | } else |_| {} |
| 90 | | return pool; |
| 90 | return t; |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | 93 | /// Statically initialize such that any call to the following functions will |
| ... | ... | @@ -96,7 +96,7 @@ pub fn init( |
| 96 | 96 | /// * `Io.VTable.concurrent` |
| 97 | 97 | /// * `Io.VTable.groupAsync` |
| 98 | 98 | /// When initialized this way, `deinit` is safe, but unnecessary to call. |
| 99 | | pub const init_single_threaded: Pool = .{ |
| 99 | pub const init_single_threaded: Threaded = .{ |
| 100 | 100 | .allocator = .failing, |
| 101 | 101 | .threads = .empty, |
| 102 | 102 | .stack_size = std.Thread.SpawnConfig.default_stack_size, |
| ... | ... | @@ -104,48 +104,48 @@ pub const init_single_threaded: Pool = .{ |
| 104 | 104 | .concurrent_count = 0, |
| 105 | 105 | }; |
| 106 | 106 | |
| 107 | | pub fn deinit(pool: *Pool) void { |
| 108 | | const gpa = pool.allocator; |
| 109 | | pool.join(); |
| 110 | | pool.threads.deinit(gpa); |
| 111 | | pool.* = undefined; |
| 107 | pub fn deinit(t: *Threaded) void { |
| 108 | const gpa = t.allocator; |
| 109 | t.join(); |
| 110 | t.threads.deinit(gpa); |
| 111 | t.* = undefined; |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | | fn join(pool: *Pool) void { |
| 114 | fn join(t: *Threaded) void { |
| 115 | 115 | if (builtin.single_threaded) return; |
| 116 | 116 | { |
| 117 | | pool.mutex.lock(); |
| 118 | | defer pool.mutex.unlock(); |
| 119 | | pool.join_requested = true; |
| 117 | t.mutex.lock(); |
| 118 | defer t.mutex.unlock(); |
| 119 | t.join_requested = true; |
| 120 | 120 | } |
| 121 | | pool.cond.broadcast(); |
| 122 | | for (pool.threads.items) |thread| thread.join(); |
| 121 | t.cond.broadcast(); |
| 122 | for (t.threads.items) |thread| thread.join(); |
| 123 | 123 | } |
| 124 | 124 | |
| 125 | | fn worker(pool: *Pool) void { |
| 126 | | pool.mutex.lock(); |
| 127 | | defer pool.mutex.unlock(); |
| 125 | fn worker(t: *Threaded) void { |
| 126 | t.mutex.lock(); |
| 127 | defer t.mutex.unlock(); |
| 128 | 128 | |
| 129 | 129 | while (true) { |
| 130 | | while (pool.run_queue.popFirst()) |closure_node| { |
| 131 | | pool.mutex.unlock(); |
| 130 | while (t.run_queue.popFirst()) |closure_node| { |
| 131 | t.mutex.unlock(); |
| 132 | 132 | const closure: *Closure = @fieldParentPtr("node", closure_node); |
| 133 | 133 | const is_concurrent = closure.is_concurrent; |
| 134 | 134 | closure.start(closure); |
| 135 | | pool.mutex.lock(); |
| 135 | t.mutex.lock(); |
| 136 | 136 | if (is_concurrent) { |
| 137 | 137 | // TODO also pop thread and join sometimes |
| 138 | | pool.concurrent_count -= 1; |
| 138 | t.concurrent_count -= 1; |
| 139 | 139 | } |
| 140 | 140 | } |
| 141 | | if (pool.join_requested) break; |
| 142 | | pool.cond.wait(&pool.mutex); |
| 141 | if (t.join_requested) break; |
| 142 | t.cond.wait(&t.mutex); |
| 143 | 143 | } |
| 144 | 144 | } |
| 145 | 145 | |
| 146 | | pub fn io(pool: *Pool) Io { |
| 146 | pub fn io(t: *Threaded) Io { |
| 147 | 147 | return .{ |
| 148 | | .userdata = pool, |
| 148 | .userdata = t, |
| 149 | 149 | .vtable = &.{ |
| 150 | 150 | .async = async, |
| 151 | 151 | .concurrent = concurrent, |
| ... | ... | @@ -324,14 +324,14 @@ fn async( |
| 324 | 324 | start(context.ptr, result.ptr); |
| 325 | 325 | return null; |
| 326 | 326 | } |
| 327 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 328 | | const cpu_count = pool.cpu_count catch { |
| 327 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 328 | const cpu_count = t.cpu_count catch { |
| 329 | 329 | return concurrent(userdata, result.len, result_alignment, context, context_alignment, start) catch { |
| 330 | 330 | start(context.ptr, result.ptr); |
| 331 | 331 | return null; |
| 332 | 332 | }; |
| 333 | 333 | }; |
| 334 | | const gpa = pool.allocator; |
| 334 | const gpa = t.allocator; |
| 335 | 335 | const context_offset = context_alignment.forward(@sizeOf(AsyncClosure)); |
| 336 | 336 | const result_offset = result_alignment.forward(context_offset + context.len); |
| 337 | 337 | const n = result_offset + result.len; |
| ... | ... | @@ -356,38 +356,38 @@ fn async( |
| 356 | 356 | |
| 357 | 357 | @memcpy(ac.contextPointer()[0..context.len], context); |
| 358 | 358 | |
| 359 | | pool.mutex.lock(); |
| 359 | t.mutex.lock(); |
| 360 | 360 | |
| 361 | | const thread_capacity = cpu_count - 1 + pool.concurrent_count; |
| 361 | const thread_capacity = cpu_count - 1 + t.concurrent_count; |
| 362 | 362 | |
| 363 | | pool.threads.ensureTotalCapacityPrecise(gpa, thread_capacity) catch { |
| 364 | | pool.mutex.unlock(); |
| 363 | t.threads.ensureTotalCapacityPrecise(gpa, thread_capacity) catch { |
| 364 | t.mutex.unlock(); |
| 365 | 365 | ac.free(gpa, result.len); |
| 366 | 366 | start(context.ptr, result.ptr); |
| 367 | 367 | return null; |
| 368 | 368 | }; |
| 369 | 369 | |
| 370 | | pool.run_queue.prepend(&ac.closure.node); |
| 370 | t.run_queue.prepend(&ac.closure.node); |
| 371 | 371 | |
| 372 | | if (pool.threads.items.len < thread_capacity) { |
| 373 | | const thread = std.Thread.spawn(.{ .stack_size = pool.stack_size }, worker, .{pool}) catch { |
| 374 | | if (pool.threads.items.len == 0) { |
| 375 | | assert(pool.run_queue.popFirst() == &ac.closure.node); |
| 376 | | pool.mutex.unlock(); |
| 372 | if (t.threads.items.len < thread_capacity) { |
| 373 | const thread = std.Thread.spawn(.{ .stack_size = t.stack_size }, worker, .{t}) catch { |
| 374 | if (t.threads.items.len == 0) { |
| 375 | assert(t.run_queue.popFirst() == &ac.closure.node); |
| 376 | t.mutex.unlock(); |
| 377 | 377 | ac.free(gpa, result.len); |
| 378 | 378 | start(context.ptr, result.ptr); |
| 379 | 379 | return null; |
| 380 | 380 | } |
| 381 | 381 | // Rely on other workers to do it. |
| 382 | | pool.mutex.unlock(); |
| 383 | | pool.cond.signal(); |
| 382 | t.mutex.unlock(); |
| 383 | t.cond.signal(); |
| 384 | 384 | return @ptrCast(ac); |
| 385 | 385 | }; |
| 386 | | pool.threads.appendAssumeCapacity(thread); |
| 386 | t.threads.appendAssumeCapacity(thread); |
| 387 | 387 | } |
| 388 | 388 | |
| 389 | | pool.mutex.unlock(); |
| 390 | | pool.cond.signal(); |
| 389 | t.mutex.unlock(); |
| 390 | t.cond.signal(); |
| 391 | 391 | return @ptrCast(ac); |
| 392 | 392 | } |
| 393 | 393 | |
| ... | ... | @@ -401,9 +401,9 @@ fn concurrent( |
| 401 | 401 | ) error{OutOfMemory}!*Io.AnyFuture { |
| 402 | 402 | if (builtin.single_threaded) unreachable; |
| 403 | 403 | |
| 404 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 405 | | const cpu_count = pool.cpu_count catch 1; |
| 406 | | const gpa = pool.allocator; |
| 404 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 405 | const cpu_count = t.cpu_count catch 1; |
| 406 | const gpa = t.allocator; |
| 407 | 407 | const context_offset = context_alignment.forward(@sizeOf(AsyncClosure)); |
| 408 | 408 | const result_offset = result_alignment.forward(context_offset + context.len); |
| 409 | 409 | const n = result_offset + result_len; |
| ... | ... | @@ -424,37 +424,37 @@ fn concurrent( |
| 424 | 424 | }; |
| 425 | 425 | @memcpy(ac.contextPointer()[0..context.len], context); |
| 426 | 426 | |
| 427 | | pool.mutex.lock(); |
| 427 | t.mutex.lock(); |
| 428 | 428 | |
| 429 | | pool.concurrent_count += 1; |
| 430 | | const thread_capacity = cpu_count - 1 + pool.concurrent_count; |
| 429 | t.concurrent_count += 1; |
| 430 | const thread_capacity = cpu_count - 1 + t.concurrent_count; |
| 431 | 431 | |
| 432 | | pool.threads.ensureTotalCapacity(gpa, thread_capacity) catch { |
| 433 | | pool.mutex.unlock(); |
| 432 | t.threads.ensureTotalCapacity(gpa, thread_capacity) catch { |
| 433 | t.mutex.unlock(); |
| 434 | 434 | ac.free(gpa, result_len); |
| 435 | 435 | return error.OutOfMemory; |
| 436 | 436 | }; |
| 437 | 437 | |
| 438 | | pool.run_queue.prepend(&ac.closure.node); |
| 438 | t.run_queue.prepend(&ac.closure.node); |
| 439 | 439 | |
| 440 | | if (pool.threads.items.len < thread_capacity) { |
| 441 | | const thread = std.Thread.spawn(.{ .stack_size = pool.stack_size }, worker, .{pool}) catch { |
| 442 | | assert(pool.run_queue.popFirst() == &ac.closure.node); |
| 443 | | pool.mutex.unlock(); |
| 440 | if (t.threads.items.len < thread_capacity) { |
| 441 | const thread = std.Thread.spawn(.{ .stack_size = t.stack_size }, worker, .{t}) catch { |
| 442 | assert(t.run_queue.popFirst() == &ac.closure.node); |
| 443 | t.mutex.unlock(); |
| 444 | 444 | ac.free(gpa, result_len); |
| 445 | 445 | return error.OutOfMemory; |
| 446 | 446 | }; |
| 447 | | pool.threads.appendAssumeCapacity(thread); |
| 447 | t.threads.appendAssumeCapacity(thread); |
| 448 | 448 | } |
| 449 | 449 | |
| 450 | | pool.mutex.unlock(); |
| 451 | | pool.cond.signal(); |
| 450 | t.mutex.unlock(); |
| 451 | t.cond.signal(); |
| 452 | 452 | return @ptrCast(ac); |
| 453 | 453 | } |
| 454 | 454 | |
| 455 | 455 | const GroupClosure = struct { |
| 456 | 456 | closure: Closure, |
| 457 | | pool: *Pool, |
| 457 | t: *Threaded, |
| 458 | 458 | group: *Io.Group, |
| 459 | 459 | /// Points to sibling `GroupClosure`. Used for walking the group to cancel all. |
| 460 | 460 | node: std.SinglyLinkedList.Node, |
| ... | ... | @@ -515,9 +515,9 @@ fn groupAsync( |
| 515 | 515 | start: *const fn (*Io.Group, context: *const anyopaque) void, |
| 516 | 516 | ) void { |
| 517 | 517 | if (builtin.single_threaded) return start(context.ptr); |
| 518 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 519 | | const cpu_count = pool.cpu_count catch 1; |
| 520 | | const gpa = pool.allocator; |
| 518 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 519 | const cpu_count = t.cpu_count catch 1; |
| 520 | const gpa = t.allocator; |
| 521 | 521 | const n = GroupClosure.contextEnd(context_alignment, context.len); |
| 522 | 522 | const gc: *GroupClosure = @ptrCast(@alignCast(gpa.alignedAlloc(u8, .of(GroupClosure), n) catch { |
| 523 | 523 | return start(group, context.ptr); |
| ... | ... | @@ -528,7 +528,7 @@ fn groupAsync( |
| 528 | 528 | .start = GroupClosure.start, |
| 529 | 529 | .is_concurrent = false, |
| 530 | 530 | }, |
| 531 | | .pool = pool, |
| 531 | .t = t, |
| 532 | 532 | .group = group, |
| 533 | 533 | .node = undefined, |
| 534 | 534 | .func = start, |
| ... | ... | @@ -537,30 +537,30 @@ fn groupAsync( |
| 537 | 537 | }; |
| 538 | 538 | @memcpy(gc.contextPointer()[0..context.len], context); |
| 539 | 539 | |
| 540 | | pool.mutex.lock(); |
| 540 | t.mutex.lock(); |
| 541 | 541 | |
| 542 | 542 | // Append to the group linked list inside the mutex to make `Io.Group.async` thread-safe. |
| 543 | 543 | gc.node = .{ .next = @ptrCast(@alignCast(group.token)) }; |
| 544 | 544 | group.token = &gc.node; |
| 545 | 545 | |
| 546 | | const thread_capacity = cpu_count - 1 + pool.concurrent_count; |
| 546 | const thread_capacity = cpu_count - 1 + t.concurrent_count; |
| 547 | 547 | |
| 548 | | pool.threads.ensureTotalCapacityPrecise(gpa, thread_capacity) catch { |
| 549 | | pool.mutex.unlock(); |
| 548 | t.threads.ensureTotalCapacityPrecise(gpa, thread_capacity) catch { |
| 549 | t.mutex.unlock(); |
| 550 | 550 | gc.free(gpa); |
| 551 | 551 | return start(group, context.ptr); |
| 552 | 552 | }; |
| 553 | 553 | |
| 554 | | pool.run_queue.prepend(&gc.closure.node); |
| 554 | t.run_queue.prepend(&gc.closure.node); |
| 555 | 555 | |
| 556 | | if (pool.threads.items.len < thread_capacity) { |
| 557 | | const thread = std.Thread.spawn(.{ .stack_size = pool.stack_size }, worker, .{pool}) catch { |
| 558 | | assert(pool.run_queue.popFirst() == &gc.closure.node); |
| 559 | | pool.mutex.unlock(); |
| 556 | if (t.threads.items.len < thread_capacity) { |
| 557 | const thread = std.Thread.spawn(.{ .stack_size = t.stack_size }, worker, .{t}) catch { |
| 558 | assert(t.run_queue.popFirst() == &gc.closure.node); |
| 559 | t.mutex.unlock(); |
| 560 | 560 | gc.free(gpa); |
| 561 | 561 | return start(group, context.ptr); |
| 562 | 562 | }; |
| 563 | | pool.threads.appendAssumeCapacity(thread); |
| 563 | t.threads.appendAssumeCapacity(thread); |
| 564 | 564 | } |
| 565 | 565 | |
| 566 | 566 | // This needs to be done before unlocking the mutex to avoid a race with |
| ... | ... | @@ -568,13 +568,13 @@ fn groupAsync( |
| 568 | 568 | const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); |
| 569 | 569 | std.Thread.WaitGroup.startStateless(group_state); |
| 570 | 570 | |
| 571 | | pool.mutex.unlock(); |
| 572 | | pool.cond.signal(); |
| 571 | t.mutex.unlock(); |
| 572 | t.cond.signal(); |
| 573 | 573 | } |
| 574 | 574 | |
| 575 | 575 | fn groupWait(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { |
| 576 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 577 | | const gpa = pool.allocator; |
| 576 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 577 | const gpa = t.allocator; |
| 578 | 578 | |
| 579 | 579 | if (builtin.single_threaded) return; |
| 580 | 580 | |
| ... | ... | @@ -593,8 +593,8 @@ fn groupWait(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { |
| 593 | 593 | } |
| 594 | 594 | |
| 595 | 595 | fn groupCancel(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { |
| 596 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 597 | | const gpa = pool.allocator; |
| 596 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 597 | const gpa = t.allocator; |
| 598 | 598 | |
| 599 | 599 | if (builtin.single_threaded) return; |
| 600 | 600 | |
| ... | ... | @@ -629,9 +629,9 @@ fn await( |
| 629 | 629 | result_alignment: std.mem.Alignment, |
| 630 | 630 | ) void { |
| 631 | 631 | _ = result_alignment; |
| 632 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 632 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 633 | 633 | const closure: *AsyncClosure = @ptrCast(@alignCast(any_future)); |
| 634 | | closure.waitAndFree(pool.allocator, result); |
| 634 | closure.waitAndFree(t.allocator, result); |
| 635 | 635 | } |
| 636 | 636 | |
| 637 | 637 | fn cancel( |
| ... | ... | @@ -641,31 +641,31 @@ fn cancel( |
| 641 | 641 | result_alignment: std.mem.Alignment, |
| 642 | 642 | ) void { |
| 643 | 643 | _ = result_alignment; |
| 644 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 644 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 645 | 645 | const ac: *AsyncClosure = @ptrCast(@alignCast(any_future)); |
| 646 | 646 | ac.closure.requestCancel(); |
| 647 | | ac.waitAndFree(pool.allocator, result); |
| 647 | ac.waitAndFree(t.allocator, result); |
| 648 | 648 | } |
| 649 | 649 | |
| 650 | 650 | fn cancelRequested(userdata: ?*anyopaque) bool { |
| 651 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 652 | | _ = pool; |
| 651 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 652 | _ = t; |
| 653 | 653 | const closure = current_closure orelse return false; |
| 654 | 654 | return @atomicLoad(std.Thread.Id, &closure.cancel_tid, .acquire) == Closure.canceling_tid; |
| 655 | 655 | } |
| 656 | 656 | |
| 657 | | fn checkCancel(pool: *Pool) error{Canceled}!void { |
| 658 | | if (cancelRequested(pool)) return error.Canceled; |
| 657 | fn checkCancel(t: *Threaded) error{Canceled}!void { |
| 658 | if (cancelRequested(t)) return error.Canceled; |
| 659 | 659 | } |
| 660 | 660 | |
| 661 | 661 | fn mutexLock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mutex) Io.Cancelable!void { |
| 662 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 662 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 663 | 663 | if (prev_state == .contended) { |
| 664 | | try pool.checkCancel(); |
| 664 | try t.checkCancel(); |
| 665 | 665 | futexWait(@ptrCast(&mutex.state), @intFromEnum(Io.Mutex.State.contended)); |
| 666 | 666 | } |
| 667 | 667 | while (@atomicRmw(Io.Mutex.State, &mutex.state, .Xchg, .contended, .acquire) != .unlocked) { |
| 668 | | try pool.checkCancel(); |
| 668 | try t.checkCancel(); |
| 669 | 669 | futexWait(@ptrCast(&mutex.state), @intFromEnum(Io.Mutex.State.contended)); |
| 670 | 670 | } |
| 671 | 671 | } |
| ... | ... | @@ -689,8 +689,8 @@ fn mutexUnlock(userdata: ?*anyopaque, prev_state: Io.Mutex.State, mutex: *Io.Mut |
| 689 | 689 | } |
| 690 | 690 | |
| 691 | 691 | fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) void { |
| 692 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 693 | | const pool_io = pool.io(); |
| 692 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 693 | const t_io = t.io(); |
| 694 | 694 | comptime assert(@TypeOf(cond.state) == u64); |
| 695 | 695 | const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state); |
| 696 | 696 | const cond_state = &ints[0]; |
| ... | ... | @@ -704,8 +704,8 @@ fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: |
| 704 | 704 | assert(state & waiter_mask != waiter_mask); |
| 705 | 705 | state += one_waiter; |
| 706 | 706 | |
| 707 | | mutex.unlock(pool_io); |
| 708 | | defer mutex.lockUncancelable(pool_io); |
| 707 | mutex.unlock(t_io); |
| 708 | defer mutex.lockUncancelable(t_io); |
| 709 | 709 | |
| 710 | 710 | while (true) { |
| 711 | 711 | futexWait(cond_epoch, epoch); |
| ... | ... | @@ -719,7 +719,7 @@ fn conditionWaitUncancelable(userdata: ?*anyopaque, cond: *Io.Condition, mutex: |
| 719 | 719 | } |
| 720 | 720 | |
| 721 | 721 | fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) Io.Cancelable!void { |
| 722 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 722 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 723 | 723 | comptime assert(@TypeOf(cond.state) == u64); |
| 724 | 724 | const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state); |
| 725 | 725 | const cond_state = &ints[0]; |
| ... | ... | @@ -743,11 +743,11 @@ fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) I |
| 743 | 743 | assert(state & waiter_mask != waiter_mask); |
| 744 | 744 | state += one_waiter; |
| 745 | 745 | |
| 746 | | mutex.unlock(pool.io()); |
| 747 | | defer mutex.lockUncancelable(pool.io()); |
| 746 | mutex.unlock(t.io()); |
| 747 | defer mutex.lockUncancelable(t.io()); |
| 748 | 748 | |
| 749 | 749 | while (true) { |
| 750 | | try pool.checkCancel(); |
| 750 | try t.checkCancel(); |
| 751 | 751 | futexWait(cond_epoch, epoch); |
| 752 | 752 | |
| 753 | 753 | epoch = cond_epoch.load(.acquire); |
| ... | ... | @@ -764,8 +764,8 @@ fn conditionWait(userdata: ?*anyopaque, cond: *Io.Condition, mutex: *Io.Mutex) I |
| 764 | 764 | } |
| 765 | 765 | |
| 766 | 766 | fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition.Wake) void { |
| 767 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 768 | | _ = pool; |
| 767 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 768 | _ = t; |
| 769 | 769 | comptime assert(@TypeOf(cond.state) == u64); |
| 770 | 770 | const ints: *[2]std.atomic.Value(u32) = @ptrCast(&cond.state); |
| 771 | 771 | const cond_state = &ints[0]; |
| ... | ... | @@ -825,13 +825,13 @@ fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition. |
| 825 | 825 | } |
| 826 | 826 | |
| 827 | 827 | fn dirMakePosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void { |
| 828 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 828 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 829 | 829 | |
| 830 | 830 | var path_buffer: [posix.PATH_MAX]u8 = undefined; |
| 831 | 831 | const sub_path_posix = try pathToPosix(sub_path, &path_buffer); |
| 832 | 832 | |
| 833 | 833 | while (true) { |
| 834 | | try pool.checkCancel(); |
| 834 | try t.checkCancel(); |
| 835 | 835 | switch (posix.errno(posix.system.mkdirat(dir.handle, sub_path_posix, mode))) { |
| 836 | 836 | .SUCCESS => return, |
| 837 | 837 | .INTR => continue, |
| ... | ... | @@ -858,8 +858,8 @@ fn dirMakePosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: |
| 858 | 858 | } |
| 859 | 859 | |
| 860 | 860 | fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat { |
| 861 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 862 | | try pool.checkCancel(); |
| 861 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 862 | try t.checkCancel(); |
| 863 | 863 | |
| 864 | 864 | _ = dir; |
| 865 | 865 | @panic("TODO"); |
| ... | ... | @@ -871,7 +871,7 @@ fn dirStatPathLinux( |
| 871 | 871 | sub_path: []const u8, |
| 872 | 872 | options: Io.Dir.StatPathOptions, |
| 873 | 873 | ) Io.Dir.StatPathError!Io.File.Stat { |
| 874 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 874 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 875 | 875 | const linux = std.os.linux; |
| 876 | 876 | |
| 877 | 877 | var path_buffer: [posix.PATH_MAX]u8 = undefined; |
| ... | ... | @@ -881,7 +881,7 @@ fn dirStatPathLinux( |
| 881 | 881 | @as(u32, if (!options.follow_symlinks) linux.AT.SYMLINK_NOFOLLOW else 0); |
| 882 | 882 | |
| 883 | 883 | while (true) { |
| 884 | | try pool.checkCancel(); |
| 884 | try t.checkCancel(); |
| 885 | 885 | var statx = std.mem.zeroes(linux.Statx); |
| 886 | 886 | const rc = linux.statx( |
| 887 | 887 | dir.handle, |
| ... | ... | @@ -913,7 +913,7 @@ fn dirStatPathPosix( |
| 913 | 913 | sub_path: []const u8, |
| 914 | 914 | options: Io.Dir.StatPathOptions, |
| 915 | 915 | ) Io.Dir.StatPathError!Io.File.Stat { |
| 916 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 916 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 917 | 917 | |
| 918 | 918 | var path_buffer: [posix.PATH_MAX]u8 = undefined; |
| 919 | 919 | const sub_path_posix = try pathToPosix(sub_path, &path_buffer); |
| ... | ... | @@ -921,7 +921,7 @@ fn dirStatPathPosix( |
| 921 | 921 | const flags: u32 = if (!options.follow_symlinks) posix.AT.SYMLINK_NOFOLLOW else 0; |
| 922 | 922 | |
| 923 | 923 | while (true) { |
| 924 | | try pool.checkCancel(); |
| 924 | try t.checkCancel(); |
| 925 | 925 | var stat = std.mem.zeroes(posix.Stat); |
| 926 | 926 | switch (posix.errno(fstatat_sym(dir.handle, sub_path_posix, &stat, flags))) { |
| 927 | 927 | .SUCCESS => return statFromPosix(stat), |
| ... | ... | @@ -943,12 +943,12 @@ fn dirStatPathPosix( |
| 943 | 943 | } |
| 944 | 944 | |
| 945 | 945 | fn fileStatPosix(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { |
| 946 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 946 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 947 | 947 | |
| 948 | 948 | if (posix.Stat == void) return error.Streaming; |
| 949 | 949 | |
| 950 | 950 | while (true) { |
| 951 | | try pool.checkCancel(); |
| 951 | try t.checkCancel(); |
| 952 | 952 | var stat = std.mem.zeroes(posix.Stat); |
| 953 | 953 | switch (posix.errno(fstat_sym(file.handle, &stat))) { |
| 954 | 954 | .SUCCESS => return statFromPosix(&stat), |
| ... | ... | @@ -963,10 +963,10 @@ fn fileStatPosix(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File |
| 963 | 963 | } |
| 964 | 964 | |
| 965 | 965 | fn fileStatLinux(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { |
| 966 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 966 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 967 | 967 | const linux = std.os.linux; |
| 968 | 968 | while (true) { |
| 969 | | try pool.checkCancel(); |
| 969 | try t.checkCancel(); |
| 970 | 970 | var statx = std.mem.zeroes(linux.Statx); |
| 971 | 971 | const rc = linux.statx( |
| 972 | 972 | file.handle, |
| ... | ... | @@ -993,17 +993,17 @@ fn fileStatLinux(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File |
| 993 | 993 | } |
| 994 | 994 | |
| 995 | 995 | fn fileStatWindows(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { |
| 996 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 997 | | try pool.checkCancel(); |
| 996 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 997 | try t.checkCancel(); |
| 998 | 998 | _ = file; |
| 999 | 999 | @panic("TODO"); |
| 1000 | 1000 | } |
| 1001 | 1001 | |
| 1002 | 1002 | fn fileStatWasi(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { |
| 1003 | 1003 | if (builtin.link_libc) return fileStatPosix(userdata, file); |
| 1004 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1004 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1005 | 1005 | while (true) { |
| 1006 | | try pool.checkCancel(); |
| 1006 | try t.checkCancel(); |
| 1007 | 1007 | var stat: std.os.wasi.filestat_t = undefined; |
| 1008 | 1008 | switch (std.os.wasi.fd_filestat_get(file.handle, &stat)) { |
| 1009 | 1009 | .SUCCESS => return statFromWasi(&stat), |
| ... | ... | @@ -1031,7 +1031,7 @@ fn dirCreateFilePosix( |
| 1031 | 1031 | sub_path: []const u8, |
| 1032 | 1032 | flags: Io.File.CreateFlags, |
| 1033 | 1033 | ) Io.File.OpenError!Io.File { |
| 1034 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1034 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1035 | 1035 | |
| 1036 | 1036 | var path_buffer: [posix.PATH_MAX]u8 = undefined; |
| 1037 | 1037 | const sub_path_posix = try pathToPosix(sub_path, &path_buffer); |
| ... | ... | @@ -1062,7 +1062,7 @@ fn dirCreateFilePosix( |
| 1062 | 1062 | }; |
| 1063 | 1063 | |
| 1064 | 1064 | const fd: posix.fd_t = while (true) { |
| 1065 | | try pool.checkCancel(); |
| 1065 | try t.checkCancel(); |
| 1066 | 1066 | const rc = openat_sym(dir.handle, sub_path_posix, os_flags, flags.mode); |
| 1067 | 1067 | switch (posix.errno(rc)) { |
| 1068 | 1068 | .SUCCESS => break @intCast(rc), |
| ... | ... | @@ -1106,7 +1106,7 @@ fn dirCreateFilePosix( |
| 1106 | 1106 | .exclusive => posix.LOCK.EX | lock_nonblocking, |
| 1107 | 1107 | }; |
| 1108 | 1108 | while (true) { |
| 1109 | | try pool.checkCancel(); |
| 1109 | try t.checkCancel(); |
| 1110 | 1110 | switch (posix.errno(posix.system.flock(fd, lock_flags))) { |
| 1111 | 1111 | .SUCCESS => break, |
| 1112 | 1112 | .INTR => continue, |
| ... | ... | @@ -1123,7 +1123,7 @@ fn dirCreateFilePosix( |
| 1123 | 1123 | |
| 1124 | 1124 | if (has_flock_open_flags and flags.lock_nonblocking) { |
| 1125 | 1125 | var fl_flags: usize = while (true) { |
| 1126 | | try pool.checkCancel(); |
| 1126 | try t.checkCancel(); |
| 1127 | 1127 | switch (posix.errno(posix.system.fcntl(fd, posix.F.GETFL, 0))) { |
| 1128 | 1128 | .SUCCESS => break, |
| 1129 | 1129 | .INTR => continue, |
| ... | ... | @@ -1132,7 +1132,7 @@ fn dirCreateFilePosix( |
| 1132 | 1132 | }; |
| 1133 | 1133 | fl_flags &= ~@as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK")); |
| 1134 | 1134 | while (true) { |
| 1135 | | try pool.checkCancel(); |
| 1135 | try t.checkCancel(); |
| 1136 | 1136 | switch (posix.errno(posix.fcntl(fd, posix.F.SETFL, fl_flags))) { |
| 1137 | 1137 | .SUCCESS => break, |
| 1138 | 1138 | .INTR => continue, |
| ... | ... | @@ -1150,7 +1150,7 @@ fn dirOpenFile( |
| 1150 | 1150 | sub_path: []const u8, |
| 1151 | 1151 | flags: Io.File.OpenFlags, |
| 1152 | 1152 | ) Io.File.OpenError!Io.File { |
| 1153 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1153 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1154 | 1154 | |
| 1155 | 1155 | var path_buffer: [posix.PATH_MAX]u8 = undefined; |
| 1156 | 1156 | const sub_path_posix = try pathToPosix(sub_path, &path_buffer); |
| ... | ... | @@ -1191,7 +1191,7 @@ fn dirOpenFile( |
| 1191 | 1191 | } |
| 1192 | 1192 | } |
| 1193 | 1193 | const fd: posix.fd_t = while (true) { |
| 1194 | | try pool.checkCancel(); |
| 1194 | try t.checkCancel(); |
| 1195 | 1195 | const rc = openat_sym(dir.handle, sub_path_posix, os_flags, @as(posix.mode_t, 0)); |
| 1196 | 1196 | switch (posix.errno(rc)) { |
| 1197 | 1197 | .SUCCESS => break @intCast(rc), |
| ... | ... | @@ -1235,7 +1235,7 @@ fn dirOpenFile( |
| 1235 | 1235 | .exclusive => posix.LOCK.EX | lock_nonblocking, |
| 1236 | 1236 | }; |
| 1237 | 1237 | while (true) { |
| 1238 | | try pool.checkCancel(); |
| 1238 | try t.checkCancel(); |
| 1239 | 1239 | switch (posix.errno(posix.system.flock(fd, lock_flags))) { |
| 1240 | 1240 | .SUCCESS => break, |
| 1241 | 1241 | .INTR => continue, |
| ... | ... | @@ -1252,7 +1252,7 @@ fn dirOpenFile( |
| 1252 | 1252 | |
| 1253 | 1253 | if (has_flock_open_flags and flags.lock_nonblocking) { |
| 1254 | 1254 | var fl_flags: usize = while (true) { |
| 1255 | | try pool.checkCancel(); |
| 1255 | try t.checkCancel(); |
| 1256 | 1256 | switch (posix.errno(posix.system.fcntl(fd, posix.F.GETFL, 0))) { |
| 1257 | 1257 | .SUCCESS => break, |
| 1258 | 1258 | .INTR => continue, |
| ... | ... | @@ -1261,7 +1261,7 @@ fn dirOpenFile( |
| 1261 | 1261 | }; |
| 1262 | 1262 | fl_flags &= ~@as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK")); |
| 1263 | 1263 | while (true) { |
| 1264 | | try pool.checkCancel(); |
| 1264 | try t.checkCancel(); |
| 1265 | 1265 | switch (posix.errno(posix.fcntl(fd, posix.F.SETFL, fl_flags))) { |
| 1266 | 1266 | .SUCCESS => break, |
| 1267 | 1267 | .INTR => continue, |
| ... | ... | @@ -1274,13 +1274,13 @@ fn dirOpenFile( |
| 1274 | 1274 | } |
| 1275 | 1275 | |
| 1276 | 1276 | fn fileClose(userdata: ?*anyopaque, file: Io.File) void { |
| 1277 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1278 | | _ = pool; |
| 1277 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1278 | _ = t; |
| 1279 | 1279 | posix.close(file.handle); |
| 1280 | 1280 | } |
| 1281 | 1281 | |
| 1282 | 1282 | fn fileReadStreaming(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File.ReadStreamingError!usize { |
| 1283 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1283 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1284 | 1284 | |
| 1285 | 1285 | if (is_windows) { |
| 1286 | 1286 | const DWORD = windows.DWORD; |
| ... | ... | @@ -1288,7 +1288,7 @@ fn fileReadStreaming(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File |
| 1288 | 1288 | var truncate: usize = 0; |
| 1289 | 1289 | var total: usize = 0; |
| 1290 | 1290 | while (index < data.len) { |
| 1291 | | try pool.checkCancel(); |
| 1291 | try t.checkCancel(); |
| 1292 | 1292 | { |
| 1293 | 1293 | const untruncated = data[index]; |
| 1294 | 1294 | data[index] = untruncated[truncate..]; |
| ... | ... | @@ -1333,7 +1333,7 @@ fn fileReadStreaming(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File |
| 1333 | 1333 | assert(dest[0].len > 0); |
| 1334 | 1334 | |
| 1335 | 1335 | if (native_os == .wasi and !builtin.link_libc) while (true) { |
| 1336 | | try pool.checkCancel(); |
| 1336 | try t.checkCancel(); |
| 1337 | 1337 | var nread: usize = undefined; |
| 1338 | 1338 | switch (std.os.wasi.fd_read(file.handle, dest.ptr, dest.len, &nread)) { |
| 1339 | 1339 | .SUCCESS => return nread, |
| ... | ... | @@ -1354,7 +1354,7 @@ fn fileReadStreaming(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File |
| 1354 | 1354 | }; |
| 1355 | 1355 | |
| 1356 | 1356 | while (true) { |
| 1357 | | try pool.checkCancel(); |
| 1357 | try t.checkCancel(); |
| 1358 | 1358 | const rc = posix.system.readv(file.handle, dest.ptr, @intCast(dest.len)); |
| 1359 | 1359 | switch (posix.errno(rc)) { |
| 1360 | 1360 | .SUCCESS => return @intCast(rc), |
| ... | ... | @@ -1377,7 +1377,7 @@ fn fileReadStreaming(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io.File |
| 1377 | 1377 | } |
| 1378 | 1378 | |
| 1379 | 1379 | fn fileReadPositional(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset: u64) Io.File.ReadPositionalError!usize { |
| 1380 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1380 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1381 | 1381 | |
| 1382 | 1382 | if (is_windows) { |
| 1383 | 1383 | const DWORD = windows.DWORD; |
| ... | ... | @@ -1386,7 +1386,7 @@ fn fileReadPositional(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset |
| 1386 | 1386 | var truncate: usize = 0; |
| 1387 | 1387 | var total: usize = 0; |
| 1388 | 1388 | while (true) { |
| 1389 | | try pool.checkCancel(); |
| 1389 | try t.checkCancel(); |
| 1390 | 1390 | { |
| 1391 | 1391 | const untruncated = data[index]; |
| 1392 | 1392 | data[index] = untruncated[truncate..]; |
| ... | ... | @@ -1454,7 +1454,7 @@ fn fileReadPositional(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset |
| 1454 | 1454 | assert(dest[0].len > 0); |
| 1455 | 1455 | |
| 1456 | 1456 | if (native_os == .wasi and !builtin.link_libc) while (true) { |
| 1457 | | try pool.checkCancel(); |
| 1457 | try t.checkCancel(); |
| 1458 | 1458 | var nread: usize = undefined; |
| 1459 | 1459 | switch (std.os.wasi.fd_pread(file.handle, dest.ptr, dest.len, offset, &nread)) { |
| 1460 | 1460 | .SUCCESS => return nread, |
| ... | ... | @@ -1479,7 +1479,7 @@ fn fileReadPositional(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset |
| 1479 | 1479 | }; |
| 1480 | 1480 | |
| 1481 | 1481 | while (true) { |
| 1482 | | try pool.checkCancel(); |
| 1482 | try t.checkCancel(); |
| 1483 | 1483 | const rc = preadv_sym(file.handle, dest.ptr, @intCast(dest.len), @bitCast(offset)); |
| 1484 | 1484 | switch (posix.errno(rc)) { |
| 1485 | 1485 | .SUCCESS => return @bitCast(rc), |
| ... | ... | @@ -1505,8 +1505,8 @@ fn fileReadPositional(userdata: ?*anyopaque, file: Io.File, data: [][]u8, offset |
| 1505 | 1505 | } |
| 1506 | 1506 | |
| 1507 | 1507 | fn fileSeekBy(userdata: ?*anyopaque, file: Io.File, offset: i64) Io.File.SeekError!void { |
| 1508 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1509 | | try pool.checkCancel(); |
| 1508 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1509 | try t.checkCancel(); |
| 1510 | 1510 | |
| 1511 | 1511 | _ = file; |
| 1512 | 1512 | _ = offset; |
| ... | ... | @@ -1514,11 +1514,11 @@ fn fileSeekBy(userdata: ?*anyopaque, file: Io.File, offset: i64) Io.File.SeekErr |
| 1514 | 1514 | } |
| 1515 | 1515 | |
| 1516 | 1516 | fn fileSeekTo(userdata: ?*anyopaque, file: Io.File, offset: u64) Io.File.SeekError!void { |
| 1517 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1517 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1518 | 1518 | const fd = file.handle; |
| 1519 | 1519 | |
| 1520 | 1520 | if (native_os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) while (true) { |
| 1521 | | try pool.checkCancel(); |
| 1521 | try t.checkCancel(); |
| 1522 | 1522 | var result: u64 = undefined; |
| 1523 | 1523 | switch (posix.errno(posix.system.llseek(fd, offset, &result, posix.SEEK.SET))) { |
| 1524 | 1524 | .SUCCESS => return, |
| ... | ... | @@ -1533,12 +1533,12 @@ fn fileSeekTo(userdata: ?*anyopaque, file: Io.File, offset: u64) Io.File.SeekErr |
| 1533 | 1533 | }; |
| 1534 | 1534 | |
| 1535 | 1535 | if (native_os == .windows) { |
| 1536 | | try pool.checkCancel(); |
| 1536 | try t.checkCancel(); |
| 1537 | 1537 | return windows.SetFilePointerEx_BEGIN(fd, offset); |
| 1538 | 1538 | } |
| 1539 | 1539 | |
| 1540 | 1540 | if (native_os == .wasi and !builtin.link_libc) while (true) { |
| 1541 | | try pool.checkCancel(); |
| 1541 | try t.checkCancel(); |
| 1542 | 1542 | var new_offset: std.os.wasi.filesize_t = undefined; |
| 1543 | 1543 | switch (std.os.wasi.fd_seek(fd, @bitCast(offset), .SET, &new_offset)) { |
| 1544 | 1544 | .SUCCESS => return, |
| ... | ... | @@ -1556,7 +1556,7 @@ fn fileSeekTo(userdata: ?*anyopaque, file: Io.File, offset: u64) Io.File.SeekErr |
| 1556 | 1556 | if (posix.SEEK == void) return error.Unseekable; |
| 1557 | 1557 | |
| 1558 | 1558 | while (true) { |
| 1559 | | try pool.checkCancel(); |
| 1559 | try t.checkCancel(); |
| 1560 | 1560 | switch (posix.errno(lseek_sym(fd, @bitCast(offset), posix.SEEK.SET))) { |
| 1561 | 1561 | .SUCCESS => return, |
| 1562 | 1562 | .INTR => continue, |
| ... | ... | @@ -1571,8 +1571,8 @@ fn fileSeekTo(userdata: ?*anyopaque, file: Io.File, offset: u64) Io.File.SeekErr |
| 1571 | 1571 | } |
| 1572 | 1572 | |
| 1573 | 1573 | fn pwrite(userdata: ?*anyopaque, file: Io.File, buffer: []const u8, offset: posix.off_t) Io.File.PWriteError!usize { |
| 1574 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1575 | | try pool.checkCancel(); |
| 1574 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1575 | try t.checkCancel(); |
| 1576 | 1576 | const fs_file: std.fs.File = .{ .handle = file.handle }; |
| 1577 | 1577 | return switch (offset) { |
| 1578 | 1578 | -1 => fs_file.write(buffer), |
| ... | ... | @@ -1581,8 +1581,8 @@ fn pwrite(userdata: ?*anyopaque, file: Io.File, buffer: []const u8, offset: posi |
| 1581 | 1581 | } |
| 1582 | 1582 | |
| 1583 | 1583 | fn nowPosix(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { |
| 1584 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1585 | | _ = pool; |
| 1584 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1585 | _ = t; |
| 1586 | 1586 | const clock_id: posix.clockid_t = clockToPosix(clock); |
| 1587 | 1587 | var tp: posix.timespec = undefined; |
| 1588 | 1588 | switch (posix.errno(posix.system.clock_gettime(clock_id, &tp))) { |
| ... | ... | @@ -1593,8 +1593,8 @@ fn nowPosix(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp |
| 1593 | 1593 | } |
| 1594 | 1594 | |
| 1595 | 1595 | fn nowWindows(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { |
| 1596 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1597 | | _ = pool; |
| 1596 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1597 | _ = t; |
| 1598 | 1598 | switch (clock) { |
| 1599 | 1599 | .realtime => { |
| 1600 | 1600 | // RtlGetSystemTimePrecise() has a granularity of 100 nanoseconds |
| ... | ... | @@ -1612,8 +1612,8 @@ fn nowWindows(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestam |
| 1612 | 1612 | } |
| 1613 | 1613 | |
| 1614 | 1614 | fn nowWasi(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { |
| 1615 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1616 | | _ = pool; |
| 1615 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1616 | _ = t; |
| 1617 | 1617 | var ns: std.os.wasi.timestamp_t = undefined; |
| 1618 | 1618 | const err = std.os.wasi.clock_time_get(clockToWasi(clock), 1, &ns); |
| 1619 | 1619 | if (err != .SUCCESS) return error.Unexpected; |
| ... | ... | @@ -1621,7 +1621,7 @@ fn nowWasi(userdata: ?*anyopaque, clock: Io.Clock) Io.Clock.Error!Io.Timestamp { |
| 1621 | 1621 | } |
| 1622 | 1622 | |
| 1623 | 1623 | fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 1624 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1624 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1625 | 1625 | const clock_id: posix.clockid_t = clockToPosix(switch (timeout) { |
| 1626 | 1626 | .none => .awake, |
| 1627 | 1627 | .duration => |d| d.clock, |
| ... | ... | @@ -1634,7 +1634,7 @@ fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 1634 | 1634 | }; |
| 1635 | 1635 | var timespec: posix.timespec = timestampToPosix(deadline_nanoseconds); |
| 1636 | 1636 | while (true) { |
| 1637 | | try pool.checkCancel(); |
| 1637 | try t.checkCancel(); |
| 1638 | 1638 | switch (std.os.linux.E.init(std.os.linux.clock_nanosleep(clock_id, .{ .ABSTIME = switch (timeout) { |
| 1639 | 1639 | .none, .duration => false, |
| 1640 | 1640 | .deadline => true, |
| ... | ... | @@ -1648,10 +1648,10 @@ fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 1648 | 1648 | } |
| 1649 | 1649 | |
| 1650 | 1650 | fn sleepWindows(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 1651 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1652 | | try pool.checkCancel(); |
| 1651 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1652 | try t.checkCancel(); |
| 1653 | 1653 | const ms = ms: { |
| 1654 | | const duration_and_clock = (try timeout.toDurationFromNow(pool.io())) orelse |
| 1654 | const duration_and_clock = (try timeout.toDurationFromNow(t.io())) orelse |
| 1655 | 1655 | break :ms std.math.maxInt(windows.DWORD); |
| 1656 | 1656 | break :ms std.math.lossyCast(windows.DWORD, duration_and_clock.duration.toMilliseconds()); |
| 1657 | 1657 | }; |
| ... | ... | @@ -1659,12 +1659,12 @@ fn sleepWindows(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 1659 | 1659 | } |
| 1660 | 1660 | |
| 1661 | 1661 | fn sleepWasi(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 1662 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1663 | | try pool.checkCancel(); |
| 1662 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1663 | try t.checkCancel(); |
| 1664 | 1664 | |
| 1665 | 1665 | const w = std.os.wasi; |
| 1666 | 1666 | |
| 1667 | | const clock: w.subscription_clock_t = if (try timeout.toDurationFromNow(pool.io())) |d| .{ |
| 1667 | const clock: w.subscription_clock_t = if (try timeout.toDurationFromNow(t.io())) |d| .{ |
| 1668 | 1668 | .id = clockToWasi(d.clock), |
| 1669 | 1669 | .timeout = std.math.lossyCast(u64, d.duration.nanoseconds), |
| 1670 | 1670 | .precision = 0, |
| ... | ... | @@ -1688,19 +1688,19 @@ fn sleepWasi(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 1688 | 1688 | } |
| 1689 | 1689 | |
| 1690 | 1690 | fn sleepPosix(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 1691 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1691 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1692 | 1692 | const sec_type = @typeInfo(posix.timespec).@"struct".fields[0].type; |
| 1693 | 1693 | const nsec_type = @typeInfo(posix.timespec).@"struct".fields[1].type; |
| 1694 | 1694 | |
| 1695 | 1695 | var timespec: posix.timespec = t: { |
| 1696 | | const d = (try timeout.toDurationFromNow(pool.io())) orelse break :t .{ |
| 1696 | const d = (try timeout.toDurationFromNow(t.io())) orelse break :t .{ |
| 1697 | 1697 | .sec = std.math.maxInt(sec_type), |
| 1698 | 1698 | .nsec = std.math.maxInt(nsec_type), |
| 1699 | 1699 | }; |
| 1700 | 1700 | break :t timestampToPosix(d.duration.nanoseconds); |
| 1701 | 1701 | }; |
| 1702 | 1702 | while (true) { |
| 1703 | | try pool.checkCancel(); |
| 1703 | try t.checkCancel(); |
| 1704 | 1704 | switch (posix.errno(posix.system.nanosleep(&timespec, &timespec))) { |
| 1705 | 1705 | .INTR => continue, |
| 1706 | 1706 | else => return, // This prong handles success as well as unexpected errors. |
| ... | ... | @@ -1709,8 +1709,8 @@ fn sleepPosix(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { |
| 1709 | 1709 | } |
| 1710 | 1710 | |
| 1711 | 1711 | fn select(userdata: ?*anyopaque, futures: []const *Io.AnyFuture) usize { |
| 1712 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1713 | | _ = pool; |
| 1712 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1713 | _ = t; |
| 1714 | 1714 | |
| 1715 | 1715 | var reset_event: ResetEvent = .unset; |
| 1716 | 1716 | |
| ... | ... | @@ -1745,26 +1745,26 @@ fn netListenIpPosix( |
| 1745 | 1745 | address: IpAddress, |
| 1746 | 1746 | options: IpAddress.ListenOptions, |
| 1747 | 1747 | ) IpAddress.ListenError!net.Server { |
| 1748 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1748 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1749 | 1749 | const family = posixAddressFamily(&address); |
| 1750 | | const socket_fd = try openSocketPosix(pool, family, .{ |
| 1750 | const socket_fd = try openSocketPosix(t, family, .{ |
| 1751 | 1751 | .mode = options.mode, |
| 1752 | 1752 | .protocol = options.protocol, |
| 1753 | 1753 | }); |
| 1754 | 1754 | errdefer posix.close(socket_fd); |
| 1755 | 1755 | |
| 1756 | 1756 | if (options.reuse_address) { |
| 1757 | | try setSocketOption(pool, socket_fd, posix.SOL.SOCKET, posix.SO.REUSEADDR, 1); |
| 1757 | try setSocketOption(t, socket_fd, posix.SOL.SOCKET, posix.SO.REUSEADDR, 1); |
| 1758 | 1758 | if (@hasDecl(posix.SO, "REUSEPORT")) |
| 1759 | | try setSocketOption(pool, socket_fd, posix.SOL.SOCKET, posix.SO.REUSEPORT, 1); |
| 1759 | try setSocketOption(t, socket_fd, posix.SOL.SOCKET, posix.SO.REUSEPORT, 1); |
| 1760 | 1760 | } |
| 1761 | 1761 | |
| 1762 | 1762 | var storage: PosixAddress = undefined; |
| 1763 | 1763 | var addr_len = addressToPosix(&address, &storage); |
| 1764 | | try posixBind(pool, socket_fd, &storage.any, addr_len); |
| 1764 | try posixBind(t, socket_fd, &storage.any, addr_len); |
| 1765 | 1765 | |
| 1766 | 1766 | while (true) { |
| 1767 | | try pool.checkCancel(); |
| 1767 | try t.checkCancel(); |
| 1768 | 1768 | switch (posix.errno(posix.system.listen(socket_fd, options.kernel_backlog))) { |
| 1769 | 1769 | .SUCCESS => break, |
| 1770 | 1770 | .ADDRINUSE => return error.AddressInUse, |
| ... | ... | @@ -1773,7 +1773,7 @@ fn netListenIpPosix( |
| 1773 | 1773 | } |
| 1774 | 1774 | } |
| 1775 | 1775 | |
| 1776 | | try posixGetSockName(pool, socket_fd, &storage.any, &addr_len); |
| 1776 | try posixGetSockName(t, socket_fd, &storage.any, &addr_len); |
| 1777 | 1777 | return .{ |
| 1778 | 1778 | .socket = .{ |
| 1779 | 1779 | .handle = socket_fd, |
| ... | ... | @@ -1788,8 +1788,8 @@ fn netListenUnix( |
| 1788 | 1788 | options: net.UnixAddress.ListenOptions, |
| 1789 | 1789 | ) net.UnixAddress.ListenError!net.Socket.Handle { |
| 1790 | 1790 | if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; |
| 1791 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1792 | | const socket_fd = openSocketPosix(pool, posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { |
| 1791 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1792 | const socket_fd = openSocketPosix(t, posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { |
| 1793 | 1793 | error.ProtocolUnsupportedBySystem => return error.AddressFamilyUnsupported, |
| 1794 | 1794 | error.ProtocolUnsupportedByAddressFamily => return error.AddressFamilyUnsupported, |
| 1795 | 1795 | error.SocketModeUnsupported => return error.AddressFamilyUnsupported, |
| ... | ... | @@ -1799,10 +1799,10 @@ fn netListenUnix( |
| 1799 | 1799 | |
| 1800 | 1800 | var storage: UnixAddress = undefined; |
| 1801 | 1801 | const addr_len = addressUnixToPosix(address, &storage); |
| 1802 | | try posixBindUnix(pool, socket_fd, &storage.any, addr_len); |
| 1802 | try posixBindUnix(t, socket_fd, &storage.any, addr_len); |
| 1803 | 1803 | |
| 1804 | 1804 | while (true) { |
| 1805 | | try pool.checkCancel(); |
| 1805 | try t.checkCancel(); |
| 1806 | 1806 | switch (posix.errno(posix.system.listen(socket_fd, options.kernel_backlog))) { |
| 1807 | 1807 | .SUCCESS => break, |
| 1808 | 1808 | .ADDRINUSE => return error.AddressInUse, |
| ... | ... | @@ -1814,9 +1814,9 @@ fn netListenUnix( |
| 1814 | 1814 | return socket_fd; |
| 1815 | 1815 | } |
| 1816 | 1816 | |
| 1817 | | fn posixBindUnix(pool: *Pool, fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { |
| 1817 | fn posixBindUnix(t: *Threaded, fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { |
| 1818 | 1818 | while (true) { |
| 1819 | | try pool.checkCancel(); |
| 1819 | try t.checkCancel(); |
| 1820 | 1820 | switch (posix.errno(posix.system.bind(fd, addr, addr_len))) { |
| 1821 | 1821 | .SUCCESS => break, |
| 1822 | 1822 | .INTR => continue, |
| ... | ... | @@ -1842,9 +1842,9 @@ fn posixBindUnix(pool: *Pool, fd: posix.socket_t, addr: *const posix.sockaddr, a |
| 1842 | 1842 | } |
| 1843 | 1843 | } |
| 1844 | 1844 | |
| 1845 | | fn posixBind(pool: *Pool, socket_fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { |
| 1845 | fn posixBind(t: *Threaded, socket_fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { |
| 1846 | 1846 | while (true) { |
| 1847 | | try pool.checkCancel(); |
| 1847 | try t.checkCancel(); |
| 1848 | 1848 | switch (posix.errno(posix.system.bind(socket_fd, addr, addr_len))) { |
| 1849 | 1849 | .SUCCESS => break, |
| 1850 | 1850 | .INTR => continue, |
| ... | ... | @@ -1861,9 +1861,9 @@ fn posixBind(pool: *Pool, socket_fd: posix.socket_t, addr: *const posix.sockaddr |
| 1861 | 1861 | } |
| 1862 | 1862 | } |
| 1863 | 1863 | |
| 1864 | | fn posixConnect(pool: *Pool, socket_fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { |
| 1864 | fn posixConnect(t: *Threaded, socket_fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { |
| 1865 | 1865 | while (true) { |
| 1866 | | try pool.checkCancel(); |
| 1866 | try t.checkCancel(); |
| 1867 | 1867 | switch (posix.errno(posix.system.connect(socket_fd, addr, addr_len))) { |
| 1868 | 1868 | .SUCCESS => return, |
| 1869 | 1869 | .INTR => continue, |
| ... | ... | @@ -1890,9 +1890,9 @@ fn posixConnect(pool: *Pool, socket_fd: posix.socket_t, addr: *const posix.socka |
| 1890 | 1890 | } |
| 1891 | 1891 | } |
| 1892 | 1892 | |
| 1893 | | fn posixConnectUnix(pool: *Pool, fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { |
| 1893 | fn posixConnectUnix(t: *Threaded, fd: posix.socket_t, addr: *const posix.sockaddr, addr_len: posix.socklen_t) !void { |
| 1894 | 1894 | while (true) { |
| 1895 | | try pool.checkCancel(); |
| 1895 | try t.checkCancel(); |
| 1896 | 1896 | switch (posix.errno(posix.system.connect(fd, addr, addr_len))) { |
| 1897 | 1897 | .SUCCESS => return, |
| 1898 | 1898 | .INTR => continue, |
| ... | ... | @@ -1919,9 +1919,9 @@ fn posixConnectUnix(pool: *Pool, fd: posix.socket_t, addr: *const posix.sockaddr |
| 1919 | 1919 | } |
| 1920 | 1920 | } |
| 1921 | 1921 | |
| 1922 | | fn posixGetSockName(pool: *Pool, socket_fd: posix.fd_t, addr: *posix.sockaddr, addr_len: *posix.socklen_t) !void { |
| 1922 | fn posixGetSockName(t: *Threaded, socket_fd: posix.fd_t, addr: *posix.sockaddr, addr_len: *posix.socklen_t) !void { |
| 1923 | 1923 | while (true) { |
| 1924 | | try pool.checkCancel(); |
| 1924 | try t.checkCancel(); |
| 1925 | 1925 | switch (posix.errno(posix.system.getsockname(socket_fd, addr, addr_len))) { |
| 1926 | 1926 | .SUCCESS => break, |
| 1927 | 1927 | .INTR => continue, |
| ... | ... | @@ -1935,10 +1935,10 @@ fn posixGetSockName(pool: *Pool, socket_fd: posix.fd_t, addr: *posix.sockaddr, a |
| 1935 | 1935 | } |
| 1936 | 1936 | } |
| 1937 | 1937 | |
| 1938 | | fn setSocketOption(pool: *Pool, fd: posix.fd_t, level: i32, opt_name: u32, option: u32) !void { |
| 1938 | fn setSocketOption(t: *Threaded, fd: posix.fd_t, level: i32, opt_name: u32, option: u32) !void { |
| 1939 | 1939 | const o: []const u8 = @ptrCast(&option); |
| 1940 | 1940 | while (true) { |
| 1941 | | try pool.checkCancel(); |
| 1941 | try t.checkCancel(); |
| 1942 | 1942 | switch (posix.errno(posix.system.setsockopt(fd, level, opt_name, o.ptr, @intCast(o.len)))) { |
| 1943 | 1943 | .SUCCESS => return, |
| 1944 | 1944 | .INTR => continue, |
| ... | ... | @@ -1957,17 +1957,17 @@ fn netConnectIpPosix( |
| 1957 | 1957 | options: IpAddress.ConnectOptions, |
| 1958 | 1958 | ) IpAddress.ConnectError!net.Stream { |
| 1959 | 1959 | if (options.timeout != .none) @panic("TODO"); |
| 1960 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1960 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1961 | 1961 | const family = posixAddressFamily(address); |
| 1962 | | const socket_fd = try openSocketPosix(pool, family, .{ |
| 1962 | const socket_fd = try openSocketPosix(t, family, .{ |
| 1963 | 1963 | .mode = options.mode, |
| 1964 | 1964 | .protocol = options.protocol, |
| 1965 | 1965 | }); |
| 1966 | 1966 | errdefer posix.close(socket_fd); |
| 1967 | 1967 | var storage: PosixAddress = undefined; |
| 1968 | 1968 | var addr_len = addressToPosix(address, &storage); |
| 1969 | | try posixConnect(pool, socket_fd, &storage.any, addr_len); |
| 1970 | | try posixGetSockName(pool, socket_fd, &storage.any, &addr_len); |
| 1969 | try posixConnect(t, socket_fd, &storage.any, addr_len); |
| 1970 | try posixGetSockName(t, socket_fd, &storage.any, &addr_len); |
| 1971 | 1971 | return .{ .socket = .{ |
| 1972 | 1972 | .handle = socket_fd, |
| 1973 | 1973 | .address = addressFromPosix(&storage), |
| ... | ... | @@ -1979,12 +1979,12 @@ fn netConnectUnix( |
| 1979 | 1979 | address: *const net.UnixAddress, |
| 1980 | 1980 | ) net.UnixAddress.ConnectError!net.Socket.Handle { |
| 1981 | 1981 | if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; |
| 1982 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1983 | | const socket_fd = try openSocketPosix(pool, posix.AF.UNIX, .{ .mode = .stream }); |
| 1982 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1983 | const socket_fd = try openSocketPosix(t, posix.AF.UNIX, .{ .mode = .stream }); |
| 1984 | 1984 | errdefer posix.close(socket_fd); |
| 1985 | 1985 | var storage: UnixAddress = undefined; |
| 1986 | 1986 | const addr_len = addressUnixToPosix(address, &storage); |
| 1987 | | try posixConnectUnix(pool, socket_fd, &storage.any, addr_len); |
| 1987 | try posixConnectUnix(t, socket_fd, &storage.any, addr_len); |
| 1988 | 1988 | return socket_fd; |
| 1989 | 1989 | } |
| 1990 | 1990 | |
| ... | ... | @@ -1993,25 +1993,25 @@ fn netBindIpPosix( |
| 1993 | 1993 | address: *const IpAddress, |
| 1994 | 1994 | options: IpAddress.BindOptions, |
| 1995 | 1995 | ) IpAddress.BindError!net.Socket { |
| 1996 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 1996 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 1997 | 1997 | const family = posixAddressFamily(address); |
| 1998 | | const socket_fd = try openSocketPosix(pool, family, options); |
| 1998 | const socket_fd = try openSocketPosix(t, family, options); |
| 1999 | 1999 | errdefer posix.close(socket_fd); |
| 2000 | 2000 | var storage: PosixAddress = undefined; |
| 2001 | 2001 | var addr_len = addressToPosix(address, &storage); |
| 2002 | | try posixBind(pool, socket_fd, &storage.any, addr_len); |
| 2003 | | try posixGetSockName(pool, socket_fd, &storage.any, &addr_len); |
| 2002 | try posixBind(t, socket_fd, &storage.any, addr_len); |
| 2003 | try posixGetSockName(t, socket_fd, &storage.any, &addr_len); |
| 2004 | 2004 | return .{ |
| 2005 | 2005 | .handle = socket_fd, |
| 2006 | 2006 | .address = addressFromPosix(&storage), |
| 2007 | 2007 | }; |
| 2008 | 2008 | } |
| 2009 | 2009 | |
| 2010 | | fn openSocketPosix(pool: *Pool, family: posix.sa_family_t, options: IpAddress.BindOptions) !posix.socket_t { |
| 2010 | fn openSocketPosix(t: *Threaded, family: posix.sa_family_t, options: IpAddress.BindOptions) !posix.socket_t { |
| 2011 | 2011 | const mode = posixSocketMode(options.mode); |
| 2012 | 2012 | const protocol = posixProtocol(options.protocol); |
| 2013 | 2013 | const socket_fd = while (true) { |
| 2014 | | try pool.checkCancel(); |
| 2014 | try t.checkCancel(); |
| 2015 | 2015 | const flags: u32 = mode | if (socket_flags_unsupported) 0 else posix.SOCK.CLOEXEC; |
| 2016 | 2016 | const socket_rc = posix.system.socket(family, flags, protocol); |
| 2017 | 2017 | switch (posix.errno(socket_rc)) { |
| ... | ... | @@ -2019,7 +2019,7 @@ fn openSocketPosix(pool: *Pool, family: posix.sa_family_t, options: IpAddress.Bi |
| 2019 | 2019 | const fd: posix.fd_t = @intCast(socket_rc); |
| 2020 | 2020 | errdefer posix.close(fd); |
| 2021 | 2021 | if (socket_flags_unsupported) while (true) { |
| 2022 | | try pool.checkCancel(); |
| 2022 | try t.checkCancel(); |
| 2023 | 2023 | switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)))) { |
| 2024 | 2024 | .SUCCESS => break, |
| 2025 | 2025 | .INTR => continue, |
| ... | ... | @@ -2044,7 +2044,7 @@ fn openSocketPosix(pool: *Pool, family: posix.sa_family_t, options: IpAddress.Bi |
| 2044 | 2044 | |
| 2045 | 2045 | if (options.ip6_only) { |
| 2046 | 2046 | if (posix.IPV6 == void) return error.OptionUnsupported; |
| 2047 | | try setSocketOption(pool, socket_fd, posix.IPPROTO.IPV6, posix.IPV6.V6ONLY, 0); |
| 2047 | try setSocketOption(t, socket_fd, posix.IPPROTO.IPV6, posix.IPV6.V6ONLY, 0); |
| 2048 | 2048 | } |
| 2049 | 2049 | |
| 2050 | 2050 | return socket_fd; |
| ... | ... | @@ -2054,11 +2054,11 @@ const socket_flags_unsupported = builtin.os.tag.isDarwin() or native_os == .haik |
| 2054 | 2054 | const have_accept4 = !socket_flags_unsupported; |
| 2055 | 2055 | |
| 2056 | 2056 | fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Server.AcceptError!net.Stream { |
| 2057 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 2057 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2058 | 2058 | var storage: PosixAddress = undefined; |
| 2059 | 2059 | var addr_len: posix.socklen_t = @sizeOf(PosixAddress); |
| 2060 | 2060 | const fd = while (true) { |
| 2061 | | try pool.checkCancel(); |
| 2061 | try t.checkCancel(); |
| 2062 | 2062 | const rc = if (have_accept4) |
| 2063 | 2063 | posix.system.accept4(listen_fd, &storage.any, &addr_len, posix.SOCK.CLOEXEC) |
| 2064 | 2064 | else |
| ... | ... | @@ -2068,7 +2068,7 @@ fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Serve |
| 2068 | 2068 | const fd: posix.fd_t = @intCast(rc); |
| 2069 | 2069 | errdefer posix.close(fd); |
| 2070 | 2070 | if (!have_accept4) while (true) { |
| 2071 | | try pool.checkCancel(); |
| 2071 | try t.checkCancel(); |
| 2072 | 2072 | switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)))) { |
| 2073 | 2073 | .SUCCESS => break, |
| 2074 | 2074 | .INTR => continue, |
| ... | ... | @@ -2101,7 +2101,7 @@ fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Serve |
| 2101 | 2101 | } |
| 2102 | 2102 | |
| 2103 | 2103 | fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize { |
| 2104 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 2104 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2105 | 2105 | |
| 2106 | 2106 | var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined; |
| 2107 | 2107 | var i: usize = 0; |
| ... | ... | @@ -2116,7 +2116,7 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net. |
| 2116 | 2116 | assert(dest[0].len > 0); |
| 2117 | 2117 | |
| 2118 | 2118 | if (native_os == .wasi and !builtin.link_libc) while (true) { |
| 2119 | | try pool.checkCancel(); |
| 2119 | try t.checkCancel(); |
| 2120 | 2120 | var n: usize = undefined; |
| 2121 | 2121 | switch (std.os.wasi.fd_read(fd, dest.ptr, dest.len, &n)) { |
| 2122 | 2122 | .SUCCESS => return n, |
| ... | ... | @@ -2137,7 +2137,7 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net. |
| 2137 | 2137 | }; |
| 2138 | 2138 | |
| 2139 | 2139 | while (true) { |
| 2140 | | try pool.checkCancel(); |
| 2140 | try t.checkCancel(); |
| 2141 | 2141 | const rc = posix.system.readv(fd, dest.ptr, @intCast(dest.len)); |
| 2142 | 2142 | switch (posix.errno(rc)) { |
| 2143 | 2143 | .SUCCESS => return @intCast(rc), |
| ... | ... | @@ -2167,7 +2167,7 @@ fn netSend( |
| 2167 | 2167 | messages: []net.OutgoingMessage, |
| 2168 | 2168 | flags: net.SendFlags, |
| 2169 | 2169 | ) struct { ?net.Socket.SendError, usize } { |
| 2170 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 2170 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2171 | 2171 | |
| 2172 | 2172 | const posix_flags: u32 = |
| 2173 | 2173 | @as(u32, if (@hasDecl(posix.MSG, "CONFIRM") and flags.confirm) posix.MSG.CONFIRM else 0) | |
| ... | ... | @@ -2180,17 +2180,17 @@ fn netSend( |
| 2180 | 2180 | var i: usize = 0; |
| 2181 | 2181 | while (messages.len - i != 0) { |
| 2182 | 2182 | if (have_sendmmsg) { |
| 2183 | | i += netSendMany(pool, handle, messages[i..], posix_flags) catch |err| return .{ err, i }; |
| 2183 | i += netSendMany(t, handle, messages[i..], posix_flags) catch |err| return .{ err, i }; |
| 2184 | 2184 | continue; |
| 2185 | 2185 | } |
| 2186 | | netSendOne(pool, handle, &messages[i], posix_flags) catch |err| return .{ err, i }; |
| 2186 | netSendOne(t, handle, &messages[i], posix_flags) catch |err| return .{ err, i }; |
| 2187 | 2187 | i += 1; |
| 2188 | 2188 | } |
| 2189 | 2189 | return .{ null, i }; |
| 2190 | 2190 | } |
| 2191 | 2191 | |
| 2192 | 2192 | fn netSendOne( |
| 2193 | | pool: *Pool, |
| 2193 | t: *Threaded, |
| 2194 | 2194 | handle: net.Socket.Handle, |
| 2195 | 2195 | message: *net.OutgoingMessage, |
| 2196 | 2196 | flags: u32, |
| ... | ... | @@ -2207,7 +2207,7 @@ fn netSendOne( |
| 2207 | 2207 | .flags = 0, |
| 2208 | 2208 | }; |
| 2209 | 2209 | while (true) { |
| 2210 | | try pool.checkCancel(); |
| 2210 | try t.checkCancel(); |
| 2211 | 2211 | const rc = posix.system.sendmsg(handle, msg, flags); |
| 2212 | 2212 | if (is_windows) { |
| 2213 | 2213 | if (rc == windows.ws2_32.SOCKET_ERROR) { |
| ... | ... | @@ -2274,7 +2274,7 @@ fn netSendOne( |
| 2274 | 2274 | } |
| 2275 | 2275 | |
| 2276 | 2276 | fn netSendMany( |
| 2277 | | pool: *Pool, |
| 2277 | t: *Threaded, |
| 2278 | 2278 | handle: net.Socket.Handle, |
| 2279 | 2279 | messages: []net.OutgoingMessage, |
| 2280 | 2280 | flags: u32, |
| ... | ... | @@ -2305,7 +2305,7 @@ fn netSendMany( |
| 2305 | 2305 | } |
| 2306 | 2306 | |
| 2307 | 2307 | while (true) { |
| 2308 | | try pool.checkCancel(); |
| 2308 | try t.checkCancel(); |
| 2309 | 2309 | const rc = posix.system.sendmmsg(handle, clamped_msgs.ptr, @intCast(clamped_msgs.len), flags); |
| 2310 | 2310 | switch (posix.errno(rc)) { |
| 2311 | 2311 | .SUCCESS => { |
| ... | ... | @@ -2348,7 +2348,7 @@ fn netReceive( |
| 2348 | 2348 | flags: net.ReceiveFlags, |
| 2349 | 2349 | timeout: Io.Timeout, |
| 2350 | 2350 | ) struct { ?net.Socket.ReceiveTimeoutError, usize } { |
| 2351 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 2351 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2352 | 2352 | |
| 2353 | 2353 | // recvmmsg is useless, here's why: |
| 2354 | 2354 | // * [timeout bug](https://bugzilla.kernel.org/show_bug.cgi?id=75371) |
| ... | ... | @@ -2375,10 +2375,10 @@ fn netReceive( |
| 2375 | 2375 | var message_i: usize = 0; |
| 2376 | 2376 | var data_i: usize = 0; |
| 2377 | 2377 | |
| 2378 | | const deadline = timeout.toDeadline(pool.io()) catch |err| return .{ err, message_i }; |
| 2378 | const deadline = timeout.toDeadline(t.io()) catch |err| return .{ err, message_i }; |
| 2379 | 2379 | |
| 2380 | 2380 | recv: while (true) { |
| 2381 | | pool.checkCancel() catch |err| return .{ err, message_i }; |
| 2381 | t.checkCancel() catch |err| return .{ err, message_i }; |
| 2382 | 2382 | |
| 2383 | 2383 | if (message_buffer.len - message_i == 0) return .{ null, message_i }; |
| 2384 | 2384 | const message = &message_buffer[message_i]; |
| ... | ... | @@ -2416,12 +2416,12 @@ fn netReceive( |
| 2416 | 2416 | continue; |
| 2417 | 2417 | }, |
| 2418 | 2418 | .AGAIN => while (true) { |
| 2419 | | pool.checkCancel() catch |err| return .{ err, message_i }; |
| 2419 | t.checkCancel() catch |err| return .{ err, message_i }; |
| 2420 | 2420 | if (message_i != 0) return .{ null, message_i }; |
| 2421 | 2421 | |
| 2422 | 2422 | const max_poll_ms = std.math.maxInt(u31); |
| 2423 | 2423 | const timeout_ms: u31 = if (deadline) |d| t: { |
| 2424 | | const duration = d.durationFromNow(pool.io()) catch |err| return .{ err, message_i }; |
| 2424 | const duration = d.durationFromNow(t.io()) catch |err| return .{ err, message_i }; |
| 2425 | 2425 | if (duration.raw.nanoseconds <= 0) return .{ error.Timeout, message_i }; |
| 2426 | 2426 | break :t @intCast(@min(max_poll_ms, duration.raw.toMilliseconds())); |
| 2427 | 2427 | } else max_poll_ms; |
| ... | ... | @@ -2473,8 +2473,8 @@ fn netWritePosix( |
| 2473 | 2473 | data: []const []const u8, |
| 2474 | 2474 | splat: usize, |
| 2475 | 2475 | ) net.Stream.Writer.Error!usize { |
| 2476 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 2477 | | try pool.checkCancel(); |
| 2476 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2477 | try t.checkCancel(); |
| 2478 | 2478 | |
| 2479 | 2479 | var iovecs: [max_iovecs_len]posix.iovec_const = undefined; |
| 2480 | 2480 | var msg: posix.msghdr_const = .{ |
| ... | ... | @@ -2527,8 +2527,8 @@ fn addBuf(v: []posix.iovec_const, i: *@FieldType(posix.msghdr_const, "iovlen"), |
| 2527 | 2527 | } |
| 2528 | 2528 | |
| 2529 | 2529 | fn netClose(userdata: ?*anyopaque, handle: net.Socket.Handle) void { |
| 2530 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 2531 | | _ = pool; |
| 2530 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2531 | _ = t; |
| 2532 | 2532 | switch (native_os) { |
| 2533 | 2533 | .windows => windows.closesocket(handle) catch recoverableOsBugDetected(), |
| 2534 | 2534 | else => posix.close(handle), |
| ... | ... | @@ -2539,10 +2539,10 @@ fn netInterfaceNameResolve( |
| 2539 | 2539 | userdata: ?*anyopaque, |
| 2540 | 2540 | name: *const net.Interface.Name, |
| 2541 | 2541 | ) net.Interface.Name.ResolveError!net.Interface { |
| 2542 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 2542 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2543 | 2543 | |
| 2544 | 2544 | if (native_os == .linux) { |
| 2545 | | const sock_fd = openSocketPosix(pool, posix.AF.UNIX, .{ .mode = .dgram }) catch |err| switch (err) { |
| 2545 | const sock_fd = openSocketPosix(t, posix.AF.UNIX, .{ .mode = .dgram }) catch |err| switch (err) { |
| 2546 | 2546 | error.ProcessFdQuotaExceeded => return error.SystemResources, |
| 2547 | 2547 | error.SystemFdQuotaExceeded => return error.SystemResources, |
| 2548 | 2548 | error.AddressFamilyUnsupported => return error.Unexpected, |
| ... | ... | @@ -2559,7 +2559,7 @@ fn netInterfaceNameResolve( |
| 2559 | 2559 | }; |
| 2560 | 2560 | |
| 2561 | 2561 | while (true) { |
| 2562 | | try pool.checkCancel(); |
| 2562 | try t.checkCancel(); |
| 2563 | 2563 | switch (posix.errno(posix.system.ioctl(sock_fd, posix.SIOCGIFINDEX, @intFromPtr(&ifr)))) { |
| 2564 | 2564 | .SUCCESS => return .{ .index = @bitCast(ifr.ifru.ivalue) }, |
| 2565 | 2565 | .INTR => continue, |
| ... | ... | @@ -2576,14 +2576,14 @@ fn netInterfaceNameResolve( |
| 2576 | 2576 | } |
| 2577 | 2577 | |
| 2578 | 2578 | if (native_os == .windows) { |
| 2579 | | try pool.checkCancel(); |
| 2579 | try t.checkCancel(); |
| 2580 | 2580 | const index = std.os.windows.ws2_32.if_nametoindex(&name.bytes); |
| 2581 | 2581 | if (index == 0) return error.InterfaceNotFound; |
| 2582 | 2582 | return .{ .index = index }; |
| 2583 | 2583 | } |
| 2584 | 2584 | |
| 2585 | 2585 | if (builtin.link_libc) { |
| 2586 | | try pool.checkCancel(); |
| 2586 | try t.checkCancel(); |
| 2587 | 2587 | const index = std.c.if_nametoindex(&name.bytes); |
| 2588 | 2588 | if (index == 0) return error.InterfaceNotFound; |
| 2589 | 2589 | return .{ .index = @bitCast(index) }; |
| ... | ... | @@ -2593,8 +2593,8 @@ fn netInterfaceNameResolve( |
| 2593 | 2593 | } |
| 2594 | 2594 | |
| 2595 | 2595 | fn netInterfaceName(userdata: ?*anyopaque, interface: net.Interface) net.Interface.NameError!net.Interface.Name { |
| 2596 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 2597 | | try pool.checkCancel(); |
| 2596 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2597 | try t.checkCancel(); |
| 2598 | 2598 | |
| 2599 | 2599 | if (native_os == .linux) { |
| 2600 | 2600 | _ = interface; |
| ... | ... | @@ -2618,18 +2618,18 @@ fn netLookup( |
| 2618 | 2618 | resolved: *Io.Queue(HostName.LookupResult), |
| 2619 | 2619 | options: HostName.LookupOptions, |
| 2620 | 2620 | ) void { |
| 2621 | | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 2622 | | const pool_io = pool.io(); |
| 2623 | | resolved.putOneUncancelable(pool_io, .{ .end = netLookupFallible(pool, host_name, resolved, options) }); |
| 2621 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2622 | const t_io = t.io(); |
| 2623 | resolved.putOneUncancelable(t_io, .{ .end = netLookupFallible(t, host_name, resolved, options) }); |
| 2624 | 2624 | } |
| 2625 | 2625 | |
| 2626 | 2626 | fn netLookupFallible( |
| 2627 | | pool: *Pool, |
| 2627 | t: *Threaded, |
| 2628 | 2628 | host_name: HostName, |
| 2629 | 2629 | resolved: *Io.Queue(HostName.LookupResult), |
| 2630 | 2630 | options: HostName.LookupOptions, |
| 2631 | 2631 | ) !void { |
| 2632 | | const pool_io = pool.io(); |
| 2632 | const t_io = t.io(); |
| 2633 | 2633 | const name = host_name.bytes; |
| 2634 | 2634 | assert(name.len <= HostName.max_len); |
| 2635 | 2635 | |
| ... | ... | @@ -2648,7 +2648,7 @@ fn netLookupFallible( |
| 2648 | 2648 | if (native_os == .linux) { |
| 2649 | 2649 | if (options.family != .ip4) { |
| 2650 | 2650 | if (IpAddress.parseIp6(name, options.port)) |addr| { |
| 2651 | | try resolved.putAll(pool_io, &.{ |
| 2651 | try resolved.putAll(t_io, &.{ |
| 2652 | 2652 | .{ .address = addr }, |
| 2653 | 2653 | .{ .canonical_name = copyCanon(options.canonical_name_buffer, name) }, |
| 2654 | 2654 | }); |
| ... | ... | @@ -2658,7 +2658,7 @@ fn netLookupFallible( |
| 2658 | 2658 | |
| 2659 | 2659 | if (options.family != .ip6) { |
| 2660 | 2660 | if (IpAddress.parseIp4(name, options.port)) |addr| { |
| 2661 | | try resolved.putAll(pool_io, &.{ |
| 2661 | try resolved.putAll(t_io, &.{ |
| 2662 | 2662 | .{ .address = addr }, |
| 2663 | 2663 | .{ .canonical_name = copyCanon(options.canonical_name_buffer, name) }, |
| 2664 | 2664 | }); |
| ... | ... | @@ -2666,7 +2666,7 @@ fn netLookupFallible( |
| 2666 | 2666 | } else |_| {} |
| 2667 | 2667 | } |
| 2668 | 2668 | |
| 2669 | | lookupHosts(pool, host_name, resolved, options) catch |err| switch (err) { |
| 2669 | lookupHosts(t, host_name, resolved, options) catch |err| switch (err) { |
| 2670 | 2670 | error.UnknownHostName => {}, |
| 2671 | 2671 | else => |e| return e, |
| 2672 | 2672 | }; |
| ... | ... | @@ -2697,11 +2697,11 @@ fn netLookupFallible( |
| 2697 | 2697 | canon_name_dest.* = canon_name.*; |
| 2698 | 2698 | results_buffer[results_index] = .{ .canonical_name = .{ .bytes = canon_name_dest } }; |
| 2699 | 2699 | results_index += 1; |
| 2700 | | try resolved.putAll(pool_io, results_buffer[0..results_index]); |
| 2700 | try resolved.putAll(t_io, results_buffer[0..results_index]); |
| 2701 | 2701 | return; |
| 2702 | 2702 | } |
| 2703 | 2703 | |
| 2704 | | return lookupDnsSearch(pool, host_name, resolved, options); |
| 2704 | return lookupDnsSearch(t, host_name, resolved, options); |
| 2705 | 2705 | } |
| 2706 | 2706 | |
| 2707 | 2707 | if (native_os == .openbsd) { |
| ... | ... | @@ -2953,13 +2953,13 @@ fn pathToPosix(file_path: []const u8, buffer: *[posix.PATH_MAX]u8) Io.Dir.PathNa |
| 2953 | 2953 | } |
| 2954 | 2954 | |
| 2955 | 2955 | fn lookupDnsSearch( |
| 2956 | | pool: *Pool, |
| 2956 | t: *Threaded, |
| 2957 | 2957 | host_name: HostName, |
| 2958 | 2958 | resolved: *Io.Queue(HostName.LookupResult), |
| 2959 | 2959 | options: HostName.LookupOptions, |
| 2960 | 2960 | ) HostName.LookupError!void { |
| 2961 | | const pool_io = pool.io(); |
| 2962 | | const rc = HostName.ResolvConf.init(pool_io) catch return error.ResolvConfParseFailed; |
| 2961 | const t_io = t.io(); |
| 2962 | const rc = HostName.ResolvConf.init(t_io) catch return error.ResolvConfParseFailed; |
| 2963 | 2963 | |
| 2964 | 2964 | // Count dots, suppress search when >=ndots or name ends in |
| 2965 | 2965 | // a dot, which is an explicit request for global scope. |
| ... | ... | @@ -2983,7 +2983,7 @@ fn lookupDnsSearch( |
| 2983 | 2983 | while (it.next()) |token| { |
| 2984 | 2984 | @memcpy(options.canonical_name_buffer[canon_name.len + 1 ..][0..token.len], token); |
| 2985 | 2985 | const lookup_canon_name = options.canonical_name_buffer[0 .. canon_name.len + 1 + token.len]; |
| 2986 | | if (lookupDns(pool, lookup_canon_name, &rc, resolved, options)) |result| { |
| 2986 | if (lookupDns(t, lookup_canon_name, &rc, resolved, options)) |result| { |
| 2987 | 2987 | return result; |
| 2988 | 2988 | } else |err| switch (err) { |
| 2989 | 2989 | error.UnknownHostName => continue, |
| ... | ... | @@ -2992,17 +2992,17 @@ fn lookupDnsSearch( |
| 2992 | 2992 | } |
| 2993 | 2993 | |
| 2994 | 2994 | const lookup_canon_name = options.canonical_name_buffer[0..canon_name.len]; |
| 2995 | | return lookupDns(pool, lookup_canon_name, &rc, resolved, options); |
| 2995 | return lookupDns(t, lookup_canon_name, &rc, resolved, options); |
| 2996 | 2996 | } |
| 2997 | 2997 | |
| 2998 | 2998 | fn lookupDns( |
| 2999 | | pool: *Pool, |
| 2999 | t: *Threaded, |
| 3000 | 3000 | lookup_canon_name: []const u8, |
| 3001 | 3001 | rc: *const HostName.ResolvConf, |
| 3002 | 3002 | resolved: *Io.Queue(HostName.LookupResult), |
| 3003 | 3003 | options: HostName.LookupOptions, |
| 3004 | 3004 | ) HostName.LookupError!void { |
| 3005 | | const pool_io = pool.io(); |
| 3005 | const t_io = t.io(); |
| 3006 | 3006 | const family_records: [2]struct { af: IpAddress.Family, rr: u8 } = .{ |
| 3007 | 3007 | .{ .af = .ip6, .rr = std.posix.RR.A }, |
| 3008 | 3008 | .{ .af = .ip4, .rr = std.posix.RR.AAAA }, |
| ... | ... | @@ -3032,7 +3032,7 @@ fn lookupDns( |
| 3032 | 3032 | var socket = s: { |
| 3033 | 3033 | if (any_ip6) ip6: { |
| 3034 | 3034 | const ip6_addr: IpAddress = .{ .ip6 = .unspecified(0) }; |
| 3035 | | const socket = ip6_addr.bind(pool_io, .{ .ip6_only = true, .mode = .dgram }) catch |err| switch (err) { |
| 3035 | const socket = ip6_addr.bind(t_io, .{ .ip6_only = true, .mode = .dgram }) catch |err| switch (err) { |
| 3036 | 3036 | error.AddressFamilyUnsupported => break :ip6, |
| 3037 | 3037 | else => |e| return e, |
| 3038 | 3038 | }; |
| ... | ... | @@ -3040,10 +3040,10 @@ fn lookupDns( |
| 3040 | 3040 | } |
| 3041 | 3041 | any_ip6 = false; |
| 3042 | 3042 | const ip4_addr: IpAddress = .{ .ip4 = .unspecified(0) }; |
| 3043 | | const socket = try ip4_addr.bind(pool_io, .{ .mode = .dgram }); |
| 3043 | const socket = try ip4_addr.bind(t_io, .{ .mode = .dgram }); |
| 3044 | 3044 | break :s socket; |
| 3045 | 3045 | }; |
| 3046 | | defer socket.close(pool_io); |
| 3046 | defer socket.close(t_io); |
| 3047 | 3047 | |
| 3048 | 3048 | const mapped_nameservers = if (any_ip6) ip4_mapped[0..rc.nameservers_len] else rc.nameservers(); |
| 3049 | 3049 | const queries = queries_buffer[0..nq]; |
| ... | ... | @@ -3054,13 +3054,13 @@ fn lookupDns( |
| 3054 | 3054 | // boot clock is chosen because time the computer is suspended should count |
| 3055 | 3055 | // against time spent waiting for external messages to arrive. |
| 3056 | 3056 | const clock: Io.Clock = .boot; |
| 3057 | | var now_ts = try clock.now(pool_io); |
| 3057 | var now_ts = try clock.now(t_io); |
| 3058 | 3058 | const final_ts = now_ts.addDuration(.fromSeconds(rc.timeout_seconds)); |
| 3059 | 3059 | const attempt_duration: Io.Duration = .{ |
| 3060 | 3060 | .nanoseconds = std.time.ns_per_s * @as(usize, rc.timeout_seconds) / rc.attempts, |
| 3061 | 3061 | }; |
| 3062 | 3062 | |
| 3063 | | send: while (now_ts.nanoseconds < final_ts.nanoseconds) : (now_ts = try clock.now(pool_io)) { |
| 3063 | send: while (now_ts.nanoseconds < final_ts.nanoseconds) : (now_ts = try clock.now(t_io)) { |
| 3064 | 3064 | const max_messages = queries_buffer.len * HostName.ResolvConf.max_nameservers; |
| 3065 | 3065 | { |
| 3066 | 3066 | var message_buffer: [max_messages]Io.net.OutgoingMessage = undefined; |
| ... | ... | @@ -3076,7 +3076,7 @@ fn lookupDns( |
| 3076 | 3076 | message_i += 1; |
| 3077 | 3077 | } |
| 3078 | 3078 | } |
| 3079 | | _ = netSend(pool, socket.handle, message_buffer[0..message_i], .{}); |
| 3079 | _ = netSend(t, socket.handle, message_buffer[0..message_i], .{}); |
| 3080 | 3080 | } |
| 3081 | 3081 | |
| 3082 | 3082 | const timeout: Io.Timeout = .{ .deadline = .{ |
| ... | ... | @@ -3087,7 +3087,7 @@ fn lookupDns( |
| 3087 | 3087 | while (true) { |
| 3088 | 3088 | var message_buffer: [max_messages]Io.net.IncomingMessage = undefined; |
| 3089 | 3089 | const buf = answer_buffer[answer_buffer_i..]; |
| 3090 | | const recv_err, const recv_n = socket.receiveManyTimeout(pool_io, &message_buffer, buf, .{}, timeout); |
| 3090 | const recv_err, const recv_n = socket.receiveManyTimeout(t_io, &message_buffer, buf, .{}, timeout); |
| 3091 | 3091 | for (message_buffer[0..recv_n]) |*received_message| { |
| 3092 | 3092 | const reply = received_message.data; |
| 3093 | 3093 | // Ignore non-identifiable packets. |
| ... | ... | @@ -3124,7 +3124,7 @@ fn lookupDns( |
| 3124 | 3124 | .data_ptr = query.ptr, |
| 3125 | 3125 | .data_len = query.len, |
| 3126 | 3126 | }; |
| 3127 | | _ = netSend(pool, socket.handle, (&retry_message)[0..1], .{}); |
| 3127 | _ = netSend(t, socket.handle, (&retry_message)[0..1], .{}); |
| 3128 | 3128 | continue; |
| 3129 | 3129 | }, |
| 3130 | 3130 | else => continue, |
| ... | ... | @@ -3155,7 +3155,7 @@ fn lookupDns( |
| 3155 | 3155 | std.posix.RR.A => { |
| 3156 | 3156 | const data = record.packet[record.data_off..][0..record.data_len]; |
| 3157 | 3157 | if (data.len != 4) return error.InvalidDnsARecord; |
| 3158 | | try resolved.putOne(pool_io, .{ .address = .{ .ip4 = .{ |
| 3158 | try resolved.putOne(t_io, .{ .address = .{ .ip4 = .{ |
| 3159 | 3159 | .bytes = data[0..4].*, |
| 3160 | 3160 | .port = options.port, |
| 3161 | 3161 | } } }); |
| ... | ... | @@ -3164,7 +3164,7 @@ fn lookupDns( |
| 3164 | 3164 | std.posix.RR.AAAA => { |
| 3165 | 3165 | const data = record.packet[record.data_off..][0..record.data_len]; |
| 3166 | 3166 | if (data.len != 16) return error.InvalidDnsAAAARecord; |
| 3167 | | try resolved.putOne(pool_io, .{ .address = .{ .ip6 = .{ |
| 3167 | try resolved.putOne(t_io, .{ .address = .{ .ip6 = .{ |
| 3168 | 3168 | .bytes = data[0..16].*, |
| 3169 | 3169 | .port = options.port, |
| 3170 | 3170 | } } }); |
| ... | ... | @@ -3178,18 +3178,18 @@ fn lookupDns( |
| 3178 | 3178 | }; |
| 3179 | 3179 | } |
| 3180 | 3180 | |
| 3181 | | try resolved.putOne(pool_io, .{ .canonical_name = canonical_name orelse .{ .bytes = lookup_canon_name } }); |
| 3181 | try resolved.putOne(t_io, .{ .canonical_name = canonical_name orelse .{ .bytes = lookup_canon_name } }); |
| 3182 | 3182 | if (addresses_len == 0) return error.NameServerFailure; |
| 3183 | 3183 | } |
| 3184 | 3184 | |
| 3185 | 3185 | fn lookupHosts( |
| 3186 | | pool: *Pool, |
| 3186 | t: *Threaded, |
| 3187 | 3187 | host_name: HostName, |
| 3188 | 3188 | resolved: *Io.Queue(HostName.LookupResult), |
| 3189 | 3189 | options: HostName.LookupOptions, |
| 3190 | 3190 | ) !void { |
| 3191 | | const pool_io = pool.io(); |
| 3192 | | const file = Io.File.openAbsolute(pool_io, "/etc/hosts", .{}) catch |err| switch (err) { |
| 3191 | const t_io = t.io(); |
| 3192 | const file = Io.File.openAbsolute(t_io, "/etc/hosts", .{}) catch |err| switch (err) { |
| 3193 | 3193 | error.FileNotFound, |
| 3194 | 3194 | error.NotDir, |
| 3195 | 3195 | error.AccessDenied, |
| ... | ... | @@ -3202,11 +3202,11 @@ fn lookupHosts( |
| 3202 | 3202 | return error.DetectingNetworkConfigurationFailed; |
| 3203 | 3203 | }, |
| 3204 | 3204 | }; |
| 3205 | | defer file.close(pool_io); |
| 3205 | defer file.close(t_io); |
| 3206 | 3206 | |
| 3207 | 3207 | var line_buf: [512]u8 = undefined; |
| 3208 | | var file_reader = file.reader(pool_io, &line_buf); |
| 3209 | | return lookupHostsReader(pool, host_name, resolved, options, &file_reader.interface) catch |err| switch (err) { |
| 3208 | var file_reader = file.reader(t_io, &line_buf); |
| 3209 | return lookupHostsReader(t, host_name, resolved, options, &file_reader.interface) catch |err| switch (err) { |
| 3210 | 3210 | error.ReadFailed => switch (file_reader.err.?) { |
| 3211 | 3211 | error.Canceled => |e| return e, |
| 3212 | 3212 | else => { |
| ... | ... | @@ -3220,13 +3220,13 @@ fn lookupHosts( |
| 3220 | 3220 | } |
| 3221 | 3221 | |
| 3222 | 3222 | fn lookupHostsReader( |
| 3223 | | pool: *Pool, |
| 3223 | t: *Threaded, |
| 3224 | 3224 | host_name: HostName, |
| 3225 | 3225 | resolved: *Io.Queue(HostName.LookupResult), |
| 3226 | 3226 | options: HostName.LookupOptions, |
| 3227 | 3227 | reader: *Io.Reader, |
| 3228 | 3228 | ) error{ ReadFailed, Canceled, UnknownHostName }!void { |
| 3229 | | const pool_io = pool.io(); |
| 3229 | const t_io = t.io(); |
| 3230 | 3230 | var addresses_len: usize = 0; |
| 3231 | 3231 | var canonical_name: ?HostName = null; |
| 3232 | 3232 | while (true) { |
| ... | ... | @@ -3268,19 +3268,19 @@ fn lookupHostsReader( |
| 3268 | 3268 | |
| 3269 | 3269 | if (options.family != .ip6) { |
| 3270 | 3270 | if (IpAddress.parseIp4(ip_text, options.port)) |addr| { |
| 3271 | | try resolved.putOne(pool_io, .{ .address = addr }); |
| 3271 | try resolved.putOne(t_io, .{ .address = addr }); |
| 3272 | 3272 | addresses_len += 1; |
| 3273 | 3273 | } else |_| {} |
| 3274 | 3274 | } |
| 3275 | 3275 | if (options.family != .ip4) { |
| 3276 | 3276 | if (IpAddress.parseIp6(ip_text, options.port)) |addr| { |
| 3277 | | try resolved.putOne(pool_io, .{ .address = addr }); |
| 3277 | try resolved.putOne(t_io, .{ .address = addr }); |
| 3278 | 3278 | addresses_len += 1; |
| 3279 | 3279 | } else |_| {} |
| 3280 | 3280 | } |
| 3281 | 3281 | } |
| 3282 | 3282 | |
| 3283 | | if (canonical_name) |canon_name| try resolved.putOne(pool_io, .{ .canonical_name = canon_name }); |
| 3283 | if (canonical_name) |canon_name| try resolved.putOne(t_io, .{ .canonical_name = canon_name }); |
| 3284 | 3284 | if (addresses_len == 0) return error.UnknownHostName; |
| 3285 | 3285 | } |
| 3286 | 3286 | |