| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | // Copyright 2023 The Libc Authors. All rights reserved. | 
					
						
							|  |  |  |  | // Use of this source code is governed by a BSD-style | 
					
						
							|  |  |  |  | // license that can be found in the LICENSE file. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-14 16:54:10 +00:00
										 |  |  |  | //go:build linux && (amd64 || arm64 || loong64 || ppc64le || s390x || riscv64 || 386 || arm) | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | //go:generate go run generator.go | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Package libc is the runtime for programs generated by ccgo/v4 or later. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // # Version compatibility | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // The API of this package, in particular the bits that directly support the | 
					
						
							|  |  |  |  | // ccgo compiler, may change in a way that is not backward compatible. If you | 
					
						
							|  |  |  |  | // have generated some Go code from C you should stick to the version of this | 
					
						
							|  |  |  |  | // package that you used at that time and was tested with your payload. The | 
					
						
							|  |  |  |  | // correct way to upgrade to a newer version of this package is to first | 
					
						
							|  |  |  |  | // recompile (C to Go) your code with a newwer version if ccgo that depends on | 
					
						
							|  |  |  |  | // the new libc version. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // If you use C to Go translated code provided by others, stick to the version | 
					
						
							|  |  |  |  | // of libc that translated code shows in its go.mod file and do not upgrade the | 
					
						
							|  |  |  |  | // dependency just because a newer libc is tagged.Vgq | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // This is if course unfortunate. However, it's somewhat similar to C code | 
					
						
							|  |  |  |  | // linked with a specific version of, say GNU libc. When such code asking for | 
					
						
							|  |  |  |  | // glibc5 is run on a system with glibc6, or vice versa, it will fail. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // As a particular example, if your project imports modernc.org/sqlite you | 
					
						
							|  |  |  |  | // should use the same libc version as seen in the go.mod file of the sqlite | 
					
						
							|  |  |  |  | // package. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // tl;dr: It is not always possible to fix ccgo bugs and/or improve performance | 
					
						
							|  |  |  |  | // of the ccgo transpiled code without occasionally making incompatible changes | 
					
						
							|  |  |  |  | // to this package. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // # Thread Local Storage | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // A TLS instance represents a main thread or a thread created by | 
					
						
							|  |  |  |  | // Xpthread_create. A TLS instance is not safe for concurrent use by multiple | 
					
						
							|  |  |  |  | // goroutines. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // If a program starts the C main function, a TLS instance is created | 
					
						
							|  |  |  |  | // automatically and the goroutine entering main() is locked to the OS thread. | 
					
						
							|  |  |  |  | // The translated C code then may create other pthreads by calling | 
					
						
							|  |  |  |  | // Xpthread_create. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // If the translated C code is part of a library package, new TLS instances | 
					
						
							|  |  |  |  | // must be created manually in user/client code. The first TLS instance created | 
					
						
							|  |  |  |  | // will be the "main" libc thread, but it will be not locked to OS thread | 
					
						
							|  |  |  |  | // automatically. Any subsequently manually created TLS instances will call | 
					
						
							|  |  |  |  | // Xpthread_create, but without spawning a new goroutine. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // A manual call to Xpthread_create will create a new TLS instance automatically | 
					
						
							|  |  |  |  | // and spawn a new goroutine executing the thread function. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Package libc provides run time support for programs generated by the | 
					
						
							|  |  |  |  | // [ccgo] C to Go transpiler, version 4 or later. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // # Concurrency | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // Many C libc functions are not thread safe. Such functions are not safe | 
					
						
							|  |  |  |  | // for concurrent use by multiple goroutines in the Go translation as well. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // # Thread Local Storage | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // C threads are modeled as Go goroutines.  Every such C thread, ie. a Go | 
					
						
							|  |  |  |  | // goroutine, must use its own Thread Local Storage instance implemented by the | 
					
						
							|  |  |  |  | // [TLS] type. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // # Signals | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // Signal handling in translated C code is not coordinated with the Go runtime. | 
					
						
							|  |  |  |  | // This is probably the same as when running C code via CGo. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // # Environmental variables | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // This package synchronizes its environ with the current Go environ lazily and | 
					
						
							|  |  |  |  | // only once. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // # libc API documentation copyright | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // From [Linux man-pages Copyleft] | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | //	Permission is granted to make and distribute verbatim copies of this | 
					
						
							|  |  |  |  | //	manual provided the copyright notice and this permission notice are | 
					
						
							|  |  |  |  | //	preserved on all copies. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | //	Permission is granted to copy and distribute modified versions of this | 
					
						
							|  |  |  |  | //	manual under the conditions for verbatim copying, provided that the | 
					
						
							|  |  |  |  | //	entire resulting derived work is distributed under the terms of a | 
					
						
							|  |  |  |  | //	permission notice identical to this one. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | //	Since the Linux kernel and libraries are constantly changing, this | 
					
						
							|  |  |  |  | //	manual page may be incorrect or out-of-date. The author(s) assume no | 
					
						
							|  |  |  |  | //	responsibility for errors or omissions, or for damages resulting from | 
					
						
							|  |  |  |  | //	the use of the information contained herein. The author(s) may not have | 
					
						
							|  |  |  |  | //	taken the same level of care in the production of this manual, which is | 
					
						
							|  |  |  |  | //	licensed free of charge, as they might when working professionally. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | //	Formatted or processed versions of this manual, if unaccompanied by the | 
					
						
							|  |  |  |  | //	source, must acknowledge the copyright and authors of this work. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // [Linux man-pages Copyleft]: https://spdx.org/licenses/Linux-man-pages-copyleft.html | 
					
						
							|  |  |  |  | // [ccgo]: http://modernc.org/ccgo/v4 | 
					
						
							|  |  |  |  | package libc // import "modernc.org/libc" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import ( | 
					
						
							|  |  |  |  | 	"fmt" | 
					
						
							|  |  |  |  | 	"io" | 
					
						
							|  |  |  |  | 	"math" | 
					
						
							|  |  |  |  | 	"math/rand" | 
					
						
							|  |  |  |  | 	"os" | 
					
						
							|  |  |  |  | 	"os/exec" | 
					
						
							|  |  |  |  | 	gosignal "os/signal" | 
					
						
							|  |  |  |  | 	"path/filepath" | 
					
						
							|  |  |  |  | 	"runtime" | 
					
						
							|  |  |  |  | 	"sort" | 
					
						
							|  |  |  |  | 	"strings" | 
					
						
							|  |  |  |  | 	"sync" | 
					
						
							|  |  |  |  | 	"sync/atomic" | 
					
						
							| 
									
										
										
										
											2025-02-14 16:54:10 +00:00
										 |  |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 	"unsafe" | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 	guuid "github.com/google/uuid" | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 	"golang.org/x/sys/unix" | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 	"modernc.org/libc/uuid/uuid" | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 	"modernc.org/memory" | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | const ( | 
					
						
							|  |  |  |  | 	heapAlign = 16 | 
					
						
							|  |  |  |  | 	heapGuard = 16 | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | var ( | 
					
						
							|  |  |  |  | 	_ error = (*MemAuditError)(nil) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	allocator   memory.Allocator | 
					
						
							|  |  |  |  | 	allocatorMu sync.Mutex | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	atExitMu sync.Mutex | 
					
						
							|  |  |  |  | 	atExit   []func() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	tid atomic.Int32 // TLS Go ID | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	Covered  = map[uintptr]struct{}{} | 
					
						
							|  |  |  |  | 	CoveredC = map[string]struct{}{} | 
					
						
							|  |  |  |  | 	coverPCs [1]uintptr //TODO not concurrent safe | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func init() { | 
					
						
							|  |  |  |  | 	nm, err := os.Executable() | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	Xprogram_invocation_name = mustCString(nm) | 
					
						
							|  |  |  |  | 	Xprogram_invocation_short_name = mustCString(filepath.Base(nm)) | 
					
						
							| 
									
										
										
										
											2025-02-14 16:54:10 +00:00
										 |  |  |  | 	X__libc.Fpage_size = Tsize_t(os.Getpagesize()) | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // RawMem64 represents the biggest uint64 array the runtime can handle. | 
					
						
							|  |  |  |  | type RawMem64 [unsafe.Sizeof(RawMem{}) / unsafe.Sizeof(uint64(0))]uint64 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | type MemAuditError struct { | 
					
						
							|  |  |  |  | 	Caller  string | 
					
						
							|  |  |  |  | 	Message string | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func (e *MemAuditError) Error() string { | 
					
						
							|  |  |  |  | 	return fmt.Sprintf("%s: %s", e.Caller, e.Message) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Start executes C's main. | 
					
						
							|  |  |  |  | func Start(main func(*TLS, int32, uintptr) int32) { | 
					
						
							|  |  |  |  | 	runtime.LockOSThread() | 
					
						
							|  |  |  |  | 	if isMemBrk { | 
					
						
							|  |  |  |  | 		defer func() { | 
					
						
							|  |  |  |  | 			trc("==== PANIC") | 
					
						
							|  |  |  |  | 			for _, v := range MemAudit() { | 
					
						
							|  |  |  |  | 				trc("", v.Error()) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		}() | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	tls := NewTLS() | 
					
						
							|  |  |  |  | 	Xexit(tls, main(tls, int32(len(os.Args)), mustAllocStrings(os.Args))) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func mustAllocStrings(a []string) (r uintptr) { | 
					
						
							|  |  |  |  | 	nPtrs := len(a) + 1 | 
					
						
							|  |  |  |  | 	pPtrs := mustCalloc(Tsize_t(uintptr(nPtrs) * unsafe.Sizeof(uintptr(0)))) | 
					
						
							|  |  |  |  | 	ptrs := unsafe.Slice((*uintptr)(unsafe.Pointer(pPtrs)), nPtrs) | 
					
						
							|  |  |  |  | 	nBytes := 0 | 
					
						
							|  |  |  |  | 	for _, v := range a { | 
					
						
							|  |  |  |  | 		nBytes += len(v) + 1 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	pBytes := mustCalloc(Tsize_t(nBytes)) | 
					
						
							|  |  |  |  | 	b := unsafe.Slice((*byte)(unsafe.Pointer(pBytes)), nBytes) | 
					
						
							|  |  |  |  | 	for i, v := range a { | 
					
						
							|  |  |  |  | 		copy(b, v) | 
					
						
							|  |  |  |  | 		b = b[len(v)+1:] | 
					
						
							|  |  |  |  | 		ptrs[i] = pBytes | 
					
						
							|  |  |  |  | 		pBytes += uintptr(len(v)) + 1 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return pPtrs | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func mustCString(s string) (r uintptr) { | 
					
						
							|  |  |  |  | 	n := len(s) | 
					
						
							|  |  |  |  | 	r = mustMalloc(Tsize_t(n + 1)) | 
					
						
							|  |  |  |  | 	copy(unsafe.Slice((*byte)(unsafe.Pointer(r)), n), s) | 
					
						
							|  |  |  |  | 	*(*byte)(unsafe.Pointer(r + uintptr(n))) = 0 | 
					
						
							|  |  |  |  | 	return r | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // CString returns a pointer to a zero-terminated version of s. The caller is | 
					
						
							|  |  |  |  | // responsible for freeing the allocated memory using Xfree. | 
					
						
							|  |  |  |  | func CString(s string) (uintptr, error) { | 
					
						
							|  |  |  |  | 	n := len(s) | 
					
						
							|  |  |  |  | 	p := Xmalloc(nil, Tsize_t(n)+1) | 
					
						
							|  |  |  |  | 	if p == 0 { | 
					
						
							|  |  |  |  | 		return 0, fmt.Errorf("CString: cannot allocate %d bytes", n+1) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	copy(unsafe.Slice((*byte)(unsafe.Pointer(p)), n), s) | 
					
						
							|  |  |  |  | 	*(*byte)(unsafe.Pointer(p + uintptr(n))) = 0 | 
					
						
							|  |  |  |  | 	return p, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func mustMalloc(sz Tsize_t) (r uintptr) { | 
					
						
							|  |  |  |  | 	if r = Xmalloc(nil, sz); r != 0 || sz == 0 { | 
					
						
							|  |  |  |  | 		return r | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	panic(todo("OOM")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func mustCalloc(sz Tsize_t) (r uintptr) { | 
					
						
							|  |  |  |  | 	if r := Xcalloc(nil, 1, sz); r != 0 || sz == 0 { | 
					
						
							|  |  |  |  | 		return r | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	panic(todo("OOM")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | type tlsStackSlot struct { | 
					
						
							|  |  |  |  | 	p  uintptr | 
					
						
							|  |  |  |  | 	sz Tsize_t | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // TLS emulates thread local storage. TLS is not safe for concurrent use by | 
					
						
							|  |  |  |  | // multiple goroutines. | 
					
						
							|  |  |  |  | type TLS struct { | 
					
						
							|  |  |  |  | 	allocaStack         []int | 
					
						
							|  |  |  |  | 	allocas             []uintptr | 
					
						
							|  |  |  |  | 	jumpBuffers         []uintptr | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 	pendingSignals      chan os.Signal | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 	pthread             uintptr // *t__pthread | 
					
						
							|  |  |  |  | 	pthreadCleanupItems []pthreadCleanupItem | 
					
						
							|  |  |  |  | 	pthreadKeyValues    map[Tpthread_key_t]uintptr | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 	sigHandlers         map[int32]uintptr | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 	sp                  int | 
					
						
							|  |  |  |  | 	stack               []tlsStackSlot | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	ID int32 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 	checkSignals bool | 
					
						
							|  |  |  |  | 	ownsPthread  bool | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | var __ccgo_environOnce sync.Once | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // NewTLS returns a newly created TLS that must be eventually closed to prevent | 
					
						
							|  |  |  |  | // resource leaks. | 
					
						
							|  |  |  |  | func NewTLS() (r *TLS) { | 
					
						
							|  |  |  |  | 	id := tid.Add(1) | 
					
						
							|  |  |  |  | 	if id == 0 { | 
					
						
							|  |  |  |  | 		id = tid.Add(1) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	__ccgo_environOnce.Do(func() { | 
					
						
							|  |  |  |  | 		Xenviron = mustAllocStrings(os.Environ()) | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 	pthread := mustMalloc(Tsize_t(unsafe.Sizeof(t__pthread{}))) | 
					
						
							|  |  |  |  | 	*(*t__pthread)(unsafe.Pointer(pthread)) = t__pthread{ | 
					
						
							|  |  |  |  | 		Flocale: uintptr(unsafe.Pointer(&X__libc.Fglobal_locale)), | 
					
						
							|  |  |  |  | 		Fself:   pthread, | 
					
						
							|  |  |  |  | 		Ftid:    id, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return &TLS{ | 
					
						
							|  |  |  |  | 		ID:          id, | 
					
						
							|  |  |  |  | 		ownsPthread: true, | 
					
						
							|  |  |  |  | 		pthread:     pthread, | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 		sigHandlers: map[int32]uintptr{}, | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // int *__errno_location(void) | 
					
						
							|  |  |  |  | func X__errno_location(tls *TLS) (r uintptr) { | 
					
						
							|  |  |  |  | 	return tls.pthread + unsafe.Offsetof(t__pthread{}.Ferrno_val) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // int *__errno_location(void) | 
					
						
							|  |  |  |  | func X___errno_location(tls *TLS) (r uintptr) { | 
					
						
							|  |  |  |  | 	return X__errno_location(tls) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func (tls *TLS) setErrno(n int32) { | 
					
						
							|  |  |  |  | 	if tls == nil { | 
					
						
							|  |  |  |  | 		return | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	*(*int32)(unsafe.Pointer(X__errno_location(tls))) = n | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func (tls *TLS) String() string { | 
					
						
							|  |  |  |  | 	return fmt.Sprintf("TLS#%v pthread=%x", tls.ID, tls.pthread) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Alloc allocates n bytes in tls's local storage. Calls to Alloc() must be | 
					
						
							|  |  |  |  | // strictly paired with calls to TLS.Free on function exit. That also means any | 
					
						
							|  |  |  |  | // memory from Alloc must not be used after a function returns. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // The order matters. This is ok: | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | //	p := tls.Alloc(11) | 
					
						
							|  |  |  |  | //		q := tls.Alloc(22) | 
					
						
							|  |  |  |  | //		tls.Free(22) | 
					
						
							|  |  |  |  | //		// q is no more usable here. | 
					
						
							|  |  |  |  | //	tls.Free(11) | 
					
						
							|  |  |  |  | //	// p is no more usable here. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // This is not correct: | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | //	tls.Alloc(11) | 
					
						
							|  |  |  |  | //		tls.Alloc(22) | 
					
						
							|  |  |  |  | //		tls.Free(11) | 
					
						
							|  |  |  |  | //	tls.Free(22) | 
					
						
							|  |  |  |  | func (tls *TLS) Alloc(n0 int) (r uintptr) { | 
					
						
							|  |  |  |  | 	// shrink	stats									speedtest1 | 
					
						
							|  |  |  |  | 	// ----------------------------------------------------------------------------------------------- | 
					
						
							|  |  |  |  | 	//    0		total  2,544, nallocs 107,553,070, nmallocs 25, nreallocs 107,553,045	10.984s | 
					
						
							|  |  |  |  | 	//    1		total  2,544, nallocs 107,553,070, nmallocs 25, nreallocs  38,905,980	 9.597s | 
					
						
							|  |  |  |  | 	//    2		total  2,616, nallocs 107,553,070, nmallocs 25, nreallocs  18,201,284	 9.206s | 
					
						
							|  |  |  |  | 	//    3		total  2,624, nallocs 107,553,070, nmallocs 25, nreallocs  16,716,302	 9.155s | 
					
						
							|  |  |  |  | 	//    4		total  2,624, nallocs 107,553,070, nmallocs 25, nreallocs  16,156,102	 9.398s | 
					
						
							|  |  |  |  | 	//    8		total  3,408, nallocs 107,553,070, nmallocs 25, nreallocs  14,364,274	 9.198s | 
					
						
							|  |  |  |  | 	//   16		total  3,976, nallocs 107,553,070, nmallocs 25, nreallocs   6,219,602	 8.910s | 
					
						
							|  |  |  |  | 	// --------------------------------------------------------------------------------------------- | 
					
						
							|  |  |  |  | 	//   32		total  5,120, nallocs 107,553,070, nmallocs 25, nreallocs   1,089,037	 8.836s | 
					
						
							|  |  |  |  | 	// --------------------------------------------------------------------------------------------- | 
					
						
							|  |  |  |  | 	//   64		total  6,520, nallocs 107,553,070, nmallocs 25, nreallocs       1,788	 8.420s | 
					
						
							|  |  |  |  | 	//  128		total  8,848, nallocs 107,553,070, nmallocs 25, nreallocs       1,098	 8.833s | 
					
						
							|  |  |  |  | 	//  256		total  8,848, nallocs 107,553,070, nmallocs 25, nreallocs       1,049	 9.508s | 
					
						
							|  |  |  |  | 	//  512		total 33,336, nallocs 107,553,070, nmallocs 25, nreallocs          88	 8.667s | 
					
						
							|  |  |  |  | 	// none		total 33,336, nallocs 107,553,070, nmallocs 25, nreallocs          88	 8.408s | 
					
						
							|  |  |  |  | 	const shrinkSegment = 32 | 
					
						
							|  |  |  |  | 	n := Tsize_t(n0) | 
					
						
							|  |  |  |  | 	if tls.sp < len(tls.stack) { | 
					
						
							|  |  |  |  | 		p := tls.stack[tls.sp].p | 
					
						
							|  |  |  |  | 		sz := tls.stack[tls.sp].sz | 
					
						
							|  |  |  |  | 		if sz >= n /* && sz <= shrinkSegment*n */ { | 
					
						
							|  |  |  |  | 			// Segment shrinking is nice to have but Tcl does some dirty hacks in coroutine | 
					
						
							|  |  |  |  | 			// handling that require stability of stack addresses, out of the C execution | 
					
						
							|  |  |  |  | 			// model. Disabled. | 
					
						
							|  |  |  |  | 			tls.sp++ | 
					
						
							|  |  |  |  | 			return p | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		Xfree(tls, p) | 
					
						
							|  |  |  |  | 		r = mustMalloc(n) | 
					
						
							|  |  |  |  | 		tls.stack[tls.sp] = tlsStackSlot{p: r, sz: Xmalloc_usable_size(tls, r)} | 
					
						
							|  |  |  |  | 		tls.sp++ | 
					
						
							|  |  |  |  | 		return r | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	r = mustMalloc(n) | 
					
						
							|  |  |  |  | 	tls.stack = append(tls.stack, tlsStackSlot{p: r, sz: Xmalloc_usable_size(tls, r)}) | 
					
						
							|  |  |  |  | 	tls.sp++ | 
					
						
							|  |  |  |  | 	return r | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Free manages memory of the preceding TLS.Alloc() | 
					
						
							|  |  |  |  | func (tls *TLS) Free(n int) { | 
					
						
							|  |  |  |  | 	//TODO shrink stacks if possible. Tcl is currently against. | 
					
						
							|  |  |  |  | 	tls.sp-- | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 	if !tls.checkSignals { | 
					
						
							|  |  |  |  | 		return | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	select { | 
					
						
							|  |  |  |  | 	case sig := <-tls.pendingSignals: | 
					
						
							| 
									
										
										
										
											2025-02-14 16:54:10 +00:00
										 |  |  |  | 		signum := int32(sig.(unix.Signal)) | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 		h, ok := tls.sigHandlers[signum] | 
					
						
							|  |  |  |  | 		if !ok { | 
					
						
							|  |  |  |  | 			break | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		switch h { | 
					
						
							|  |  |  |  | 		case SIG_DFL: | 
					
						
							|  |  |  |  | 			// nop | 
					
						
							|  |  |  |  | 		case SIG_IGN: | 
					
						
							|  |  |  |  | 			// nop | 
					
						
							|  |  |  |  | 		default: | 
					
						
							|  |  |  |  | 			(*(*func(*TLS, int32))(unsafe.Pointer(&struct{ uintptr }{h})))(tls, signum) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		// nop | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func (tls *TLS) alloca(n Tsize_t) (r uintptr) { | 
					
						
							|  |  |  |  | 	r = mustMalloc(n) | 
					
						
							|  |  |  |  | 	tls.allocas = append(tls.allocas, r) | 
					
						
							|  |  |  |  | 	return r | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AllocaEntry must be called early on function entry when the function calls | 
					
						
							|  |  |  |  | // or may call alloca(3). | 
					
						
							|  |  |  |  | func (tls *TLS) AllocaEntry() { | 
					
						
							|  |  |  |  | 	tls.allocaStack = append(tls.allocaStack, len(tls.allocas)) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AllocaExit must be defer-called on function exit when the function calls or | 
					
						
							|  |  |  |  | // may call alloca(3). | 
					
						
							|  |  |  |  | func (tls *TLS) AllocaExit() { | 
					
						
							|  |  |  |  | 	n := len(tls.allocaStack) | 
					
						
							|  |  |  |  | 	x := tls.allocaStack[n-1] | 
					
						
							|  |  |  |  | 	tls.allocaStack = tls.allocaStack[:n-1] | 
					
						
							|  |  |  |  | 	for _, v := range tls.allocas[x:] { | 
					
						
							|  |  |  |  | 		Xfree(tls, v) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	tls.allocas = tls.allocas[:x] | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func (tls *TLS) Close() { | 
					
						
							|  |  |  |  | 	defer func() { *tls = TLS{} }() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	for _, v := range tls.allocas { | 
					
						
							|  |  |  |  | 		Xfree(tls, v) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	for _, v := range tls.stack /* shrink diabled[:tls.sp] */ { | 
					
						
							|  |  |  |  | 		Xfree(tls, v.p) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if tls.ownsPthread { | 
					
						
							|  |  |  |  | 		Xfree(tls, tls.pthread) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func (tls *TLS) PushJumpBuffer(jb uintptr) { | 
					
						
							|  |  |  |  | 	tls.jumpBuffers = append(tls.jumpBuffers, jb) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | type LongjmpRetval int32 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func (tls *TLS) PopJumpBuffer(jb uintptr) { | 
					
						
							|  |  |  |  | 	n := len(tls.jumpBuffers) | 
					
						
							|  |  |  |  | 	if n == 0 || tls.jumpBuffers[n-1] != jb { | 
					
						
							|  |  |  |  | 		panic(todo("unsupported setjmp/longjmp usage")) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	tls.jumpBuffers = tls.jumpBuffers[:n-1] | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func (tls *TLS) Longjmp(jb uintptr, val int32) { | 
					
						
							|  |  |  |  | 	tls.PopJumpBuffer(jb) | 
					
						
							|  |  |  |  | 	if val == 0 { | 
					
						
							|  |  |  |  | 		val = 1 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	panic(LongjmpRetval(val)) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ============================================================================ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Xexit(tls *TLS, code int32) { | 
					
						
							|  |  |  |  | 	//TODO atexit finalizers | 
					
						
							|  |  |  |  | 	X__stdio_exit(tls) | 
					
						
							|  |  |  |  | 	for _, v := range atExit { | 
					
						
							|  |  |  |  | 		v() | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 	atExitHandlersMu.Lock() | 
					
						
							|  |  |  |  | 	for _, v := range atExitHandlers { | 
					
						
							|  |  |  |  | 		(*(*func(*TLS))(unsafe.Pointer(&struct{ uintptr }{v})))(tls) | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 	os.Exit(int(code)) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func _exit(tls *TLS, code int32) { | 
					
						
							|  |  |  |  | 	Xexit(tls, code) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | var abort Tsigaction | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Xabort(tls *TLS) { | 
					
						
							|  |  |  |  | 	X__libc_sigaction(tls, SIGABRT, uintptr(unsafe.Pointer(&abort)), 0) | 
					
						
							| 
									
										
										
										
											2025-02-14 16:54:10 +00:00
										 |  |  |  | 	unix.Kill(unix.Getpid(), unix.Signal(SIGABRT)) | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 	panic(todo("unrechable")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | type lock struct { | 
					
						
							|  |  |  |  | 	sync.Mutex | 
					
						
							|  |  |  |  | 	waiters int | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | var ( | 
					
						
							|  |  |  |  | 	locksMu sync.Mutex | 
					
						
							|  |  |  |  | 	locks   = map[uintptr]*lock{} | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	T1		T2 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	lock(&foo)			// foo: 0 -> 1 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			lock(&foo)	// foo: 1 -> 2 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	unlock(&foo)			// foo: 2 -> 1, non zero means waiter(s) active | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			unlock(&foo)	// foo: 1 -> 0 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func ___lock(tls *TLS, p uintptr) { | 
					
						
							|  |  |  |  | 	if atomic.AddInt32((*int32)(unsafe.Pointer(p)), 1) == 1 { | 
					
						
							|  |  |  |  | 		return | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// foo was already acquired by some other C thread. | 
					
						
							|  |  |  |  | 	locksMu.Lock() | 
					
						
							|  |  |  |  | 	l := locks[p] | 
					
						
							|  |  |  |  | 	if l == nil { | 
					
						
							|  |  |  |  | 		l = &lock{} | 
					
						
							|  |  |  |  | 		locks[p] = l | 
					
						
							|  |  |  |  | 		l.Lock() | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	l.waiters++ | 
					
						
							|  |  |  |  | 	locksMu.Unlock() | 
					
						
							|  |  |  |  | 	l.Lock() // Wait for T1 to release foo. (X below) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func ___unlock(tls *TLS, p uintptr) { | 
					
						
							|  |  |  |  | 	if atomic.AddInt32((*int32)(unsafe.Pointer(p)), -1) == 0 { | 
					
						
							|  |  |  |  | 		return | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// Some other C thread is waiting for foo. | 
					
						
							|  |  |  |  | 	locksMu.Lock() | 
					
						
							|  |  |  |  | 	l := locks[p] | 
					
						
							|  |  |  |  | 	if l == nil { | 
					
						
							|  |  |  |  | 		// We are T1 and we got the locksMu locked before T2. | 
					
						
							|  |  |  |  | 		l = &lock{waiters: 1} | 
					
						
							|  |  |  |  | 		l.Lock() | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	l.Unlock() // Release foo, T2 may now lock it. (X above) | 
					
						
							|  |  |  |  | 	l.waiters-- | 
					
						
							|  |  |  |  | 	if l.waiters == 0 { // we are T2 | 
					
						
							|  |  |  |  | 		delete(locks, p) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	locksMu.Unlock() | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | type lockedFile struct { | 
					
						
							|  |  |  |  | 	ch      chan struct{} | 
					
						
							|  |  |  |  | 	waiters int | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | var ( | 
					
						
							|  |  |  |  | 	lockedFilesMu sync.Mutex | 
					
						
							|  |  |  |  | 	lockedFiles   = map[uintptr]*lockedFile{} | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func X__lockfile(tls *TLS, file uintptr) int32 { | 
					
						
							|  |  |  |  | 	return ___lockfile(tls, file) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // int __lockfile(FILE *f) | 
					
						
							|  |  |  |  | func ___lockfile(tls *TLS, file uintptr) int32 { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | 	// lockedFilesMu.Lock() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// defer lockedFilesMu.Unlock() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// l := lockedFiles[file] | 
					
						
							|  |  |  |  | 	// if l == nil { | 
					
						
							|  |  |  |  | 	// 	l = &lockedFile{ch: make(chan struct{}, 1)} | 
					
						
							|  |  |  |  | 	// 	lockedFiles[file] = l | 
					
						
							|  |  |  |  | 	// } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// l.waiters++ | 
					
						
							|  |  |  |  | 	// l.ch <- struct{}{} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func X__unlockfile(tls *TLS, file uintptr) { | 
					
						
							|  |  |  |  | 	___unlockfile(tls, file) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // void __unlockfile(FILE *f) | 
					
						
							|  |  |  |  | func ___unlockfile(tls *TLS, file uintptr) { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | 	lockedFilesMu.Lock() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer lockedFilesMu.Unlock() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	l := lockedFiles[file] | 
					
						
							|  |  |  |  | 	l.waiters-- | 
					
						
							|  |  |  |  | 	if l.waiters == 0 { | 
					
						
							|  |  |  |  | 		delete(lockedFiles, file) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	<-l.ch | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // void __synccall(void (*func)(void *), void *ctx) | 
					
						
							|  |  |  |  | func ___synccall(tls *TLS, fn, ctx uintptr) { | 
					
						
							|  |  |  |  | 	(*(*func(*TLS, uintptr))(unsafe.Pointer(&struct{ uintptr }{fn})))(tls, ctx) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-14 16:54:10 +00:00
										 |  |  |  | // func ___randname(tls *TLS, template uintptr) (r1 uintptr) { | 
					
						
							|  |  |  |  | // 	bp := tls.Alloc(16) | 
					
						
							|  |  |  |  | // 	defer tls.Free(16) | 
					
						
							|  |  |  |  | // 	var i int32 | 
					
						
							|  |  |  |  | // 	var r uint64 | 
					
						
							|  |  |  |  | // 	var _ /* ts at bp+0 */ Ttimespec | 
					
						
							|  |  |  |  | // 	X__clock_gettime(tls, CLOCK_REALTIME, bp) | 
					
						
							|  |  |  |  | // 	goto _2 | 
					
						
							|  |  |  |  | // _2: | 
					
						
							|  |  |  |  | // 	r = uint64((*(*Ttimespec)(unsafe.Pointer(bp))).Ftv_sec+(*(*Ttimespec)(unsafe.Pointer(bp))).Ftv_nsec) + uint64(tls.ID)*uint64(65537) | 
					
						
							|  |  |  |  | // 	i = 0 | 
					
						
							|  |  |  |  | // 	for { | 
					
						
							|  |  |  |  | // 		if !(i < int32(6)) { | 
					
						
							|  |  |  |  | // 			break | 
					
						
							|  |  |  |  | // 		} | 
					
						
							|  |  |  |  | // 		*(*int8)(unsafe.Pointer(template + uintptr(i))) = int8(uint64('A') + r&uint64(15) + r&uint64(16)*uint64(2)) | 
					
						
							|  |  |  |  | // 		goto _3 | 
					
						
							|  |  |  |  | // 	_3: | 
					
						
							|  |  |  |  | // 		i++ | 
					
						
							|  |  |  |  | // 		r >>= uint64(5) | 
					
						
							|  |  |  |  | // 	} | 
					
						
							|  |  |  |  | // 	return template | 
					
						
							|  |  |  |  | // } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // #include <time.h> | 
					
						
							|  |  |  |  | // #include <stdint.h> | 
					
						
							|  |  |  |  | // #include "pthread_impl.h" | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // /* This assumes that a check for the | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | //	template size has already been made */ | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // char *__randname(char *template) | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | //	{ | 
					
						
							|  |  |  |  | //		int i; | 
					
						
							|  |  |  |  | //		struct timespec ts; | 
					
						
							|  |  |  |  | //		unsigned long r; | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | //		__clock_gettime(CLOCK_REALTIME, &ts); | 
					
						
							|  |  |  |  | //		r = ts.tv_sec + ts.tv_nsec + __pthread_self()->tid * 65537UL; | 
					
						
							|  |  |  |  | //		for (i=0; i<6; i++, r>>=5) | 
					
						
							|  |  |  |  | //			template[i] = 'A'+(r&15)+(r&16)*2; | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | //		return template; | 
					
						
							|  |  |  |  | //	} | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | func ___randname(tls *TLS, template uintptr) (r1 uintptr) { | 
					
						
							|  |  |  |  | 	var i int32 | 
					
						
							| 
									
										
										
										
											2025-02-14 16:54:10 +00:00
										 |  |  |  | 	ts := time.Now().UnixNano() | 
					
						
							|  |  |  |  | 	r := uint64(ts) + uint64(tls.ID)*65537 | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 	i = 0 | 
					
						
							|  |  |  |  | 	for { | 
					
						
							|  |  |  |  | 		if !(i < int32(6)) { | 
					
						
							|  |  |  |  | 			break | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		*(*int8)(unsafe.Pointer(template + uintptr(i))) = int8(uint64('A') + r&uint64(15) + r&uint64(16)*uint64(2)) | 
					
						
							|  |  |  |  | 		goto _3 | 
					
						
							|  |  |  |  | 	_3: | 
					
						
							|  |  |  |  | 		i++ | 
					
						
							|  |  |  |  | 		r >>= uint64(5) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return template | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func ___get_tp(tls *TLS) uintptr { | 
					
						
							|  |  |  |  | 	return tls.pthread | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Xfork(t *TLS) int32 { | 
					
						
							|  |  |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  |  | 		trc("t=%v, (%v:)", t, origin(2)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	t.setErrno(ENOSYS) | 
					
						
							|  |  |  |  | 	return -1 | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | const SIG_DFL = 0 | 
					
						
							|  |  |  |  | const SIG_IGN = 1 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Xsignal(tls *TLS, signum int32, handler uintptr) (r uintptr) { | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 	r, tls.sigHandlers[signum] = tls.sigHandlers[signum], handler | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 	switch handler { | 
					
						
							|  |  |  |  | 	case SIG_DFL: | 
					
						
							| 
									
										
										
										
											2025-02-14 16:54:10 +00:00
										 |  |  |  | 		gosignal.Reset(unix.Signal(signum)) | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 	case SIG_IGN: | 
					
						
							| 
									
										
										
										
											2025-02-14 16:54:10 +00:00
										 |  |  |  | 		gosignal.Ignore(unix.Signal(signum)) | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 		if tls.pendingSignals == nil { | 
					
						
							|  |  |  |  | 			tls.pendingSignals = make(chan os.Signal, 3) | 
					
						
							|  |  |  |  | 			tls.checkSignals = true | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-02-14 16:54:10 +00:00
										 |  |  |  | 		gosignal.Notify(tls.pendingSignals, unix.Signal(signum)) | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return r | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | var ( | 
					
						
							|  |  |  |  | 	atExitHandlersMu sync.Mutex | 
					
						
							|  |  |  |  | 	atExitHandlers   []uintptr | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | func Xatexit(tls *TLS, func_ uintptr) (r int32) { | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 	atExitHandlersMu.Lock() | 
					
						
							|  |  |  |  | 	atExitHandlers = append(atExitHandlers, func_) | 
					
						
							|  |  |  |  | 	atExitHandlersMu.Unlock() | 
					
						
							|  |  |  |  | 	return 0 | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | var __sync_synchronize_dummy int32 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // __sync_synchronize(); | 
					
						
							|  |  |  |  | func X__sync_synchronize(t *TLS) { | 
					
						
							|  |  |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  |  | 		trc("t=%v, (%v:)", t, origin(2)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	// Attempt to implement a full memory barrier without assembler. | 
					
						
							|  |  |  |  | 	atomic.StoreInt32(&__sync_synchronize_dummy, atomic.LoadInt32(&__sync_synchronize_dummy)+1) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Xdlopen(t *TLS, filename uintptr, flags int32) uintptr { | 
					
						
							|  |  |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  |  | 		trc("t=%v filename=%v flags=%v, (%v:)", t, filename, flags, origin(2)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return 0 | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Xdlsym(t *TLS, handle, symbol uintptr) uintptr { | 
					
						
							|  |  |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  |  | 		trc("t=%v symbol=%v, (%v:)", t, symbol, origin(2)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return 0 | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | var dlErrorMsg = []byte("not supported\x00") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Xdlerror(t *TLS) uintptr { | 
					
						
							|  |  |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  |  | 		trc("t=%v, (%v:)", t, origin(2)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return uintptr(unsafe.Pointer(&dlErrorMsg[0])) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Xdlclose(t *TLS, handle uintptr) int32 { | 
					
						
							|  |  |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  |  | 		trc("t=%v handle=%v, (%v:)", t, handle, origin(2)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Xsystem(t *TLS, command uintptr) int32 { | 
					
						
							|  |  |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  |  | 		trc("t=%v command=%v, (%v:)", t, command, origin(2)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	s := GoString(command) | 
					
						
							|  |  |  |  | 	if command == 0 { | 
					
						
							|  |  |  |  | 		panic(todo("")) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	cmd := exec.Command("sh", "-c", s) | 
					
						
							|  |  |  |  | 	cmd.Stdout = os.Stdout | 
					
						
							|  |  |  |  | 	cmd.Stderr = os.Stderr | 
					
						
							|  |  |  |  | 	err := cmd.Run() | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		ps := err.(*exec.ExitError) | 
					
						
							|  |  |  |  | 		return int32(ps.ExitCode()) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0 | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Xsched_yield(tls *TLS) int32 { | 
					
						
							|  |  |  |  | 	runtime.Gosched() | 
					
						
							|  |  |  |  | 	return 0 | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // AtExit will attempt to run f at process exit. The execution cannot be | 
					
						
							|  |  |  |  | // guaranteed, neither its ordering with respect to any other handlers | 
					
						
							|  |  |  |  | // registered by AtExit. | 
					
						
							|  |  |  |  | func AtExit(f func()) { | 
					
						
							|  |  |  |  | 	atExitMu.Lock() | 
					
						
							|  |  |  |  | 	atExit = append(atExit, f) | 
					
						
							|  |  |  |  | 	atExitMu.Unlock() | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Bool64(b bool) int64 { | 
					
						
							|  |  |  |  | 	if b { | 
					
						
							|  |  |  |  | 		return 1 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 0 | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Environ() uintptr { | 
					
						
							|  |  |  |  | 	__ccgo_environOnce.Do(func() { | 
					
						
							|  |  |  |  | 		Xenviron = mustAllocStrings(os.Environ()) | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 	return Xenviron | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func EnvironP() uintptr { | 
					
						
							|  |  |  |  | 	__ccgo_environOnce.Do(func() { | 
					
						
							|  |  |  |  | 		Xenviron = mustAllocStrings(os.Environ()) | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | 	return uintptr(unsafe.Pointer(&Xenviron)) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // NewVaList is like VaList but automatically allocates the correct amount of | 
					
						
							|  |  |  |  | // memory for all of the items in args. | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // The va_list return value is used to pass the constructed var args to var | 
					
						
							|  |  |  |  | // args accepting functions. The caller of NewVaList is responsible for freeing | 
					
						
							|  |  |  |  | // the va_list. | 
					
						
							|  |  |  |  | func NewVaList(args ...interface{}) (va_list uintptr) { | 
					
						
							|  |  |  |  | 	return VaList(NewVaListN(len(args)), args...) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // NewVaListN returns a newly allocated va_list for n items. The caller of | 
					
						
							|  |  |  |  | // NewVaListN is responsible for freeing the va_list. | 
					
						
							|  |  |  |  | func NewVaListN(n int) (va_list uintptr) { | 
					
						
							|  |  |  |  | 	return Xmalloc(nil, Tsize_t(8*n)) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func SetEnviron(t *TLS, env []string) { | 
					
						
							|  |  |  |  | 	__ccgo_environOnce.Do(func() { | 
					
						
							|  |  |  |  | 		Xenviron = mustAllocStrings(env) | 
					
						
							|  |  |  |  | 	}) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Dmesg(s string, args ...interface{}) { | 
					
						
							|  |  |  |  | 	// nop | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Xalloca(tls *TLS, size Tsize_t) uintptr { | 
					
						
							|  |  |  |  | 	return tls.alloca(size) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // struct cmsghdr *CMSG_NXTHDR(struct msghdr *msgh, struct cmsghdr *cmsg); | 
					
						
							|  |  |  |  | func X__cmsg_nxthdr(t *TLS, msgh, cmsg uintptr) uintptr { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Cover() { | 
					
						
							|  |  |  |  | 	runtime.Callers(2, coverPCs[:]) | 
					
						
							|  |  |  |  | 	Covered[coverPCs[0]] = struct{}{} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func CoverReport(w io.Writer) error { | 
					
						
							|  |  |  |  | 	var a []string | 
					
						
							|  |  |  |  | 	pcs := make([]uintptr, 1) | 
					
						
							|  |  |  |  | 	for pc := range Covered { | 
					
						
							|  |  |  |  | 		pcs[0] = pc | 
					
						
							|  |  |  |  | 		frame, _ := runtime.CallersFrames(pcs).Next() | 
					
						
							|  |  |  |  | 		a = append(a, fmt.Sprintf("%s:%07d:%s", filepath.Base(frame.File), frame.Line, frame.Func.Name())) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	sort.Strings(a) | 
					
						
							|  |  |  |  | 	_, err := fmt.Fprintf(w, "%s\n", strings.Join(a, "\n")) | 
					
						
							|  |  |  |  | 	return err | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func CoverC(s string) { | 
					
						
							|  |  |  |  | 	CoveredC[s] = struct{}{} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func CoverCReport(w io.Writer) error { | 
					
						
							|  |  |  |  | 	var a []string | 
					
						
							|  |  |  |  | 	for k := range CoveredC { | 
					
						
							|  |  |  |  | 		a = append(a, k) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	sort.Strings(a) | 
					
						
							|  |  |  |  | 	_, err := fmt.Fprintf(w, "%s\n", strings.Join(a, "\n")) | 
					
						
							|  |  |  |  | 	return err | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func X__ccgo_dmesg(t *TLS, fmt uintptr, va uintptr) { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func X__ccgo_getMutexType(tls *TLS, m uintptr) int32 { /* pthread_mutex_lock.c:3:5: */ | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func X__ccgo_in6addr_anyp(t *TLS) uintptr { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func X__ccgo_pthreadAttrGetDetachState(tls *TLS, a uintptr) int32 { /* pthread_attr_get.c:3:5: */ | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func X__ccgo_pthreadMutexattrGettype(tls *TLS, a uintptr) int32 { /* pthread_attr_get.c:93:5: */ | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // void sqlite3_log(int iErrCode, const char *zFormat, ...); | 
					
						
							|  |  |  |  | func X__ccgo_sqlite3_log(t *TLS, iErrCode int32, zFormat uintptr, args uintptr) { | 
					
						
							|  |  |  |  | 	// nop | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // unsigned __sync_add_and_fetch_uint32(*unsigned, unsigned) | 
					
						
							|  |  |  |  | func X__sync_add_and_fetch_uint32(t *TLS, p uintptr, v uint32) uint32 { | 
					
						
							|  |  |  |  | 	return atomic.AddUint32((*uint32)(unsafe.Pointer(p)), v) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // unsigned __sync_sub_and_fetch_uint32(*unsigned, unsigned) | 
					
						
							|  |  |  |  | func X__sync_sub_and_fetch_uint32(t *TLS, p uintptr, v uint32) uint32 { | 
					
						
							|  |  |  |  | 	return atomic.AddUint32((*uint32)(unsafe.Pointer(p)), -v) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | var ( | 
					
						
							|  |  |  |  | 	randomData   = map[uintptr]*rand.Rand{} | 
					
						
							|  |  |  |  | 	randomDataMu sync.Mutex | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // The initstate_r() function is like initstate(3) except that it initializes | 
					
						
							|  |  |  |  | // the state in the object pointed to by buf, rather than initializing the | 
					
						
							|  |  |  |  | // global state  variable.   Before  calling this function, the buf.state field | 
					
						
							|  |  |  |  | // must be initialized to NULL.  The initstate_r() function records a pointer | 
					
						
							|  |  |  |  | // to the statebuf argument inside the structure pointed to by buf.  Thus, | 
					
						
							|  |  |  |  | // state‐ buf should not be deallocated so long as buf is still in use.  (So, | 
					
						
							|  |  |  |  | // statebuf should typically be allocated as a static variable, or allocated on | 
					
						
							|  |  |  |  | // the heap using malloc(3) or similar.) | 
					
						
							|  |  |  |  | // | 
					
						
							|  |  |  |  | // char *initstate_r(unsigned int seed, char *statebuf, size_t statelen, struct random_data *buf); | 
					
						
							|  |  |  |  | func Xinitstate_r(t *TLS, seed uint32, statebuf uintptr, statelen Tsize_t, buf uintptr) int32 { | 
					
						
							|  |  |  |  | 	if buf == 0 { | 
					
						
							|  |  |  |  | 		panic(todo("")) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	randomDataMu.Lock() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer randomDataMu.Unlock() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	randomData[buf] = rand.New(rand.NewSource(int64(seed))) | 
					
						
							|  |  |  |  | 	return 0 | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // int random_r(struct random_data *buf, int32_t *result); | 
					
						
							|  |  |  |  | func Xrandom_r(t *TLS, buf, result uintptr) int32 { | 
					
						
							|  |  |  |  | 	randomDataMu.Lock() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer randomDataMu.Unlock() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	mr := randomData[buf] | 
					
						
							|  |  |  |  | 	if RAND_MAX != math.MaxInt32 { | 
					
						
							|  |  |  |  | 		panic(todo("")) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	*(*int32)(unsafe.Pointer(result)) = mr.Int31() | 
					
						
							|  |  |  |  | 	return 0 | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // void longjmp(jmp_buf env, int val); | 
					
						
							|  |  |  |  | func Xlongjmp(t *TLS, env uintptr, val int32) { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // void _longjmp(jmp_buf env, int val); | 
					
						
							|  |  |  |  | func X_longjmp(t *TLS, env uintptr, val int32) { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // int _obstack_begin (struct obstack *h, _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment,	void *(*chunkfun) (size_t),  void (*freefun) (void *)) | 
					
						
							|  |  |  |  | func X_obstack_begin(t *TLS, obstack uintptr, size, alignment int32, chunkfun, freefun uintptr) int32 { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // extern void _obstack_newchunk(struct obstack *, int); | 
					
						
							|  |  |  |  | func X_obstack_newchunk(t *TLS, obstack uintptr, length int32) int32 { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // void obstack_free (struct obstack *h, void *obj) | 
					
						
							|  |  |  |  | func Xobstack_free(t *TLS, obstack, obj uintptr) { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // int obstack_vprintf (struct obstack *obstack, const char *template, va_list ap) | 
					
						
							|  |  |  |  | func Xobstack_vprintf(t *TLS, obstack, template, va uintptr) int32 { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // int _setjmp(jmp_buf env); | 
					
						
							|  |  |  |  | func X_setjmp(t *TLS, env uintptr) int32 { | 
					
						
							|  |  |  |  | 	return 0 //TODO | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // int setjmp(jmp_buf env); | 
					
						
							|  |  |  |  | func Xsetjmp(t *TLS, env uintptr) int32 { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // int backtrace(void **buffer, int size); | 
					
						
							|  |  |  |  | func Xbacktrace(t *TLS, buf uintptr, size int32) int32 { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // void backtrace_symbols_fd(void *const *buffer, int size, int fd); | 
					
						
							|  |  |  |  | func Xbacktrace_symbols_fd(t *TLS, buffer uintptr, size, fd int32) { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // int fts_close(FTS *ftsp); | 
					
						
							|  |  |  |  | func Xfts_close(t *TLS, ftsp uintptr) int32 { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // FTS *fts_open(char * const *path_argv, int options, int (*compar)(const FTSENT **, const FTSENT **)); | 
					
						
							|  |  |  |  | func Xfts_open(t *TLS, path_argv uintptr, options int32, compar uintptr) uintptr { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // FTSENT *fts_read(FTS *ftsp); | 
					
						
							|  |  |  |  | func Xfts64_read(t *TLS, ftsp uintptr) uintptr { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // int fts_close(FTS *ftsp); | 
					
						
							|  |  |  |  | func Xfts64_close(t *TLS, ftsp uintptr) int32 { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // FTS *fts_open(char * const *path_argv, int options, int (*compar)(const FTSENT **, const FTSENT **)); | 
					
						
							|  |  |  |  | func Xfts64_open(t *TLS, path_argv uintptr, options int32, compar uintptr) uintptr { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // FTSENT *fts_read(FTS *ftsp); | 
					
						
							|  |  |  |  | func Xfts_read(t *TLS, ftsp uintptr) uintptr { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // FILE *popen(const char *command, const char *type); | 
					
						
							|  |  |  |  | func Xpopen(t *TLS, command, type1 uintptr) uintptr { | 
					
						
							|  |  |  |  | 	panic(todo("")) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen); | 
					
						
							|  |  |  |  | func Xsysctlbyname(t *TLS, name, oldp, oldlenp, newp uintptr, newlen Tsize_t) int32 { | 
					
						
							|  |  |  |  | 	oldlen := *(*Tsize_t)(unsafe.Pointer(oldlenp)) | 
					
						
							|  |  |  |  | 	switch GoString(name) { | 
					
						
							|  |  |  |  | 	case "hw.ncpu": | 
					
						
							|  |  |  |  | 		if oldlen != 4 { | 
					
						
							|  |  |  |  | 			panic(todo("")) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		*(*int32)(unsafe.Pointer(oldp)) = int32(runtime.GOMAXPROCS(-1)) | 
					
						
							|  |  |  |  | 		return 0 | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		panic(todo("")) | 
					
						
							|  |  |  |  | 		t.setErrno(ENOENT) | 
					
						
							|  |  |  |  | 		return -1 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // void uuid_copy(uuid_t dst, uuid_t src); | 
					
						
							|  |  |  |  | func Xuuid_copy(t *TLS, dst, src uintptr) { | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  |  | 		trc("t=%v src=%v, (%v:)", t, src, origin(2)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	*(*uuid.Uuid_t)(unsafe.Pointer(dst)) = *(*uuid.Uuid_t)(unsafe.Pointer(src)) | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // int uuid_parse( char *in, uuid_t uu); | 
					
						
							|  |  |  |  | func Xuuid_parse(t *TLS, in uintptr, uu uintptr) int32 { | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  |  | 		trc("t=%v in=%v uu=%v, (%v:)", t, in, uu, origin(2)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	r, err := guuid.Parse(GoString(in)) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return -1 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	copy((*RawMem)(unsafe.Pointer(uu))[:unsafe.Sizeof(uuid.Uuid_t{})], r[:]) | 
					
						
							|  |  |  |  | 	return 0 | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // void uuid_generate_random(uuid_t out); | 
					
						
							|  |  |  |  | func Xuuid_generate_random(t *TLS, out uintptr) { | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  |  | 		trc("t=%v out=%v, (%v:)", t, out, origin(2)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	x := guuid.New() | 
					
						
							|  |  |  |  | 	copy((*RawMem)(unsafe.Pointer(out))[:], x[:]) | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // void uuid_unparse(uuid_t uu, char *out); | 
					
						
							|  |  |  |  | func Xuuid_unparse(t *TLS, uu, out uintptr) { | 
					
						
							| 
									
										
										
										
											2024-09-27 22:53:36 +00:00
										 |  |  |  | 	if __ccgo_strace { | 
					
						
							|  |  |  |  | 		trc("t=%v out=%v, (%v:)", t, out, origin(2)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	s := (*guuid.UUID)(unsafe.Pointer(uu)).String() | 
					
						
							|  |  |  |  | 	copy((*RawMem)(unsafe.Pointer(out))[:], s) | 
					
						
							|  |  |  |  | 	*(*byte)(unsafe.Pointer(out + uintptr(len(s)))) = 0 | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | var Xzero_struct_address Taddress |