internal/fakecgo: deduplicate arch-agnostic code (#342)
fakecgo contains multiple functions whose implementation is duplicated verbatim (excluding comments) for every supported GOOS/GOARCH pair. They can be deduplicated into arch-agnostic Go files.
- commit
- 73cecc9f4127e8ae88b26bc76c1bb2c9c7c3065a
- author
- Quim Muntal · · 2025-09-30 15:33 UTC
- committer
- GitHub · · 2025-09-30 15:33 UTC
- parent
- 684058f
- signature
- GPG Unverified
B5690EEEBB952194The key is unknown - refs
- tag: v0.10.0-alpha.2
8 files · +6 -356
M README.md +2 -1
| @@ -103,11 +103,12 @@ This is a list of the copied files: | |||
| 103 | 103 | * `internal/fakecgo/abi_*.h` from package `runtime/cgo` | |
| 104 | 104 | * `internal/fakecgo/asm_GOARCH.s` from package `runtime/cgo` | |
| 105 | 105 | * `internal/fakecgo/callbacks.go` from package `runtime/cgo` | |
| 106 | - | * `internal/fakecgo/go_GOOS_GOARCH.go` from package `runtime/cgo` | |
| 107 | 106 | * `internal/fakecgo/iscgo.go` from package `runtime/cgo` | |
| 108 | 107 | * `internal/fakecgo/setenv.go` from package `runtime/cgo` | |
| 109 | 108 | * `internal/fakecgo/freebsd.go` from package `runtime/cgo` | |
| 110 | 109 | * `internal/fakecgo/netbsd.go` from package `runtime/cgo` | |
| 111 | 110 | ||
| 111 | + | The `internal/fakecgo/go_GOOS.go` files were modified from `runtime/cgo/gcc_GOOS_GOARCH.go`. | |
| 112 | + | ||
| 112 | 113 | The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of | |
| 113 | 114 | `#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636)) | |
| @@ -103,11 +103,12 @@ This is a list of the copied files: | |||||
| 103 | * `internal/fakecgo/abi_*.h` from package `runtime/cgo` | 103 | * `internal/fakecgo/abi_*.h` from package `runtime/cgo` | ||
| 104 | * `internal/fakecgo/asm_GOARCH.s` from package `runtime/cgo` | 104 | * `internal/fakecgo/asm_GOARCH.s` from package `runtime/cgo` | ||
| 105 | * `internal/fakecgo/callbacks.go` from package `runtime/cgo` | 105 | * `internal/fakecgo/callbacks.go` from package `runtime/cgo` | ||
| 106 | - | * `internal/fakecgo/go_GOOS_GOARCH.go` from package `runtime/cgo` | |||
| 107 | * `internal/fakecgo/iscgo.go` from package `runtime/cgo` | 106 | * `internal/fakecgo/iscgo.go` from package `runtime/cgo` | ||
| 108 | * `internal/fakecgo/setenv.go` from package `runtime/cgo` | 107 | * `internal/fakecgo/setenv.go` from package `runtime/cgo` | ||
| 109 | * `internal/fakecgo/freebsd.go` from package `runtime/cgo` | 108 | * `internal/fakecgo/freebsd.go` from package `runtime/cgo` | ||
| 110 | * `internal/fakecgo/netbsd.go` from package `runtime/cgo` | 109 | * `internal/fakecgo/netbsd.go` from package `runtime/cgo` | ||
| 111 | 110 | ||||
| 111 | + | The `internal/fakecgo/go_GOOS.go` files were modified from `runtime/cgo/gcc_GOOS_GOARCH.go`. | |||
| 112 | + | ||||
| 112 | The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of | 113 | The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of | ||
| 113 | `#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636)) | 114 | `#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636)) | ||
R internal/fakecgo/go_darwin_arm64.go → internal/fakecgo/go_darwin.go +0 -0 renamed, 100% similar
renamed, 100% similar
D internal/fakecgo/go_darwin_amd64.go +0 -73
| @@ -1,73 +0,0 @@ | |||
| 1 | - | // Copyright 2011 The Go Authors. All rights reserved. | |
| 2 | - | // Use of this source code is governed by a BSD-style | |
| 3 | - | // license that can be found in the LICENSE file. | |
| 4 | - | ||
| 5 | - | //go:build !cgo | |
| 6 | - | ||
| 7 | - | package fakecgo | |
| 8 | - | ||
| 9 | - | import "unsafe" | |
| 10 | - | ||
| 11 | - | //go:nosplit | |
| 12 | - | //go:norace | |
| 13 | - | func _cgo_sys_thread_start(ts *ThreadStart) { | |
| 14 | - | var attr pthread_attr_t | |
| 15 | - | var ign, oset sigset_t | |
| 16 | - | var p pthread_t | |
| 17 | - | var size size_t | |
| 18 | - | var err int | |
| 19 | - | ||
| 20 | - | sigfillset(&ign) | |
| 21 | - | pthread_sigmask(SIG_SETMASK, &ign, &oset) | |
| 22 | - | ||
| 23 | - | size = pthread_get_stacksize_np(pthread_self()) | |
| 24 | - | pthread_attr_init(&attr) | |
| 25 | - | pthread_attr_setstacksize(&attr, size) | |
| 26 | - | // Leave stacklo=0 and set stackhi=size; mstart will do the rest. | |
| 27 | - | ts.g.stackhi = uintptr(size) | |
| 28 | - | ||
| 29 | - | err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts) | |
| 30 | - | ||
| 31 | - | pthread_sigmask(SIG_SETMASK, &oset, nil) | |
| 32 | - | ||
| 33 | - | if err != 0 { | |
| 34 | - | print("fakecgo: pthread_create failed: ") | |
| 35 | - | println(err) | |
| 36 | - | abort() | |
| 37 | - | } | |
| 38 | - | } | |
| 39 | - | ||
| 40 | - | // threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function | |
| 41 | - | // | |
| 42 | - | //go:linkname x_threadentry_trampoline threadentry_trampoline | |
| 43 | - | var x_threadentry_trampoline byte | |
| 44 | - | var threadentry_trampolineABI0 = &x_threadentry_trampoline | |
| 45 | - | ||
| 46 | - | //go:nosplit | |
| 47 | - | //go:norace | |
| 48 | - | func threadentry(v unsafe.Pointer) unsafe.Pointer { | |
| 49 | - | ts := *(*ThreadStart)(v) | |
| 50 | - | free(v) | |
| 51 | - | ||
| 52 | - | setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g))) | |
| 53 | - | ||
| 54 | - | // faking funcs in go is a bit a... involved - but the following works :) | |
| 55 | - | fn := uintptr(unsafe.Pointer(&ts.fn)) | |
| 56 | - | (*(*func())(unsafe.Pointer(&fn)))() | |
| 57 | - | ||
| 58 | - | return nil | |
| 59 | - | } | |
| 60 | - | ||
| 61 | - | // here we will store a pointer to the provided setg func | |
| 62 | - | var setg_func uintptr | |
| 63 | - | ||
| 64 | - | //go:nosplit | |
| 65 | - | //go:norace | |
| 66 | - | func x_cgo_init(g *G, setg uintptr) { | |
| 67 | - | var size size_t | |
| 68 | - | ||
| 69 | - | setg_func = setg | |
| 70 | - | ||
| 71 | - | size = pthread_get_stacksize_np(pthread_self()) | |
| 72 | - | g.stacklo = uintptr(unsafe.Add(unsafe.Pointer(&size), -size+4096)) | |
| 73 | - | } | |
| @@ -1,73 +0,0 @@ | |||||
| 1 | - | // Copyright 2011 The Go Authors. All rights reserved. | |||
| 2 | - | // Use of this source code is governed by a BSD-style | |||
| 3 | - | // license that can be found in the LICENSE file. | |||
| 4 | - | ||||
| 5 | - | //go:build !cgo | |||
| 6 | - | ||||
| 7 | - | package fakecgo | |||
| 8 | - | ||||
| 9 | - | import "unsafe" | |||
| 10 | - | ||||
| 11 | - | //go:nosplit | |||
| 12 | - | //go:norace | |||
| 13 | - | func _cgo_sys_thread_start(ts *ThreadStart) { | |||
| 14 | - | var attr pthread_attr_t | |||
| 15 | - | var ign, oset sigset_t | |||
| 16 | - | var p pthread_t | |||
| 17 | - | var size size_t | |||
| 18 | - | var err int | |||
| 19 | - | ||||
| 20 | - | sigfillset(&ign) | |||
| 21 | - | pthread_sigmask(SIG_SETMASK, &ign, &oset) | |||
| 22 | - | ||||
| 23 | - | size = pthread_get_stacksize_np(pthread_self()) | |||
| 24 | - | pthread_attr_init(&attr) | |||
| 25 | - | pthread_attr_setstacksize(&attr, size) | |||
| 26 | - | // Leave stacklo=0 and set stackhi=size; mstart will do the rest. | |||
| 27 | - | ts.g.stackhi = uintptr(size) | |||
| 28 | - | ||||
| 29 | - | err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts) | |||
| 30 | - | ||||
| 31 | - | pthread_sigmask(SIG_SETMASK, &oset, nil) | |||
| 32 | - | ||||
| 33 | - | if err != 0 { | |||
| 34 | - | print("fakecgo: pthread_create failed: ") | |||
| 35 | - | println(err) | |||
| 36 | - | abort() | |||
| 37 | - | } | |||
| 38 | - | } | |||
| 39 | - | ||||
| 40 | - | // threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function | |||
| 41 | - | // | |||
| 42 | - | //go:linkname x_threadentry_trampoline threadentry_trampoline | |||
| 43 | - | var x_threadentry_trampoline byte | |||
| 44 | - | var threadentry_trampolineABI0 = &x_threadentry_trampoline | |||
| 45 | - | ||||
| 46 | - | //go:nosplit | |||
| 47 | - | //go:norace | |||
| 48 | - | func threadentry(v unsafe.Pointer) unsafe.Pointer { | |||
| 49 | - | ts := *(*ThreadStart)(v) | |||
| 50 | - | free(v) | |||
| 51 | - | ||||
| 52 | - | setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g))) | |||
| 53 | - | ||||
| 54 | - | // faking funcs in go is a bit a... involved - but the following works :) | |||
| 55 | - | fn := uintptr(unsafe.Pointer(&ts.fn)) | |||
| 56 | - | (*(*func())(unsafe.Pointer(&fn)))() | |||
| 57 | - | ||||
| 58 | - | return nil | |||
| 59 | - | } | |||
| 60 | - | ||||
| 61 | - | // here we will store a pointer to the provided setg func | |||
| 62 | - | var setg_func uintptr | |||
| 63 | - | ||||
| 64 | - | //go:nosplit | |||
| 65 | - | //go:norace | |||
| 66 | - | func x_cgo_init(g *G, setg uintptr) { | |||
| 67 | - | var size size_t | |||
| 68 | - | ||||
| 69 | - | setg_func = setg | |||
| 70 | - | ||||
| 71 | - | size = pthread_get_stacksize_np(pthread_self()) | |||
| 72 | - | g.stacklo = uintptr(unsafe.Add(unsafe.Pointer(&size), -size+4096)) | |||
| 73 | - | } | |||
R internal/fakecgo/go_freebsd_arm64.go → internal/fakecgo/go_freebsd.go +2 -0 renamed, 94% similar
| @@ -92,6 +92,8 @@ func x_cgo_init(g *G, setg uintptr) { | |||
| 92 | 92 | } | |
| 93 | 93 | pthread_attr_init(attr) | |
| 94 | 94 | pthread_attr_getstacksize(attr, &size) | |
| 95 | + | // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))` | |
| 96 | + | // but this should be OK since we are taking the address of the first variable in this function. | |
| 95 | 97 | g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 | |
| 96 | 98 | pthread_attr_destroy(attr) | |
| 97 | 99 | free(unsafe.Pointer(attr)) | |
| @@ -92,6 +92,8 @@ func x_cgo_init(g *G, setg uintptr) { | |||||
| 92 | } | 92 | } | ||
| 93 | pthread_attr_init(attr) | 93 | pthread_attr_init(attr) | ||
| 94 | pthread_attr_getstacksize(attr, &size) | 94 | pthread_attr_getstacksize(attr, &size) | ||
| 95 | + | // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))` | |||
| 96 | + | // but this should be OK since we are taking the address of the first variable in this function. | |||
| 95 | g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 | 97 | g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 | ||
| 96 | pthread_attr_destroy(attr) | 98 | pthread_attr_destroy(attr) | ||
| 97 | free(unsafe.Pointer(attr)) | 99 | free(unsafe.Pointer(attr)) | ||
D internal/fakecgo/go_freebsd_amd64.go +0 -95
| @@ -1,95 +0,0 @@ | |||
| 1 | - | // Copyright 2011 The Go Authors. All rights reserved. | |
| 2 | - | // Use of this source code is governed by a BSD-style | |
| 3 | - | // license that can be found in the LICENSE file. | |
| 4 | - | ||
| 5 | - | //go:build !cgo | |
| 6 | - | ||
| 7 | - | package fakecgo | |
| 8 | - | ||
| 9 | - | import "unsafe" | |
| 10 | - | ||
| 11 | - | //go:nosplit | |
| 12 | - | func _cgo_sys_thread_start(ts *ThreadStart) { | |
| 13 | - | var attr pthread_attr_t | |
| 14 | - | var ign, oset sigset_t | |
| 15 | - | var p pthread_t | |
| 16 | - | var size size_t | |
| 17 | - | var err int | |
| 18 | - | ||
| 19 | - | //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug | |
| 20 | - | sigfillset(&ign) | |
| 21 | - | pthread_sigmask(SIG_SETMASK, &ign, &oset) | |
| 22 | - | ||
| 23 | - | pthread_attr_init(&attr) | |
| 24 | - | pthread_attr_getstacksize(&attr, &size) | |
| 25 | - | // Leave stacklo=0 and set stackhi=size; mstart will do the rest. | |
| 26 | - | ts.g.stackhi = uintptr(size) | |
| 27 | - | ||
| 28 | - | err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts) | |
| 29 | - | ||
| 30 | - | pthread_sigmask(SIG_SETMASK, &oset, nil) | |
| 31 | - | ||
| 32 | - | if err != 0 { | |
| 33 | - | print("fakecgo: pthread_create failed: ") | |
| 34 | - | println(err) | |
| 35 | - | abort() | |
| 36 | - | } | |
| 37 | - | } | |
| 38 | - | ||
| 39 | - | // threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function | |
| 40 | - | // | |
| 41 | - | //go:linkname x_threadentry_trampoline threadentry_trampoline | |
| 42 | - | var x_threadentry_trampoline byte | |
| 43 | - | var threadentry_trampolineABI0 = &x_threadentry_trampoline | |
| 44 | - | ||
| 45 | - | //go:nosplit | |
| 46 | - | func threadentry(v unsafe.Pointer) unsafe.Pointer { | |
| 47 | - | ts := *(*ThreadStart)(v) | |
| 48 | - | free(v) | |
| 49 | - | ||
| 50 | - | setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g))) | |
| 51 | - | ||
| 52 | - | // faking funcs in go is a bit a... involved - but the following works :) | |
| 53 | - | fn := uintptr(unsafe.Pointer(&ts.fn)) | |
| 54 | - | (*(*func())(unsafe.Pointer(&fn)))() | |
| 55 | - | ||
| 56 | - | return nil | |
| 57 | - | } | |
| 58 | - | ||
| 59 | - | // here we will store a pointer to the provided setg func | |
| 60 | - | var setg_func uintptr | |
| 61 | - | ||
| 62 | - | //go:nosplit | |
| 63 | - | func x_cgo_init(g *G, setg uintptr) { | |
| 64 | - | var size size_t | |
| 65 | - | var attr *pthread_attr_t | |
| 66 | - | ||
| 67 | - | /* The memory sanitizer distributed with versions of clang | |
| 68 | - | before 3.8 has a bug: if you call mmap before malloc, mmap | |
| 69 | - | may return an address that is later overwritten by the msan | |
| 70 | - | library. Avoid this problem by forcing a call to malloc | |
| 71 | - | here, before we ever call malloc. | |
| 72 | - | ||
| 73 | - | This is only required for the memory sanitizer, so it's | |
| 74 | - | unfortunate that we always run it. It should be possible | |
| 75 | - | to remove this when we no longer care about versions of | |
| 76 | - | clang before 3.8. The test for this is | |
| 77 | - | misc/cgo/testsanitizers. | |
| 78 | - | ||
| 79 | - | GCC works hard to eliminate a seemingly unnecessary call to | |
| 80 | - | malloc, so we actually use the memory we allocate. */ | |
| 81 | - | ||
| 82 | - | setg_func = setg | |
| 83 | - | attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr))) | |
| 84 | - | if attr == nil { | |
| 85 | - | println("fakecgo: malloc failed") | |
| 86 | - | abort() | |
| 87 | - | } | |
| 88 | - | pthread_attr_init(attr) | |
| 89 | - | pthread_attr_getstacksize(attr, &size) | |
| 90 | - | // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))` | |
| 91 | - | // but this should be OK since we are taking the address of the first variable in this function. | |
| 92 | - | g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 | |
| 93 | - | pthread_attr_destroy(attr) | |
| 94 | - | free(unsafe.Pointer(attr)) | |
| 95 | - | } | |
| @@ -1,95 +0,0 @@ | |||||
| 1 | - | // Copyright 2011 The Go Authors. All rights reserved. | |||
| 2 | - | // Use of this source code is governed by a BSD-style | |||
| 3 | - | // license that can be found in the LICENSE file. | |||
| 4 | - | ||||
| 5 | - | //go:build !cgo | |||
| 6 | - | ||||
| 7 | - | package fakecgo | |||
| 8 | - | ||||
| 9 | - | import "unsafe" | |||
| 10 | - | ||||
| 11 | - | //go:nosplit | |||
| 12 | - | func _cgo_sys_thread_start(ts *ThreadStart) { | |||
| 13 | - | var attr pthread_attr_t | |||
| 14 | - | var ign, oset sigset_t | |||
| 15 | - | var p pthread_t | |||
| 16 | - | var size size_t | |||
| 17 | - | var err int | |||
| 18 | - | ||||
| 19 | - | //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug | |||
| 20 | - | sigfillset(&ign) | |||
| 21 | - | pthread_sigmask(SIG_SETMASK, &ign, &oset) | |||
| 22 | - | ||||
| 23 | - | pthread_attr_init(&attr) | |||
| 24 | - | pthread_attr_getstacksize(&attr, &size) | |||
| 25 | - | // Leave stacklo=0 and set stackhi=size; mstart will do the rest. | |||
| 26 | - | ts.g.stackhi = uintptr(size) | |||
| 27 | - | ||||
| 28 | - | err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts) | |||
| 29 | - | ||||
| 30 | - | pthread_sigmask(SIG_SETMASK, &oset, nil) | |||
| 31 | - | ||||
| 32 | - | if err != 0 { | |||
| 33 | - | print("fakecgo: pthread_create failed: ") | |||
| 34 | - | println(err) | |||
| 35 | - | abort() | |||
| 36 | - | } | |||
| 37 | - | } | |||
| 38 | - | ||||
| 39 | - | // threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function | |||
| 40 | - | // | |||
| 41 | - | //go:linkname x_threadentry_trampoline threadentry_trampoline | |||
| 42 | - | var x_threadentry_trampoline byte | |||
| 43 | - | var threadentry_trampolineABI0 = &x_threadentry_trampoline | |||
| 44 | - | ||||
| 45 | - | //go:nosplit | |||
| 46 | - | func threadentry(v unsafe.Pointer) unsafe.Pointer { | |||
| 47 | - | ts := *(*ThreadStart)(v) | |||
| 48 | - | free(v) | |||
| 49 | - | ||||
| 50 | - | setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g))) | |||
| 51 | - | ||||
| 52 | - | // faking funcs in go is a bit a... involved - but the following works :) | |||
| 53 | - | fn := uintptr(unsafe.Pointer(&ts.fn)) | |||
| 54 | - | (*(*func())(unsafe.Pointer(&fn)))() | |||
| 55 | - | ||||
| 56 | - | return nil | |||
| 57 | - | } | |||
| 58 | - | ||||
| 59 | - | // here we will store a pointer to the provided setg func | |||
| 60 | - | var setg_func uintptr | |||
| 61 | - | ||||
| 62 | - | //go:nosplit | |||
| 63 | - | func x_cgo_init(g *G, setg uintptr) { | |||
| 64 | - | var size size_t | |||
| 65 | - | var attr *pthread_attr_t | |||
| 66 | - | ||||
| 67 | - | /* The memory sanitizer distributed with versions of clang | |||
| 68 | - | before 3.8 has a bug: if you call mmap before malloc, mmap | |||
| 69 | - | may return an address that is later overwritten by the msan | |||
| 70 | - | library. Avoid this problem by forcing a call to malloc | |||
| 71 | - | here, before we ever call malloc. | |||
| 72 | - | ||||
| 73 | - | This is only required for the memory sanitizer, so it's | |||
| 74 | - | unfortunate that we always run it. It should be possible | |||
| 75 | - | to remove this when we no longer care about versions of | |||
| 76 | - | clang before 3.8. The test for this is | |||
| 77 | - | misc/cgo/testsanitizers. | |||
| 78 | - | ||||
| 79 | - | GCC works hard to eliminate a seemingly unnecessary call to | |||
| 80 | - | malloc, so we actually use the memory we allocate. */ | |||
| 81 | - | ||||
| 82 | - | setg_func = setg | |||
| 83 | - | attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr))) | |||
| 84 | - | if attr == nil { | |||
| 85 | - | println("fakecgo: malloc failed") | |||
| 86 | - | abort() | |||
| 87 | - | } | |||
| 88 | - | pthread_attr_init(attr) | |||
| 89 | - | pthread_attr_getstacksize(attr, &size) | |||
| 90 | - | // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))` | |||
| 91 | - | // but this should be OK since we are taking the address of the first variable in this function. | |||
| 92 | - | g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 | |||
| 93 | - | pthread_attr_destroy(attr) | |||
| 94 | - | free(unsafe.Pointer(attr)) | |||
| 95 | - | } | |||
R internal/fakecgo/go_linux_arm64.go → internal/fakecgo/go_linux.go +2 -0 renamed, 94% similar
| @@ -92,6 +92,8 @@ func x_cgo_init(g *G, setg uintptr) { | |||
| 92 | 92 | } | |
| 93 | 93 | pthread_attr_init(attr) | |
| 94 | 94 | pthread_attr_getstacksize(attr, &size) | |
| 95 | + | // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))` | |
| 96 | + | // but this should be OK since we are taking the address of the first variable in this function. | |
| 95 | 97 | g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 | |
| 96 | 98 | pthread_attr_destroy(attr) | |
| 97 | 99 | free(unsafe.Pointer(attr)) | |
| @@ -92,6 +92,8 @@ func x_cgo_init(g *G, setg uintptr) { | |||||
| 92 | } | 92 | } | ||
| 93 | pthread_attr_init(attr) | 93 | pthread_attr_init(attr) | ||
| 94 | pthread_attr_getstacksize(attr, &size) | 94 | pthread_attr_getstacksize(attr, &size) | ||
| 95 | + | // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))` | |||
| 96 | + | // but this should be OK since we are taking the address of the first variable in this function. | |||
| 95 | g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 | 97 | g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 | ||
| 96 | pthread_attr_destroy(attr) | 98 | pthread_attr_destroy(attr) | ||
| 97 | free(unsafe.Pointer(attr)) | 99 | free(unsafe.Pointer(attr)) | ||
D internal/fakecgo/go_linux_amd64.go +0 -95
| @@ -1,95 +0,0 @@ | |||
| 1 | - | // Copyright 2011 The Go Authors. All rights reserved. | |
| 2 | - | // Use of this source code is governed by a BSD-style | |
| 3 | - | // license that can be found in the LICENSE file. | |
| 4 | - | ||
| 5 | - | //go:build !cgo | |
| 6 | - | ||
| 7 | - | package fakecgo | |
| 8 | - | ||
| 9 | - | import "unsafe" | |
| 10 | - | ||
| 11 | - | //go:nosplit | |
| 12 | - | func _cgo_sys_thread_start(ts *ThreadStart) { | |
| 13 | - | var attr pthread_attr_t | |
| 14 | - | var ign, oset sigset_t | |
| 15 | - | var p pthread_t | |
| 16 | - | var size size_t | |
| 17 | - | var err int | |
| 18 | - | ||
| 19 | - | //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug | |
| 20 | - | sigfillset(&ign) | |
| 21 | - | pthread_sigmask(SIG_SETMASK, &ign, &oset) | |
| 22 | - | ||
| 23 | - | pthread_attr_init(&attr) | |
| 24 | - | pthread_attr_getstacksize(&attr, &size) | |
| 25 | - | // Leave stacklo=0 and set stackhi=size; mstart will do the rest. | |
| 26 | - | ts.g.stackhi = uintptr(size) | |
| 27 | - | ||
| 28 | - | err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts) | |
| 29 | - | ||
| 30 | - | pthread_sigmask(SIG_SETMASK, &oset, nil) | |
| 31 | - | ||
| 32 | - | if err != 0 { | |
| 33 | - | print("fakecgo: pthread_create failed: ") | |
| 34 | - | println(err) | |
| 35 | - | abort() | |
| 36 | - | } | |
| 37 | - | } | |
| 38 | - | ||
| 39 | - | // threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function | |
| 40 | - | // | |
| 41 | - | //go:linkname x_threadentry_trampoline threadentry_trampoline | |
| 42 | - | var x_threadentry_trampoline byte | |
| 43 | - | var threadentry_trampolineABI0 = &x_threadentry_trampoline | |
| 44 | - | ||
| 45 | - | //go:nosplit | |
| 46 | - | func threadentry(v unsafe.Pointer) unsafe.Pointer { | |
| 47 | - | ts := *(*ThreadStart)(v) | |
| 48 | - | free(v) | |
| 49 | - | ||
| 50 | - | setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g))) | |
| 51 | - | ||
| 52 | - | // faking funcs in go is a bit a... involved - but the following works :) | |
| 53 | - | fn := uintptr(unsafe.Pointer(&ts.fn)) | |
| 54 | - | (*(*func())(unsafe.Pointer(&fn)))() | |
| 55 | - | ||
| 56 | - | return nil | |
| 57 | - | } | |
| 58 | - | ||
| 59 | - | // here we will store a pointer to the provided setg func | |
| 60 | - | var setg_func uintptr | |
| 61 | - | ||
| 62 | - | //go:nosplit | |
| 63 | - | func x_cgo_init(g *G, setg uintptr) { | |
| 64 | - | var size size_t | |
| 65 | - | var attr *pthread_attr_t | |
| 66 | - | ||
| 67 | - | /* The memory sanitizer distributed with versions of clang | |
| 68 | - | before 3.8 has a bug: if you call mmap before malloc, mmap | |
| 69 | - | may return an address that is later overwritten by the msan | |
| 70 | - | library. Avoid this problem by forcing a call to malloc | |
| 71 | - | here, before we ever call malloc. | |
| 72 | - | ||
| 73 | - | This is only required for the memory sanitizer, so it's | |
| 74 | - | unfortunate that we always run it. It should be possible | |
| 75 | - | to remove this when we no longer care about versions of | |
| 76 | - | clang before 3.8. The test for this is | |
| 77 | - | misc/cgo/testsanitizers. | |
| 78 | - | ||
| 79 | - | GCC works hard to eliminate a seemingly unnecessary call to | |
| 80 | - | malloc, so we actually use the memory we allocate. */ | |
| 81 | - | ||
| 82 | - | setg_func = setg | |
| 83 | - | attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr))) | |
| 84 | - | if attr == nil { | |
| 85 | - | println("fakecgo: malloc failed") | |
| 86 | - | abort() | |
| 87 | - | } | |
| 88 | - | pthread_attr_init(attr) | |
| 89 | - | pthread_attr_getstacksize(attr, &size) | |
| 90 | - | // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))` | |
| 91 | - | // but this should be OK since we are taking the address of the first variable in this function. | |
| 92 | - | g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 | |
| 93 | - | pthread_attr_destroy(attr) | |
| 94 | - | free(unsafe.Pointer(attr)) | |
| 95 | - | } | |
| @@ -1,95 +0,0 @@ | |||||
| 1 | - | // Copyright 2011 The Go Authors. All rights reserved. | |||
| 2 | - | // Use of this source code is governed by a BSD-style | |||
| 3 | - | // license that can be found in the LICENSE file. | |||
| 4 | - | ||||
| 5 | - | //go:build !cgo | |||
| 6 | - | ||||
| 7 | - | package fakecgo | |||
| 8 | - | ||||
| 9 | - | import "unsafe" | |||
| 10 | - | ||||
| 11 | - | //go:nosplit | |||
| 12 | - | func _cgo_sys_thread_start(ts *ThreadStart) { | |||
| 13 | - | var attr pthread_attr_t | |||
| 14 | - | var ign, oset sigset_t | |||
| 15 | - | var p pthread_t | |||
| 16 | - | var size size_t | |||
| 17 | - | var err int | |||
| 18 | - | ||||
| 19 | - | //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug | |||
| 20 | - | sigfillset(&ign) | |||
| 21 | - | pthread_sigmask(SIG_SETMASK, &ign, &oset) | |||
| 22 | - | ||||
| 23 | - | pthread_attr_init(&attr) | |||
| 24 | - | pthread_attr_getstacksize(&attr, &size) | |||
| 25 | - | // Leave stacklo=0 and set stackhi=size; mstart will do the rest. | |||
| 26 | - | ts.g.stackhi = uintptr(size) | |||
| 27 | - | ||||
| 28 | - | err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts) | |||
| 29 | - | ||||
| 30 | - | pthread_sigmask(SIG_SETMASK, &oset, nil) | |||
| 31 | - | ||||
| 32 | - | if err != 0 { | |||
| 33 | - | print("fakecgo: pthread_create failed: ") | |||
| 34 | - | println(err) | |||
| 35 | - | abort() | |||
| 36 | - | } | |||
| 37 | - | } | |||
| 38 | - | ||||
| 39 | - | // threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function | |||
| 40 | - | // | |||
| 41 | - | //go:linkname x_threadentry_trampoline threadentry_trampoline | |||
| 42 | - | var x_threadentry_trampoline byte | |||
| 43 | - | var threadentry_trampolineABI0 = &x_threadentry_trampoline | |||
| 44 | - | ||||
| 45 | - | //go:nosplit | |||
| 46 | - | func threadentry(v unsafe.Pointer) unsafe.Pointer { | |||
| 47 | - | ts := *(*ThreadStart)(v) | |||
| 48 | - | free(v) | |||
| 49 | - | ||||
| 50 | - | setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g))) | |||
| 51 | - | ||||
| 52 | - | // faking funcs in go is a bit a... involved - but the following works :) | |||
| 53 | - | fn := uintptr(unsafe.Pointer(&ts.fn)) | |||
| 54 | - | (*(*func())(unsafe.Pointer(&fn)))() | |||
| 55 | - | ||||
| 56 | - | return nil | |||
| 57 | - | } | |||
| 58 | - | ||||
| 59 | - | // here we will store a pointer to the provided setg func | |||
| 60 | - | var setg_func uintptr | |||
| 61 | - | ||||
| 62 | - | //go:nosplit | |||
| 63 | - | func x_cgo_init(g *G, setg uintptr) { | |||
| 64 | - | var size size_t | |||
| 65 | - | var attr *pthread_attr_t | |||
| 66 | - | ||||
| 67 | - | /* The memory sanitizer distributed with versions of clang | |||
| 68 | - | before 3.8 has a bug: if you call mmap before malloc, mmap | |||
| 69 | - | may return an address that is later overwritten by the msan | |||
| 70 | - | library. Avoid this problem by forcing a call to malloc | |||
| 71 | - | here, before we ever call malloc. | |||
| 72 | - | ||||
| 73 | - | This is only required for the memory sanitizer, so it's | |||
| 74 | - | unfortunate that we always run it. It should be possible | |||
| 75 | - | to remove this when we no longer care about versions of | |||
| 76 | - | clang before 3.8. The test for this is | |||
| 77 | - | misc/cgo/testsanitizers. | |||
| 78 | - | ||||
| 79 | - | GCC works hard to eliminate a seemingly unnecessary call to | |||
| 80 | - | malloc, so we actually use the memory we allocate. */ | |||
| 81 | - | ||||
| 82 | - | setg_func = setg | |||
| 83 | - | attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr))) | |||
| 84 | - | if attr == nil { | |||
| 85 | - | println("fakecgo: malloc failed") | |||
| 86 | - | abort() | |||
| 87 | - | } | |||
| 88 | - | pthread_attr_init(attr) | |||
| 89 | - | pthread_attr_getstacksize(attr, &size) | |||
| 90 | - | // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))` | |||
| 91 | - | // but this should be OK since we are taking the address of the first variable in this function. | |||
| 92 | - | g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 | |||
| 93 | - | pthread_attr_destroy(attr) | |||
| 94 | - | free(unsafe.Pointer(attr)) | |||
| 95 | - | } | |||
D internal/fakecgo/go_linux_loong64.go +0 -92
| @@ -1,92 +0,0 @@ | |||
| 1 | - | // Copyright 2011 The Go Authors. All rights reserved. | |
| 2 | - | // Use of this source code is governed by a BSD-style | |
| 3 | - | // license that can be found in the LICENSE file. | |
| 4 | - | ||
| 5 | - | //go:build !cgo | |
| 6 | - | ||
| 7 | - | package fakecgo | |
| 8 | - | ||
| 9 | - | import "unsafe" | |
| 10 | - | ||
| 11 | - | //go:nosplit | |
| 12 | - | func _cgo_sys_thread_start(ts *ThreadStart) { | |
| 13 | - | var attr pthread_attr_t | |
| 14 | - | var ign, oset sigset_t | |
| 15 | - | var p pthread_t | |
| 16 | - | var size size_t | |
| 17 | - | var err int | |
| 18 | - | ||
| 19 | - | sigfillset(&ign) | |
| 20 | - | pthread_sigmask(SIG_SETMASK, &ign, &oset) | |
| 21 | - | ||
| 22 | - | pthread_attr_init(&attr) | |
| 23 | - | pthread_attr_getstacksize(&attr, &size) | |
| 24 | - | // Leave stacklo=0 and set stackhi=size; mstart will do the rest. | |
| 25 | - | ts.g.stackhi = uintptr(size) | |
| 26 | - | ||
| 27 | - | err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts) | |
| 28 | - | ||
| 29 | - | pthread_sigmask(SIG_SETMASK, &oset, nil) | |
| 30 | - | ||
| 31 | - | if err != 0 { | |
| 32 | - | print("fakecgo: pthread_create failed: ") | |
| 33 | - | println(err) | |
| 34 | - | abort() | |
| 35 | - | } | |
| 36 | - | } | |
| 37 | - | ||
| 38 | - | // threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function | |
| 39 | - | // | |
| 40 | - | //go:linkname x_threadentry_trampoline threadentry_trampoline | |
| 41 | - | var x_threadentry_trampoline byte | |
| 42 | - | var threadentry_trampolineABI0 = &x_threadentry_trampoline | |
| 43 | - | ||
| 44 | - | //go:nosplit | |
| 45 | - | func threadentry(v unsafe.Pointer) unsafe.Pointer { | |
| 46 | - | ts := *(*ThreadStart)(v) | |
| 47 | - | free(v) | |
| 48 | - | ||
| 49 | - | setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g))) | |
| 50 | - | ||
| 51 | - | // faking funcs in go is a bit a... involved - but the following works :) | |
| 52 | - | fn := uintptr(unsafe.Pointer(&ts.fn)) | |
| 53 | - | (*(*func())(unsafe.Pointer(&fn)))() | |
| 54 | - | ||
| 55 | - | return nil | |
| 56 | - | } | |
| 57 | - | ||
| 58 | - | // here we will store a pointer to the provided setg func | |
| 59 | - | var setg_func uintptr | |
| 60 | - | ||
| 61 | - | //go:nosplit | |
| 62 | - | func x_cgo_init(g *G, setg uintptr) { | |
| 63 | - | var size size_t | |
| 64 | - | var attr *pthread_attr_t | |
| 65 | - | ||
| 66 | - | /* The memory sanitizer distributed with versions of clang | |
| 67 | - | before 3.8 has a bug: if you call mmap before malloc, mmap | |
| 68 | - | may return an address that is later overwritten by the msan | |
| 69 | - | library. Avoid this problem by forcing a call to malloc | |
| 70 | - | here, before we ever call malloc. | |
| 71 | - | ||
| 72 | - | This is only required for the memory sanitizer, so it's | |
| 73 | - | unfortunate that we always run it. It should be possible | |
| 74 | - | to remove this when we no longer care about versions of | |
| 75 | - | clang before 3.8. The test for this is | |
| 76 | - | misc/cgo/testsanitizers. | |
| 77 | - | ||
| 78 | - | GCC works hard to eliminate a seemingly unnecessary call to | |
| 79 | - | malloc, so we actually use the memory we allocate. */ | |
| 80 | - | ||
| 81 | - | setg_func = setg | |
| 82 | - | attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr))) | |
| 83 | - | if attr == nil { | |
| 84 | - | println("fakecgo: malloc failed") | |
| 85 | - | abort() | |
| 86 | - | } | |
| 87 | - | pthread_attr_init(attr) | |
| 88 | - | pthread_attr_getstacksize(attr, &size) | |
| 89 | - | g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 | |
| 90 | - | pthread_attr_destroy(attr) | |
| 91 | - | free(unsafe.Pointer(attr)) | |
| 92 | - | } | |
| @@ -1,92 +0,0 @@ | |||||
| 1 | - | // Copyright 2011 The Go Authors. All rights reserved. | |||
| 2 | - | // Use of this source code is governed by a BSD-style | |||
| 3 | - | // license that can be found in the LICENSE file. | |||
| 4 | - | ||||
| 5 | - | //go:build !cgo | |||
| 6 | - | ||||
| 7 | - | package fakecgo | |||
| 8 | - | ||||
| 9 | - | import "unsafe" | |||
| 10 | - | ||||
| 11 | - | //go:nosplit | |||
| 12 | - | func _cgo_sys_thread_start(ts *ThreadStart) { | |||
| 13 | - | var attr pthread_attr_t | |||
| 14 | - | var ign, oset sigset_t | |||
| 15 | - | var p pthread_t | |||
| 16 | - | var size size_t | |||
| 17 | - | var err int | |||
| 18 | - | ||||
| 19 | - | sigfillset(&ign) | |||
| 20 | - | pthread_sigmask(SIG_SETMASK, &ign, &oset) | |||
| 21 | - | ||||
| 22 | - | pthread_attr_init(&attr) | |||
| 23 | - | pthread_attr_getstacksize(&attr, &size) | |||
| 24 | - | // Leave stacklo=0 and set stackhi=size; mstart will do the rest. | |||
| 25 | - | ts.g.stackhi = uintptr(size) | |||
| 26 | - | ||||
| 27 | - | err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts) | |||
| 28 | - | ||||
| 29 | - | pthread_sigmask(SIG_SETMASK, &oset, nil) | |||
| 30 | - | ||||
| 31 | - | if err != 0 { | |||
| 32 | - | print("fakecgo: pthread_create failed: ") | |||
| 33 | - | println(err) | |||
| 34 | - | abort() | |||
| 35 | - | } | |||
| 36 | - | } | |||
| 37 | - | ||||
| 38 | - | // threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function | |||
| 39 | - | // | |||
| 40 | - | //go:linkname x_threadentry_trampoline threadentry_trampoline | |||
| 41 | - | var x_threadentry_trampoline byte | |||
| 42 | - | var threadentry_trampolineABI0 = &x_threadentry_trampoline | |||
| 43 | - | ||||
| 44 | - | //go:nosplit | |||
| 45 | - | func threadentry(v unsafe.Pointer) unsafe.Pointer { | |||
| 46 | - | ts := *(*ThreadStart)(v) | |||
| 47 | - | free(v) | |||
| 48 | - | ||||
| 49 | - | setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g))) | |||
| 50 | - | ||||
| 51 | - | // faking funcs in go is a bit a... involved - but the following works :) | |||
| 52 | - | fn := uintptr(unsafe.Pointer(&ts.fn)) | |||
| 53 | - | (*(*func())(unsafe.Pointer(&fn)))() | |||
| 54 | - | ||||
| 55 | - | return nil | |||
| 56 | - | } | |||
| 57 | - | ||||
| 58 | - | // here we will store a pointer to the provided setg func | |||
| 59 | - | var setg_func uintptr | |||
| 60 | - | ||||
| 61 | - | //go:nosplit | |||
| 62 | - | func x_cgo_init(g *G, setg uintptr) { | |||
| 63 | - | var size size_t | |||
| 64 | - | var attr *pthread_attr_t | |||
| 65 | - | ||||
| 66 | - | /* The memory sanitizer distributed with versions of clang | |||
| 67 | - | before 3.8 has a bug: if you call mmap before malloc, mmap | |||
| 68 | - | may return an address that is later overwritten by the msan | |||
| 69 | - | library. Avoid this problem by forcing a call to malloc | |||
| 70 | - | here, before we ever call malloc. | |||
| 71 | - | ||||
| 72 | - | This is only required for the memory sanitizer, so it's | |||
| 73 | - | unfortunate that we always run it. It should be possible | |||
| 74 | - | to remove this when we no longer care about versions of | |||
| 75 | - | clang before 3.8. The test for this is | |||
| 76 | - | misc/cgo/testsanitizers. | |||
| 77 | - | ||||
| 78 | - | GCC works hard to eliminate a seemingly unnecessary call to | |||
| 79 | - | malloc, so we actually use the memory we allocate. */ | |||
| 80 | - | ||||
| 81 | - | setg_func = setg | |||
| 82 | - | attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr))) | |||
| 83 | - | if attr == nil { | |||
| 84 | - | println("fakecgo: malloc failed") | |||
| 85 | - | abort() | |||
| 86 | - | } | |||
| 87 | - | pthread_attr_init(attr) | |||
| 88 | - | pthread_attr_getstacksize(attr, &size) | |||
| 89 | - | g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096 | |||
| 90 | - | pthread_attr_destroy(attr) | |||
| 91 | - | free(unsafe.Pointer(attr)) | |||
| 92 | - | } | |||