Leotard6963
Joined 3 years ago
Joined 3 years ago
The feature of generating go packages from C in `ffigen` still needs significant work to be done (mostly dealing with C calling conventions on different platforms), and the generated go package only works with dynamic libraries (as it uses the pragma `go:cgo_import_dynamic`).
And in brief introduction, the `g` register is a non-scratch register, and is preserved by the go compiler, it stores the poitner to current goroutine (type `g` in the official runtime, a structure serves the similar purpose of TCB), and since all general purpose registers are thread local, the goroutine may enjoy some thread-local features without any thread-local requirements to the running environment.
[1]: https://github.com/golang/go/blob/master/src/cmd/compile/abi...
The problem is, in order to build a std, we have to use a lot of <ABIInternal> stuff in assembly, and use internal/abi.FuncPCABIInternal in Go, so we can not make any promise regarding to the inter-std-compatibility for the time being, unless the Go project decided to make these features stable.
The project is to build a stdlib, and by its nature is to be used by developers to build applications just like the official Go std.
And Yes, we are defining brand new interfaces as well, in order to improve usability and fix inconsistent user experience.
For your specific example `os.WriteFile` (names mentioned below may subject to change):
The api won't make it inside the std, because the local filesystem will be implemented as a `fs.FS` (concrete type `*sysfs.FS`), so you can have multiple `sysfs.FS` instances each at its own working directory, and the `os.WriteFile` will be replaced with `fs.WriteFile(fsys fs.FS, path *fs.PathBuf, wctx *io.WriteContext) io.Status`, where `fs.PathBuf` is our solution to handle all kinds of path styles (windows, unix, cygwin, utf8, utf16, end-null) and operations (join, base, dir).
For variables you are sure living on the stack, you can use `mark.NoEscape(&v)` to obtain its pointer (a hack to cheat escape analysis found in the official runtime & reflect package), and the variable will be freed on function return.
For variables you want to control lifecycle, call `alloc.New` or `alloc.Make` with a explicit allocator, which can be an allocator whose storage is on the previous call stack (and there is a default goroutine local allocator thread.G().G().DefaultAlloc()) to allocate a non-stack-local variable, and call `alloc.Free` with the same allocator to free that variable.
The use of `make` is discouraged as go compiler does mid-stack inlining and escape analysis, so the return value of a `make` can be either on stack or on heap, thus to free it, the allocator needs to compare the address to thread.G().Stack.Lo and thread.G().Stack.Hi.
Making GC/goroutine optional & customizable requires building a std works with no GC/goroutine.
> dropping std
relax, this is a new std, let's spare the baby some hope?
We decided to make it this way so:
1) you can import packages from the pcz std module like you do with any other Go package without setting `GOROOT` to an unofficial std.
2) and because of 1), you can import packages from pcz std in your go application but still using the `go` command rather the `pcz` command.
In the future, we may provide drop-in replacement for applications using official std by introducing a compatibility module and a cli flag to redirect imports using packages from the official std to that module.
Neither, though the final result can be similar, but at project level, tinygo and pcz has very different approaches to achieve the final result:
- tinygo chose the hard path to write a llvm backed toolchain with some custom behavior that compiles Go code (using official std) to llvm targets.
- pcz chose the easy path to write a stdlib from scratch that compiles to desired targets using the official Go toolchain.
One major benefit of pcz's approach is you can import packages from the pcz std module like you do with any other Go package, the development experience can remain unchanged.
Were the confusion caused by the choice of project name `pcz` instead of `xxxstd`? or any suggestion for us to improve?
Precondition: in Go, each goroutine has its own `g` structure (like TCB, but for controlling goroutines) and its address is stored in the `g` register, which is reserved by the go compiler, active goroutines can call a function runtime.getg() to obtain the value of the `g` register.
In the official runtime, the `g` structure is a concrete type and the scheduler is implemented globally in the runtime package.
But we have made the `g` structure customizable (still requires a fixed header expected by the function prologue & epilogue and linker), so custom g implementations may contain a link to a custom scheduler, and the scheduler can decide how to handle an active goroutine.
> "goroutines" that automatically suspend themselves
The automatic suspend and resume happens by
- calling `runtime.entersyscall` from a running goroutine - and calling `runtime.exitsyscall` from an finished systemstack
all these operations can interact with the custom `g`, thus can interact with the custom scheduler.