...
Run Format

Source file src/runtime/os3_solaris.go

Documentation: runtime

     1  // Copyright 2011 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  	"runtime/internal/sys"
     9  	"unsafe"
    10  )
    11  
    12  //go:cgo_export_dynamic runtime.end _end
    13  //go:cgo_export_dynamic runtime.etext _etext
    14  //go:cgo_export_dynamic runtime.edata _edata
    15  
    16  //go:cgo_import_dynamic libc____errno ___errno "libc.so"
    17  //go:cgo_import_dynamic libc_clock_gettime clock_gettime "libc.so"
    18  //go:cgo_import_dynamic libc_exit exit "libc.so"
    19  //go:cgo_import_dynamic libc_getcontext getcontext "libc.so"
    20  //go:cgo_import_dynamic libc_kill kill "libc.so"
    21  //go:cgo_import_dynamic libc_madvise madvise "libc.so"
    22  //go:cgo_import_dynamic libc_malloc malloc "libc.so"
    23  //go:cgo_import_dynamic libc_mmap mmap "libc.so"
    24  //go:cgo_import_dynamic libc_munmap munmap "libc.so"
    25  //go:cgo_import_dynamic libc_open open "libc.so"
    26  //go:cgo_import_dynamic libc_pthread_attr_destroy pthread_attr_destroy "libc.so"
    27  //go:cgo_import_dynamic libc_pthread_attr_getstack pthread_attr_getstack "libc.so"
    28  //go:cgo_import_dynamic libc_pthread_attr_init pthread_attr_init "libc.so"
    29  //go:cgo_import_dynamic libc_pthread_attr_setdetachstate pthread_attr_setdetachstate "libc.so"
    30  //go:cgo_import_dynamic libc_pthread_attr_setstack pthread_attr_setstack "libc.so"
    31  //go:cgo_import_dynamic libc_pthread_create pthread_create "libc.so"
    32  //go:cgo_import_dynamic libc_raise raise "libc.so"
    33  //go:cgo_import_dynamic libc_read read "libc.so"
    34  //go:cgo_import_dynamic libc_select select "libc.so"
    35  //go:cgo_import_dynamic libc_sched_yield sched_yield "libc.so"
    36  //go:cgo_import_dynamic libc_sem_init sem_init "libc.so"
    37  //go:cgo_import_dynamic libc_sem_post sem_post "libc.so"
    38  //go:cgo_import_dynamic libc_sem_reltimedwait_np sem_reltimedwait_np "libc.so"
    39  //go:cgo_import_dynamic libc_sem_wait sem_wait "libc.so"
    40  //go:cgo_import_dynamic libc_setitimer setitimer "libc.so"
    41  //go:cgo_import_dynamic libc_sigaction sigaction "libc.so"
    42  //go:cgo_import_dynamic libc_sigaltstack sigaltstack "libc.so"
    43  //go:cgo_import_dynamic libc_sigprocmask sigprocmask "libc.so"
    44  //go:cgo_import_dynamic libc_sysconf sysconf "libc.so"
    45  //go:cgo_import_dynamic libc_usleep usleep "libc.so"
    46  //go:cgo_import_dynamic libc_write write "libc.so"
    47  
    48  //go:linkname libc____errno libc____errno
    49  //go:linkname libc_clock_gettime libc_clock_gettime
    50  //go:linkname libc_exit libc_exit
    51  //go:linkname libc_getcontext libc_getcontext
    52  //go:linkname libc_kill libc_kill
    53  //go:linkname libc_madvise libc_madvise
    54  //go:linkname libc_malloc libc_malloc
    55  //go:linkname libc_mmap libc_mmap
    56  //go:linkname libc_munmap libc_munmap
    57  //go:linkname libc_open libc_open
    58  //go:linkname libc_pthread_attr_destroy libc_pthread_attr_destroy
    59  //go:linkname libc_pthread_attr_getstack libc_pthread_attr_getstack
    60  //go:linkname libc_pthread_attr_init libc_pthread_attr_init
    61  //go:linkname libc_pthread_attr_setdetachstate libc_pthread_attr_setdetachstate
    62  //go:linkname libc_pthread_attr_setstack libc_pthread_attr_setstack
    63  //go:linkname libc_pthread_create libc_pthread_create
    64  //go:linkname libc_raise libc_raise
    65  //go:linkname libc_read libc_read
    66  //go:linkname libc_select libc_select
    67  //go:linkname libc_sched_yield libc_sched_yield
    68  //go:linkname libc_sem_init libc_sem_init
    69  //go:linkname libc_sem_post libc_sem_post
    70  //go:linkname libc_sem_reltimedwait_np libc_sem_reltimedwait_np
    71  //go:linkname libc_sem_wait libc_sem_wait
    72  //go:linkname libc_setitimer libc_setitimer
    73  //go:linkname libc_sigaction libc_sigaction
    74  //go:linkname libc_sigaltstack libc_sigaltstack
    75  //go:linkname libc_sigprocmask libc_sigprocmask
    76  //go:linkname libc_sysconf libc_sysconf
    77  //go:linkname libc_usleep libc_usleep
    78  //go:linkname libc_write libc_write
    79  
    80  var (
    81  	libc____errno,
    82  	libc_clock_gettime,
    83  	libc_exit,
    84  	libc_getcontext,
    85  	libc_kill,
    86  	libc_madvise,
    87  	libc_malloc,
    88  	libc_mmap,
    89  	libc_munmap,
    90  	libc_open,
    91  	libc_pthread_attr_destroy,
    92  	libc_pthread_attr_getstack,
    93  	libc_pthread_attr_init,
    94  	libc_pthread_attr_setdetachstate,
    95  	libc_pthread_attr_setstack,
    96  	libc_pthread_create,
    97  	libc_raise,
    98  	libc_read,
    99  	libc_sched_yield,
   100  	libc_select,
   101  	libc_sem_init,
   102  	libc_sem_post,
   103  	libc_sem_reltimedwait_np,
   104  	libc_sem_wait,
   105  	libc_setitimer,
   106  	libc_sigaction,
   107  	libc_sigaltstack,
   108  	libc_sigprocmask,
   109  	libc_sysconf,
   110  	libc_usleep,
   111  	libc_write libcFunc
   112  )
   113  
   114  var sigset_all = sigset{[4]uint32{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}}
   115  
   116  func getncpu() int32 {
   117  	n := int32(sysconf(__SC_NPROCESSORS_ONLN))
   118  	if n < 1 {
   119  		return 1
   120  	}
   121  	return n
   122  }
   123  
   124  func getPageSize() uintptr {
   125  	n := int32(sysconf(__SC_PAGESIZE))
   126  	if n <= 0 {
   127  		return 0
   128  	}
   129  	return uintptr(n)
   130  }
   131  
   132  func osinit() {
   133  	ncpu = getncpu()
   134  	if physPageSize == 0 {
   135  		physPageSize = getPageSize()
   136  	}
   137  }
   138  
   139  func tstart_sysvicall(newm *m) uint32
   140  
   141  // May run with m.p==nil, so write barriers are not allowed.
   142  //go:nowritebarrier
   143  func newosproc(mp *m) {
   144  	var (
   145  		attr pthreadattr
   146  		oset sigset
   147  		tid  pthread
   148  		ret  int32
   149  		size uint64
   150  	)
   151  
   152  	if pthread_attr_init(&attr) != 0 {
   153  		throw("pthread_attr_init")
   154  	}
   155  	// Allocate a new 2MB stack.
   156  	if pthread_attr_setstack(&attr, 0, 0x200000) != 0 {
   157  		throw("pthread_attr_setstack")
   158  	}
   159  	// Read back the allocated stack.
   160  	if pthread_attr_getstack(&attr, unsafe.Pointer(&mp.g0.stack.hi), &size) != 0 {
   161  		throw("pthread_attr_getstack")
   162  	}
   163  	mp.g0.stack.lo = mp.g0.stack.hi - uintptr(size)
   164  	if pthread_attr_setdetachstate(&attr, _PTHREAD_CREATE_DETACHED) != 0 {
   165  		throw("pthread_attr_setdetachstate")
   166  	}
   167  
   168  	// Disable signals during create, so that the new thread starts
   169  	// with signals disabled. It will enable them in minit.
   170  	sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
   171  	ret = pthread_create(&tid, &attr, funcPC(tstart_sysvicall), unsafe.Pointer(mp))
   172  	sigprocmask(_SIG_SETMASK, &oset, nil)
   173  	if ret != 0 {
   174  		print("runtime: failed to create new OS thread (have ", mcount(), " already; errno=", ret, ")\n")
   175  		if ret == -_EAGAIN {
   176  			println("runtime: may need to increase max user processes (ulimit -u)")
   177  		}
   178  		throw("newosproc")
   179  	}
   180  }
   181  
   182  func exitThread(wait *uint32) {
   183  	// We should never reach exitThread on Solaris because we let
   184  	// libc clean up threads.
   185  	throw("exitThread")
   186  }
   187  
   188  var urandom_dev = []byte("/dev/urandom\x00")
   189  
   190  //go:nosplit
   191  func getRandomData(r []byte) {
   192  	fd := open(&urandom_dev[0], 0 /* O_RDONLY */, 0)
   193  	n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
   194  	closefd(fd)
   195  	extendRandom(r, int(n))
   196  }
   197  
   198  func goenvs() {
   199  	goenvs_unix()
   200  }
   201  
   202  // Called to initialize a new m (including the bootstrap m).
   203  // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
   204  func mpreinit(mp *m) {
   205  	mp.gsignal = malg(32 * 1024)
   206  	mp.gsignal.m = mp
   207  }
   208  
   209  func miniterrno()
   210  
   211  // Called to initialize a new m (including the bootstrap m).
   212  // Called on the new thread, cannot allocate memory.
   213  func minit() {
   214  	asmcgocall(unsafe.Pointer(funcPC(miniterrno)), unsafe.Pointer(&libc____errno))
   215  
   216  	minitSignals()
   217  }
   218  
   219  // Called from dropm to undo the effect of an minit.
   220  func unminit() {
   221  	unminitSignals()
   222  }
   223  
   224  func sigtramp()
   225  
   226  //go:nosplit
   227  //go:nowritebarrierrec
   228  func setsig(i uint32, fn uintptr) {
   229  	var sa sigactiont
   230  
   231  	sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
   232  	sa.sa_mask = sigset_all
   233  	if fn == funcPC(sighandler) {
   234  		fn = funcPC(sigtramp)
   235  	}
   236  	*((*uintptr)(unsafe.Pointer(&sa._funcptr))) = fn
   237  	sigaction(i, &sa, nil)
   238  }
   239  
   240  //go:nosplit
   241  //go:nowritebarrierrec
   242  func setsigstack(i uint32) {
   243  	var sa sigactiont
   244  	sigaction(i, nil, &sa)
   245  	if sa.sa_flags&_SA_ONSTACK != 0 {
   246  		return
   247  	}
   248  	sa.sa_flags |= _SA_ONSTACK
   249  	sigaction(i, &sa, nil)
   250  }
   251  
   252  //go:nosplit
   253  //go:nowritebarrierrec
   254  func getsig(i uint32) uintptr {
   255  	var sa sigactiont
   256  	sigaction(i, nil, &sa)
   257  	return *((*uintptr)(unsafe.Pointer(&sa._funcptr)))
   258  }
   259  
   260  // setSignaltstackSP sets the ss_sp field of a stackt.
   261  //go:nosplit
   262  func setSignalstackSP(s *stackt, sp uintptr) {
   263  	*(*uintptr)(unsafe.Pointer(&s.ss_sp)) = sp
   264  }
   265  
   266  //go:nosplit
   267  //go:nowritebarrierrec
   268  func sigaddset(mask *sigset, i int) {
   269  	mask.__sigbits[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31)
   270  }
   271  
   272  func sigdelset(mask *sigset, i int) {
   273  	mask.__sigbits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
   274  }
   275  
   276  func (c *sigctxt) fixsigcode(sig uint32) {
   277  }
   278  
   279  //go:nosplit
   280  func semacreate(mp *m) {
   281  	if mp.waitsema != 0 {
   282  		return
   283  	}
   284  
   285  	var sem *semt
   286  	_g_ := getg()
   287  
   288  	// Call libc's malloc rather than malloc. This will
   289  	// allocate space on the C heap. We can't call malloc
   290  	// here because it could cause a deadlock.
   291  	_g_.m.libcall.fn = uintptr(unsafe.Pointer(&libc_malloc))
   292  	_g_.m.libcall.n = 1
   293  	_g_.m.scratch = mscratch{}
   294  	_g_.m.scratch.v[0] = unsafe.Sizeof(*sem)
   295  	_g_.m.libcall.args = uintptr(unsafe.Pointer(&_g_.m.scratch))
   296  	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_g_.m.libcall))
   297  	sem = (*semt)(unsafe.Pointer(_g_.m.libcall.r1))
   298  	if sem_init(sem, 0, 0) != 0 {
   299  		throw("sem_init")
   300  	}
   301  	mp.waitsema = uintptr(unsafe.Pointer(sem))
   302  }
   303  
   304  //go:nosplit
   305  func semasleep(ns int64) int32 {
   306  	_m_ := getg().m
   307  	if ns >= 0 {
   308  		_m_.ts.tv_sec = ns / 1000000000
   309  		_m_.ts.tv_nsec = ns % 1000000000
   310  
   311  		_m_.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_reltimedwait_np))
   312  		_m_.libcall.n = 2
   313  		_m_.scratch = mscratch{}
   314  		_m_.scratch.v[0] = _m_.waitsema
   315  		_m_.scratch.v[1] = uintptr(unsafe.Pointer(&_m_.ts))
   316  		_m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch))
   317  		asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_m_.libcall))
   318  		if *_m_.perrno != 0 {
   319  			if *_m_.perrno == _ETIMEDOUT || *_m_.perrno == _EAGAIN || *_m_.perrno == _EINTR {
   320  				return -1
   321  			}
   322  			throw("sem_reltimedwait_np")
   323  		}
   324  		return 0
   325  	}
   326  	for {
   327  		_m_.libcall.fn = uintptr(unsafe.Pointer(&libc_sem_wait))
   328  		_m_.libcall.n = 1
   329  		_m_.scratch = mscratch{}
   330  		_m_.scratch.v[0] = _m_.waitsema
   331  		_m_.libcall.args = uintptr(unsafe.Pointer(&_m_.scratch))
   332  		asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&_m_.libcall))
   333  		if _m_.libcall.r1 == 0 {
   334  			break
   335  		}
   336  		if *_m_.perrno == _EINTR {
   337  			continue
   338  		}
   339  		throw("sem_wait")
   340  	}
   341  	return 0
   342  }
   343  
   344  //go:nosplit
   345  func semawakeup(mp *m) {
   346  	if sem_post((*semt)(unsafe.Pointer(mp.waitsema))) != 0 {
   347  		throw("sem_post")
   348  	}
   349  }
   350  
   351  //go:nosplit
   352  func closefd(fd int32) int32 {
   353  	return int32(sysvicall1(&libc_close, uintptr(fd)))
   354  }
   355  
   356  //go:nosplit
   357  func exit(r int32) {
   358  	sysvicall1(&libc_exit, uintptr(r))
   359  }
   360  
   361  //go:nosplit
   362  func getcontext(context *ucontext) /* int32 */ {
   363  	sysvicall1(&libc_getcontext, uintptr(unsafe.Pointer(context)))
   364  }
   365  
   366  //go:nosplit
   367  func madvise(addr unsafe.Pointer, n uintptr, flags int32) {
   368  	sysvicall3(&libc_madvise, uintptr(addr), uintptr(n), uintptr(flags))
   369  }
   370  
   371  //go:nosplit
   372  func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (unsafe.Pointer, int) {
   373  	p, err := doMmap(uintptr(addr), n, uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off))
   374  	if p == ^uintptr(0) {
   375  		return nil, int(err)
   376  	}
   377  	return unsafe.Pointer(p), 0
   378  }
   379  
   380  //go:nosplit
   381  func doMmap(addr, n, prot, flags, fd, off uintptr) (uintptr, uintptr) {
   382  	var libcall libcall
   383  	libcall.fn = uintptr(unsafe.Pointer(&libc_mmap))
   384  	libcall.n = 6
   385  	libcall.args = uintptr(noescape(unsafe.Pointer(&addr)))
   386  	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
   387  	return libcall.r1, libcall.err
   388  }
   389  
   390  //go:nosplit
   391  func munmap(addr unsafe.Pointer, n uintptr) {
   392  	sysvicall2(&libc_munmap, uintptr(addr), uintptr(n))
   393  }
   394  
   395  func nanotime1()
   396  
   397  //go:nosplit
   398  func nanotime() int64 {
   399  	return int64(sysvicall0((*libcFunc)(unsafe.Pointer(funcPC(nanotime1)))))
   400  }
   401  
   402  //go:nosplit
   403  func open(path *byte, mode, perm int32) int32 {
   404  	return int32(sysvicall3(&libc_open, uintptr(unsafe.Pointer(path)), uintptr(mode), uintptr(perm)))
   405  }
   406  
   407  func pthread_attr_destroy(attr *pthreadattr) int32 {
   408  	return int32(sysvicall1(&libc_pthread_attr_destroy, uintptr(unsafe.Pointer(attr))))
   409  }
   410  
   411  func pthread_attr_getstack(attr *pthreadattr, addr unsafe.Pointer, size *uint64) int32 {
   412  	return int32(sysvicall3(&libc_pthread_attr_getstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(unsafe.Pointer(size))))
   413  }
   414  
   415  func pthread_attr_init(attr *pthreadattr) int32 {
   416  	return int32(sysvicall1(&libc_pthread_attr_init, uintptr(unsafe.Pointer(attr))))
   417  }
   418  
   419  func pthread_attr_setdetachstate(attr *pthreadattr, state int32) int32 {
   420  	return int32(sysvicall2(&libc_pthread_attr_setdetachstate, uintptr(unsafe.Pointer(attr)), uintptr(state)))
   421  }
   422  
   423  func pthread_attr_setstack(attr *pthreadattr, addr uintptr, size uint64) int32 {
   424  	return int32(sysvicall3(&libc_pthread_attr_setstack, uintptr(unsafe.Pointer(attr)), uintptr(addr), uintptr(size)))
   425  }
   426  
   427  func pthread_create(thread *pthread, attr *pthreadattr, fn uintptr, arg unsafe.Pointer) int32 {
   428  	return int32(sysvicall4(&libc_pthread_create, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(fn), uintptr(arg)))
   429  }
   430  
   431  //go:nosplit
   432  //go:nowritebarrierrec
   433  func raise(sig uint32) /* int32 */ {
   434  	sysvicall1(&libc_raise, uintptr(sig))
   435  }
   436  
   437  func raiseproc(sig uint32) /* int32 */ {
   438  	pid := sysvicall0(&libc_getpid)
   439  	sysvicall2(&libc_kill, pid, uintptr(sig))
   440  }
   441  
   442  //go:nosplit
   443  func read(fd int32, buf unsafe.Pointer, nbyte int32) int32 {
   444  	return int32(sysvicall3(&libc_read, uintptr(fd), uintptr(buf), uintptr(nbyte)))
   445  }
   446  
   447  //go:nosplit
   448  func sem_init(sem *semt, pshared int32, value uint32) int32 {
   449  	return int32(sysvicall3(&libc_sem_init, uintptr(unsafe.Pointer(sem)), uintptr(pshared), uintptr(value)))
   450  }
   451  
   452  //go:nosplit
   453  func sem_post(sem *semt) int32 {
   454  	return int32(sysvicall1(&libc_sem_post, uintptr(unsafe.Pointer(sem))))
   455  }
   456  
   457  //go:nosplit
   458  func sem_reltimedwait_np(sem *semt, timeout *timespec) int32 {
   459  	return int32(sysvicall2(&libc_sem_reltimedwait_np, uintptr(unsafe.Pointer(sem)), uintptr(unsafe.Pointer(timeout))))
   460  }
   461  
   462  //go:nosplit
   463  func sem_wait(sem *semt) int32 {
   464  	return int32(sysvicall1(&libc_sem_wait, uintptr(unsafe.Pointer(sem))))
   465  }
   466  
   467  func setitimer(which int32, value *itimerval, ovalue *itimerval) /* int32 */ {
   468  	sysvicall3(&libc_setitimer, uintptr(which), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(ovalue)))
   469  }
   470  
   471  //go:nosplit
   472  //go:nowritebarrierrec
   473  func sigaction(sig uint32, act *sigactiont, oact *sigactiont) /* int32 */ {
   474  	sysvicall3(&libc_sigaction, uintptr(sig), uintptr(unsafe.Pointer(act)), uintptr(unsafe.Pointer(oact)))
   475  }
   476  
   477  //go:nosplit
   478  //go:nowritebarrierrec
   479  func sigaltstack(ss *stackt, oss *stackt) /* int32 */ {
   480  	sysvicall2(&libc_sigaltstack, uintptr(unsafe.Pointer(ss)), uintptr(unsafe.Pointer(oss)))
   481  }
   482  
   483  //go:nosplit
   484  //go:nowritebarrierrec
   485  func sigprocmask(how int32, set *sigset, oset *sigset) /* int32 */ {
   486  	sysvicall3(&libc_sigprocmask, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oset)))
   487  }
   488  
   489  func sysconf(name int32) int64 {
   490  	return int64(sysvicall1(&libc_sysconf, uintptr(name)))
   491  }
   492  
   493  func usleep1(usec uint32)
   494  
   495  //go:nosplit
   496  func usleep(µs uint32) {
   497  	usleep1(µs)
   498  }
   499  
   500  //go:nosplit
   501  func write(fd uintptr, buf unsafe.Pointer, nbyte int32) int32 {
   502  	return int32(sysvicall3(&libc_write, uintptr(fd), uintptr(buf), uintptr(nbyte)))
   503  }
   504  
   505  func osyield1()
   506  
   507  //go:nosplit
   508  func osyield() {
   509  	_g_ := getg()
   510  
   511  	// Check the validity of m because we might be called in cgo callback
   512  	// path early enough where there isn't a m available yet.
   513  	if _g_ != nil && _g_.m != nil {
   514  		sysvicall0(&libc_sched_yield)
   515  		return
   516  	}
   517  	osyield1()
   518  }
   519  
   520  //go:linkname executablePath os.executablePath
   521  var executablePath string
   522  
   523  func sysargs(argc int32, argv **byte) {
   524  	n := argc + 1
   525  
   526  	// skip over argv, envp to get to auxv
   527  	for argv_index(argv, n) != nil {
   528  		n++
   529  	}
   530  
   531  	// skip NULL separator
   532  	n++
   533  
   534  	// now argv+n is auxv
   535  	auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
   536  	sysauxv(auxv[:])
   537  }
   538  
   539  const (
   540  	_AT_NULL         = 0    // Terminates the vector
   541  	_AT_PAGESZ       = 6    // Page size in bytes
   542  	_AT_SUN_EXECNAME = 2014 // exec() path name
   543  )
   544  
   545  func sysauxv(auxv []uintptr) {
   546  	for i := 0; auxv[i] != _AT_NULL; i += 2 {
   547  		tag, val := auxv[i], auxv[i+1]
   548  		switch tag {
   549  		case _AT_PAGESZ:
   550  			physPageSize = val
   551  		case _AT_SUN_EXECNAME:
   552  			executablePath = gostringnocopy((*byte)(unsafe.Pointer(val)))
   553  		}
   554  	}
   555  }
   556  

View as plain text