detached 68d977d

internal/fakecgo: improve generation of OS-specific symbols (#384)

The fakecgo package autogenerates some symbols that are not used on all supported OSes.
For example, pthread_self is only used on Darwin.

Those symbols shouldn't "leak" into OSes not using them, but they currently do. The Go linker
is smart enough to avoid adding them in the final binary, although this is a bit brittle. Regardless,
it is confusing to have a symbol defined on a platform that doesn't support it, like
purego_pthread_get_stacksize_np which is only supported on Darwin.

Note that I plan to grow the list of OS-specific symbols as part of #343, so this problem is only
going to get worse.
commit
68d977deec745157f1ff09e576819db62cdf8dcf
author
Quim Muntal · · 2026-01-13 06:10 UTC
committer
GitHub · · 2026-01-13 06:10 UTC
parent
200df60
signature
GPG UnverifiedB5690EEEBB952194 The key is unknown
11 files · +326 -186
M internal/fakecgo/gen.go +151 -100
@@ -11,25 +11,31 @@ import (
1111 "go/format"
1212 "log"
1313 "os"
14+ "path/filepath"
15+ "sort"
1416 "strings"
1517 "text/template"
1618 )
1719
18-const templateSymbols = `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
20+var templateSymbols = template.Must(template.New("symbols").Funcs(funcs).Parse(
21+ `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
1922
2023 // SPDX-License-Identifier: Apache-2.0
2124 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
2225
23-//go:build !cgo && (darwin || freebsd || linux || netbsd)
26+//go:build {{.Tag}}
2427
2528 package fakecgo
2629
27-import (
28- "syscall"
29- "unsafe"
30-)
30+{{ imports .Symbols }}
31+
32+{{- range $di := .DynamicImports }}
33+{{- range $sym := $di.Symbols }}
34+//go:cgo_import_dynamic purego_{{ $sym }} {{ $sym }} "{{ $di.Name }}"
35+{{- end }}
36+{{- end }}
3137
32-{{ range . -}}
38+{{ range .Symbols -}}
3339 //go:nosplit
3440 //go:norace
3541 func {{.Name}}(
@@ -69,44 +75,29 @@ call5({{.Name}}ABI0,
6975 }
7076
7177 {{end}}
72-{{- range . }}
78+{{- range .Symbols }}
7379 //go:linkname _{{.Name}} _{{.Name}}
7480 var _{{.Name}} uint8
7581 var {{.Name}}ABI0 = uintptr(unsafe.Pointer(&_{{.Name}}))
7682 {{ end }}
77-`
83+`))
7884
79-const templateTrampolinesStubs = `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
85+var templateTrampolinesStubs = template.Must(template.New("trampolines").Parse(
86+ `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
8087
8188 // SPDX-License-Identifier: Apache-2.0
8289 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
8390
84-//go:build !cgo && (darwin || freebsd || linux || netbsd)
91+//go:build {{.Tag}}
8592
8693 #include "textflag.h"
8794
88-// these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm64
89-{{ range . }}
95+// these stubs are here because it is not possible to go:linkname directly the C functions
96+{{ range .Symbols }}
9097 TEXT _{{.Name}}(SB), NOSPLIT|NOFRAME, $0-0
9198 JMP purego_{{.Name}}(SB)
9299 {{ end -}}
93-`
94-
95-const templateSymbolsGoos = `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
96-
97-// SPDX-License-Identifier: Apache-2.0
98-// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
99-
100-//go:build !cgo
101-
102-package fakecgo
103-
104-{{- range $location := . }}
105-{{- range .Symbols }}
106-//go:cgo_import_dynamic purego_{{ .Name }} {{ .Name }} "{{ $location.SharedObject }}"
107-{{- end }}
108-{{- end }}
109-`
100+`))
110101
111102 type Arg struct {
112103 Name string
@@ -117,90 +108,149 @@ type Symbol struct {
117108 Name string
118109 Args [5]Arg
119110 Return string
120-}
121-
122-type LocatedSymbols struct {
123- SharedObject string
124- Symbols []Symbol
111+ GOOSes []string // empty means all GOOSes
125112 }
126113
127114 var (
128115 libcSymbols = []Symbol{
129- {"malloc", [5]Arg{{"size", "uintptr"}}, "unsafe.Pointer"},
130- {"free", [5]Arg{{"ptr", "unsafe.Pointer"}}, ""},
131- {"setenv", [5]Arg{{"name", "*byte"}, {"value", "*byte"}, {"overwrite", "int32"}}, "int32"},
132- {"unsetenv", [5]Arg{{"name", "*byte"}}, "int32"},
133- {"sigfillset", [5]Arg{{"set", "*sigset_t"}}, "int32"},
134- {"nanosleep", [5]Arg{{"ts", "*syscall.Timespec"}, {"rem", "*syscall.Timespec"}}, "int32"},
135- {"abort", [5]Arg{}, ""},
136- {"sigaltstack", [5]Arg{{"ss", "*stack_t"}, {"old_ss", "*stack_t"}}, "int32"},
116+ {"malloc", [5]Arg{{"size", "uintptr"}}, "unsafe.Pointer", nil},
117+ {"free", [5]Arg{{"ptr", "unsafe.Pointer"}}, "", nil},
118+ {"setenv", [5]Arg{{"name", "*byte"}, {"value", "*byte"}, {"overwrite", "int32"}}, "int32", nil},
119+ {"unsetenv", [5]Arg{{"name", "*byte"}}, "int32", nil},
120+ {"sigfillset", [5]Arg{{"set", "*sigset_t"}}, "int32", nil},
121+ {"nanosleep", [5]Arg{{"ts", "*syscall.Timespec"}, {"rem", "*syscall.Timespec"}}, "int32", nil},
122+ {"abort", [5]Arg{}, "", nil},
123+ {"sigaltstack", [5]Arg{{"ss", "*stack_t"}, {"old_ss", "*stack_t"}}, "int32", nil},
137124 }
138125 pthreadSymbols = []Symbol{
139- {"pthread_attr_init", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32"},
140- {"pthread_create", [5]Arg{{"thread", "*pthread_t"}, {"attr", "*pthread_attr_t"}, {"start", "unsafe.Pointer"}, {"arg", "unsafe.Pointer"}}, "int32"},
141- {"pthread_detach", [5]Arg{{"thread", "pthread_t"}}, "int32"},
142- {"pthread_sigmask", [5]Arg{{"how", "sighow"}, {"ign", "*sigset_t"}, {"oset", "*sigset_t"}}, "int32"},
143- {"pthread_self", [5]Arg{}, "pthread_t"},
144- {"pthread_get_stacksize_np", [5]Arg{{"thread", "pthread_t"}}, "size_t"},
145- {"pthread_attr_getstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"stacksize", "*size_t"}}, "int32"},
146- {"pthread_attr_setstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"size", "size_t"}}, "int32"},
147- {"pthread_attr_destroy", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32"},
148- {"pthread_mutex_lock", [5]Arg{{"mutex", "*pthread_mutex_t"}}, "int32"},
149- {"pthread_mutex_unlock", [5]Arg{{"mutex", "*pthread_mutex_t"}}, "int32"},
150- {"pthread_cond_broadcast", [5]Arg{{"cond", "*pthread_cond_t"}}, "int32"},
151- {"pthread_setspecific", [5]Arg{{"key", "pthread_key_t"}, {"value", "unsafe.Pointer"}}, "int32"},
126+ {"pthread_attr_init", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32", nil},
127+ {"pthread_create", [5]Arg{{"thread", "*pthread_t"}, {"attr", "*pthread_attr_t"}, {"start", "unsafe.Pointer"}, {"arg", "unsafe.Pointer"}}, "int32", nil},
128+ {"pthread_detach", [5]Arg{{"thread", "pthread_t"}}, "int32", nil},
129+ {"pthread_sigmask", [5]Arg{{"how", "sighow"}, {"ign", "*sigset_t"}, {"oset", "*sigset_t"}}, "int32", nil},
130+ {"pthread_self", [5]Arg{}, "pthread_t", []string{"darwin"}},
131+ {"pthread_get_stacksize_np", [5]Arg{{"thread", "pthread_t"}}, "size_t", []string{"darwin"}},
132+ {"pthread_attr_getstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"stacksize", "*size_t"}}, "int32", []string{"linux", "freebsd", "netbsd"}},
133+ {"pthread_attr_setstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"size", "size_t"}}, "int32", []string{"darwin"}},
134+ {"pthread_attr_destroy", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32", []string{"linux", "freebsd", "netbsd"}},
135+ {"pthread_mutex_lock", [5]Arg{{"mutex", "*pthread_mutex_t"}}, "int32", nil},
136+ {"pthread_mutex_unlock", [5]Arg{{"mutex", "*pthread_mutex_t"}}, "int32", nil},
137+ {"pthread_cond_broadcast", [5]Arg{{"cond", "*pthread_cond_t"}}, "int32", nil},
138+ {"pthread_setspecific", [5]Arg{{"key", "pthread_key_t"}, {"value", "unsafe.Pointer"}}, "int32", nil},
152139 }
153140 )
154141
155142 var funcs = map[string]any{
156143 "hasPrefix": strings.HasPrefix,
144+ "imports": imports,
157145 }
158146
159-func run() error {
160- t, err := template.New("zsymbol.go").Funcs(funcs).Parse(templateSymbols)
161- if err != nil {
162- return err
163- }
164- f, err := os.Create("zsymbols.go")
165- defer f.Close()
166- if err != nil {
167- return err
147+var GOOSes = []string{"darwin", "freebsd", "linux", "netbsd"}
148+
149+func imports(symbols []Symbol) string {
150+ if len(symbols) == 0 {
151+ return ""
168152 }
169- allSymbols := append(append([]Symbol{}, libcSymbols...), pthreadSymbols...)
170- buf := new(bytes.Buffer)
171- if err := t.Execute(buf, allSymbols); err != nil {
172- return err
153+ imports := make(map[string]struct{})
154+ imports["unsafe"] = struct{}{}
155+ for _, s := range symbols {
156+ for _, arg := range s.Args {
157+ if pkg, _, found := strings.Cut(arg.Type, "."); found {
158+ pkg = strings.TrimPrefix(pkg, "*")
159+ imports[pkg] = struct{}{}
160+ }
161+ }
173162 }
174- source, err := format.Source(buf.Bytes())
175- if err != nil {
176- return err
163+ if len(imports) == 1 {
164+ return `import "unsafe"`
177165 }
178- if _, err = f.Write(source); err != nil {
179- return err
166+ result := make([]string, 0, len(imports))
167+ for imp := range imports {
168+ result = append(result, imp)
180169 }
181- t, err = template.New("ztrampolines_stubs.s").Funcs(funcs).Parse(templateTrampolinesStubs)
182- if err != nil {
183- return err
170+ sort.Strings(result)
171+ var sb strings.Builder
172+ sb.WriteString("import (")
173+ for _, imp := range result {
174+ sb.WriteString("\n\t\"")
175+ sb.WriteString(imp)
176+ sb.WriteString("\"")
184177 }
185- f, err = os.Create("ztrampolines_stubs.s")
186- defer f.Close()
187- if err != nil {
188- return err
178+ sb.WriteString("\n)")
179+ return sb.String()
180+}
181+
182+// filterSymbols filters the symbols by GOOS.
183+// If goos is empty, it returns symbols that are not specific to any GOOS.
184+func filterSymbols(symbols []Symbol, goos string) []Symbol {
185+ filtered := make([]Symbol, 0, len(symbols))
186+ for _, s := range symbols {
187+ if (s.GOOSes == nil && goos == "") || contains(s.GOOSes, goos) {
188+ filtered = append(filtered, s)
189+ }
189190 }
190- if err := t.Execute(f, allSymbols); err != nil {
191- return err
191+ return filtered
192+}
193+
194+func contains(slice []string, item string) bool {
195+ for _, s := range slice {
196+ if s == item {
197+ return true
198+ }
192199 }
193- t, err = template.New("zsymbols_goos.go").Parse(templateSymbolsGoos)
194- if err != nil {
200+ return false
201+}
202+
203+func execute(t *template.Template, path string, data any) error {
204+ var buf bytes.Buffer
205+ if err := t.Execute(&buf, data); err != nil {
195206 return err
196207 }
197- for _, goos := range []string{"darwin", "freebsd", "linux", "netbsd"} {
198- f, err = os.Create(fmt.Sprintf("zsymbols_%s.go", goos))
199- defer f.Close()
208+ if filepath.Ext(path) == ".go" {
209+ source, err := format.Source(buf.Bytes())
200210 if err != nil {
201211 return err
202212 }
203- b := &bytes.Buffer{}
213+ buf.Reset()
214+ buf.Write(source)
215+ }
216+ return os.WriteFile(path, buf.Bytes(), 0644)
217+}
218+
219+func symbolsNames(symbols []Symbol) []string {
220+ names := make([]string, len(symbols))
221+ for i, s := range symbols {
222+ names[i] = s.Name
223+ }
224+ return names
225+}
226+
227+type dynamicImport struct {
228+ Name string
229+ Symbols []string
230+}
231+
232+type fileContent struct {
233+ Tag string
234+ Symbols []Symbol
235+ DynamicImports []dynamicImport
236+}
237+
238+func run() error {
239+ allSymbols := append(append([]Symbol{}, libcSymbols...), pthreadSymbols...)
240+ goosAgnosticContent := fileContent{
241+ Symbols: filterSymbols(allSymbols, ""),
242+ Tag: "!cgo && (" + strings.Join(GOOSes, " || ") + ")",
243+ }
244+ if err := execute(templateSymbols, "zsymbols.go", goosAgnosticContent); err != nil {
245+ return err
246+ }
247+ if err := execute(templateTrampolinesStubs, "ztrampolines_stubs.s", goosAgnosticContent); err != nil {
248+ return err
249+ }
250+ goosAgnosticLibCSymbols := filterSymbols(libcSymbols, "")
251+ goosAgnosticPthreadSymbols := filterSymbols(pthreadSymbols, "")
252+ for _, goos := range GOOSes {
253+ goosSymbols := filterSymbols(allSymbols, goos)
204254 var libcSO, pthreadSO string
205255 switch goos {
206256 case "darwin":
@@ -218,20 +268,21 @@ func run() error {
218268 default:
219269 return fmt.Errorf("unsupported OS: %s", goos)
220270 }
221- located := []LocatedSymbols{
222- {SharedObject: libcSO, Symbols: libcSymbols},
223- {SharedObject: pthreadSO, Symbols: pthreadSymbols},
271+ located := fileContent{
272+ DynamicImports: []dynamicImport{
273+ {libcSO, symbolsNames(append(goosAgnosticLibCSymbols, filterSymbols(libcSymbols, goos)...))},
274+ {pthreadSO, symbolsNames(append(goosAgnosticPthreadSymbols, filterSymbols(pthreadSymbols, goos)...))},
275+ },
276+ Symbols: goosSymbols,
277+ Tag: "!cgo",
224278 }
225- if err = t.Execute(b, located); err != nil {
279+ if err := execute(templateSymbols, fmt.Sprintf("zsymbols_%s.go", goos), located); err != nil {
226280 return err
227281 }
228- var src []byte
229- src, err = format.Source(b.Bytes())
230- if err != nil {
231- return err
232- }
233- if _, err = f.Write(src); err != nil {
234- return err
282+ if len(goosSymbols) != 0 {
283+ if err := execute(templateTrampolinesStubs, fmt.Sprintf("ztrampolines_%s.s", goos), located); err != nil {
284+ return err
285+ }
235286 }
236287 }
237288 return nil
@@ -11,25 +11,31 @@ import (
11 "go/format"11 "go/format"
12 "log"12 "log"
13 "os"13 "os"
14+ "path/filepath"
15+ "sort"
14 "strings"16 "strings"
15 "text/template"17 "text/template"
16 )18 )
17 19
18-const templateSymbols = `// Code generated by 'go generate' with gen.go. DO NOT EDIT.20+var templateSymbols = template.Must(template.New("symbols").Funcs(funcs).Parse(
21+ `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
19 22
20 // SPDX-License-Identifier: Apache-2.023 // SPDX-License-Identifier: Apache-2.0
21 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors24 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
22 25
23-//go:build !cgo && (darwin || freebsd || linux || netbsd)26+//go:build {{.Tag}}
24 27
25 package fakecgo28 package fakecgo
26 29
27-import (30+{{ imports .Symbols }}
28- "syscall"31+
29- "unsafe"32+{{- range $di := .DynamicImports }}
30-)33+{{- range $sym := $di.Symbols }}
34+//go:cgo_import_dynamic purego_{{ $sym }} {{ $sym }} "{{ $di.Name }}"
35+{{- end }}
36+{{- end }}
31 37
32-{{ range . -}}38+{{ range .Symbols -}}
33 //go:nosplit39 //go:nosplit
34 //go:norace40 //go:norace
35 func {{.Name}}(41 func {{.Name}}(
@@ -69,44 +75,29 @@ call5({{.Name}}ABI0,
69 }75 }
70 76
71 {{end}}77 {{end}}
72-{{- range . }}78+{{- range .Symbols }}
73 //go:linkname _{{.Name}} _{{.Name}}79 //go:linkname _{{.Name}} _{{.Name}}
74 var _{{.Name}} uint880 var _{{.Name}} uint8
75 var {{.Name}}ABI0 = uintptr(unsafe.Pointer(&_{{.Name}}))81 var {{.Name}}ABI0 = uintptr(unsafe.Pointer(&_{{.Name}}))
76 {{ end }}82 {{ end }}
77-`83+`))
78 84
79-const templateTrampolinesStubs = `// Code generated by 'go generate' with gen.go. DO NOT EDIT.85+var templateTrampolinesStubs = template.Must(template.New("trampolines").Parse(
86+ `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
80 87
81 // SPDX-License-Identifier: Apache-2.088 // SPDX-License-Identifier: Apache-2.0
82 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors89 // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
83 90
84-//go:build !cgo && (darwin || freebsd || linux || netbsd)91+//go:build {{.Tag}}
85 92
86 #include "textflag.h"93 #include "textflag.h"
87 94
88-// these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm6495+// these stubs are here because it is not possible to go:linkname directly the C functions
89-{{ range . }}96+{{ range .Symbols }}
90 TEXT _{{.Name}}(SB), NOSPLIT|NOFRAME, $0-097 TEXT _{{.Name}}(SB), NOSPLIT|NOFRAME, $0-0
91 JMP purego_{{.Name}}(SB)98 JMP purego_{{.Name}}(SB)
92 {{ end -}}99 {{ end -}}
93-`100+`))
94-
95-const templateSymbolsGoos = `// Code generated by 'go generate' with gen.go. DO NOT EDIT.
96-
97-// SPDX-License-Identifier: Apache-2.0
98-// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
99-
100-//go:build !cgo
101-
102-package fakecgo
103-
104-{{- range $location := . }}
105-{{- range .Symbols }}
106-//go:cgo_import_dynamic purego_{{ .Name }} {{ .Name }} "{{ $location.SharedObject }}"
107-{{- end }}
108-{{- end }}
109-`
110 101
111 type Arg struct {102 type Arg struct {
112 Name string103 Name string
@@ -117,90 +108,149 @@ type Symbol struct {
117 Name string108 Name string
118 Args [5]Arg109 Args [5]Arg
119 Return string110 Return string
120-}111+ GOOSes []string // empty means all GOOSes
121-
122-type LocatedSymbols struct {
123- SharedObject string
124- Symbols []Symbol
125 }112 }
126 113
127 var (114 var (
128 libcSymbols = []Symbol{115 libcSymbols = []Symbol{
129- {"malloc", [5]Arg{{"size", "uintptr"}}, "unsafe.Pointer"},116+ {"malloc", [5]Arg{{"size", "uintptr"}}, "unsafe.Pointer", nil},
130- {"free", [5]Arg{{"ptr", "unsafe.Pointer"}}, ""},117+ {"free", [5]Arg{{"ptr", "unsafe.Pointer"}}, "", nil},
131- {"setenv", [5]Arg{{"name", "*byte"}, {"value", "*byte"}, {"overwrite", "int32"}}, "int32"},118+ {"setenv", [5]Arg{{"name", "*byte"}, {"value", "*byte"}, {"overwrite", "int32"}}, "int32", nil},
132- {"unsetenv", [5]Arg{{"name", "*byte"}}, "int32"},119+ {"unsetenv", [5]Arg{{"name", "*byte"}}, "int32", nil},
133- {"sigfillset", [5]Arg{{"set", "*sigset_t"}}, "int32"},120+ {"sigfillset", [5]Arg{{"set", "*sigset_t"}}, "int32", nil},
134- {"nanosleep", [5]Arg{{"ts", "*syscall.Timespec"}, {"rem", "*syscall.Timespec"}}, "int32"},121+ {"nanosleep", [5]Arg{{"ts", "*syscall.Timespec"}, {"rem", "*syscall.Timespec"}}, "int32", nil},
135- {"abort", [5]Arg{}, ""},122+ {"abort", [5]Arg{}, "", nil},
136- {"sigaltstack", [5]Arg{{"ss", "*stack_t"}, {"old_ss", "*stack_t"}}, "int32"},123+ {"sigaltstack", [5]Arg{{"ss", "*stack_t"}, {"old_ss", "*stack_t"}}, "int32", nil},
137 }124 }
138 pthreadSymbols = []Symbol{125 pthreadSymbols = []Symbol{
139- {"pthread_attr_init", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32"},126+ {"pthread_attr_init", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32", nil},
140- {"pthread_create", [5]Arg{{"thread", "*pthread_t"}, {"attr", "*pthread_attr_t"}, {"start", "unsafe.Pointer"}, {"arg", "unsafe.Pointer"}}, "int32"},127+ {"pthread_create", [5]Arg{{"thread", "*pthread_t"}, {"attr", "*pthread_attr_t"}, {"start", "unsafe.Pointer"}, {"arg", "unsafe.Pointer"}}, "int32", nil},
141- {"pthread_detach", [5]Arg{{"thread", "pthread_t"}}, "int32"},128+ {"pthread_detach", [5]Arg{{"thread", "pthread_t"}}, "int32", nil},
142- {"pthread_sigmask", [5]Arg{{"how", "sighow"}, {"ign", "*sigset_t"}, {"oset", "*sigset_t"}}, "int32"},129+ {"pthread_sigmask", [5]Arg{{"how", "sighow"}, {"ign", "*sigset_t"}, {"oset", "*sigset_t"}}, "int32", nil},
143- {"pthread_self", [5]Arg{}, "pthread_t"},130+ {"pthread_self", [5]Arg{}, "pthread_t", []string{"darwin"}},
144- {"pthread_get_stacksize_np", [5]Arg{{"thread", "pthread_t"}}, "size_t"},131+ {"pthread_get_stacksize_np", [5]Arg{{"thread", "pthread_t"}}, "size_t", []string{"darwin"}},
145- {"pthread_attr_getstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"stacksize", "*size_t"}}, "int32"},132+ {"pthread_attr_getstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"stacksize", "*size_t"}}, "int32", []string{"linux", "freebsd", "netbsd"}},
146- {"pthread_attr_setstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"size", "size_t"}}, "int32"},133+ {"pthread_attr_setstacksize", [5]Arg{{"attr", "*pthread_attr_t"}, {"size", "size_t"}}, "int32", []string{"darwin"}},
147- {"pthread_attr_destroy", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32"},134+ {"pthread_attr_destroy", [5]Arg{{"attr", "*pthread_attr_t"}}, "int32", []string{"linux", "freebsd", "netbsd"}},
148- {"pthread_mutex_lock", [5]Arg{{"mutex", "*pthread_mutex_t"}}, "int32"},135+ {"pthread_mutex_lock", [5]Arg{{"mutex", "*pthread_mutex_t"}}, "int32", nil},
149- {"pthread_mutex_unlock", [5]Arg{{"mutex", "*pthread_mutex_t"}}, "int32"},136+ {"pthread_mutex_unlock", [5]Arg{{"mutex", "*pthread_mutex_t"}}, "int32", nil},
150- {"pthread_cond_broadcast", [5]Arg{{"cond", "*pthread_cond_t"}}, "int32"},137+ {"pthread_cond_broadcast", [5]Arg{{"cond", "*pthread_cond_t"}}, "int32", nil},
151- {"pthread_setspecific", [5]Arg{{"key", "pthread_key_t"}, {"value", "unsafe.Pointer"}}, "int32"},138+ {"pthread_setspecific", [5]Arg{{"key", "pthread_key_t"}, {"value", "unsafe.Pointer"}}, "int32", nil},
152 }139 }
153 )140 )
154 141
155 var funcs = map[string]any{142 var funcs = map[string]any{
156 "hasPrefix": strings.HasPrefix,143 "hasPrefix": strings.HasPrefix,
144+ "imports": imports,
157 }145 }
158 146
159-func run() error {147+var GOOSes = []string{"darwin", "freebsd", "linux", "netbsd"}
160- t, err := template.New("zsymbol.go").Funcs(funcs).Parse(templateSymbols)148+
161- if err != nil {149+func imports(symbols []Symbol) string {
162- return err150+ if len(symbols) == 0 {
163- }151+ return ""
164- f, err := os.Create("zsymbols.go")
165- defer f.Close()
166- if err != nil {
167- return err
168 }152 }
169- allSymbols := append(append([]Symbol{}, libcSymbols...), pthreadSymbols...)153+ imports := make(map[string]struct{})
170- buf := new(bytes.Buffer)154+ imports["unsafe"] = struct{}{}
171- if err := t.Execute(buf, allSymbols); err != nil {155+ for _, s := range symbols {
172- return err156+ for _, arg := range s.Args {
157+ if pkg, _, found := strings.Cut(arg.Type, "."); found {
158+ pkg = strings.TrimPrefix(pkg, "*")
159+ imports[pkg] = struct{}{}
160+ }
161+ }
173 }162 }
174- source, err := format.Source(buf.Bytes())163+ if len(imports) == 1 {
175- if err != nil {164+ return `import "unsafe"`
176- return err
177 }165 }
178- if _, err = f.Write(source); err != nil {166+ result := make([]string, 0, len(imports))
179- return err167+ for imp := range imports {
168+ result = append(result, imp)
180 }169 }
181- t, err = template.New("ztrampolines_stubs.s").Funcs(funcs).Parse(templateTrampolinesStubs)170+ sort.Strings(result)
182- if err != nil {171+ var sb strings.Builder
183- return err172+ sb.WriteString("import (")
173+ for _, imp := range result {
174+ sb.WriteString("\n\t\"")
175+ sb.WriteString(imp)
176+ sb.WriteString("\"")
184 }177 }
185- f, err = os.Create("ztrampolines_stubs.s")178+ sb.WriteString("\n)")
186- defer f.Close()179+ return sb.String()
187- if err != nil {180+}
188- return err181+
182+// filterSymbols filters the symbols by GOOS.
183+// If goos is empty, it returns symbols that are not specific to any GOOS.
184+func filterSymbols(symbols []Symbol, goos string) []Symbol {
185+ filtered := make([]Symbol, 0, len(symbols))
186+ for _, s := range symbols {
187+ if (s.GOOSes == nil && goos == "") || contains(s.GOOSes, goos) {
188+ filtered = append(filtered, s)
189+ }
189 }190 }
190- if err := t.Execute(f, allSymbols); err != nil {191+ return filtered
191- return err192+}
193+
194+func contains(slice []string, item string) bool {
195+ for _, s := range slice {
196+ if s == item {
197+ return true
198+ }
192 }199 }
193- t, err = template.New("zsymbols_goos.go").Parse(templateSymbolsGoos)200+ return false
194- if err != nil {201+}
202+
203+func execute(t *template.Template, path string, data any) error {
204+ var buf bytes.Buffer
205+ if err := t.Execute(&buf, data); err != nil {
195 return err206 return err
196 }207 }
197- for _, goos := range []string{"darwin", "freebsd", "linux", "netbsd"} {208+ if filepath.Ext(path) == ".go" {
198- f, err = os.Create(fmt.Sprintf("zsymbols_%s.go", goos))209+ source, err := format.Source(buf.Bytes())
199- defer f.Close()
200 if err != nil {210 if err != nil {
201 return err211 return err
202 }212 }
203- b := &bytes.Buffer{}213+ buf.Reset()
214+ buf.Write(source)
215+ }
216+ return os.WriteFile(path, buf.Bytes(), 0644)
217+}
218+
219+func symbolsNames(symbols []Symbol) []string {
220+ names := make([]string, len(symbols))
221+ for i, s := range symbols {
222+ names[i] = s.Name
223+ }
224+ return names
225+}
226+
227+type dynamicImport struct {
228+ Name string
229+ Symbols []string
230+}
231+
232+type fileContent struct {
233+ Tag string
234+ Symbols []Symbol
235+ DynamicImports []dynamicImport
236+}
237+
238+func run() error {
239+ allSymbols := append(append([]Symbol{}, libcSymbols...), pthreadSymbols...)
240+ goosAgnosticContent := fileContent{
241+ Symbols: filterSymbols(allSymbols, ""),
242+ Tag: "!cgo && (" + strings.Join(GOOSes, " || ") + ")",
243+ }
244+ if err := execute(templateSymbols, "zsymbols.go", goosAgnosticContent); err != nil {
245+ return err
246+ }
247+ if err := execute(templateTrampolinesStubs, "ztrampolines_stubs.s", goosAgnosticContent); err != nil {
248+ return err
249+ }
250+ goosAgnosticLibCSymbols := filterSymbols(libcSymbols, "")
251+ goosAgnosticPthreadSymbols := filterSymbols(pthreadSymbols, "")
252+ for _, goos := range GOOSes {
253+ goosSymbols := filterSymbols(allSymbols, goos)
204 var libcSO, pthreadSO string254 var libcSO, pthreadSO string
205 switch goos {255 switch goos {
206 case "darwin":256 case "darwin":
@@ -218,20 +268,21 @@ func run() error {
218 default:268 default:
219 return fmt.Errorf("unsupported OS: %s", goos)269 return fmt.Errorf("unsupported OS: %s", goos)
220 }270 }
221- located := []LocatedSymbols{271+ located := fileContent{
222- {SharedObject: libcSO, Symbols: libcSymbols},272+ DynamicImports: []dynamicImport{
223- {SharedObject: pthreadSO, Symbols: pthreadSymbols},273+ {libcSO, symbolsNames(append(goosAgnosticLibCSymbols, filterSymbols(libcSymbols, goos)...))},
274+ {pthreadSO, symbolsNames(append(goosAgnosticPthreadSymbols, filterSymbols(pthreadSymbols, goos)...))},
275+ },
276+ Symbols: goosSymbols,
277+ Tag: "!cgo",
224 }278 }
225- if err = t.Execute(b, located); err != nil {279+ if err := execute(templateSymbols, fmt.Sprintf("zsymbols_%s.go", goos), located); err != nil {
226 return err280 return err
227 }281 }
228- var src []byte282+ if len(goosSymbols) != 0 {
229- src, err = format.Source(b.Bytes())283+ if err := execute(templateTrampolinesStubs, fmt.Sprintf("ztrampolines_%s.s", goos), located); err != nil {
230- if err != nil {284+ return err
231- return err285+ }
232- }
233- if _, err = f.Write(src); err != nil {
234- return err
235 }286 }
236 }287 }
237 return nil288 return nil
M internal/fakecgo/zsymbols.go +0 -50
@@ -86,36 +86,6 @@ func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int32 {
8686 return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0))
8787 }
8888
89-//go:nosplit
90-//go:norace
91-func pthread_self() pthread_t {
92- return pthread_t(call5(pthread_selfABI0, 0, 0, 0, 0, 0))
93-}
94-
95-//go:nosplit
96-//go:norace
97-func pthread_get_stacksize_np(thread pthread_t) size_t {
98- return size_t(call5(pthread_get_stacksize_npABI0, uintptr(thread), 0, 0, 0, 0))
99-}
100-
101-//go:nosplit
102-//go:norace
103-func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
104- return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
105-}
106-
107-//go:nosplit
108-//go:norace
109-func pthread_attr_setstacksize(attr *pthread_attr_t, size size_t) int32 {
110- return int32(call5(pthread_attr_setstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(size), 0, 0, 0))
111-}
112-
113-//go:nosplit
114-//go:norace
115-func pthread_attr_destroy(attr *pthread_attr_t) int32 {
116- return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
117-}
118-
11989 //go:nosplit
12090 //go:norace
12191 func pthread_mutex_lock(mutex *pthread_mutex_t) int32 {
@@ -188,26 +158,6 @@ var pthread_detachABI0 = uintptr(unsafe.Pointer(&_pthread_detach))
188158 var _pthread_sigmask uint8
189159 var pthread_sigmaskABI0 = uintptr(unsafe.Pointer(&_pthread_sigmask))
190160
191-//go:linkname _pthread_self _pthread_self
192-var _pthread_self uint8
193-var pthread_selfABI0 = uintptr(unsafe.Pointer(&_pthread_self))
194-
195-//go:linkname _pthread_get_stacksize_np _pthread_get_stacksize_np
196-var _pthread_get_stacksize_np uint8
197-var pthread_get_stacksize_npABI0 = uintptr(unsafe.Pointer(&_pthread_get_stacksize_np))
198-
199-//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
200-var _pthread_attr_getstacksize uint8
201-var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
202-
203-//go:linkname _pthread_attr_setstacksize _pthread_attr_setstacksize
204-var _pthread_attr_setstacksize uint8
205-var pthread_attr_setstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_setstacksize))
206-
207-//go:linkname _pthread_attr_destroy _pthread_attr_destroy
208-var _pthread_attr_destroy uint8
209-var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
210-
211161 //go:linkname _pthread_mutex_lock _pthread_mutex_lock
212162 var _pthread_mutex_lock uint8
213163 var pthread_mutex_lockABI0 = uintptr(unsafe.Pointer(&_pthread_mutex_lock))
@@ -86,36 +86,6 @@ func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int32 {
86 return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0))86 return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0))
87 }87 }
88 88
89-//go:nosplit
90-//go:norace
91-func pthread_self() pthread_t {
92- return pthread_t(call5(pthread_selfABI0, 0, 0, 0, 0, 0))
93-}
94-
95-//go:nosplit
96-//go:norace
97-func pthread_get_stacksize_np(thread pthread_t) size_t {
98- return size_t(call5(pthread_get_stacksize_npABI0, uintptr(thread), 0, 0, 0, 0))
99-}
100-
101-//go:nosplit
102-//go:norace
103-func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
104- return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
105-}
106-
107-//go:nosplit
108-//go:norace
109-func pthread_attr_setstacksize(attr *pthread_attr_t, size size_t) int32 {
110- return int32(call5(pthread_attr_setstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(size), 0, 0, 0))
111-}
112-
113-//go:nosplit
114-//go:norace
115-func pthread_attr_destroy(attr *pthread_attr_t) int32 {
116- return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
117-}
118-
119 //go:nosplit89 //go:nosplit
120 //go:norace90 //go:norace
121 func pthread_mutex_lock(mutex *pthread_mutex_t) int32 {91 func pthread_mutex_lock(mutex *pthread_mutex_t) int32 {
@@ -188,26 +158,6 @@ var pthread_detachABI0 = uintptr(unsafe.Pointer(&_pthread_detach))
188 var _pthread_sigmask uint8158 var _pthread_sigmask uint8
189 var pthread_sigmaskABI0 = uintptr(unsafe.Pointer(&_pthread_sigmask))159 var pthread_sigmaskABI0 = uintptr(unsafe.Pointer(&_pthread_sigmask))
190 160
191-//go:linkname _pthread_self _pthread_self
192-var _pthread_self uint8
193-var pthread_selfABI0 = uintptr(unsafe.Pointer(&_pthread_self))
194-
195-//go:linkname _pthread_get_stacksize_np _pthread_get_stacksize_np
196-var _pthread_get_stacksize_np uint8
197-var pthread_get_stacksize_npABI0 = uintptr(unsafe.Pointer(&_pthread_get_stacksize_np))
198-
199-//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
200-var _pthread_attr_getstacksize uint8
201-var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
202-
203-//go:linkname _pthread_attr_setstacksize _pthread_attr_setstacksize
204-var _pthread_attr_setstacksize uint8
205-var pthread_attr_setstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_setstacksize))
206-
207-//go:linkname _pthread_attr_destroy _pthread_attr_destroy
208-var _pthread_attr_destroy uint8
209-var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
210-
211 //go:linkname _pthread_mutex_lock _pthread_mutex_lock161 //go:linkname _pthread_mutex_lock _pthread_mutex_lock
212 var _pthread_mutex_lock uint8162 var _pthread_mutex_lock uint8
213 var pthread_mutex_lockABI0 = uintptr(unsafe.Pointer(&_pthread_mutex_lock))163 var pthread_mutex_lockABI0 = uintptr(unsafe.Pointer(&_pthread_mutex_lock))
M internal/fakecgo/zsymbols_darwin.go +35 -5
@@ -7,6 +7,8 @@
77
88 package fakecgo
99
10+import "unsafe"
11+
1012 //go:cgo_import_dynamic purego_malloc malloc "/usr/lib/libSystem.B.dylib"
1113 //go:cgo_import_dynamic purego_free free "/usr/lib/libSystem.B.dylib"
1214 //go:cgo_import_dynamic purego_setenv setenv "/usr/lib/libSystem.B.dylib"
@@ -19,12 +21,40 @@ package fakecgo
1921 //go:cgo_import_dynamic purego_pthread_create pthread_create "/usr/lib/libSystem.B.dylib"
2022 //go:cgo_import_dynamic purego_pthread_detach pthread_detach "/usr/lib/libSystem.B.dylib"
2123 //go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "/usr/lib/libSystem.B.dylib"
22-//go:cgo_import_dynamic purego_pthread_self pthread_self "/usr/lib/libSystem.B.dylib"
23-//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "/usr/lib/libSystem.B.dylib"
24-//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "/usr/lib/libSystem.B.dylib"
25-//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "/usr/lib/libSystem.B.dylib"
26-//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "/usr/lib/libSystem.B.dylib"
2724 //go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "/usr/lib/libSystem.B.dylib"
2825 //go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "/usr/lib/libSystem.B.dylib"
2926 //go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "/usr/lib/libSystem.B.dylib"
3027 //go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "/usr/lib/libSystem.B.dylib"
28+//go:cgo_import_dynamic purego_pthread_self pthread_self "/usr/lib/libSystem.B.dylib"
29+//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "/usr/lib/libSystem.B.dylib"
30+//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "/usr/lib/libSystem.B.dylib"
31+
32+//go:nosplit
33+//go:norace
34+func pthread_self() pthread_t {
35+ return pthread_t(call5(pthread_selfABI0, 0, 0, 0, 0, 0))
36+}
37+
38+//go:nosplit
39+//go:norace
40+func pthread_get_stacksize_np(thread pthread_t) size_t {
41+ return size_t(call5(pthread_get_stacksize_npABI0, uintptr(thread), 0, 0, 0, 0))
42+}
43+
44+//go:nosplit
45+//go:norace
46+func pthread_attr_setstacksize(attr *pthread_attr_t, size size_t) int32 {
47+ return int32(call5(pthread_attr_setstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(size), 0, 0, 0))
48+}
49+
50+//go:linkname _pthread_self _pthread_self
51+var _pthread_self uint8
52+var pthread_selfABI0 = uintptr(unsafe.Pointer(&_pthread_self))
53+
54+//go:linkname _pthread_get_stacksize_np _pthread_get_stacksize_np
55+var _pthread_get_stacksize_np uint8
56+var pthread_get_stacksize_npABI0 = uintptr(unsafe.Pointer(&_pthread_get_stacksize_np))
57+
58+//go:linkname _pthread_attr_setstacksize _pthread_attr_setstacksize
59+var _pthread_attr_setstacksize uint8
60+var pthread_attr_setstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_setstacksize))
@@ -7,6 +7,8 @@
7 7
8 package fakecgo8 package fakecgo
9 9
10+import "unsafe"
11+
10 //go:cgo_import_dynamic purego_malloc malloc "/usr/lib/libSystem.B.dylib"12 //go:cgo_import_dynamic purego_malloc malloc "/usr/lib/libSystem.B.dylib"
11 //go:cgo_import_dynamic purego_free free "/usr/lib/libSystem.B.dylib"13 //go:cgo_import_dynamic purego_free free "/usr/lib/libSystem.B.dylib"
12 //go:cgo_import_dynamic purego_setenv setenv "/usr/lib/libSystem.B.dylib"14 //go:cgo_import_dynamic purego_setenv setenv "/usr/lib/libSystem.B.dylib"
@@ -19,12 +21,40 @@ package fakecgo
19 //go:cgo_import_dynamic purego_pthread_create pthread_create "/usr/lib/libSystem.B.dylib"21 //go:cgo_import_dynamic purego_pthread_create pthread_create "/usr/lib/libSystem.B.dylib"
20 //go:cgo_import_dynamic purego_pthread_detach pthread_detach "/usr/lib/libSystem.B.dylib"22 //go:cgo_import_dynamic purego_pthread_detach pthread_detach "/usr/lib/libSystem.B.dylib"
21 //go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "/usr/lib/libSystem.B.dylib"23 //go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "/usr/lib/libSystem.B.dylib"
22-//go:cgo_import_dynamic purego_pthread_self pthread_self "/usr/lib/libSystem.B.dylib"
23-//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "/usr/lib/libSystem.B.dylib"
24-//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "/usr/lib/libSystem.B.dylib"
25-//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "/usr/lib/libSystem.B.dylib"
26-//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "/usr/lib/libSystem.B.dylib"
27 //go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "/usr/lib/libSystem.B.dylib"24 //go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "/usr/lib/libSystem.B.dylib"
28 //go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "/usr/lib/libSystem.B.dylib"25 //go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "/usr/lib/libSystem.B.dylib"
29 //go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "/usr/lib/libSystem.B.dylib"26 //go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "/usr/lib/libSystem.B.dylib"
30 //go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "/usr/lib/libSystem.B.dylib"27 //go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "/usr/lib/libSystem.B.dylib"
28+//go:cgo_import_dynamic purego_pthread_self pthread_self "/usr/lib/libSystem.B.dylib"
29+//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "/usr/lib/libSystem.B.dylib"
30+//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "/usr/lib/libSystem.B.dylib"
31+
32+//go:nosplit
33+//go:norace
34+func pthread_self() pthread_t {
35+ return pthread_t(call5(pthread_selfABI0, 0, 0, 0, 0, 0))
36+}
37+
38+//go:nosplit
39+//go:norace
40+func pthread_get_stacksize_np(thread pthread_t) size_t {
41+ return size_t(call5(pthread_get_stacksize_npABI0, uintptr(thread), 0, 0, 0, 0))
42+}
43+
44+//go:nosplit
45+//go:norace
46+func pthread_attr_setstacksize(attr *pthread_attr_t, size size_t) int32 {
47+ return int32(call5(pthread_attr_setstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(size), 0, 0, 0))
48+}
49+
50+//go:linkname _pthread_self _pthread_self
51+var _pthread_self uint8
52+var pthread_selfABI0 = uintptr(unsafe.Pointer(&_pthread_self))
53+
54+//go:linkname _pthread_get_stacksize_np _pthread_get_stacksize_np
55+var _pthread_get_stacksize_np uint8
56+var pthread_get_stacksize_npABI0 = uintptr(unsafe.Pointer(&_pthread_get_stacksize_np))
57+
58+//go:linkname _pthread_attr_setstacksize _pthread_attr_setstacksize
59+var _pthread_attr_setstacksize uint8
60+var pthread_attr_setstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_setstacksize))
M internal/fakecgo/zsymbols_freebsd.go +24 -5
@@ -7,6 +7,8 @@
77
88 package fakecgo
99
10+import "unsafe"
11+
1012 //go:cgo_import_dynamic purego_malloc malloc "libc.so.7"
1113 //go:cgo_import_dynamic purego_free free "libc.so.7"
1214 //go:cgo_import_dynamic purego_setenv setenv "libc.so.7"
@@ -19,12 +21,29 @@ package fakecgo
1921 //go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so"
2022 //go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so"
2123 //go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so"
22-//go:cgo_import_dynamic purego_pthread_self pthread_self "libpthread.so"
23-//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "libpthread.so"
24-//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
25-//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "libpthread.so"
26-//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
2724 //go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so"
2825 //go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so"
2926 //go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so"
3027 //go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so"
28+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
29+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
30+
31+//go:nosplit
32+//go:norace
33+func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
34+ return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
35+}
36+
37+//go:nosplit
38+//go:norace
39+func pthread_attr_destroy(attr *pthread_attr_t) int32 {
40+ return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
41+}
42+
43+//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
44+var _pthread_attr_getstacksize uint8
45+var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
46+
47+//go:linkname _pthread_attr_destroy _pthread_attr_destroy
48+var _pthread_attr_destroy uint8
49+var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
@@ -7,6 +7,8 @@
7 7
8 package fakecgo8 package fakecgo
9 9
10+import "unsafe"
11+
10 //go:cgo_import_dynamic purego_malloc malloc "libc.so.7"12 //go:cgo_import_dynamic purego_malloc malloc "libc.so.7"
11 //go:cgo_import_dynamic purego_free free "libc.so.7"13 //go:cgo_import_dynamic purego_free free "libc.so.7"
12 //go:cgo_import_dynamic purego_setenv setenv "libc.so.7"14 //go:cgo_import_dynamic purego_setenv setenv "libc.so.7"
@@ -19,12 +21,29 @@ package fakecgo
19 //go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so"21 //go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so"
20 //go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so"22 //go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so"
21 //go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so"23 //go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so"
22-//go:cgo_import_dynamic purego_pthread_self pthread_self "libpthread.so"
23-//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "libpthread.so"
24-//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
25-//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "libpthread.so"
26-//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
27 //go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so"24 //go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so"
28 //go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so"25 //go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so"
29 //go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so"26 //go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so"
30 //go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so"27 //go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so"
28+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
29+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
30+
31+//go:nosplit
32+//go:norace
33+func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
34+ return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
35+}
36+
37+//go:nosplit
38+//go:norace
39+func pthread_attr_destroy(attr *pthread_attr_t) int32 {
40+ return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
41+}
42+
43+//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
44+var _pthread_attr_getstacksize uint8
45+var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
46+
47+//go:linkname _pthread_attr_destroy _pthread_attr_destroy
48+var _pthread_attr_destroy uint8
49+var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
M internal/fakecgo/zsymbols_linux.go +24 -5
@@ -7,6 +7,8 @@
77
88 package fakecgo
99
10+import "unsafe"
11+
1012 //go:cgo_import_dynamic purego_malloc malloc "libc.so.6"
1113 //go:cgo_import_dynamic purego_free free "libc.so.6"
1214 //go:cgo_import_dynamic purego_setenv setenv "libc.so.6"
@@ -19,12 +21,29 @@ package fakecgo
1921 //go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so.0"
2022 //go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so.0"
2123 //go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so.0"
22-//go:cgo_import_dynamic purego_pthread_self pthread_self "libpthread.so.0"
23-//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "libpthread.so.0"
24-//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so.0"
25-//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "libpthread.so.0"
26-//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so.0"
2724 //go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so.0"
2825 //go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so.0"
2926 //go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so.0"
3027 //go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so.0"
28+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so.0"
29+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so.0"
30+
31+//go:nosplit
32+//go:norace
33+func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
34+ return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
35+}
36+
37+//go:nosplit
38+//go:norace
39+func pthread_attr_destroy(attr *pthread_attr_t) int32 {
40+ return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
41+}
42+
43+//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
44+var _pthread_attr_getstacksize uint8
45+var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
46+
47+//go:linkname _pthread_attr_destroy _pthread_attr_destroy
48+var _pthread_attr_destroy uint8
49+var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
@@ -7,6 +7,8 @@
7 7
8 package fakecgo8 package fakecgo
9 9
10+import "unsafe"
11+
10 //go:cgo_import_dynamic purego_malloc malloc "libc.so.6"12 //go:cgo_import_dynamic purego_malloc malloc "libc.so.6"
11 //go:cgo_import_dynamic purego_free free "libc.so.6"13 //go:cgo_import_dynamic purego_free free "libc.so.6"
12 //go:cgo_import_dynamic purego_setenv setenv "libc.so.6"14 //go:cgo_import_dynamic purego_setenv setenv "libc.so.6"
@@ -19,12 +21,29 @@ package fakecgo
19 //go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so.0"21 //go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so.0"
20 //go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so.0"22 //go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so.0"
21 //go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so.0"23 //go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so.0"
22-//go:cgo_import_dynamic purego_pthread_self pthread_self "libpthread.so.0"
23-//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "libpthread.so.0"
24-//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so.0"
25-//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "libpthread.so.0"
26-//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so.0"
27 //go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so.0"24 //go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so.0"
28 //go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so.0"25 //go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so.0"
29 //go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so.0"26 //go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so.0"
30 //go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so.0"27 //go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so.0"
28+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so.0"
29+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so.0"
30+
31+//go:nosplit
32+//go:norace
33+func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
34+ return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
35+}
36+
37+//go:nosplit
38+//go:norace
39+func pthread_attr_destroy(attr *pthread_attr_t) int32 {
40+ return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
41+}
42+
43+//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
44+var _pthread_attr_getstacksize uint8
45+var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
46+
47+//go:linkname _pthread_attr_destroy _pthread_attr_destroy
48+var _pthread_attr_destroy uint8
49+var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
M internal/fakecgo/zsymbols_netbsd.go +24 -5
@@ -7,6 +7,8 @@
77
88 package fakecgo
99
10+import "unsafe"
11+
1012 //go:cgo_import_dynamic purego_malloc malloc "libc.so"
1113 //go:cgo_import_dynamic purego_free free "libc.so"
1214 //go:cgo_import_dynamic purego_setenv setenv "libc.so"
@@ -19,12 +21,29 @@ package fakecgo
1921 //go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so"
2022 //go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so"
2123 //go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so"
22-//go:cgo_import_dynamic purego_pthread_self pthread_self "libpthread.so"
23-//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "libpthread.so"
24-//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
25-//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "libpthread.so"
26-//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
2724 //go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so"
2825 //go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so"
2926 //go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so"
3027 //go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so"
28+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
29+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
30+
31+//go:nosplit
32+//go:norace
33+func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
34+ return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
35+}
36+
37+//go:nosplit
38+//go:norace
39+func pthread_attr_destroy(attr *pthread_attr_t) int32 {
40+ return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
41+}
42+
43+//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
44+var _pthread_attr_getstacksize uint8
45+var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
46+
47+//go:linkname _pthread_attr_destroy _pthread_attr_destroy
48+var _pthread_attr_destroy uint8
49+var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
@@ -7,6 +7,8 @@
7 7
8 package fakecgo8 package fakecgo
9 9
10+import "unsafe"
11+
10 //go:cgo_import_dynamic purego_malloc malloc "libc.so"12 //go:cgo_import_dynamic purego_malloc malloc "libc.so"
11 //go:cgo_import_dynamic purego_free free "libc.so"13 //go:cgo_import_dynamic purego_free free "libc.so"
12 //go:cgo_import_dynamic purego_setenv setenv "libc.so"14 //go:cgo_import_dynamic purego_setenv setenv "libc.so"
@@ -19,12 +21,29 @@ package fakecgo
19 //go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so"21 //go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so"
20 //go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so"22 //go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so"
21 //go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so"23 //go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so"
22-//go:cgo_import_dynamic purego_pthread_self pthread_self "libpthread.so"
23-//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "libpthread.so"
24-//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
25-//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "libpthread.so"
26-//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
27 //go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so"24 //go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so"
28 //go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so"25 //go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so"
29 //go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so"26 //go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so"
30 //go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so"27 //go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so"
28+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
29+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
30+
31+//go:nosplit
32+//go:norace
33+func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
34+ return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
35+}
36+
37+//go:nosplit
38+//go:norace
39+func pthread_attr_destroy(attr *pthread_attr_t) int32 {
40+ return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
41+}
42+
43+//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
44+var _pthread_attr_getstacksize uint8
45+var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
46+
47+//go:linkname _pthread_attr_destroy _pthread_attr_destroy
48+var _pthread_attr_destroy uint8
49+var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
A internal/fakecgo/ztrampolines_darwin.s +19 -0
@@ -0,0 +1,19 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
3+// SPDX-License-Identifier: Apache-2.0
4+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5+
6+//go:build !cgo
7+
8+#include "textflag.h"
9+
10+// these stubs are here because it is not possible to go:linkname directly the C functions
11+
12+TEXT _pthread_self(SB), NOSPLIT|NOFRAME, $0-0
13+ JMP purego_pthread_self(SB)
14+
15+TEXT _pthread_get_stacksize_np(SB), NOSPLIT|NOFRAME, $0-0
16+ JMP purego_pthread_get_stacksize_np(SB)
17+
18+TEXT _pthread_attr_setstacksize(SB), NOSPLIT|NOFRAME, $0-0
19+ JMP purego_pthread_attr_setstacksize(SB)
@@ -0,0 +1,19 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
3+// SPDX-License-Identifier: Apache-2.0
4+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5+
6+//go:build !cgo
7+
8+#include "textflag.h"
9+
10+// these stubs are here because it is not possible to go:linkname directly the C functions
11+
12+TEXT _pthread_self(SB), NOSPLIT|NOFRAME, $0-0
13+ JMP purego_pthread_self(SB)
14+
15+TEXT _pthread_get_stacksize_np(SB), NOSPLIT|NOFRAME, $0-0
16+ JMP purego_pthread_get_stacksize_np(SB)
17+
18+TEXT _pthread_attr_setstacksize(SB), NOSPLIT|NOFRAME, $0-0
19+ JMP purego_pthread_attr_setstacksize(SB)
A internal/fakecgo/ztrampolines_freebsd.s +16 -0
@@ -0,0 +1,16 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
3+// SPDX-License-Identifier: Apache-2.0
4+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5+
6+//go:build !cgo
7+
8+#include "textflag.h"
9+
10+// these stubs are here because it is not possible to go:linkname directly the C functions
11+
12+TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0
13+ JMP purego_pthread_attr_getstacksize(SB)
14+
15+TEXT _pthread_attr_destroy(SB), NOSPLIT|NOFRAME, $0-0
16+ JMP purego_pthread_attr_destroy(SB)
@@ -0,0 +1,16 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
3+// SPDX-License-Identifier: Apache-2.0
4+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5+
6+//go:build !cgo
7+
8+#include "textflag.h"
9+
10+// these stubs are here because it is not possible to go:linkname directly the C functions
11+
12+TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0
13+ JMP purego_pthread_attr_getstacksize(SB)
14+
15+TEXT _pthread_attr_destroy(SB), NOSPLIT|NOFRAME, $0-0
16+ JMP purego_pthread_attr_destroy(SB)
A internal/fakecgo/ztrampolines_linux.s +16 -0
@@ -0,0 +1,16 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
3+// SPDX-License-Identifier: Apache-2.0
4+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5+
6+//go:build !cgo
7+
8+#include "textflag.h"
9+
10+// these stubs are here because it is not possible to go:linkname directly the C functions
11+
12+TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0
13+ JMP purego_pthread_attr_getstacksize(SB)
14+
15+TEXT _pthread_attr_destroy(SB), NOSPLIT|NOFRAME, $0-0
16+ JMP purego_pthread_attr_destroy(SB)
@@ -0,0 +1,16 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
3+// SPDX-License-Identifier: Apache-2.0
4+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5+
6+//go:build !cgo
7+
8+#include "textflag.h"
9+
10+// these stubs are here because it is not possible to go:linkname directly the C functions
11+
12+TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0
13+ JMP purego_pthread_attr_getstacksize(SB)
14+
15+TEXT _pthread_attr_destroy(SB), NOSPLIT|NOFRAME, $0-0
16+ JMP purego_pthread_attr_destroy(SB)
A internal/fakecgo/ztrampolines_netbsd.s +16 -0
@@ -0,0 +1,16 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
3+// SPDX-License-Identifier: Apache-2.0
4+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5+
6+//go:build !cgo
7+
8+#include "textflag.h"
9+
10+// these stubs are here because it is not possible to go:linkname directly the C functions
11+
12+TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0
13+ JMP purego_pthread_attr_getstacksize(SB)
14+
15+TEXT _pthread_attr_destroy(SB), NOSPLIT|NOFRAME, $0-0
16+ JMP purego_pthread_attr_destroy(SB)
@@ -0,0 +1,16 @@
1+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
2+
3+// SPDX-License-Identifier: Apache-2.0
4+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
5+
6+//go:build !cgo
7+
8+#include "textflag.h"
9+
10+// these stubs are here because it is not possible to go:linkname directly the C functions
11+
12+TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0
13+ JMP purego_pthread_attr_getstacksize(SB)
14+
15+TEXT _pthread_attr_destroy(SB), NOSPLIT|NOFRAME, $0-0
16+ JMP purego_pthread_attr_destroy(SB)
M internal/fakecgo/ztrampolines_stubs.s +1 -16
@@ -7,7 +7,7 @@
77
88 #include "textflag.h"
99
10-// these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm64
10+// these stubs are here because it is not possible to go:linkname directly the C functions
1111
1212 TEXT _malloc(SB), NOSPLIT|NOFRAME, $0-0
1313 JMP purego_malloc(SB)
@@ -45,21 +45,6 @@ TEXT _pthread_detach(SB), NOSPLIT|NOFRAME, $0-0
4545 TEXT _pthread_sigmask(SB), NOSPLIT|NOFRAME, $0-0
4646 JMP purego_pthread_sigmask(SB)
4747
48-TEXT _pthread_self(SB), NOSPLIT|NOFRAME, $0-0
49- JMP purego_pthread_self(SB)
50-
51-TEXT _pthread_get_stacksize_np(SB), NOSPLIT|NOFRAME, $0-0
52- JMP purego_pthread_get_stacksize_np(SB)
53-
54-TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0
55- JMP purego_pthread_attr_getstacksize(SB)
56-
57-TEXT _pthread_attr_setstacksize(SB), NOSPLIT|NOFRAME, $0-0
58- JMP purego_pthread_attr_setstacksize(SB)
59-
60-TEXT _pthread_attr_destroy(SB), NOSPLIT|NOFRAME, $0-0
61- JMP purego_pthread_attr_destroy(SB)
62-
6348 TEXT _pthread_mutex_lock(SB), NOSPLIT|NOFRAME, $0-0
6449 JMP purego_pthread_mutex_lock(SB)
6550
@@ -7,7 +7,7 @@
7 7
8 #include "textflag.h"8 #include "textflag.h"
9 9
10-// these stubs are here because it is not possible to go:linkname directly the C functions on darwin arm6410+// these stubs are here because it is not possible to go:linkname directly the C functions
11 11
12 TEXT _malloc(SB), NOSPLIT|NOFRAME, $0-012 TEXT _malloc(SB), NOSPLIT|NOFRAME, $0-0
13 JMP purego_malloc(SB)13 JMP purego_malloc(SB)
@@ -45,21 +45,6 @@ TEXT _pthread_detach(SB), NOSPLIT|NOFRAME, $0-0
45 TEXT _pthread_sigmask(SB), NOSPLIT|NOFRAME, $0-045 TEXT _pthread_sigmask(SB), NOSPLIT|NOFRAME, $0-0
46 JMP purego_pthread_sigmask(SB)46 JMP purego_pthread_sigmask(SB)
47 47
48-TEXT _pthread_self(SB), NOSPLIT|NOFRAME, $0-0
49- JMP purego_pthread_self(SB)
50-
51-TEXT _pthread_get_stacksize_np(SB), NOSPLIT|NOFRAME, $0-0
52- JMP purego_pthread_get_stacksize_np(SB)
53-
54-TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0
55- JMP purego_pthread_attr_getstacksize(SB)
56-
57-TEXT _pthread_attr_setstacksize(SB), NOSPLIT|NOFRAME, $0-0
58- JMP purego_pthread_attr_setstacksize(SB)
59-
60-TEXT _pthread_attr_destroy(SB), NOSPLIT|NOFRAME, $0-0
61- JMP purego_pthread_attr_destroy(SB)
62-
63 TEXT _pthread_mutex_lock(SB), NOSPLIT|NOFRAME, $0-048 TEXT _pthread_mutex_lock(SB), NOSPLIT|NOFRAME, $0-0
64 JMP purego_pthread_mutex_lock(SB)49 JMP purego_pthread_mutex_lock(SB)
65 50

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 102

↑↓ moveenter openesc close