* Reuse bytes of async function frames when non-async functions
make `noasync` calls. This prevents explosive stack growth.
* Zig now passes a stack size argument to the linker when linking ELF
binaries. Linux ignores this value, but it is available as a program
header called GNU_STACK. I prototyped some code that memory maps
extra space to the stack using this program header, but there was
still a problem when accessing stack memory very far down. Stack
probing is needed or not working or something. I also prototyped
using `@newStackCall` to call main and that does work around the
issue but it also brings its own issues. That code is commented out
for now in std/special/start.zig. I'm on a plane with no Internet,
but I plan to consult with the musl community for advice when I get a
chance.
* Added `noasync` to a bunch of function calls in std.debug. It's very
messy but it's a workaround that makes stack traces functional with
evented I/O enabled. Eventually these will be cleaned up as the root
bugs are found and fixed. Programs built in blocking mode are
unaffected.
* Lowered the default stack size of std.io.InStream (for the async
version) to 1 MiB instead of 4. Until we figure out how to get
choosing a stack size working (see 2nd bullet point above), 4 MiB
tends to cause segfaults due to stack size running out, or usage of
stack memory too far apart, or something like that.
* Default thread stack size is bumped from 8 MiB to 16 to match the
size we give for the main thread. It's planned to eventually remove
this hard coded value and have Zig able to determine this value
during semantic analysis, with call graph analysis and function
pointer annotations and extern function annotations.
Let's not be writing 0xaa in safe modes for upwards of 4 MiB for every
stream read. This is equivalent to the fact that we don't memset the
entire call stack to 0xaa for every function call.
* Add missing <stdint.h> include for uint8_t type declaration
* Add needed FreeBSD check to link to libpthread
* Apply patch to enable more tests in the FreeBSD CI
This applies 91864f82c7d7bd1a151fdfd076a3a67a2893b868 from LLVM trunk to
the embedded LLD.
Once Zig upgrades to LLD 10, there will be no difference between Zig's
fork and upstream, and Zig's fork can be dropped.
This introduces the concept of "IO mode" which is configurable by the
root source file (e.g. next to `pub fn main`). Applications can put this
in their root source file:
```
pub const io_mode = .evented;
```
This will populate `std.io.mode` to be `std.io.Mode.evented`. When I/O
mode is evented, `std.os.read` handles EAGAIN by suspending until the
file descriptor becomes available for reading. Although the std lib
event loop supports epoll, kqueue, and Windows I/O Completion Ports,
this integration with `std.os.read` currently only works on Linux.
This integration is currently only hooked up to `std.os.read`, and not,
for example, `std.os.write`, child processes, and timers. The fact that
we can do this and still have a working master branch is thanks to Zig's
lazy analysis, comptime, and inferred async. We can continue to make
incremental progress on async std lib features, enabling more and more
test cases and coverage.
In addition to `std.io.mode` there is `std.io.is_async` which is equal
to `std.io.mode == .evented`. In case I/O mode is async, `std.io.InStream`
notices this and the read function pointer becomes an async function
pointer rather than a blocking function pointer. Even in this case,
`std.io.InStream` can *still be used as a blocking input stream*.
Users of the API control whether it is blocking or async at runtime by whether
or not the read function suspends. In case of file descriptors, for
example, this might correspond to whether it was opened with `O_NONBLOCK`.
The `noasync` keyword makes a function call or `await` assert that no
suspension happens. This assertion has runtime safety enabled.
`std.io.InStream`, in the case of async I/O, uses by default a 4 MiB
frame size for calling the read function. If this is too large or too
small, the application can globally increase the frame size used by
declaring `pub const stack_size_std_io_InStream = 1234;` in their root
source file. This way, `std.io.InStream` will only be generated once,
avoiding bloat, and as long as this number is configured to be high
enough, everything works fine. Zig has runtime safety to detect when
`@asyncCall` is given too small of a buffer for the frame size.
This merge introduces -fstack-report which can help identify large async
function frame sizes and explain what is making them so big. Until #3069 is
solved, it's recommended to stick with blocking IO mode.
-fstack-report outputs JSON format, which can then be viewed in a GUI
that represents the tree structure. As an example, Firefox does a decent
job of this.
One feature that is currently missing is detecting that the call stack
upper bound is greater than the default for a given target, and passing
this upper bound to the linker. As an example, if Zig detects that 20
MiB stack upper bound is needed - which would be quite reasonable -
currently on Linux the application would only be given the default of 16
MiB.
Unrelated miscellaneous change: added std.c.readv
Sometimes the frontend and LLVM would disagree on the ABI alignment of a
packed union. Solve the problem by telling LLVM we're gonna manage the
struct layout by ourselves.
Closes#3184
- include native-target when native-target ∉ cross_targets
old behavior:
- do nothing when `-Dskip-non-native`
- never execute pkg tests for non-members of cross_targets