Source file src/runtime/os_solaris.go

     1  // Copyright 2014 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  package runtime
     6  
     7  import (
     8  	"internal/runtime/sys"
     9  	"unsafe"
    10  )
    11  
    12  type mts struct {
    13  	tv_sec  int64
    14  	tv_nsec int64
    15  }
    16  
    17  type mscratch struct {
    18  	v [6]uintptr
    19  }
    20  
    21  type mOS struct {
    22  	waitsema uintptr // semaphore for parking on locks
    23  	perrno   *int32  // pointer to tls errno
    24  	// these are here because they are too large to be on the stack
    25  	// of low-level NOSPLIT functions.
    26  	//LibCall       libcall;
    27  	ts      mts
    28  	scratch mscratch
    29  }
    30  
    31  type libcFunc uintptr
    32  
    33  //go:linkname asmsysvicall6x runtime.asmsysvicall6
    34  var asmsysvicall6x libcFunc // name to take addr of asmsysvicall6
    35  
    36  func asmsysvicall6() // declared for vet; do NOT call
    37  
    38  //go:nosplit
    39  func sysvicall0(fn *libcFunc) uintptr {
    40  	// Leave caller's PC/SP around for traceback.
    41  	gp := getg()
    42  	var mp *m
    43  	if gp != nil {
    44  		mp = gp.m
    45  	}
    46  	if mp != nil && mp.libcallsp == 0 {
    47  		mp.libcallg.set(gp)
    48  		mp.libcallpc = sys.GetCallerPC()
    49  		// sp must be the last, because once async cpu profiler finds
    50  		// all three values to be non-zero, it will use them
    51  		mp.libcallsp = sys.GetCallerSP()
    52  	} else {
    53  		mp = nil // See comment in sys_darwin.go:libcCall
    54  	}
    55  
    56  	var libcall libcall
    57  	libcall.fn = uintptr(unsafe.Pointer(fn))
    58  	libcall.n = 0
    59  	libcall.args = uintptr(unsafe.Pointer(fn)) // it's unused but must be non-nil, otherwise crashes
    60  	asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall))
    61  	if mp != nil {
    62  		mp.libcallsp = 0
    63  	}
    64  	return libcall.r1
    65  }
    66  
    67  //go:nosplit
    68  func sysvicall1(fn *libcFunc, a1 uintptr) uintptr {
    69  	r1, _ := sysvicall1Err(fn, a1)
    70  	return r1
    71  }
    72  
    73  // sysvicall1Err returns both the system call result and the errno value.
    74  // This is used by sysvicall1 and pipe.
    75  //
    76  //go:nosplit
    77  func sysvicall1Err(fn *libcFunc, a1 uintptr) (r1, err uintptr) {
    78  	// Leave caller's PC/SP around for traceback.
    79  	gp := getg()
    80  	var mp *m
    81  	if gp != nil {
    82  		mp = gp.m
    83  	}
    84  	if mp != nil && mp.libcallsp == 0 {
    85  		mp.libcallg.set(gp)
    86  		mp.libcallpc = sys.GetCallerPC()
    87  		// sp must be the last, because once async cpu profiler finds
    88  		// all three values to be non-zero, it will use them
    89  		mp.libcallsp = sys.GetCallerSP()
    90  	} else {
    91  		mp = nil
    92  	}
    93  
    94  	var libcall libcall
    95  	libcall.fn = uintptr(unsafe.Pointer(fn))
    96  	libcall.n = 1
    97  	// TODO(rsc): Why is noescape necessary here and below?
    98  	libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
    99  	asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall))
   100  	if mp != nil {
   101  		mp.libcallsp = 0
   102  	}
   103  	return libcall.r1, libcall.err
   104  }
   105  
   106  //go:nosplit
   107  func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr {
   108  	r1, _ := sysvicall2Err(fn, a1, a2)
   109  	return r1
   110  }
   111  
   112  //go:nosplit
   113  //go:cgo_unsafe_args
   114  
   115  // sysvicall2Err returns both the system call result and the errno value.
   116  // This is used by sysvicall2 and pipe2.
   117  func sysvicall2Err(fn *libcFunc, a1, a2 uintptr) (uintptr, uintptr) {
   118  	// Leave caller's PC/SP around for traceback.
   119  	gp := getg()
   120  	var mp *m
   121  	if gp != nil {
   122  		mp = gp.m
   123  	}
   124  	if mp != nil && mp.libcallsp == 0 {
   125  		mp.libcallg.set(gp)
   126  		mp.libcallpc = sys.GetCallerPC()
   127  		// sp must be the last, because once async cpu profiler finds
   128  		// all three values to be non-zero, it will use them
   129  		mp.libcallsp = sys.GetCallerSP()
   130  	} else {
   131  		mp = nil
   132  	}
   133  
   134  	var libcall libcall
   135  	libcall.fn = uintptr(unsafe.Pointer(fn))
   136  	libcall.n = 2
   137  	libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
   138  	asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall))
   139  	if mp != nil {
   140  		mp.libcallsp = 0
   141  	}
   142  	return libcall.r1, libcall.err
   143  }
   144  
   145  //go:nosplit
   146  func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr {
   147  	r1, _ := sysvicall3Err(fn, a1, a2, a3)
   148  	return r1
   149  }
   150  
   151  //go:nosplit
   152  //go:cgo_unsafe_args
   153  
   154  // sysvicall3Err returns both the system call result and the errno value.
   155  // This is used by sysvicall3 and write1.
   156  func sysvicall3Err(fn *libcFunc, a1, a2, a3 uintptr) (r1, err uintptr) {
   157  	// Leave caller's PC/SP around for traceback.
   158  	gp := getg()
   159  	var mp *m
   160  	if gp != nil {
   161  		mp = gp.m
   162  	}
   163  	if mp != nil && mp.libcallsp == 0 {
   164  		mp.libcallg.set(gp)
   165  		mp.libcallpc = sys.GetCallerPC()
   166  		// sp must be the last, because once async cpu profiler finds
   167  		// all three values to be non-zero, it will use them
   168  		mp.libcallsp = sys.GetCallerSP()
   169  	} else {
   170  		mp = nil
   171  	}
   172  
   173  	var libcall libcall
   174  	libcall.fn = uintptr(unsafe.Pointer(fn))
   175  	libcall.n = 3
   176  	libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
   177  	asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall))
   178  	if mp != nil {
   179  		mp.libcallsp = 0
   180  	}
   181  	return libcall.r1, libcall.err
   182  }
   183  
   184  //go:nosplit
   185  //go:cgo_unsafe_args
   186  func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr {
   187  	// Leave caller's PC/SP around for traceback.
   188  	gp := getg()
   189  	var mp *m
   190  	if gp != nil {
   191  		mp = gp.m
   192  	}
   193  	if mp != nil && mp.libcallsp == 0 {
   194  		mp.libcallg.set(gp)
   195  		mp.libcallpc = sys.GetCallerPC()
   196  		// sp must be the last, because once async cpu profiler finds
   197  		// all three values to be non-zero, it will use them
   198  		mp.libcallsp = sys.GetCallerSP()
   199  	} else {
   200  		mp = nil
   201  	}
   202  
   203  	var libcall libcall
   204  	libcall.fn = uintptr(unsafe.Pointer(fn))
   205  	libcall.n = 4
   206  	libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
   207  	asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall))
   208  	if mp != nil {
   209  		mp.libcallsp = 0
   210  	}
   211  	return libcall.r1
   212  }
   213  
   214  //go:nosplit
   215  //go:cgo_unsafe_args
   216  func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr {
   217  	// Leave caller's PC/SP around for traceback.
   218  	gp := getg()
   219  	var mp *m
   220  	if gp != nil {
   221  		mp = gp.m
   222  	}
   223  	if mp != nil && mp.libcallsp == 0 {
   224  		mp.libcallg.set(gp)
   225  		mp.libcallpc = sys.GetCallerPC()
   226  		// sp must be the last, because once async cpu profiler finds
   227  		// all three values to be non-zero, it will use them
   228  		mp.libcallsp = sys.GetCallerSP()
   229  	} else {
   230  		mp = nil
   231  	}
   232  
   233  	var libcall libcall
   234  	libcall.fn = uintptr(unsafe.Pointer(fn))
   235  	libcall.n = 5
   236  	libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
   237  	asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall))
   238  	if mp != nil {
   239  		mp.libcallsp = 0
   240  	}
   241  	return libcall.r1
   242  }
   243  
   244  //go:nosplit
   245  //go:cgo_unsafe_args
   246  func sysvicall6(fn *libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
   247  	// Leave caller's PC/SP around for traceback.
   248  	gp := getg()
   249  	var mp *m
   250  	if gp != nil {
   251  		mp = gp.m
   252  	}
   253  	if mp != nil && mp.libcallsp == 0 {
   254  		mp.libcallg.set(gp)
   255  		mp.libcallpc = sys.GetCallerPC()
   256  		// sp must be the last, because once async cpu profiler finds
   257  		// all three values to be non-zero, it will use them
   258  		mp.libcallsp = sys.GetCallerSP()
   259  	} else {
   260  		mp = nil
   261  	}
   262  
   263  	var libcall libcall
   264  	libcall.fn = uintptr(unsafe.Pointer(fn))
   265  	libcall.n = 6
   266  	libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
   267  	asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&libcall))
   268  	if mp != nil {
   269  		mp.libcallsp = 0
   270  	}
   271  	return libcall.r1
   272  }
   273  
   274  func issetugid() int32 {
   275  	return int32(sysvicall0(&libc_issetugid))
   276  }
   277  

View as plain text