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