github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/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  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  }