github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/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  	close(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  		close(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  var random_dev = []byte("/dev/random\x00")
    89  
    90  //go:nosplit
    91  func getRandomData(r []byte) {
    92  	fd := open(&random_dev[0], 0 /* O_RDONLY */, 0)
    93  	n := read(fd, unsafe.Pointer(&r[0]), int32(len(r)))
    94  	close(fd)
    95  	extendRandom(r, int(n))
    96  }
    97  
    98  func goenvs() {
    99  }
   100  
   101  func initsig() {
   102  }
   103  
   104  //go:nosplit
   105  func osyield() {
   106  	sleep(0)
   107  }
   108  
   109  //go:nosplit
   110  func usleep(µs uint32) {
   111  	ms := int32(µs / 1000)
   112  	if ms == 0 {
   113  		ms = 1
   114  	}
   115  	sleep(ms)
   116  }
   117  
   118  //go:nosplit
   119  func nanotime() int64 {
   120  	var scratch int64
   121  	ns := nsec(&scratch)
   122  	// TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
   123  	if ns == 0 {
   124  		return scratch
   125  	}
   126  	return ns
   127  }
   128  
   129  //go:nosplit
   130  func itoa(buf []byte, val uint64) []byte {
   131  	i := len(buf) - 1
   132  	for val >= 10 {
   133  		buf[i] = byte(val%10 + '0')
   134  		i--
   135  		val /= 10
   136  	}
   137  	buf[i] = byte(val + '0')
   138  	return buf[i:]
   139  }
   140  
   141  var goexits = []byte("go: exit ")
   142  
   143  func goexitsall(status *byte) {
   144  	var buf [_ERRMAX]byte
   145  	n := copy(buf[:], goexits)
   146  	n = copy(buf[n:], gostringnocopy(status))
   147  	pid := getpid()
   148  	for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
   149  		if mp.procid != pid {
   150  			postnote(mp.procid, buf[:])
   151  		}
   152  	}
   153  }
   154  
   155  var procdir = []byte("/proc/")
   156  var notefile = []byte("/note\x00")
   157  
   158  func postnote(pid uint64, msg []byte) int {
   159  	var buf [128]byte
   160  	var tmp [32]byte
   161  	n := copy(buf[:], procdir)
   162  	n += copy(buf[n:], itoa(tmp[:], pid))
   163  	copy(buf[n:], notefile)
   164  	fd := open(&buf[0], _OWRITE, 0)
   165  	if fd < 0 {
   166  		return -1
   167  	}
   168  	len := findnull(&msg[0])
   169  	if write(uintptr(fd), (unsafe.Pointer)(&msg[0]), int32(len)) != int64(len) {
   170  		close(fd)
   171  		return -1
   172  	}
   173  	close(fd)
   174  	return 0
   175  }
   176  
   177  //go:nosplit
   178  func exit(e int) {
   179  	var status []byte
   180  	if e == 0 {
   181  		status = []byte("\x00")
   182  	} else {
   183  		// build error string
   184  		var tmp [32]byte
   185  		status = []byte(gostringnocopy(&itoa(tmp[:len(tmp)-1], uint64(e))[0]))
   186  	}
   187  	goexitsall(&status[0])
   188  	exits(&status[0])
   189  }
   190  
   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 _atoi(b []byte) int {
   258  	n := 0
   259  	for len(b) > 0 && '0' <= b[0] && b[0] <= '9' {
   260  		n = n*10 + int(b[0]) - '0'
   261  		b = b[1:]
   262  	}
   263  	return n
   264  }