...

Source file src/runtime/sys_libc.go

Documentation: runtime

		 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
		 6  // +build darwin openbsd
		 7  
		 8  package runtime
		 9  
		10  import "unsafe"
		11  
		12  // Call fn with arg as its argument. Return what fn returns.
		13  // fn is the raw pc value of the entry point of the desired function.
		14  // Switches to the system stack, if not already there.
		15  // Preserves the calling point as the location where a profiler traceback will begin.
		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