|  | // Copyright 2014 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 runtime | 
|  |  | 
|  | import "unsafe" | 
|  |  | 
|  | type mts struct { | 
|  | tv_sec  int64 | 
|  | tv_nsec int64 | 
|  | } | 
|  |  | 
|  | type mscratch struct { | 
|  | v [6]uintptr | 
|  | } | 
|  |  | 
|  | type mOS struct { | 
|  | waitsema uintptr // semaphore for parking on locks | 
|  | perrno   *int32  // pointer to tls errno | 
|  | // these are here because they are too large to be on the stack | 
|  | // of low-level NOSPLIT functions. | 
|  | //LibCall       libcall; | 
|  | ts      mts | 
|  | scratch mscratch | 
|  | } | 
|  |  | 
|  | type libcFunc uintptr | 
|  |  | 
|  | var asmsysvicall6 libcFunc | 
|  |  | 
|  | //go:nosplit | 
|  | func sysvicall0(fn *libcFunc) uintptr { | 
|  | // Leave caller's PC/SP around for traceback. | 
|  | gp := getg() | 
|  | var mp *m | 
|  | if gp != nil { | 
|  | mp = gp.m | 
|  | } | 
|  | if mp != nil && mp.libcallsp == 0 { | 
|  | mp.libcallg.set(gp) | 
|  | mp.libcallpc = getcallerpc() | 
|  | // sp must be the last, because once async cpu profiler finds | 
|  | // all three values to be non-zero, it will use them | 
|  | mp.libcallsp = getcallersp() | 
|  | } else { | 
|  | mp = nil // See comment in sys_darwin.go:libcCall | 
|  | } | 
|  |  | 
|  | var libcall libcall | 
|  | libcall.fn = uintptr(unsafe.Pointer(fn)) | 
|  | libcall.n = 0 | 
|  | libcall.args = uintptr(unsafe.Pointer(fn)) // it's unused but must be non-nil, otherwise crashes | 
|  | asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall)) | 
|  | if mp != nil { | 
|  | mp.libcallsp = 0 | 
|  | } | 
|  | return libcall.r1 | 
|  | } | 
|  |  | 
|  | //go:nosplit | 
|  | func sysvicall1(fn *libcFunc, a1 uintptr) uintptr { | 
|  | // Leave caller's PC/SP around for traceback. | 
|  | gp := getg() | 
|  | var mp *m | 
|  | if gp != nil { | 
|  | mp = gp.m | 
|  | } | 
|  | if mp != nil && mp.libcallsp == 0 { | 
|  | mp.libcallg.set(gp) | 
|  | mp.libcallpc = getcallerpc() | 
|  | // sp must be the last, because once async cpu profiler finds | 
|  | // all three values to be non-zero, it will use them | 
|  | mp.libcallsp = getcallersp() | 
|  | } else { | 
|  | mp = nil | 
|  | } | 
|  |  | 
|  | var libcall libcall | 
|  | libcall.fn = uintptr(unsafe.Pointer(fn)) | 
|  | libcall.n = 1 | 
|  | // TODO(rsc): Why is noescape necessary here and below? | 
|  | libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) | 
|  | asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall)) | 
|  | if mp != nil { | 
|  | mp.libcallsp = 0 | 
|  | } | 
|  | return libcall.r1 | 
|  | } | 
|  |  | 
|  | //go:nosplit | 
|  | func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr { | 
|  | // Leave caller's PC/SP around for traceback. | 
|  | gp := getg() | 
|  | var mp *m | 
|  | if gp != nil { | 
|  | mp = gp.m | 
|  | } | 
|  | if mp != nil && mp.libcallsp == 0 { | 
|  | mp.libcallg.set(gp) | 
|  | mp.libcallpc = getcallerpc() | 
|  | // sp must be the last, because once async cpu profiler finds | 
|  | // all three values to be non-zero, it will use them | 
|  | mp.libcallsp = getcallersp() | 
|  | } else { | 
|  | mp = nil | 
|  | } | 
|  |  | 
|  | var libcall libcall | 
|  | libcall.fn = uintptr(unsafe.Pointer(fn)) | 
|  | libcall.n = 2 | 
|  | libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) | 
|  | asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall)) | 
|  | if mp != nil { | 
|  | mp.libcallsp = 0 | 
|  | } | 
|  | return libcall.r1 | 
|  | } | 
|  |  | 
|  | //go:nosplit | 
|  | func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr { | 
|  | // Leave caller's PC/SP around for traceback. | 
|  | gp := getg() | 
|  | var mp *m | 
|  | if gp != nil { | 
|  | mp = gp.m | 
|  | } | 
|  | if mp != nil && mp.libcallsp == 0 { | 
|  | mp.libcallg.set(gp) | 
|  | mp.libcallpc = getcallerpc() | 
|  | // sp must be the last, because once async cpu profiler finds | 
|  | // all three values to be non-zero, it will use them | 
|  | mp.libcallsp = getcallersp() | 
|  | } else { | 
|  | mp = nil | 
|  | } | 
|  |  | 
|  | var libcall libcall | 
|  | libcall.fn = uintptr(unsafe.Pointer(fn)) | 
|  | libcall.n = 3 | 
|  | libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) | 
|  | asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall)) | 
|  | if mp != nil { | 
|  | mp.libcallsp = 0 | 
|  | } | 
|  | return libcall.r1 | 
|  | } | 
|  |  | 
|  | //go:nosplit | 
|  | func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr { | 
|  | // Leave caller's PC/SP around for traceback. | 
|  | gp := getg() | 
|  | var mp *m | 
|  | if gp != nil { | 
|  | mp = gp.m | 
|  | } | 
|  | if mp != nil && mp.libcallsp == 0 { | 
|  | mp.libcallg.set(gp) | 
|  | mp.libcallpc = getcallerpc() | 
|  | // sp must be the last, because once async cpu profiler finds | 
|  | // all three values to be non-zero, it will use them | 
|  | mp.libcallsp = getcallersp() | 
|  | } else { | 
|  | mp = nil | 
|  | } | 
|  |  | 
|  | var libcall libcall | 
|  | libcall.fn = uintptr(unsafe.Pointer(fn)) | 
|  | libcall.n = 4 | 
|  | libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) | 
|  | asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall)) | 
|  | if mp != nil { | 
|  | mp.libcallsp = 0 | 
|  | } | 
|  | return libcall.r1 | 
|  | } | 
|  |  | 
|  | //go:nosplit | 
|  | func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr { | 
|  | // Leave caller's PC/SP around for traceback. | 
|  | gp := getg() | 
|  | var mp *m | 
|  | if gp != nil { | 
|  | mp = gp.m | 
|  | } | 
|  | if mp != nil && mp.libcallsp == 0 { | 
|  | mp.libcallg.set(gp) | 
|  | mp.libcallpc = getcallerpc() | 
|  | // sp must be the last, because once async cpu profiler finds | 
|  | // all three values to be non-zero, it will use them | 
|  | mp.libcallsp = getcallersp() | 
|  | } else { | 
|  | mp = nil | 
|  | } | 
|  |  | 
|  | var libcall libcall | 
|  | libcall.fn = uintptr(unsafe.Pointer(fn)) | 
|  | libcall.n = 5 | 
|  | libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) | 
|  | asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall)) | 
|  | if mp != nil { | 
|  | mp.libcallsp = 0 | 
|  | } | 
|  | return libcall.r1 | 
|  | } | 
|  |  | 
|  | //go:nosplit | 
|  | func sysvicall6(fn *libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr { | 
|  | // Leave caller's PC/SP around for traceback. | 
|  | gp := getg() | 
|  | var mp *m | 
|  | if gp != nil { | 
|  | mp = gp.m | 
|  | } | 
|  | if mp != nil && mp.libcallsp == 0 { | 
|  | mp.libcallg.set(gp) | 
|  | mp.libcallpc = getcallerpc() | 
|  | // sp must be the last, because once async cpu profiler finds | 
|  | // all three values to be non-zero, it will use them | 
|  | mp.libcallsp = getcallersp() | 
|  | } else { | 
|  | mp = nil | 
|  | } | 
|  |  | 
|  | var libcall libcall | 
|  | libcall.fn = uintptr(unsafe.Pointer(fn)) | 
|  | libcall.n = 6 | 
|  | libcall.args = uintptr(noescape(unsafe.Pointer(&a1))) | 
|  | asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall)) | 
|  | if mp != nil { | 
|  | mp.libcallsp = 0 | 
|  | } | 
|  | return libcall.r1 | 
|  | } |