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

View as plain text