| ... | ... | @@ -2458,81 +2458,84 @@ fn operate(userdata: ?*anyopaque, operations: []Io.Operation) void { |
| 2458 | 2458 | |
| 2459 | 2459 | var poll_buffer: [poll_buffer_len]posix.pollfd = undefined; |
| 2460 | 2460 | var map_buffer: [poll_buffer_len]u8 = undefined; // poll_buffer index to operations index |
| 2461 | | var poll_i: usize = 0; |
| 2462 | | |
| 2463 | | // Put all the file reads with nonblocking enabled into the poll set. |
| 2464 | | if (operations.len > poll_buffer.len) @panic("TODO"); |
| 2465 | | |
| 2466 | | for (operations, 0..) |*operation, operation_index| switch (operation.*) { |
| 2467 | | .noop => continue, |
| 2468 | | .file_read_streaming => |*o| { |
| 2469 | | if (o.nonblocking) { |
| 2470 | | o.result = error.WouldBlock; |
| 2471 | | poll_buffer[poll_i] = .{ |
| 2472 | | .fd = o.file.handle, |
| 2473 | | .events = posix.POLL.IN, |
| 2474 | | .revents = undefined, |
| 2475 | | }; |
| 2476 | | map_buffer[poll_i] = @intCast(operation_index); |
| 2477 | | poll_i += 1; |
| 2478 | | } else { |
| 2479 | | o.result = fileReadStreaming(o.file, o.data) catch |err| switch (err) { |
| 2480 | | error.Canceled => { |
| 2481 | | setOperationsCanceled(operations[operation_index..]); |
| 2482 | | return; |
| 2483 | | }, |
| 2484 | | else => err, |
| 2485 | | }; |
| 2461 | var operation_index: usize = 0; |
| 2462 | |
| 2463 | while (operation_index < operations.len) { |
| 2464 | var poll_i: usize = 0; |
| 2465 | while (operation_index < operations.len) : (operation_index += 1) { |
| 2466 | switch (operations[operation_index]) { |
| 2467 | .noop => continue, |
| 2468 | .file_read_streaming => |*o| { |
| 2469 | if (o.nonblocking) { |
| 2470 | o.result = error.WouldBlock; |
| 2471 | poll_buffer[poll_i] = .{ |
| 2472 | .fd = o.file.handle, |
| 2473 | .events = posix.POLL.IN, |
| 2474 | .revents = 0, |
| 2475 | }; |
| 2476 | if (map_buffer.len - poll_i == 0) break; |
| 2477 | map_buffer[poll_i] = @intCast(operation_index); |
| 2478 | poll_i += 1; |
| 2479 | } else { |
| 2480 | o.result = fileReadStreaming(o.file, o.data) catch |err| switch (err) { |
| 2481 | error.Canceled => { |
| 2482 | setOperationsError(operations[operation_index..], error.Canceled); |
| 2483 | return; |
| 2484 | }, |
| 2485 | else => err, |
| 2486 | }; |
| 2487 | } |
| 2488 | }, |
| 2486 | 2489 | } |
| 2487 | | }, |
| 2488 | | }; |
| 2489 | | |
| 2490 | | if (poll_i == 0) { |
| 2491 | | @branchHint(.likely); |
| 2492 | | return; |
| 2493 | | } |
| 2490 | } |
| 2494 | 2491 | |
| 2495 | | while (true) { |
| 2496 | | const syscall = Syscall.start() catch |err| switch (err) { |
| 2497 | | error.Canceled => { |
| 2498 | | setAllOperationsError(operations, map_buffer[0..poll_i], error.Canceled); |
| 2499 | | return; |
| 2500 | | }, |
| 2501 | | }; |
| 2502 | | const poll_rc = posix.system.poll(&poll_buffer, poll_i, -1); |
| 2503 | | syscall.finish(); |
| 2504 | | switch (posix.errno(poll_rc)) { |
| 2505 | | .SUCCESS => { |
| 2506 | | if (poll_rc == 0) { |
| 2507 | | // Spurious timeout; handle same as INTR. |
| 2508 | | continue; |
| 2509 | | } |
| 2510 | | break; |
| 2511 | | }, |
| 2512 | | .INTR => continue, |
| 2513 | | .NOMEM => { |
| 2514 | | setAllOperationsError(operations, map_buffer[0..poll_i], error.SystemResources); |
| 2515 | | return; |
| 2516 | | }, |
| 2517 | | else => { |
| 2518 | | setAllOperationsError(operations, map_buffer[0..poll_i], error.Unexpected); |
| 2519 | | return; |
| 2520 | | }, |
| 2492 | if (poll_i == 0) { |
| 2493 | @branchHint(.likely); |
| 2494 | return; |
| 2521 | 2495 | } |
| 2522 | | } |
| 2523 | 2496 | |
| 2524 | | for (poll_buffer[0..poll_i], map_buffer[0..poll_i]) |*poll_fd, operation_index| { |
| 2525 | | if (poll_fd.revents == 0) continue; |
| 2526 | | switch (operations[operation_index]) { |
| 2527 | | .noop => unreachable, |
| 2528 | | .file_read_streaming => |*o| { |
| 2529 | | o.result = fileReadStreaming(o.file, o.data); |
| 2530 | | }, |
| 2497 | while (true) { |
| 2498 | const syscall = Syscall.start() catch |err| switch (err) { |
| 2499 | error.Canceled => { |
| 2500 | setPollOperationsError(operations, map_buffer[0..poll_i], error.Canceled); |
| 2501 | setOperationsError(operations[operation_index..], error.Canceled); |
| 2502 | return; |
| 2503 | }, |
| 2504 | }; |
| 2505 | const poll_rc = posix.system.poll(&poll_buffer, poll_i, -1); |
| 2506 | syscall.finish(); |
| 2507 | switch (posix.errno(poll_rc)) { |
| 2508 | .SUCCESS => { |
| 2509 | if (poll_rc == 0) { |
| 2510 | // Spurious timeout; handle same as INTR. |
| 2511 | continue; |
| 2512 | } |
| 2513 | for (poll_buffer[0..poll_i], map_buffer[0..poll_i]) |*poll_fd, i| { |
| 2514 | if (poll_fd.revents == 0) continue; |
| 2515 | switch (operations[i]) { |
| 2516 | .noop => unreachable, |
| 2517 | .file_read_streaming => |*o| { |
| 2518 | o.result = fileReadStreaming(o.file, o.data); |
| 2519 | }, |
| 2520 | } |
| 2521 | } |
| 2522 | break; |
| 2523 | }, |
| 2524 | .INTR => continue, |
| 2525 | .NOMEM => { |
| 2526 | setPollOperationsError(operations, map_buffer[0..poll_i], error.SystemResources); |
| 2527 | break; |
| 2528 | }, |
| 2529 | else => { |
| 2530 | setPollOperationsError(operations, map_buffer[0..poll_i], error.Unexpected); |
| 2531 | break; |
| 2532 | }, |
| 2533 | } |
| 2531 | 2534 | } |
| 2532 | 2535 | } |
| 2533 | 2536 | } |
| 2534 | 2537 | |
| 2535 | | fn setAllOperationsError( |
| 2538 | fn setPollOperationsError( |
| 2536 | 2539 | operations: []Io.Operation, |
| 2537 | 2540 | map: []const u8, |
| 2538 | 2541 | err: error{ Canceled, SystemResources, Unexpected }, |
| ... | ... | @@ -2543,10 +2546,10 @@ fn setAllOperationsError( |
| 2543 | 2546 | }; |
| 2544 | 2547 | } |
| 2545 | 2548 | |
| 2546 | | fn setOperationsCanceled(operations: []Io.Operation) void { |
| 2549 | fn setOperationsError(operations: []Io.Operation, err: error{ Canceled, SystemResources, Unexpected }) void { |
| 2547 | 2550 | for (operations) |*op| switch (op.*) { |
| 2548 | 2551 | .noop => unreachable, |
| 2549 | | inline else => |*o| o.result = error.Canceled, |
| 2552 | inline else => |*o| o.result = err, |
| 2550 | 2553 | }; |
| 2551 | 2554 | } |
| 2552 | 2555 | |