| ... | @@ -177,7 +177,6 @@ pub fn io(t: *Threaded) Io { | ... | @@ -177,7 +177,6 @@ pub fn io(t: *Threaded) Io { |
| 177 | | 177 | |
| 178 | .groupAsync = groupAsync, | 178 | .groupAsync = groupAsync, |
| 179 | .groupWait = groupWait, | 179 | .groupWait = groupWait, |
| 180 | .groupWaitUncancelable = groupWaitUncancelable, | | |
| 181 | .groupCancel = groupCancel, | 180 | .groupCancel = groupCancel, |
| 182 | | 181 | |
| 183 | .mutexLock = mutexLock, | 182 | .mutexLock = mutexLock, |
| ... | @@ -274,7 +273,6 @@ pub fn ioBasic(t: *Threaded) Io { | ... | @@ -274,7 +273,6 @@ pub fn ioBasic(t: *Threaded) Io { |
| 274 | | 273 | |
| 275 | .groupAsync = groupAsync, | 274 | .groupAsync = groupAsync, |
| 276 | .groupWait = groupWait, | 275 | .groupWait = groupWait, |
| 277 | .groupWaitUncancelable = groupWaitUncancelable, | | |
| 278 | .groupCancel = groupCancel, | 276 | .groupCancel = groupCancel, |
| 279 | | 277 | |
| 280 | .mutexLock = mutexLock, | 278 | .mutexLock = mutexLock, |
| ... | @@ -579,7 +577,9 @@ const GroupClosure = struct { | ... | @@ -579,7 +577,9 @@ const GroupClosure = struct { |
| 579 | assert(cancel_tid == .canceling); | 577 | assert(cancel_tid == .canceling); |
| 580 | } | 578 | } |
| 581 | | 579 | |
| 582 | syncFinish(group_state, reset_event); | 580 | const prev_state = group_state.fetchSub(sync_one_pending, .acq_rel); |
| | 581 | assert((prev_state / sync_one_pending) > 0); |
| | 582 | if (prev_state == (sync_one_pending | sync_is_waiting)) reset_event.set(); |
| 583 | } | 583 | } |
| 584 | | 584 | |
| 585 | fn free(gc: *GroupClosure, gpa: Allocator) void { | 585 | fn free(gc: *GroupClosure, gpa: Allocator) void { |
| ... | @@ -602,29 +602,6 @@ const GroupClosure = struct { | ... | @@ -602,29 +602,6 @@ const GroupClosure = struct { |
| 602 | | 602 | |
| 603 | const sync_is_waiting: usize = 1 << 0; | 603 | const sync_is_waiting: usize = 1 << 0; |
| 604 | const sync_one_pending: usize = 1 << 1; | 604 | const sync_one_pending: usize = 1 << 1; |
| 605 | | | |
| 606 | fn syncStart(state: *std.atomic.Value(usize)) void { | | |
| 607 | const prev_state = state.fetchAdd(sync_one_pending, .monotonic); | | |
| 608 | assert((prev_state / sync_one_pending) < (std.math.maxInt(usize) / sync_one_pending)); | | |
| 609 | } | | |
| 610 | | | |
| 611 | fn syncFinish(state: *std.atomic.Value(usize), event: *ResetEvent) void { | | |
| 612 | const prev_state = state.fetchSub(sync_one_pending, .acq_rel); | | |
| 613 | assert((prev_state / sync_one_pending) > 0); | | |
| 614 | if (prev_state == (sync_one_pending | sync_is_waiting)) event.set(); | | |
| 615 | } | | |
| 616 | | | |
| 617 | fn syncWait(t: *Threaded, state: *std.atomic.Value(usize), event: *ResetEvent) Io.Cancelable!void { | | |
| 618 | const prev_state = state.fetchAdd(sync_is_waiting, .acquire); | | |
| 619 | assert(prev_state & sync_is_waiting == 0); | | |
| 620 | if ((prev_state / sync_one_pending) > 0) try event.wait(t); | | |
| 621 | } | | |
| 622 | | | |
| 623 | fn syncWaitUncancelable(state: *std.atomic.Value(usize), event: *ResetEvent) void { | | |
| 624 | const prev_state = state.fetchAdd(sync_is_waiting, .acquire); | | |
| 625 | assert(prev_state & sync_is_waiting == 0); | | |
| 626 | if ((prev_state / sync_one_pending) > 0) event.waitUncancelable(); | | |
| 627 | } | | |
| 628 | }; | 605 | }; |
| 629 | | 606 | |
| 630 | fn groupAsync( | 607 | fn groupAsync( |
| ... | @@ -686,32 +663,14 @@ fn groupAsync( | ... | @@ -686,32 +663,14 @@ fn groupAsync( |
| 686 | // This needs to be done before unlocking the mutex to avoid a race with | 663 | // This needs to be done before unlocking the mutex to avoid a race with |
| 687 | // the associated task finishing. | 664 | // the associated task finishing. |
| 688 | const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); | 665 | const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); |
| 689 | GroupClosure.syncStart(group_state); | 666 | const prev_state = group_state.fetchAdd(GroupClosure.sync_one_pending, .monotonic); |
| | 667 | assert((prev_state / GroupClosure.sync_one_pending) < (std.math.maxInt(usize) / GroupClosure.sync_one_pending)); |
| 690 | | 668 | |
| 691 | t.mutex.unlock(); | 669 | t.mutex.unlock(); |
| 692 | t.cond.signal(); | 670 | t.cond.signal(); |
| 693 | } | 671 | } |
| 694 | | 672 | |
| 695 | fn groupWait(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) Io.Cancelable!void { | 673 | fn groupWait(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { |
| 696 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | | |
| 697 | const gpa = t.allocator; | | |
| 698 | | | |
| 699 | if (builtin.single_threaded) return; | | |
| 700 | | | |
| 701 | const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); | | |
| 702 | const reset_event: *ResetEvent = @ptrCast(&group.context); | | |
| 703 | try GroupClosure.syncWait(t, group_state, reset_event); | | |
| 704 | | | |
| 705 | var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); | | |
| 706 | while (true) { | | |
| 707 | const gc: *GroupClosure = @fieldParentPtr("node", node); | | |
| 708 | const node_next = node.next; | | |
| 709 | gc.free(gpa); | | |
| 710 | node = node_next orelse break; | | |
| 711 | } | | |
| 712 | } | | |
| 713 | | | |
| 714 | fn groupWaitUncancelable(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void { | | |
| 715 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 674 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 716 | const gpa = t.allocator; | 675 | const gpa = t.allocator; |
| 717 | | 676 | |
| ... | @@ -719,7 +678,19 @@ fn groupWaitUncancelable(userdata: ?*anyopaque, group: *Io.Group, token: *anyopa | ... | @@ -719,7 +678,19 @@ fn groupWaitUncancelable(userdata: ?*anyopaque, group: *Io.Group, token: *anyopa |
| 719 | | 678 | |
| 720 | const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); | 679 | const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); |
| 721 | const reset_event: *ResetEvent = @ptrCast(&group.context); | 680 | const reset_event: *ResetEvent = @ptrCast(&group.context); |
| 722 | GroupClosure.syncWaitUncancelable(group_state, reset_event); | 681 | const prev_state = group_state.fetchAdd(GroupClosure.sync_is_waiting, .acquire); |
| | 682 | assert(prev_state & GroupClosure.sync_is_waiting == 0); |
| | 683 | if ((prev_state / GroupClosure.sync_one_pending) > 0) reset_event.wait(t) catch |err| switch (err) { |
| | 684 | error.Canceled => { |
| | 685 | var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); |
| | 686 | while (true) { |
| | 687 | const gc: *GroupClosure = @fieldParentPtr("node", node); |
| | 688 | gc.closure.requestCancel(); |
| | 689 | node = node.next orelse break; |
| | 690 | } |
| | 691 | reset_event.waitUncancelable(); |
| | 692 | }, |
| | 693 | }; |
| 723 | | 694 | |
| 724 | var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); | 695 | var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); |
| 725 | while (true) { | 696 | while (true) { |
| ... | @@ -747,7 +718,9 @@ fn groupCancel(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void | ... | @@ -747,7 +718,9 @@ fn groupCancel(userdata: ?*anyopaque, group: *Io.Group, token: *anyopaque) void |
| 747 | | 718 | |
| 748 | const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); | 719 | const group_state: *std.atomic.Value(usize) = @ptrCast(&group.state); |
| 749 | const reset_event: *ResetEvent = @ptrCast(&group.context); | 720 | const reset_event: *ResetEvent = @ptrCast(&group.context); |
| 750 | GroupClosure.syncWaitUncancelable(group_state, reset_event); | 721 | const prev_state = group_state.fetchAdd(GroupClosure.sync_is_waiting, .acquire); |
| | 722 | assert(prev_state & GroupClosure.sync_is_waiting == 0); |
| | 723 | if ((prev_state / GroupClosure.sync_one_pending) > 0) reset_event.waitUncancelable(); |
| 751 | | 724 | |
| 752 | { | 725 | { |
| 753 | var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); | 726 | var node: *std.SinglyLinkedList.Node = @ptrCast(@alignCast(token)); |
| ... | @@ -1549,7 +1522,7 @@ fn dirAccessPosix( | ... | @@ -1549,7 +1522,7 @@ fn dirAccessPosix( |
| 1549 | .FAULT => |err| return errnoBug(err), | 1522 | .FAULT => |err| return errnoBug(err), |
| 1550 | .IO => return error.InputOutput, | 1523 | .IO => return error.InputOutput, |
| 1551 | .NOMEM => return error.SystemResources, | 1524 | .NOMEM => return error.SystemResources, |
| 1552 | .ILSEQ => return error.BadPathName, // TODO move to wasi | 1525 | .ILSEQ => return error.BadPathName, |
| 1553 | else => |err| return posix.unexpectedErrno(err), | 1526 | else => |err| return posix.unexpectedErrno(err), |
| 1554 | } | 1527 | } |
| 1555 | } | 1528 | } |