Source file src/runtime/sys_libc.go

     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  //
    16  //go:nosplit
    17  func libcCall(fn, arg unsafe.Pointer) int32 {
    18  	// Leave caller's PC/SP/G around for traceback.
    19  	gp := getg()
    20  	var mp *m
    21  	if gp != nil {
    22  		mp = gp.m
    23  	}
    24  	if mp != nil && mp.libcallsp == 0 {
    25  		mp.libcallg.set(gp)
    26  		mp.libcallpc = getcallerpc()
    27  		// sp must be the last, because once async cpu profiler finds
    28  		// all three values to be non-zero, it will use them
    29  		mp.libcallsp = getcallersp()
    30  	} else {
    31  		// Make sure we don't reset libcallsp. This makes
    32  		// libcCall reentrant; We remember the g/pc/sp for the
    33  		// first call on an M, until that libcCall instance
    34  		// returns.  Reentrance only matters for signals, as
    35  		// libc never calls back into Go.  The tricky case is
    36  		// where we call libcX from an M and record g/pc/sp.
    37  		// Before that call returns, a signal arrives on the
    38  		// same M and the signal handling code calls another
    39  		// libc function.  We don't want that second libcCall
    40  		// from within the handler to be recorded, and we
    41  		// don't want that call's completion to zero
    42  		// libcallsp.
    43  		// We don't need to set libcall* while we're in a sighandler
    44  		// (even if we're not currently in libc) because we block all
    45  		// signals while we're handling a signal. That includes the
    46  		// profile signal, which is the one that uses the libcall* info.
    47  		mp = nil
    48  	}
    49  	res := asmcgocall(fn, arg)
    50  	if mp != nil {
    51  		mp.libcallsp = 0
    52  	}
    53  	return res
    54  }
    55  

View as plain text