Source file 
src/runtime/os_plan9.go
     1  
     2  
     3  
     4  
     5  package runtime
     6  
     7  import (
     8  	"internal/abi"
     9  	"internal/byteorder"
    10  	"internal/runtime/atomic"
    11  	"internal/stringslite"
    12  	"unsafe"
    13  )
    14  
    15  type mOS struct {
    16  	waitsemacount uint32
    17  	notesig       *int8
    18  	errstr        *byte
    19  	ignoreHangup  bool
    20  }
    21  
    22  func dupfd(old, new int32) int32
    23  func closefd(fd int32) int32
    24  
    25  
    26  func open(name *byte, mode, perm int32) int32
    27  
    28  
    29  func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
    30  
    31  
    32  func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
    33  
    34  func seek(fd int32, offset int64, whence int32) int64
    35  
    36  
    37  func exits(msg *byte)
    38  
    39  
    40  func brk_(addr unsafe.Pointer) int32
    41  
    42  func sleep(ms int32) int32
    43  
    44  func rfork(flags int32) int32
    45  
    46  
    47  func plan9_semacquire(addr *uint32, block int32) int32
    48  
    49  
    50  func plan9_tsemacquire(addr *uint32, ms int32) int32
    51  
    52  
    53  func plan9_semrelease(addr *uint32, count int32) int32
    54  
    55  
    56  func notify(fn unsafe.Pointer) int32
    57  
    58  func noted(mode int32) int32
    59  
    60  
    61  func nsec(*int64) int64
    62  
    63  
    64  func sigtramp(ureg, note unsafe.Pointer)
    65  
    66  func setfpmasks()
    67  
    68  
    69  func tstart_plan9(newm *m)
    70  
    71  func errstr() string
    72  
    73  type _Plink uintptr
    74  
    75  func sigpanic() {
    76  	gp := getg()
    77  	if !canpanic() {
    78  		throw("unexpected signal during runtime execution")
    79  	}
    80  
    81  	note := gostringnocopy((*byte)(unsafe.Pointer(gp.m.notesig)))
    82  	switch gp.sig {
    83  	case _SIGRFAULT, _SIGWFAULT:
    84  		i := indexNoFloat(note, "addr=")
    85  		if i >= 0 {
    86  			i += 5
    87  		} else if i = indexNoFloat(note, "va="); i >= 0 {
    88  			i += 3
    89  		} else {
    90  			panicmem()
    91  		}
    92  		addr := note[i:]
    93  		gp.sigcode1 = uintptr(atolwhex(addr))
    94  		if gp.sigcode1 < 0x1000 {
    95  			panicmem()
    96  		}
    97  		if gp.paniconfault {
    98  			panicmemAddr(gp.sigcode1)
    99  		}
   100  		if inUserArenaChunk(gp.sigcode1) {
   101  			
   102  			
   103  			
   104  			print("accessed data from freed user arena ", hex(gp.sigcode1), "\n")
   105  		} else {
   106  			print("unexpected fault address ", hex(gp.sigcode1), "\n")
   107  		}
   108  		throw("fault")
   109  	case _SIGTRAP:
   110  		if gp.paniconfault {
   111  			panicmem()
   112  		}
   113  		throw(note)
   114  	case _SIGINTDIV:
   115  		panicdivide()
   116  	case _SIGFLOAT:
   117  		panicfloat()
   118  	default:
   119  		panic(errorString(note))
   120  	}
   121  }
   122  
   123  
   124  
   125  func indexNoFloat(s, t string) int {
   126  	if len(t) == 0 {
   127  		return 0
   128  	}
   129  	for i := 0; i < len(s); i++ {
   130  		if s[i] == t[0] && stringslite.HasPrefix(s[i:], t) {
   131  			return i
   132  		}
   133  	}
   134  	return -1
   135  }
   136  
   137  func atolwhex(p string) int64 {
   138  	for stringslite.HasPrefix(p, " ") || stringslite.HasPrefix(p, "\t") {
   139  		p = p[1:]
   140  	}
   141  	neg := false
   142  	if stringslite.HasPrefix(p, "-") || stringslite.HasPrefix(p, "+") {
   143  		neg = p[0] == '-'
   144  		p = p[1:]
   145  		for stringslite.HasPrefix(p, " ") || stringslite.HasPrefix(p, "\t") {
   146  			p = p[1:]
   147  		}
   148  	}
   149  	var n int64
   150  	switch {
   151  	case stringslite.HasPrefix(p, "0x"), stringslite.HasPrefix(p, "0X"):
   152  		p = p[2:]
   153  		for ; len(p) > 0; p = p[1:] {
   154  			if '0' <= p[0] && p[0] <= '9' {
   155  				n = n*16 + int64(p[0]-'0')
   156  			} else if 'a' <= p[0] && p[0] <= 'f' {
   157  				n = n*16 + int64(p[0]-'a'+10)
   158  			} else if 'A' <= p[0] && p[0] <= 'F' {
   159  				n = n*16 + int64(p[0]-'A'+10)
   160  			} else {
   161  				break
   162  			}
   163  		}
   164  	case stringslite.HasPrefix(p, "0"):
   165  		for ; len(p) > 0 && '0' <= p[0] && p[0] <= '7'; p = p[1:] {
   166  			n = n*8 + int64(p[0]-'0')
   167  		}
   168  	default:
   169  		for ; len(p) > 0 && '0' <= p[0] && p[0] <= '9'; p = p[1:] {
   170  			n = n*10 + int64(p[0]-'0')
   171  		}
   172  	}
   173  	if neg {
   174  		n = -n
   175  	}
   176  	return n
   177  }
   178  
   179  type sigset struct{}
   180  
   181  
   182  
   183  func mpreinit(mp *m) {
   184  	
   185  	mp.gsignal = malg(32 * 1024)
   186  	mp.gsignal.m = mp
   187  	mp.notesig = (*int8)(mallocgc(_ERRMAX, nil, true))
   188  	
   189  	
   190  	mp.errstr = (*byte)(mallocgc(_ERRMAX, nil, true))
   191  }
   192  
   193  func sigsave(p *sigset) {
   194  }
   195  
   196  func msigrestore(sigmask sigset) {
   197  }
   198  
   199  
   200  
   201  func clearSignalHandlers() {
   202  }
   203  
   204  func sigblock(exiting bool) {
   205  }
   206  
   207  
   208  
   209  func minit() {
   210  	if atomic.Load(&exiting) != 0 {
   211  		exits(&emptystatus[0])
   212  	}
   213  	
   214  	
   215  	setfpmasks()
   216  }
   217  
   218  
   219  func unminit() {
   220  }
   221  
   222  
   223  
   224  
   225  
   226  
   227  
   228  func mdestroy(mp *m) {
   229  }
   230  
   231  var sysstat = []byte("/dev/sysstat\x00")
   232  
   233  func getCPUCount() int32 {
   234  	var buf [2048]byte
   235  	fd := open(&sysstat[0], _OREAD|_OCEXEC, 0)
   236  	if fd < 0 {
   237  		return 1
   238  	}
   239  	ncpu := int32(0)
   240  	for {
   241  		n := read(fd, unsafe.Pointer(&buf), int32(len(buf)))
   242  		if n <= 0 {
   243  			break
   244  		}
   245  		for i := int32(0); i < n; i++ {
   246  			if buf[i] == '\n' {
   247  				ncpu++
   248  			}
   249  		}
   250  	}
   251  	closefd(fd)
   252  	if ncpu == 0 {
   253  		ncpu = 1
   254  	}
   255  	return ncpu
   256  }
   257  
   258  var devswap = []byte("/dev/swap\x00")
   259  var pagesize = []byte(" pagesize\n")
   260  
   261  func getPageSize() uintptr {
   262  	var buf [2048]byte
   263  	var pos int
   264  	fd := open(&devswap[0], _OREAD|_OCEXEC, 0)
   265  	if fd < 0 {
   266  		
   267  		
   268  		
   269  		return minPhysPageSize
   270  	}
   271  	for pos < len(buf) {
   272  		n := read(fd, unsafe.Pointer(&buf[pos]), int32(len(buf)-pos))
   273  		if n <= 0 {
   274  			break
   275  		}
   276  		pos += int(n)
   277  	}
   278  	closefd(fd)
   279  	text := buf[:pos]
   280  	
   281  	bol := 0
   282  	for i, c := range text {
   283  		if c == '\n' {
   284  			bol = i + 1
   285  		}
   286  		if bytesHasPrefix(text[i:], pagesize) {
   287  			
   288  			return uintptr(_atoi(text[bol:]))
   289  		}
   290  	}
   291  	
   292  	return minPhysPageSize
   293  }
   294  
   295  func bytesHasPrefix(s, prefix []byte) bool {
   296  	if len(s) < len(prefix) {
   297  		return false
   298  	}
   299  	for i, p := range prefix {
   300  		if s[i] != p {
   301  			return false
   302  		}
   303  	}
   304  	return true
   305  }
   306  
   307  var pid = []byte("#c/pid\x00")
   308  
   309  func getpid() uint64 {
   310  	var b [20]byte
   311  	fd := open(&pid[0], 0, 0)
   312  	if fd >= 0 {
   313  		read(fd, unsafe.Pointer(&b), int32(len(b)))
   314  		closefd(fd)
   315  	}
   316  	c := b[:]
   317  	for c[0] == ' ' || c[0] == '\t' {
   318  		c = c[1:]
   319  	}
   320  	return uint64(_atoi(c))
   321  }
   322  
   323  var (
   324  	bintimeFD int32 = -1
   325  
   326  	bintimeDev = []byte("/dev/bintime\x00")
   327  	randomDev  = []byte("/dev/random\x00")
   328  )
   329  
   330  func osinit() {
   331  	physPageSize = getPageSize()
   332  	initBloc()
   333  	numCPUStartup = getCPUCount()
   334  	getg().m.procid = getpid()
   335  
   336  	fd := open(&bintimeDev[0], _OREAD|_OCEXEC, 0)
   337  	if fd < 0 {
   338  		fatal("cannot open /dev/bintime")
   339  	}
   340  	bintimeFD = fd
   341  
   342  	
   343  	
   344  	
   345  	
   346  	if bintimeFD < 18 {
   347  		if dupfd(bintimeFD, 18) < 0 {
   348  			fatal("cannot dup /dev/bintime onto 18")
   349  		}
   350  		closefd(bintimeFD)
   351  		bintimeFD = 18
   352  	}
   353  }
   354  
   355  
   356  func crash() {
   357  	notify(nil)
   358  	*(*int)(nil) = 0
   359  }
   360  
   361  
   362  
   363  
   364  
   365  
   366  func readRandom(r []byte) int {
   367  	return 0
   368  }
   369  
   370  func initsig(preinit bool) {
   371  	if !preinit {
   372  		notify(unsafe.Pointer(abi.FuncPCABI0(sigtramp)))
   373  	}
   374  }
   375  
   376  
   377  func osyield() {
   378  	sleep(0)
   379  }
   380  
   381  
   382  func osyield_no_g() {
   383  	osyield()
   384  }
   385  
   386  
   387  func usleep(µs uint32) {
   388  	ms := int32(µs / 1000)
   389  	if ms == 0 {
   390  		ms = 1
   391  	}
   392  	sleep(ms)
   393  }
   394  
   395  
   396  func usleep_no_g(usec uint32) {
   397  	usleep(usec)
   398  }
   399  
   400  var goexits = []byte("go: exit ")
   401  var emptystatus = []byte("\x00")
   402  var exiting uint32
   403  
   404  func goexitsall(status *byte) {
   405  	var buf [_ERRMAX]byte
   406  	if !atomic.Cas(&exiting, 0, 1) {
   407  		return
   408  	}
   409  	getg().m.locks++
   410  	n := copy(buf[:], goexits)
   411  	n = copy(buf[n:], gostringnocopy(status))
   412  	pid := getpid()
   413  	for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
   414  		if mp.procid != 0 && mp.procid != pid {
   415  			postnote(mp.procid, buf[:])
   416  		}
   417  	}
   418  	getg().m.locks--
   419  }
   420  
   421  var procdir = []byte("/proc/")
   422  var notefile = []byte("/note\x00")
   423  
   424  func postnote(pid uint64, msg []byte) int {
   425  	var buf [128]byte
   426  	var tmp [32]byte
   427  	n := copy(buf[:], procdir)
   428  	n += copy(buf[n:], itoa(tmp[:], pid))
   429  	copy(buf[n:], notefile)
   430  	fd := open(&buf[0], _OWRITE, 0)
   431  	if fd < 0 {
   432  		return -1
   433  	}
   434  	len := findnull(&msg[0])
   435  	if write1(uintptr(fd), unsafe.Pointer(&msg[0]), int32(len)) != int32(len) {
   436  		closefd(fd)
   437  		return -1
   438  	}
   439  	closefd(fd)
   440  	return 0
   441  }
   442  
   443  
   444  func exit(e int32) {
   445  	var status []byte
   446  	if e == 0 {
   447  		status = emptystatus
   448  	} else {
   449  		
   450  		var tmp [32]byte
   451  		sl := itoa(tmp[:len(tmp)-1], uint64(e))
   452  		
   453  		status = sl[:len(sl)+1]
   454  	}
   455  	goexitsall(&status[0])
   456  	exits(&status[0])
   457  }
   458  
   459  
   460  
   461  
   462  func newosproc(mp *m) {
   463  	if false {
   464  		print("newosproc mp=", mp, " ostk=", &mp, "\n")
   465  	}
   466  	pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT)
   467  	if pid < 0 {
   468  		throw("newosproc: rfork failed")
   469  	}
   470  	if pid == 0 {
   471  		tstart_plan9(mp)
   472  	}
   473  }
   474  
   475  func exitThread(wait *atomic.Uint32) {
   476  	
   477  	
   478  	throw("exitThread")
   479  }
   480  
   481  
   482  func semacreate(mp *m) {
   483  }
   484  
   485  
   486  func semasleep(ns int64) int {
   487  	gp := getg()
   488  	if ns >= 0 {
   489  		ms := timediv(ns, 1000000, nil)
   490  		if ms == 0 {
   491  			ms = 1
   492  		}
   493  		ret := plan9_tsemacquire(&gp.m.waitsemacount, ms)
   494  		if ret == 1 {
   495  			return 0 
   496  		}
   497  		return -1 
   498  	}
   499  	for plan9_semacquire(&gp.m.waitsemacount, 1) < 0 {
   500  		
   501  	}
   502  	return 0 
   503  }
   504  
   505  
   506  func semawakeup(mp *m) {
   507  	plan9_semrelease(&mp.waitsemacount, 1)
   508  }
   509  
   510  
   511  func read(fd int32, buf unsafe.Pointer, n int32) int32 {
   512  	return pread(fd, buf, n, -1)
   513  }
   514  
   515  
   516  func write1(fd uintptr, buf unsafe.Pointer, n int32) int32 {
   517  	return pwrite(int32(fd), buf, n, -1)
   518  }
   519  
   520  var _badsignal = []byte("runtime: signal received on thread not created by Go.\n")
   521  
   522  
   523  
   524  
   525  func badsignal2() {
   526  	pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1)
   527  	exits(&_badsignal[0])
   528  }
   529  
   530  func raisebadsignal(sig uint32) {
   531  	badsignal2()
   532  }
   533  
   534  func _atoi(b []byte) int {
   535  	n := 0
   536  	for len(b) > 0 && '0' <= b[0] && b[0] <= '9' {
   537  		n = n*10 + int(b[0]) - '0'
   538  		b = b[1:]
   539  	}
   540  	return n
   541  }
   542  
   543  func signame(sig uint32) string {
   544  	if sig >= uint32(len(sigtable)) {
   545  		return ""
   546  	}
   547  	return sigtable[sig].name
   548  }
   549  
   550  const preemptMSupported = false
   551  
   552  func preemptM(mp *m) {
   553  	
   554  	
   555  	
   556  }
   557  
   558  
   559  func readtime(t *uint64, min, n int) int {
   560  	if bintimeFD < 0 {
   561  		fatal("/dev/bintime not opened")
   562  	}
   563  	const uint64size = 8
   564  	r := pread(bintimeFD, unsafe.Pointer(t), int32(n*uint64size), 0)
   565  	if int(r) < min*uint64size {
   566  		fatal("cannot read /dev/bintime")
   567  	}
   568  	return int(r) / uint64size
   569  }
   570  
   571  
   572  func timesplit(u uint64) (sec int64, nsec int32)
   573  
   574  func frombe(u uint64) uint64 {
   575  	b := (*[8]byte)(unsafe.Pointer(&u))
   576  	return byteorder.BEUint64(b[:])
   577  }
   578  
   579  
   580  func nanotime1() int64 {
   581  	var t [4]uint64
   582  	if readtime(&t[0], 1, 4) == 4 {
   583  		
   584  		
   585  		return int64(frombe(t[3]))
   586  	}
   587  	
   588  	return int64(frombe(t[0]))
   589  }
   590  
   591  
   592  func walltime() (sec int64, nsec int32) {
   593  	var t [1]uint64
   594  	readtime(&t[0], 1, 1)
   595  	return timesplit(frombe(t[0]))
   596  }
   597  
View as plain text