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