github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/runtime/sys_libc.go (about)

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build darwin || (openbsd && !mips64)
     6  
     7  package runtime
     8  
     9  import "unsafe"
    10  
    11  // Call fn with arg as its argument. Return what fn returns.
    12  // fn is the raw pc value of the entry point of the desired function.
    13  // Switches to the system stack, if not already there.
    14  // Preserves the calling point as the location where a profiler traceback will begin.
    15  //go:nosplit
    16  func libcCall(fn, arg unsafe.Pointer) int32 {
    17  	// Leave caller's PC/SP/G around for traceback.
    18  	gp := getg()
    19  	var mp *m
    20  	if gp != nil {
    21  		mp = gp.m
    22  	}
    23  	if mp != nil && mp.libcallsp == 0 {
    24  		mp.libcallg.set(gp)
    25  		mp.libcallpc = getcallerpc()
    26  		// sp must be the last, because once async cpu profiler finds
    27  		// all three values to be non-zero, it will use them
    28  		mp.libcallsp = getcallersp()
    29  	} else {
    30  		// Make sure we don't reset libcallsp. This makes
    31  		// libcCall reentrant; We remember the g/pc/sp for the
    32  		// first call on an M, until that libcCall instance
    33  		// returns.  Reentrance only matters for signals, as
    34  		// libc never calls back into Go.  The tricky case is
    35  		// where we call libcX from an M and record g/pc/sp.
    36  		// Before that call returns, a signal arrives on the
    37  		// same M and the signal handling code calls another
    38  		// libc function.  We don't want that second libcCall
    39  		// from within the handler to be recorded, and we
    40  		// don't want that call's completion to zero
    41  		// libcallsp.
    42  		// We don't need to set libcall* while we're in a sighandler
    43  		// (even if we're not currently in libc) because we block all
    44  		// signals while we're handling a signal. That includes the
    45  		// profile signal, which is the one that uses the libcall* info.
    46  		mp = nil
    47  	}
    48  	res := asmcgocall(fn, arg)
    49  	if mp != nil {
    50  		mp.libcallsp = 0
    51  	}
    52  	return res
    53  }