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