Home | History | Annotate | Download | only in runtime
      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 type mOS struct {
     10 	waitsema      int32 // semaphore for parking on locks
     11 	waitsemacount int32
     12 	waitsemalock  int32
     13 }
     14 
     15 func nacl_exception_stack(p uintptr, size int32) int32
     16 func nacl_exception_handler(fn uintptr, arg unsafe.Pointer) int32
     17 func nacl_sem_create(flag int32) int32
     18 func nacl_sem_wait(sem int32) int32
     19 func nacl_sem_post(sem int32) int32
     20 func nacl_mutex_create(flag int32) int32
     21 func nacl_mutex_lock(mutex int32) int32
     22 func nacl_mutex_trylock(mutex int32) int32
     23 func nacl_mutex_unlock(mutex int32) int32
     24 func nacl_cond_create(flag int32) int32
     25 func nacl_cond_wait(cond, n int32) int32
     26 func nacl_cond_signal(cond int32) int32
     27 func nacl_cond_broadcast(cond int32) int32
     28 
     29 //go:noescape
     30 func nacl_cond_timed_wait_abs(cond, lock int32, ts *timespec) int32
     31 func nacl_thread_create(fn uintptr, stk, tls, xx unsafe.Pointer) int32
     32 
     33 //go:noescape
     34 func nacl_nanosleep(ts, extra *timespec) int32
     35 func nanotime() int64
     36 func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
     37 func exit(code int32)
     38 func osyield()
     39 
     40 //go:noescape
     41 func write(fd uintptr, p unsafe.Pointer, n int32) int32
     42 
     43 //go:linkname os_sigpipe os.sigpipe
     44 func os_sigpipe() {
     45 	throw("too many writes on closed pipe")
     46 }
     47 
     48 func dieFromSignal(sig uint32) {
     49 	exit(2)
     50 }
     51 
     52 func sigpanic() {
     53 	g := getg()
     54 	if !canpanic(g) {
     55 		throw("unexpected signal during runtime execution")
     56 	}
     57 
     58 	// Native Client only invokes the exception handler for memory faults.
     59 	g.sig = _SIGSEGV
     60 	panicmem()
     61 }
     62 
     63 func raiseproc(sig uint32) {
     64 }
     65 
     66 // Stubs so tests can link correctly. These should never be called.
     67 func open(name *byte, mode, perm int32) int32
     68 func closefd(fd int32) int32
     69 func read(fd int32, p unsafe.Pointer, n int32) int32
     70 
     71 type sigset struct{}
     72 
     73 // Called to initialize a new m (including the bootstrap m).
     74 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
     75 func mpreinit(mp *m) {
     76 	mp.gsignal = malg(32 * 1024)
     77 	mp.gsignal.m = mp
     78 }
     79 
     80 func sigtramp()
     81 
     82 //go:nosplit
     83 func msigsave(mp *m) {
     84 }
     85 
     86 //go:nosplit
     87 func msigrestore(sigmask sigset) {
     88 }
     89 
     90 //go:nosplit
     91 func sigblock() {
     92 }
     93 
     94 // Called to initialize a new m (including the bootstrap m).
     95 // Called on the new thread, cannot allocate memory.
     96 func minit() {
     97 	_g_ := getg()
     98 
     99 	// Initialize signal handling
    100 	ret := nacl_exception_stack(_g_.m.gsignal.stack.lo, 32*1024)
    101 	if ret < 0 {
    102 		print("runtime: nacl_exception_stack: error ", -ret, "\n")
    103 	}
    104 
    105 	ret = nacl_exception_handler(funcPC(sigtramp), nil)
    106 	if ret < 0 {
    107 		print("runtime: nacl_exception_handler: error ", -ret, "\n")
    108 	}
    109 }
    110 
    111 // Called from dropm to undo the effect of an minit.
    112 func unminit() {
    113 }
    114 
    115 func osinit() {
    116 	ncpu = 1
    117 	getg().m.procid = 2
    118 	//nacl_exception_handler(funcPC(sigtramp), nil);
    119 	physPageSize = 65536
    120 }
    121 
    122 func signame(sig uint32) string {
    123 	if sig >= uint32(len(sigtable)) {
    124 		return ""
    125 	}
    126 	return sigtable[sig].name
    127 }
    128 
    129 func crash() {
    130 	*(*int32)(nil) = 0
    131 }
    132 
    133 //go:noescape
    134 func getRandomData([]byte)
    135 
    136 func goenvs() {
    137 	goenvs_unix()
    138 }
    139 
    140 func initsig(preinit bool) {
    141 }
    142 
    143 //go:nosplit
    144 func usleep(us uint32) {
    145 	var ts timespec
    146 
    147 	ts.tv_sec = int64(us / 1e6)
    148 	ts.tv_nsec = int32(us%1e6) * 1e3
    149 	nacl_nanosleep(&ts, nil)
    150 }
    151 
    152 func mstart_nacl()
    153 
    154 // May run with m.p==nil, so write barriers are not allowed.
    155 //go:nowritebarrier
    156 func newosproc(mp *m, stk unsafe.Pointer) {
    157 	mp.tls[0] = uintptr(unsafe.Pointer(mp.g0))
    158 	mp.tls[1] = uintptr(unsafe.Pointer(mp))
    159 	ret := nacl_thread_create(funcPC(mstart_nacl), stk, unsafe.Pointer(&mp.tls[2]), nil)
    160 	if ret < 0 {
    161 		print("nacl_thread_create: error ", -ret, "\n")
    162 		throw("newosproc")
    163 	}
    164 }
    165 
    166 //go:nosplit
    167 func semacreate(mp *m) {
    168 	if mp.waitsema != 0 {
    169 		return
    170 	}
    171 	systemstack(func() {
    172 		mu := nacl_mutex_create(0)
    173 		if mu < 0 {
    174 			print("nacl_mutex_create: error ", -mu, "\n")
    175 			throw("semacreate")
    176 		}
    177 		c := nacl_cond_create(0)
    178 		if c < 0 {
    179 			print("nacl_cond_create: error ", -c, "\n")
    180 			throw("semacreate")
    181 		}
    182 		mp.waitsema = c
    183 		mp.waitsemalock = mu
    184 	})
    185 }
    186 
    187 //go:nosplit
    188 func semasleep(ns int64) int32 {
    189 	var ret int32
    190 
    191 	systemstack(func() {
    192 		_g_ := getg()
    193 		if nacl_mutex_lock(_g_.m.waitsemalock) < 0 {
    194 			throw("semasleep")
    195 		}
    196 
    197 		for _g_.m.waitsemacount == 0 {
    198 			if ns < 0 {
    199 				if nacl_cond_wait(_g_.m.waitsema, _g_.m.waitsemalock) < 0 {
    200 					throw("semasleep")
    201 				}
    202 			} else {
    203 				var ts timespec
    204 				end := ns + nanotime()
    205 				ts.tv_sec = end / 1e9
    206 				ts.tv_nsec = int32(end % 1e9)
    207 				r := nacl_cond_timed_wait_abs(_g_.m.waitsema, _g_.m.waitsemalock, &ts)
    208 				if r == -_ETIMEDOUT {
    209 					nacl_mutex_unlock(_g_.m.waitsemalock)
    210 					ret = -1
    211 					return
    212 				}
    213 				if r < 0 {
    214 					throw("semasleep")
    215 				}
    216 			}
    217 		}
    218 
    219 		_g_.m.waitsemacount = 0
    220 		nacl_mutex_unlock(_g_.m.waitsemalock)
    221 		ret = 0
    222 	})
    223 	return ret
    224 }
    225 
    226 //go:nosplit
    227 func semawakeup(mp *m) {
    228 	systemstack(func() {
    229 		if nacl_mutex_lock(mp.waitsemalock) < 0 {
    230 			throw("semawakeup")
    231 		}
    232 		if mp.waitsemacount != 0 {
    233 			throw("semawakeup")
    234 		}
    235 		mp.waitsemacount = 1
    236 		nacl_cond_signal(mp.waitsema)
    237 		nacl_mutex_unlock(mp.waitsemalock)
    238 	})
    239 }
    240 
    241 func memlimit() uintptr {
    242 	return 0
    243 }
    244 
    245 // This runs on a foreign stack, without an m or a g. No stack split.
    246 //go:nosplit
    247 //go:norace
    248 //go:nowritebarrierrec
    249 func badsignal(sig uintptr) {
    250 	cgocallback(unsafe.Pointer(funcPC(badsignalgo)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig), 0)
    251 }
    252 
    253 func badsignalgo(sig uintptr) {
    254 	if !sigsend(uint32(sig)) {
    255 		// A foreign thread received the signal sig, and the
    256 		// Go code does not want to handle it.
    257 		raisebadsignal(uint32(sig))
    258 	}
    259 }
    260 
    261 // This runs on a foreign stack, without an m or a g. No stack split.
    262 //go:nosplit
    263 func badsignal2() {
    264 	write(2, unsafe.Pointer(&badsignal1[0]), int32(len(badsignal1)))
    265 	exit(2)
    266 }
    267 
    268 var badsignal1 = []byte("runtime: signal received on thread not created by Go.\n")
    269 
    270 func raisebadsignal(sig uint32) {
    271 	badsignal2()
    272 }
    273 
    274 func madvise(addr unsafe.Pointer, n uintptr, flags int32) {}
    275 func munmap(addr unsafe.Pointer, n uintptr)               {}
    276 func resetcpuprofiler(hz int32)                           {}
    277 func sigdisable(uint32)                                   {}
    278 func sigenable(uint32)                                    {}
    279 func sigignore(uint32)                                    {}
    280 func closeonexec(int32)                                   {}
    281 
    282 var writelock uint32 // test-and-set spin lock for write
    283 
    284 /*
    285 An attempt at IRT. Doesn't work. See end of sys_nacl_amd64.s.
    286 
    287 void (*nacl_irt_query)(void);
    288 
    289 int8 nacl_irt_basic_v0_1_str[] = "nacl-irt-basic-0.1";
    290 void *nacl_irt_basic_v0_1[6]; // exit, gettod, clock, nanosleep, sched_yield, sysconf
    291 int32 nacl_irt_basic_v0_1_size = sizeof(nacl_irt_basic_v0_1);
    292 
    293 int8 nacl_irt_memory_v0_3_str[] = "nacl-irt-memory-0.3";
    294 void *nacl_irt_memory_v0_3[3]; // mmap, munmap, mprotect
    295 int32 nacl_irt_memory_v0_3_size = sizeof(nacl_irt_memory_v0_3);
    296 
    297 int8 nacl_irt_thread_v0_1_str[] = "nacl-irt-thread-0.1";
    298 void *nacl_irt_thread_v0_1[3]; // thread_create, thread_exit, thread_nice
    299 int32 nacl_irt_thread_v0_1_size = sizeof(nacl_irt_thread_v0_1);
    300 */
    301