github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/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_data [_HashRandomBytes]byte
    89  var random_dev = []byte("/dev/random\x00")
    90  
    91  //go:nosplit
    92  func get_random_data(rnd *unsafe.Pointer, rnd_len *int32) {
    93  	fd := open(&random_dev[0], 0 /* O_RDONLY */, 0)
    94  	if read(fd, unsafe.Pointer(&random_data), _HashRandomBytes) == _HashRandomBytes {
    95  		*rnd = unsafe.Pointer(&random_data[0])
    96  		*rnd_len = _HashRandomBytes
    97  	} else {
    98  		*rnd = nil
    99  		*rnd_len = 0
   100  	}
   101  	close(fd)
   102  }
   103  
   104  func goenvs() {
   105  }
   106  
   107  func initsig() {
   108  }
   109  
   110  //go:nosplit
   111  func osyield() {
   112  	sleep(0)
   113  }
   114  
   115  //go:nosplit
   116  func usleep(µs uint32) {
   117  	ms := int32(µs / 1000)
   118  	if ms == 0 {
   119  		ms = 1
   120  	}
   121  	sleep(ms)
   122  }
   123  
   124  //go:nosplit
   125  func nanotime() int64 {
   126  	var scratch int64
   127  	ns := nsec(&scratch)
   128  	// TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
   129  	if ns == 0 {
   130  		return scratch
   131  	}
   132  	return ns
   133  }
   134  
   135  //go:nosplit
   136  func itoa(buf []byte, val uint64) []byte {
   137  	i := len(buf) - 1
   138  	for val >= 10 {
   139  		buf[i] = byte(val%10 + '0')
   140  		i--
   141  		val /= 10
   142  	}
   143  	buf[i] = byte(val + '0')
   144  	return buf[i:]
   145  }
   146  
   147  var goexits = []byte("go: exit ")
   148  
   149  func goexitsall(status *byte) {
   150  	var buf [_ERRMAX]byte
   151  	n := copy(buf[:], goexits)
   152  	n = copy(buf[n:], gostringnocopy(status))
   153  	pid := getpid()
   154  	for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
   155  		if mp.procid != pid {
   156  			postnote(mp.procid, buf[:])
   157  		}
   158  	}
   159  }
   160  
   161  var procdir = []byte("/proc/")
   162  var notefile = []byte("/note\x00")
   163  
   164  func postnote(pid uint64, msg []byte) int {
   165  	var buf [128]byte
   166  	var tmp [32]byte
   167  	n := copy(buf[:], procdir)
   168  	n += copy(buf[n:], itoa(tmp[:], pid))
   169  	copy(buf[n:], notefile)
   170  	fd := open(&buf[0], _OWRITE, 0)
   171  	if fd < 0 {
   172  		return -1
   173  	}
   174  	len := findnull(&msg[0])
   175  	if write(uintptr(fd), (unsafe.Pointer)(&msg[0]), int32(len)) != int64(len) {
   176  		close(fd)
   177  		return -1
   178  	}
   179  	close(fd)
   180  	return 0
   181  }
   182  
   183  //go:nosplit
   184  func exit(e int) {
   185  	var status []byte
   186  	if e == 0 {
   187  		status = []byte("\x00")
   188  	} else {
   189  		// build error string
   190  		var tmp [32]byte
   191  		status = []byte(gostringnocopy(&itoa(tmp[:], uint64(e))[0]) + "\x00")
   192  	}
   193  	goexitsall(&status[0])
   194  	exits(&status[0])
   195  }
   196  
   197  func newosproc(mp *m, stk unsafe.Pointer) {
   198  	if false {
   199  		print("newosproc mp=", mp, " ostk=", &mp, "\n")
   200  	}
   201  	pid := rfork(_RFPROC | _RFMEM | _RFNOWAIT)
   202  	if pid < 0 {
   203  		gothrow("newosproc: rfork failed")
   204  	}
   205  	if pid == 0 {
   206  		tstart_plan9(mp)
   207  	}
   208  }
   209  
   210  //go:nosplit
   211  func semacreate() uintptr {
   212  	return 1
   213  }
   214  
   215  //go:nosplit
   216  func semasleep(ns int64) int {
   217  	_g_ := getg()
   218  	if ns >= 0 {
   219  		ms := timediv(ns, 1000000, nil)
   220  		if ms == 0 {
   221  			ms = 1
   222  		}
   223  		ret := plan9_tsemacquire(&_g_.m.waitsemacount, ms)
   224  		if ret == 1 {
   225  			return 0 // success
   226  		}
   227  		return -1 // timeout or interrupted
   228  	}
   229  	for plan9_semacquire(&_g_.m.waitsemacount, 1) < 0 {
   230  		// interrupted; try again (c.f. lock_sema.go)
   231  	}
   232  	return 0 // success
   233  }
   234  
   235  //go:nosplit
   236  func semawakeup(mp *m) {
   237  	plan9_semrelease(&mp.waitsemacount, 1)
   238  }
   239  
   240  //go:nosplit
   241  func read(fd int32, buf unsafe.Pointer, n int32) int32 {
   242  	return pread(fd, buf, n, -1)
   243  }
   244  
   245  //go:nosplit
   246  func write(fd uintptr, buf unsafe.Pointer, n int32) int64 {
   247  	return int64(pwrite(int32(fd), buf, n, -1))
   248  }
   249  
   250  func memlimit() uint64 {
   251  	return 0
   252  }
   253  
   254  var _badsignal = []byte("runtime: signal received on thread not created by Go.\n")
   255  
   256  // This runs on a foreign stack, without an m or a g.  No stack split.
   257  //go:nosplit
   258  func badsignal2() {
   259  	pwrite(2, unsafe.Pointer(&_badsignal[0]), int32(len(_badsignal)), -1)
   260  	exits(&_badsignal[0])
   261  }
   262  
   263  func atoi(b []byte) int {
   264  	n := 0
   265  	for len(b) > 0 && '0' <= b[0] && b[0] <= '9' {
   266  		n = n*10 + int(b[0]) - '0'
   267  		b = b[1:]
   268  	}
   269  	return n
   270  }