| // Copyright 2011 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // +build cgo |
| // +build fuchsia |
| |
| #include "libcgo.h" |
| |
| #include <stdlib.h> |
| #include <pthread.h> |
| |
| #include <lib/fdio/fd.h> |
| #include <lib/fdio/namespace.h> |
| #include <zircon/process.h> |
| #include <zircon/processargs.h> |
| #include <zircon/threads.h> |
| #include <zircon/types.h> |
| |
| extern char **environ; |
| |
| // fdio_init matches a Go struct of the same name in os_fuchsia.go. |
| struct fdio_init { |
| zx_handle_t stdioClones[3]; |
| uint32_t stdioCloneNumHandles[3]; |
| uint32_t stdioCloneTypes[3]; |
| zx_handle_t processSelf; |
| zx_handle_t vmarRootSelf; |
| int32_t envlen; |
| char** environ; |
| uint8_t padding[4]; |
| int32_t rootNSNumHandles; |
| zx_handle_t *rootNSHandles; |
| char** rootNSPaths; |
| }; |
| |
| void |
| x_cgo_get_initial_handles(struct fdio_init *handles) |
| { |
| // When running with cgo support, there are two FDIO libraries in the |
| // same process. We let the C FDIO start first, then clone its namespace |
| // and use that for Go. |
| // TODO: there is some small amount of fdio library state we |
| // have to share between Go and C, in particular, cwd. |
| // Work out how. |
| |
| // fdio may have initialized std{in,out,err} with a single fd if the FDIO_FLAG_USE_FOR_STDIO |
| // flag was set, or have separate in/out/err fds. We clone fds {0,1,2} to separate fds for use |
| // in the Go runtime. The cloned fds aren't installed into fdio's fd table so they are only |
| // usable from Go's table. |
| for (int i = 0; i < 3; ++i) { |
| zx_status_t status = fdio_fd_clone(i, &handles->stdioClones[i]); |
| if (status != ZX_OK) { |
| printf("runtime/cgo: fdio_fd_clone of stdio[%d] failed: %d\n", i, status); |
| handles->stdioCloneNumHandles[i] = 0; |
| } else { |
| handles->stdioCloneNumHandles[i] = 1; |
| handles->stdioCloneTypes[i] = PA_FD; |
| } |
| } |
| |
| handles->processSelf = zx_process_self(); |
| handles->vmarRootSelf = zx_vmar_root_self(); |
| |
| for (char** env = environ; *env; env++) { |
| handles->envlen++; |
| } |
| handles->environ = environ; |
| |
| fdio_flat_namespace_t* root_ns = NULL; |
| zx_status_t status = fdio_ns_export_root(&root_ns); |
| if (status != ZX_OK) { |
| handles->rootNSNumHandles = 0; |
| handles->rootNSHandles = NULL; |
| handles->rootNSPaths = NULL; |
| } else { |
| handles->rootNSNumHandles = (int32_t)root_ns->count; |
| handles->rootNSHandles = root_ns->handle; |
| handles->rootNSPaths = (char**)root_ns->path; |
| } |
| } |
| |
| void |
| x_cgo_get_thread_self_handle(zx_handle_t *h) |
| { |
| // N.B.: libc currently (and probably always will) share the same type for |
| // C11 threads and pthreads. |
| *h = thrd_get_zx_handle(pthread_self()); |
| } |