rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/runtime/os1_plan9.go (about)

     1  // Copyright 2010 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 "unsafe"
     8  
     9  // Called to initialize a new m (including the bootstrap m).
    10  // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
    11  func mpreinit(mp *m) {
    12  	// Initialize stack and goroutine for note handling.
    13  	mp.gsignal = malg(32 * 1024)
    14  	mp.gsignal.m = mp
    15  	mp.notesig = (*int8)(mallocgc(_ERRMAX, nil, _FlagNoScan))
    16  	// Initialize stack for handling strings from the
    17  	// errstr system call, as used in package syscall.
    18  	mp.errstr = (*byte)(mallocgc(_ERRMAX, nil, _FlagNoScan))
    19  }
    20  
    21  // Called to initialize a new m (including the bootstrap m).
    22  // Called on the new thread, can not allocate memory.
    23  func minit() {
    24  	// Mask all SSE floating-point exceptions
    25  	// when running on the 64-bit kernel.
    26  	setfpmasks()
    27  }
    28  
    29  // Called from dropm to undo the effect of an minit.
    30  func unminit() {
    31  }
    32  
    33  var sysstat = []byte("/dev/sysstat\x00")
    34  
    35  func getproccount() int32 {
    36  	var buf [2048]byte
    37  	fd := open(&sysstat[0], _OREAD, 0)
    38  	if fd < 0 {
    39  		return 1
    40  	}
    41  	ncpu := int32(0)
    42  	for {
    43  		n := read(fd, unsafe.Pointer(&buf), int32(len(buf)))
    44  		if n <= 0 {
    45  			break
    46  		}
    47  		for i := int32(0); i < n; i++ {
    48  			if buf[i] == '\n' {
    49  				ncpu++
    50  			}
    51  		}
    52  	}
    53  	closefd(fd)
    54  	if ncpu == 0 {
    55  		ncpu = 1
    56  	}
    57  	return ncpu
    58  }
    59  
    60  var pid = []byte("#c/pid\x00")
    61  
    62  func getpid() uint64 {
    63  	var b [20]byte
    64  	fd := open(&pid[0], 0, 0)
    65  	if fd >= 0 {
    66  		read(fd, unsafe.Pointer(&b), int32(len(b)))
    67  		closefd(fd)
    68  	}
    69  	c := b[:]
    70  	for c[0] == ' ' || c[0] == '\t' {
    71  		c = c[1:]
    72  	}
    73  	return uint64(_atoi(c))
    74  }
    75  
    76  func osinit() {
    77  	initBloc()
    78  	ncpu = getproccount()
    79  	getg().m.procid = getpid()
    80  	notify(unsafe.Pointer(funcPC(sigtramp)))
    81  }
    82  
    83  func crash() {
    84  	notify(nil)
    85  	*(*int)(nil) = 0
    86  }
    87  
    88  //go:nosplit
    89  func getRandomData(r []byte) {
    90  	extendRandom(r, 0)
    91  }
    92  
    93  func goenvs() {
    94  }
    95  
    96  func initsig() {
    97  }
    98  
    99  //go:nosplit
   100  func osyield() {
   101  	sleep(0)
   102  }
   103  
   104  //go:nosplit
   105  func usleep(µs uint32) {
   106  	ms := int32(µs / 1000)
   107  	if ms == 0 {
   108  		ms = 1
   109  	}
   110  	sleep(ms)
   111  }
   112  
   113  //go:nosplit
   114  func nanotime() int64 {
   115  	var scratch int64
   116  	ns := nsec(&scratch)
   117  	// TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
   118  	if ns == 0 {
   119  		return scratch
   120  	}
   121  	return ns
   122  }
   123  
   124  //go:nosplit
   125  func itoa(buf []byte, val uint64) []byte {
   126  	i := len(buf) - 1
   127  	for val >= 10 {
   128  		buf[i] = byte(val%10 + '0')
   129  		i--
   130  		val /= 10
   131  	}
   132  	buf[i] = byte(val + '0')
   133  	return buf[i:]
   134  }
   135  
   136  var goexits = []byte("go: exit ")
   137  
   138  func goexitsall(status *byte) {
   139  	var buf [_ERRMAX]byte
   140  	n := copy(buf[:], goexits)
   141  	n = copy(buf[n:], gostringnocopy(status))
   142  	pid := getpid()
   143  	for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
   144  		if mp.procid != pid {
   145  			postnote(mp.procid, buf[:])
   146  		}
   147  	}
   148  }
   149  
   150  var procdir = []byte("/proc/")
   151  var notefile = []byte("/note\x00")
   152  
   153  func postnote(pid uint64, msg []byte) int {
   154  	var buf [128]byte
   155  	var tmp [32]byte
   156  	n := copy(buf[:], procdir)
   157  	n += copy(buf[n:], itoa(tmp[:], pid))
   158  	copy(buf[n:], notefile)
   159  	fd := open(&buf[0], _OWRITE, 0)
   160  	if fd < 0 {
   161  		return -1
   162  	}
   163  	len := findnull(&msg[0])
   164  	if write(uintptr(fd), (unsafe.Pointer)(&msg[0]), int32(len)) != int64(len) {
   165  		closefd(fd)
   166  		return -1
   167  	}
   168  	closefd(fd)
   169  	return 0
   170  }
   171  
   172  //go:nosplit
   173  func exit(e int) {
   174  	var status []byte
   175  	if e == 0 {
   176  		status = []byte("\x00")
   177  	} else {
   178  		// build error string
   179  		var tmp [32]byte
   180  		status = []byte(gostringnocopy(&itoa(tmp[:len(tmp)-1], uint64(e))[0]))
   181  	}
   182  	goexitsall(&status[0])
   183  	exits(&status[0])
   184  }
   185  
   186  // May run with m.p==nil, so write barriers are not allowed.
   187  //go:nowritebarrier
   188  func newosproc(mp *m, stk unsafe.Pointer) {
   189  	if false {
   190  		print("newosproc mp=", mp, " ostk=", &mp, "\n")
   191  	}
   192  	pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT)
   193  	if pid < 0 {
   194  		throw("newosproc: rfork failed")
   195  	}
   196  	if pid == 0 {
   197  		tstart_plan9(mp)
   198  	}
   199  }
   200  
   201  //go:nosplit
   202  func semacreate() uintptr {
   203  	return 1
   204  }
   205  
   206  //go:nosplit
   207  func semasleep(ns int64) int {
   208  	_g_ := getg()
   209  	if ns >= 0 {
   210  		ms := timediv(ns, 1000000, nil)
   211  		if ms == 0 {
   212  			ms = 1
   213  		}
   214  		ret := plan9_tsemacquire(&_g_.m.waitsemacount, ms)
   215  		if ret == 1 {
   216  			return 0 // success
   217  		}
   218  		return -1 // timeout or interrupted
   219  	}
   220  	for plan9_semacquire(&_g_.m.waitsemacount, 1) < 0 {
   221  		// interrupted; try again (c.f. lock_sema.go)
   222  	}
   223  	return 0 // success
   224  }
   225  
   226  //go:nosplit
   227  func semawakeup(mp *m) {
   228  	plan9_semrelease(&mp.waitsemacount, 1)
   229  }
   230  
   231  //go:nosplit
   232  func read(fd int32, buf unsafe.Pointer, n int32) int32 {
   233  	return pread(fd, buf, n, -1)
   234  }
   235  
   236  //go:nosplit
   237  func write(fd uintptr, buf unsafe.Pointer, n int32) int64 {
   238  	return int64(pwrite(int32(fd), buf, n, -1))
   239  }
   240  
   241  func memlimit() uint64 {
   242  	return 0
   243  }
   244  
   245  var _badsignal = []byte("runtime: signal received on thread not created by Go.\n")
   246  
   247  // This runs on a foreign stack, without an m or a g.  No stack split.
   248  //go:nosplit
   249  func badsignal2() {
   250  	pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1)
   251  	exits(&_badsignal[0])
   252  }
   253  
   254  func _atoi(b []byte) int {
   255  	n := 0
   256  	for len(b) > 0 && '0' <= b[0] && b[0] <= '9' {
   257  		n = n*10 + int(b[0]) - '0'
   258  		b = b[1:]
   259  	}
   260  	return n
   261  }