mirror of
https://github.com/rwinkhart/sys.git
synced 2026-09-06 00:57:18 -04:00
go.sys: copy files from syscall package to go.sys/{plan9,windows,unix}
This CL copies to each package of go.sys the files from syscall it will need.
Different directories have different files, but these:
mkall.sh
str.go
syscall.go
mksyscall.pl
race.go
race0.go
syscall_test.go
are copied to all three.
No changes yet, these are just copies. They are not ready to use yet:
package names are wrong, for starters. But this clean copy will make
it easier to follow the changes as the packages are enabled.
LGTM=rsc
R=golang-codereviews, rsc
CC=golang-codereviews
https://golang.org/cl/126960043
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package syscall
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// soError describes reasons for shared library load failures.
|
||||
type soError struct {
|
||||
Err error
|
||||
ObjName string
|
||||
Msg string
|
||||
}
|
||||
|
||||
func (e *soError) Error() string { return e.Msg }
|
||||
|
||||
// Implemented in ../runtime/syscall_solaris.goc.
|
||||
func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||
func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||
func dlclose(handle uintptr) (err Errno)
|
||||
func dlopen(name *uint8, mode uintptr) (handle uintptr, err Errno)
|
||||
func dlsym(handle uintptr, name *uint8) (proc uintptr, err Errno)
|
||||
|
||||
// A so implements access to a single shared library object.
|
||||
type so struct {
|
||||
Name string
|
||||
Handle uintptr
|
||||
}
|
||||
|
||||
// loadSO loads shared library file into memory.
|
||||
func loadSO(name string) (*so, error) {
|
||||
namep, err := BytePtrFromString(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h, e := dlopen(namep, 1) // RTLD_LAZY
|
||||
if e != 0 {
|
||||
return nil, &soError{
|
||||
Err: e,
|
||||
ObjName: name,
|
||||
Msg: "Failed to load " + name + ": " + e.Error(),
|
||||
}
|
||||
}
|
||||
d := &so{
|
||||
Name: name,
|
||||
Handle: uintptr(h),
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// mustLoadSO is like loadSO but panics if load operation fails.
|
||||
func mustLoadSO(name string) *so {
|
||||
d, e := loadSO(name)
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// FindProc searches shared library d for procedure named name and returns
|
||||
// *proc if found. It returns an error if the search fails.
|
||||
func (d *so) FindProc(name string) (*proc, error) {
|
||||
namep, err := BytePtrFromString(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a, _ := dlsym(uintptr(d.Handle), namep)
|
||||
if a == 0 {
|
||||
return nil, &soError{
|
||||
Err: ENOSYS,
|
||||
ObjName: name,
|
||||
Msg: "Failed to find " + name + " procedure in " + d.Name,
|
||||
}
|
||||
}
|
||||
p := &proc{
|
||||
SO: d,
|
||||
Name: name,
|
||||
addr: a,
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// MustFindProc is like FindProc but panics if search fails.
|
||||
func (d *so) MustFindProc(name string) *proc {
|
||||
p, e := d.FindProc(name)
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// Release unloads shared library d from memory.
|
||||
func (d *so) Release() (err error) {
|
||||
return dlclose(d.Handle)
|
||||
}
|
||||
|
||||
// A proc implements access to a procedure inside a shared library.
|
||||
type proc struct {
|
||||
SO *so
|
||||
Name string
|
||||
addr uintptr
|
||||
}
|
||||
|
||||
// Addr returns the address of the procedure represented by p.
|
||||
// The return value can be passed to Syscall to run the procedure.
|
||||
func (p *proc) Addr() uintptr {
|
||||
return p.addr
|
||||
}
|
||||
|
||||
// Call executes procedure p with arguments a. It will panic, if more then
|
||||
// 6 arguments are supplied.
|
||||
//
|
||||
// The returned error is always non-nil, constructed from the result of
|
||||
// GetLastError. Callers must inspect the primary return value to decide
|
||||
// whether an error occurred (according to the semantics of the specific
|
||||
// function being called) before consulting the error. The error will be
|
||||
// guaranteed to contain syscall.Errno.
|
||||
func (p *proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
||||
switch len(a) {
|
||||
case 0:
|
||||
return sysvicall6(p.Addr(), uintptr(len(a)), 0, 0, 0, 0, 0, 0)
|
||||
case 1:
|
||||
return sysvicall6(p.Addr(), uintptr(len(a)), a[0], 0, 0, 0, 0, 0)
|
||||
case 2:
|
||||
return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], 0, 0, 0, 0)
|
||||
case 3:
|
||||
return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], 0, 0, 0)
|
||||
case 4:
|
||||
return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], 0, 0)
|
||||
case 5:
|
||||
return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], 0)
|
||||
case 6:
|
||||
return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5])
|
||||
default:
|
||||
panic("Call " + p.Name + " with too many arguments " + itoa(len(a)) + ".")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// A lazySO implements access to a single shared library. It will delay
|
||||
// the load of the shared library until the first call to its Handle method
|
||||
// or to one of its lazyProc's Addr method.
|
||||
type lazySO struct {
|
||||
mu sync.Mutex
|
||||
so *so // non nil once SO is loaded
|
||||
Name string
|
||||
}
|
||||
|
||||
// Load loads single shared file d.Name into memory. It returns an error if
|
||||
// fails. Load will not try to load SO, if it is already loaded into memory.
|
||||
func (d *lazySO) Load() error {
|
||||
// Non-racy version of:
|
||||
// if d.so == nil {
|
||||
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.so))) == nil {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
if d.so == nil {
|
||||
so, e := loadSO(d.Name)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
// Non-racy version of:
|
||||
// d.so = so
|
||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.so)), unsafe.Pointer(so))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// mustLoad is like Load but panics if search fails.
|
||||
func (d *lazySO) mustLoad() {
|
||||
e := d.Load()
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle returns d's module handle.
|
||||
func (d *lazySO) Handle() uintptr {
|
||||
d.mustLoad()
|
||||
return uintptr(d.so.Handle)
|
||||
}
|
||||
|
||||
// NewProc returns a lazyProc for accessing the named procedure in the SO d.
|
||||
func (d *lazySO) NewProc(name string) *lazyProc {
|
||||
return &lazyProc{l: d, Name: name}
|
||||
}
|
||||
|
||||
// newLazySO creates new lazySO associated with SO file.
|
||||
func newLazySO(name string) *lazySO {
|
||||
return &lazySO{Name: name}
|
||||
}
|
||||
|
||||
// A lazyProc implements access to a procedure inside a lazySO.
|
||||
// It delays the lookup until the Addr method is called.
|
||||
type lazyProc struct {
|
||||
mu sync.Mutex
|
||||
Name string
|
||||
l *lazySO
|
||||
proc *proc
|
||||
}
|
||||
|
||||
// Find searches the shared library for procedure named p.Name. It returns an
|
||||
// error if search fails. Find will not search procedure, if it is already
|
||||
// found and loaded into memory.
|
||||
func (p *lazyProc) Find() error {
|
||||
// Non-racy version of:
|
||||
// if p.proc == nil {
|
||||
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc))) == nil {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
if p.proc == nil {
|
||||
e := p.l.Load()
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
proc, e := p.l.so.FindProc(p.Name)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
// Non-racy version of:
|
||||
// p.proc = proc
|
||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc)), unsafe.Pointer(proc))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// mustFind is like Find but panics if search fails.
|
||||
func (p *lazyProc) mustFind() {
|
||||
e := p.Find()
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Addr returns the address of the procedure represented by p.
|
||||
// The return value can be passed to Syscall to run the procedure.
|
||||
func (p *lazyProc) Addr() uintptr {
|
||||
p.mustFind()
|
||||
return p.proc.Addr()
|
||||
}
|
||||
|
||||
// Call executes procedure p with arguments a. It will panic, if more then
|
||||
// 6 arguments are supplied.
|
||||
//
|
||||
// The returned error is always non-nil, constructed from the result of
|
||||
// GetLastError. Callers must inspect the primary return value to decide
|
||||
// whether an error occurred (according to the semantics of the specific
|
||||
// function being called) before consulting the error. The error will be
|
||||
// guaranteed to contain syscall.Errno.
|
||||
func (p *lazyProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
|
||||
p.mustFind()
|
||||
return p.proc.Call(a...)
|
||||
}
|
||||
Reference in New Issue
Block a user