Files
kyle 2f9d3d97e6 p2: digest with in-sift FIFO, SQLite caches, Honcho context, recover
Dixie is capped (max_inflight 2, queue_depth 8, queue_wait 20s) and
never queued on llama-server. Streaming chat, thinking off, 45s
fallback to clean. Digest and chunk-embedding caches are
content-addressed SQLite (Honcho context is not cached). Recover
uses the guarded Fetcher. guardian-star is refused in code.
2026-09-22 23:54:49 -07:00

166 lines
5.1 KiB
Go

// Copyright 2026 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.
//go:build linux && (amd64 || arm64 || loong64 || ppc64le || s390x || riscv64 || 386 || arm)
package libc // import "modernc.org/libc"
import (
"bytes"
"math"
"math/bits"
"unsafe"
)
// This file replaces hot transpiled musl routines with native Go
// implementations on every musl-derived (linux) target. The transpiled
// mem* routines move at most four bytes per load/store; the Go
// runtime's memmove, memclr, and bytes.Compare use much wider (SIMD)
// operations. The transpiled originals are kept in the generated
// ccgo_linux_<goarch>.go files under ___musl_* names; generator.go
// renames them as part of generation, so make generate maintains this
// arrangement. (On linux/arm musl's memcpy is assembly and was never
// transpiled; the hand-written memcpy in libc_musl_linux_arm.go plays
// the ___musl_memcpy role there.) Should the two ever fall out of
// sync, the build fails with duplicate or missing definitions rather
// than silently reverting. native_musl_test.go verifies these against
// the ___musl_* originals and benchmarks them; the choices below are
// those measurements' winners on linux/amd64 and linux/arm64,
// reworked to use native-word operations where the originals leaned
// on 64-bit ones, so that the 32-bit targets are not penalized.
// void *memcpy(void *dest, const void *src, size_t n);
func Xmemcpy(tls *TLS, dest uintptr, src uintptr, n Tsize_t) (r uintptr) {
if __ccgo_strace {
trc("tls=%v dest=%v src=%v n=%v, (%v:)", tls, dest, src, n, origin(2))
defer func() { trc("-> %v", r) }()
}
if n != 0 {
copy(unsafe.Slice((*byte)(unsafe.Pointer(dest)), n), unsafe.Slice((*byte)(unsafe.Pointer(src)), n))
}
return dest
}
// void *memmove(void *dest, const void *src, size_t n);
func Xmemmove(tls *TLS, dest uintptr, src uintptr, n Tsize_t) (r uintptr) {
if __ccgo_strace {
trc("tls=%v dest=%v src=%v n=%v, (%v:)", tls, dest, src, n, origin(2))
defer func() { trc("-> %v", r) }()
}
if n != 0 {
copy(unsafe.Slice((*byte)(unsafe.Pointer(dest)), n), unsafe.Slice((*byte)(unsafe.Pointer(src)), n))
}
return dest
}
// void *memset(void *s, int c, size_t n);
func Xmemset(tls *TLS, dest uintptr, c int32, n Tsize_t) (r uintptr) {
if __ccgo_strace {
trc("tls=%v dest=%v c=%v n=%v, (%v:)", tls, dest, c, n, origin(2))
defer func() { trc("-> %v", r) }()
}
if n == 0 {
return dest
}
b := unsafe.Slice((*byte)(unsafe.Pointer(dest)), n)
bc := byte(c)
if bc == 0 {
clear(b)
return dest
}
if len(b) < 8 {
for i := range b {
b[i] = bc
}
return dest
}
// Fill the first min(n, 512) bytes: byte stores up to the first
// word-aligned address, then aligned native-word stores of the
// replicated fill byte (fast and alignment-safe on every arch,
// and free of 64-bit arithmetic, which is expensive on the 32-bit
// targets), then repeatedly double the filled prefix with copy,
// which runs as the runtime's vectorized memmove.
const ws = bits.UintSize / 8
x := uint(math.MaxUint/0xff) * uint(bc) // bc replicated into every byte
seed := min(len(b), 512)
i := 0
for ; i < seed && uintptr(unsafe.Pointer(&b[i]))%ws != 0; i++ {
b[i] = bc
}
for ; i+4*ws <= seed; i += 4 * ws {
q := (*[4]uint)(unsafe.Pointer(&b[i]))
q[0] = x
q[1] = x
q[2] = x
q[3] = x
}
for ; i+ws <= seed; i += ws {
*(*uint)(unsafe.Pointer(&b[i])) = x
}
for ; i < seed; i++ {
b[i] = bc
}
for i := seed; i < len(b); {
i += copy(b[i:], b[:i]) // doubles i without ever overflowing int
}
return dest
}
// int memcmp(const void *vl, const void *vr, size_t n);
func Xmemcmp(tls *TLS, vl uintptr, vr uintptr, n Tsize_t) (r1 int32) {
if __ccgo_strace {
trc("tls=%v vl=%v vr=%v n=%v, (%v:)", tls, vl, vr, n, origin(2))
defer func() { trc("-> %v", r1) }()
}
if n == 0 {
return 0
}
l := unsafe.Slice((*byte)(unsafe.Pointer(vl)), n)
r := unsafe.Slice((*byte)(unsafe.Pointer(vr)), n)
// bytes.Compare returns -1/0/+1 rather than musl's difference of
// the first mismatched bytes; C99 7.21.4 specifies only the sign.
return int32(bytes.Compare(l, r))
}
// double fabs(double x);
func Xfabs(tls *TLS, x float64) (r float64) {
if __ccgo_strace {
trc("tls=%v x=%v, (%v:)", tls, x, origin(2))
defer func() { trc("-> %v", r) }()
}
r = math.Abs(x)
if tls.checkSignals {
tls.checkSignal()
}
return r
}
// size_t strcspn(const char *s, const char *c);
func Xstrcspn(tls *TLS, s uintptr, c uintptr) (r Tsize_t) {
if __ccgo_strace {
trc("tls=%v s=%v c=%v, (%v:)", tls, s, c, origin(2))
defer func() { trc("-> %v", r) }()
}
// Native words rather than uint64 so that the 32-bit targets do
// not pay for 64-bit shifts on every byte.
var set [256 / bits.UintSize]uint
for p := c; ; p++ {
ch := *(*byte)(unsafe.Pointer(p))
if ch == 0 {
break
}
set[ch/bits.UintSize] |= 1 << (ch % bits.UintSize)
}
for q := s; ; q++ {
ch := *(*byte)(unsafe.Pointer(q))
if ch == 0 || set[ch/bits.UintSize]&(1<<(ch%bits.UintSize)) != 0 {
r = Tsize_t(q - s)
if tls.checkSignals {
tls.checkSignal()
}
return r
}
}
}